- char buf[1024];
- sprintf(buf,
- "const mat3 %s = mat3(\n"
- " %.8f, %.8f, %.8f,\n"
- " %.8f, %.8f, %.8f,\n"
- " %.8f, %.8f, %.8f);\n\n",
- name.c_str(),
- m(0,0), m(1,0), m(2,0),
- m(0,1), m(1,1), m(2,1),
- m(0,2), m(1,2), m(2,2));
- return buf;
+ // Use stringstream to be independent of the current locale in a thread-safe manner.
+ stringstream ss;
+ ss.imbue(locale("C"));
+ ss.precision(8);
+ ss << scientific;
+ ss << "const vec3 " << name << " = vec3(" << x << ", " << y << ", " << z << ");\n";
+ return ss.str();
+}
+
+GLuint generate_vbo(GLint size, GLenum type, GLsizeiptr data_size, const GLvoid *data)
+{
+ GLuint vbo;
+ glGenBuffers(1, &vbo);
+ check_error();
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ check_error();
+ glBufferData(GL_ARRAY_BUFFER, data_size, data, GL_STATIC_DRAW);
+ check_error();
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ check_error();
+
+ return vbo;
+}
+
+GLuint fill_vertex_attribute(GLuint glsl_program_num, const string &attribute_name, GLint size, GLenum type, GLsizeiptr data_size, const GLvoid *data)
+{
+ int attrib = glGetAttribLocation(glsl_program_num, attribute_name.c_str());
+ if (attrib == -1) {
+ return -1;
+ }
+
+ GLuint vbo = generate_vbo(size, type, data_size, data);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ check_error();
+ glEnableVertexAttribArray(attrib);
+ check_error();
+ glVertexAttribPointer(attrib, size, type, GL_FALSE, 0, BUFFER_OFFSET(0));
+ check_error();
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ check_error();
+
+ return vbo;
+}
+
+void cleanup_vertex_attribute(GLuint glsl_program_num, const string &attribute_name, GLuint vbo)
+{
+ int attrib = glGetAttribLocation(glsl_program_num, attribute_name.c_str());
+ if (attrib == -1) {
+ return;
+ }
+
+ glDisableVertexAttribArray(attrib);
+ check_error();
+ glDeleteBuffers(1, &vbo);
+ check_error();