Add cylinder mesh generation Mesh generation can be used by everyone Mesh generation also gives vertex normals for convenience
		
			
				
	
	
		
			884 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			884 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| * Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net
 | |
| *
 | |
| * This software is provided 'as-is', without any express or implied
 | |
| * warranty.  In no event will the authors be held liable for any damages
 | |
| * arising from the use of this software.
 | |
| * Permission is granted to anyone to use this software for any purpose,
 | |
| * including commercial applications, and to alter it and redistribute it
 | |
| * freely, subject to the following restrictions:
 | |
| * 1. The origin of this software must not be misrepresented; you must not
 | |
| * claim that you wrote the original software. If you use this software
 | |
| * in a product, an acknowledgment in the product documentation would be
 | |
| * appreciated but is not required.
 | |
| * 2. Altered source versions must be plainly marked as such, and must not be
 | |
| * misrepresented as being the original software.
 | |
| * 3. This notice may not be removed or altered from any source distribution.
 | |
| */
 | |
| 
 | |
| #ifndef DRAW_GL4_H
 | |
| #define DRAW_GL4_H
 | |
| 
 | |
| #include <glad_4/glad.h>
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdarg.h>
 | |
| 
 | |
| #include <bounce/common/math/transform.h>
 | |
| #include <bounce/common/math/mat44.h>
 | |
| #include <bounce/common/draw.h>
 | |
| 
 | |
| #include <bounce/meshgen/sphere_mesh.h>
 | |
| #include <bounce/meshgen/cylinder_mesh.h>
 | |
| 
 | |
| #define BUFFER_OFFSET(i) ((char*)NULL + (i))
 | |
| 
 | |
| extern bool g_glDrawPoints;
 | |
| extern bool g_glDrawLines;
 | |
| extern bool g_glDrawTriangles;
 | |
| 
 | |
| extern b3Mat44 g_glViewMatrix;
 | |
| extern b3Mat44 g_glProjectionMatrix;
 | |
| 
 | |
| static void AssertGL()
 | |
| {
 | |
| 	GLenum errorCode = glGetError();
 | |
| 	if (errorCode != GL_NO_ERROR)
 | |
| 	{
 | |
| 		fprintf(stderr, "OpenGL error = %d\n", errorCode);
 | |
| 		assert(false);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void PrintLog(GLuint id)
 | |
| {
 | |
| 	GLint log_length = 0;
 | |
| 	if (glIsShader(id))
 | |
| 	{
 | |
| 		glGetShaderiv(id, GL_INFO_LOG_LENGTH, &log_length);
 | |
| 	}
 | |
| 	else if (glIsProgram(id))
 | |
| 	{
 | |
| 		glGetProgramiv(id, GL_INFO_LOG_LENGTH, &log_length);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		fprintf(stderr, "Not a shader or a program\n");
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	char* log = (char*)malloc(log_length);
 | |
| 
 | |
| 	if (glIsShader(id))
 | |
| 	{
 | |
| 		glGetShaderInfoLog(id, log_length, NULL, log);
 | |
| 	}
 | |
| 	else if (glIsProgram(id))
 | |
| 	{
 | |
| 		glGetProgramInfoLog(id, log_length, NULL, log);
 | |
| 	}
 | |
| 
 | |
| 	fprintf(stderr, "%s", log);
 | |
| 	free(log);
 | |
| }
 | |
| 
 | |
| static GLuint CreateShader(const char* source, GLenum type)
 | |
| {
 | |
| 	GLuint shaderId = glCreateShader(type);
 | |
| 
 | |
| 	const char* sources[] = { source };
 | |
| 	glShaderSource(shaderId, 1, sources, NULL);
 | |
| 	glCompileShader(shaderId);
 | |
| 
 | |
| 	GLint status = GL_FALSE;
 | |
| 	glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status);
 | |
| 	if (status == GL_FALSE)
 | |
| 	{
 | |
| 		fprintf(stderr, "Error compiling %d shader.\n", type);
 | |
| 		PrintLog(shaderId);
 | |
| 		glDeleteShader(shaderId);
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	return shaderId;
 | |
| }
 | |
| 
 | |
| // 
 | |
| static GLuint CreateShaderProgram(const char* vs, const char* fs)
 | |
| {
 | |
| 	GLuint vsId = CreateShader(vs, GL_VERTEX_SHADER);
 | |
| 	GLuint fsId = CreateShader(fs, GL_FRAGMENT_SHADER);
 | |
| 	assert(vsId != 0 && fsId != 0);
 | |
| 
 | |
| 	GLuint programId = glCreateProgram();
 | |
| 	glAttachShader(programId, vsId);
 | |
| 	glAttachShader(programId, fsId);
 | |
| 	glBindFragDataLocation(programId, 0, "color");
 | |
| 	glLinkProgram(programId);
 | |
| 
 | |
| 	glDeleteShader(vsId);
 | |
| 	glDeleteShader(fsId);
 | |
| 
 | |
| 	GLint status = GL_FALSE;
 | |
| 	glGetProgramiv(programId, GL_LINK_STATUS, &status);
 | |
| 	assert(status != GL_FALSE);
 | |
| 
 | |
| 	return programId;
 | |
| }
 | |
| 
 | |
| struct DrawPoints
 | |
| {
 | |
| 	DrawPoints()
 | |
| 	{
 | |
| 		const char* vs = \
 | |
| 			"#version 400\n"
 | |
| 			"uniform mat4 projectionMatrix;\n"
 | |
| 			"layout(location = 0) in vec3 v_position;\n"
 | |
| 			"layout(location = 1) in vec4 v_color;\n"
 | |
| 			"layout(location = 2) in float v_size;\n"
 | |
| 			"out vec4 f_color;\n"
 | |
| 			"void main()\n"
 | |
| 			"{\n"
 | |
| 			"	f_color = v_color;\n"
 | |
| 			"	gl_Position = projectionMatrix * vec4(v_position, 1.0f);\n"
 | |
| 			"   gl_PointSize = v_size;\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		const char* fs = \
 | |
| 			"#version 400\n"
 | |
| 			"in vec4 f_color;\n"
 | |
| 			"out vec4 color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	color = f_color;\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		m_programId = CreateShaderProgram(vs, fs);
 | |
| 		m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
 | |
| 		m_vertexAttribute = 0;
 | |
| 		m_colorAttribute = 1;
 | |
| 		m_sizeAttribute = 2;
 | |
| 
 | |
| 		glGenBuffers(3, m_vboIds);
 | |
| 
 | |
| 		glGenVertexArrays(1, &m_vaoId);
 | |
| 
 | |
| 		glBindVertexArray(m_vaoId);
 | |
| 		glEnableVertexAttribArray(m_vertexAttribute);
 | |
| 		glEnableVertexAttribArray(m_colorAttribute);
 | |
| 		glEnableVertexAttribArray(m_sizeAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glVertexAttribPointer(m_vertexAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Vec3), m_vertices, GL_DYNAMIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Color), m_colors, GL_DYNAMIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
 | |
| 		glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(float32), m_sizes, GL_DYNAMIC_DRAW);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindVertexArray(0);
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 
 | |
| 		m_count = 0;
 | |
| 	}
 | |
| 
 | |
| 	~DrawPoints()
 | |
| 	{
 | |
| 		glDeleteVertexArrays(1, &m_vaoId);
 | |
| 		glDeleteProgram(m_programId);
 | |
| 		glDeleteBuffers(3, m_vboIds);
 | |
| 	}
 | |
| 
 | |
| 	void Vertex(const b3Vec3& v, float32 size, const b3Color& color)
 | |
| 	{
 | |
| 		if (m_count == e_vertexCapacity)
 | |
| 		{
 | |
| 			Flush();
 | |
| 		}
 | |
| 
 | |
| 		m_vertices[m_count] = v;
 | |
| 		m_colors[m_count] = color;
 | |
| 		m_sizes[m_count] = size;
 | |
| 		++m_count;
 | |
| 	}
 | |
| 
 | |
| 	void Flush()
 | |
| 	{
 | |
| 		if (m_count == 0)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 		
 | |
| 		if (!g_glDrawPoints)
 | |
| 		{
 | |
| 			m_count = 0;
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		glUseProgram(m_programId);
 | |
| 
 | |
| 		b3Mat44 m1 = g_glViewMatrix;
 | |
| 		b3Mat44 m2 = g_glProjectionMatrix;
 | |
| 		b3Mat44 m = m2 * m1;
 | |
| 
 | |
| 		glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x);
 | |
| 
 | |
| 		glBindVertexArray(m_vaoId);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Vec3), m_vertices);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Color), m_colors);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(float32), m_sizes);
 | |
| 
 | |
| 		glEnable(GL_PROGRAM_POINT_SIZE);
 | |
| 		glDrawArrays(GL_POINTS, 0, m_count);
 | |
| 		glDisable(GL_PROGRAM_POINT_SIZE);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 		glBindVertexArray(0);
 | |
| 		glUseProgram(0);
 | |
| 
 | |
| 		m_count = 0;
 | |
| 	}
 | |
| 
 | |
| 	enum
 | |
| 	{
 | |
| 		e_vertexCapacity = 1024
 | |
| 	};
 | |
| 
 | |
| 	b3Vec3 m_vertices[e_vertexCapacity];
 | |
| 	b3Color m_colors[e_vertexCapacity];
 | |
| 	float32 m_sizes[e_vertexCapacity];
 | |
| 	u32 m_count;
 | |
| 
 | |
| 	GLuint m_programId;
 | |
| 	GLuint m_projectionUniform;
 | |
| 	GLuint m_vertexAttribute;
 | |
| 	GLuint m_colorAttribute;
 | |
| 	GLuint m_sizeAttribute;
 | |
| 
 | |
| 	GLuint m_vboIds[3];
 | |
| 	GLuint m_vaoId;
 | |
| };
 | |
| 
 | |
| struct DrawLines
 | |
| {
 | |
| 	DrawLines()
 | |
| 	{
 | |
| 		const char* vs = \
 | |
| 			"#version 400\n"
 | |
| 			"uniform mat4 projectionMatrix;\n"
 | |
| 			"layout(location = 0) in vec3 v_position;\n"
 | |
| 			"layout(location = 1) in vec4 v_color;\n"
 | |
| 			"out vec4 f_color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	f_color = v_color;\n"
 | |
| 			"	gl_Position = projectionMatrix * vec4(v_position, 1.0f);\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		const char* fs = \
 | |
| 			"#version 400\n"
 | |
| 			"in vec4 f_color;\n"
 | |
| 			"out vec4 color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	color = f_color;\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		m_programId = CreateShaderProgram(vs, fs);
 | |
| 		m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
 | |
| 		m_vertexAttribute = 0;
 | |
| 		m_colorAttribute = 1;
 | |
| 
 | |
| 		glGenVertexArrays(1, &m_vaoId);
 | |
| 		glGenBuffers(2, m_vboIds);
 | |
| 
 | |
| 		glBindVertexArray(m_vaoId);
 | |
| 		glEnableVertexAttribArray(m_vertexAttribute);
 | |
| 		glEnableVertexAttribArray(m_colorAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glVertexAttribPointer(m_vertexAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Vec3), m_vertices, GL_DYNAMIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Color), m_colors, GL_DYNAMIC_DRAW);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindVertexArray(0);
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 
 | |
| 		m_count = 0;
 | |
| 	}
 | |
| 
 | |
| 	~DrawLines()
 | |
| 	{
 | |
| 		glDeleteProgram(m_programId);
 | |
| 		glDeleteVertexArrays(1, &m_vaoId);
 | |
| 		glDeleteBuffers(2, m_vboIds);
 | |
| 	}
 | |
| 
 | |
| 	void Vertex(const b3Vec3& v, const b3Color& c)
 | |
| 	{
 | |
| 		if (m_count == e_vertexCapacity)
 | |
| 		{
 | |
| 			Flush();
 | |
| 		}
 | |
| 
 | |
| 		m_vertices[m_count] = v;
 | |
| 		m_colors[m_count] = c;
 | |
| 		++m_count;
 | |
| 	}
 | |
| 
 | |
| 	void Flush()
 | |
| 	{
 | |
| 		if (m_count == 0)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 		
 | |
| 		if (!g_glDrawLines)
 | |
| 		{
 | |
| 			m_count = 0;
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		glUseProgram(m_programId);
 | |
| 
 | |
| 		b3Mat44 m1 = g_glViewMatrix;
 | |
| 		b3Mat44 m2 = g_glProjectionMatrix;
 | |
| 		b3Mat44 m = m2 * m1;
 | |
| 		glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x);
 | |
| 
 | |
| 		glBindVertexArray(m_vaoId);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Vec3), m_vertices);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Color), m_colors);
 | |
| 
 | |
| 		glDrawArrays(GL_LINES, 0, m_count);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindVertexArray(0);
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 		glUseProgram(0);
 | |
| 
 | |
| 		m_count = 0;
 | |
| 	}
 | |
| 
 | |
| 	enum
 | |
| 	{
 | |
| 		e_vertexCapacity = 2 * 1024
 | |
| 	};
 | |
| 
 | |
| 	b3Vec3 m_vertices[e_vertexCapacity];
 | |
| 	b3Color m_colors[e_vertexCapacity];
 | |
| 	u32 m_count;
 | |
| 
 | |
| 	GLuint m_programId;
 | |
| 	GLuint m_projectionUniform;
 | |
| 	GLuint m_vertexAttribute;
 | |
| 	GLuint m_colorAttribute;
 | |
| 
 | |
| 	GLuint m_vboIds[2];
 | |
| 	GLuint m_vaoId;
 | |
| };
 | |
| 
 | |
| struct DrawTriangles
 | |
| {
 | |
| 	DrawTriangles()
 | |
| 	{
 | |
| 		const char* vs = \
 | |
| 			"#version 400\n"
 | |
| 			"uniform mat4 projectionMatrix;\n"
 | |
| 			"layout(location = 0) in vec3 v_position;\n"
 | |
| 			"layout(location = 1) in vec4 v_color;\n"
 | |
| 			"layout(location = 2) in vec3 v_normal;\n"
 | |
| 			"out vec4 f_color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	vec3 La = vec3(0.5f, 0.5f, 0.5f);\n"
 | |
| 			"	vec3 Ld = vec3(0.5f, 0.5f, 0.5f);\n"
 | |
| 			"	vec3 L = vec3(0.0f, 0.3f, 0.7f);\n"
 | |
| 			"	vec3 Ma = v_color.xyz;\n"
 | |
| 			"	vec3 Md = v_color.xyz;\n"
 | |
| 			"	vec3 a = La * Ma;\n"
 | |
| 			"	vec3 d = max(dot(v_normal, L), 0.0f) * Ld * Md;\n"
 | |
| 			"	f_color = vec4(a + d, v_color.w);\n"
 | |
| 			"	gl_Position = projectionMatrix * vec4(v_position, 1.0f);\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		const char* fs = \
 | |
| 			"#version 400\n"
 | |
| 			"in vec4 f_color;\n"
 | |
| 			"out vec4 color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	color = f_color;\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		m_programId = CreateShaderProgram(vs, fs);
 | |
| 		m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
 | |
| 		m_vertexAttribute = 0;
 | |
| 		m_colorAttribute = 1;
 | |
| 		m_normalAttribute = 2;
 | |
| 
 | |
| 		glGenVertexArrays(1, &m_vaoId);
 | |
| 		glGenBuffers(3, m_vboIds);
 | |
| 
 | |
| 		glBindVertexArray(m_vaoId);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Vec3), m_vertices, GL_DYNAMIC_DRAW);
 | |
| 		glVertexAttribPointer(m_vertexAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_vertexAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Color), m_colors, GL_DYNAMIC_DRAW);
 | |
| 		glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_colorAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Vec3), m_normals, GL_DYNAMIC_DRAW);
 | |
| 		glVertexAttribPointer(m_normalAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_normalAttribute);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindVertexArray(0);
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 
 | |
| 		m_count = 0;
 | |
| 	}
 | |
| 
 | |
| 	~DrawTriangles()
 | |
| 	{
 | |
| 		glDeleteProgram(m_programId);
 | |
| 		glDeleteVertexArrays(1, &m_vaoId);
 | |
| 		glDeleteBuffers(3, m_vboIds);
 | |
| 	}
 | |
| 
 | |
| 	void Vertex(const b3Vec3& v, const b3Color& c, const b3Vec3& n)
 | |
| 	{
 | |
| 		if (m_count == e_vertexCapacity)
 | |
| 		{
 | |
| 			Flush();
 | |
| 		}
 | |
| 
 | |
| 		m_vertices[m_count] = v;
 | |
| 		m_colors[m_count] = c;
 | |
| 		m_normals[m_count] = n;
 | |
| 		++m_count;
 | |
| 	}
 | |
| 
 | |
| 	void Flush()
 | |
| 	{
 | |
| 		if (m_count == 0)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		if (!g_glDrawTriangles)
 | |
| 		{
 | |
| 			m_count = 0;
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		glUseProgram(m_programId);
 | |
| 
 | |
| 		b3Mat44 m1 = g_glViewMatrix;
 | |
| 		b3Mat44 m2 = g_glProjectionMatrix;
 | |
| 		b3Mat44 m = m2 * m1;
 | |
| 
 | |
| 		glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x);
 | |
| 
 | |
| 		glBindVertexArray(m_vaoId);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Vec3), m_vertices);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Color), m_colors);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
 | |
| 		glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Vec3), m_normals);
 | |
| 
 | |
| 		glDrawArrays(GL_TRIANGLES, 0, m_count);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 		glBindVertexArray(0);
 | |
| 		glUseProgram(0);
 | |
| 
 | |
| 		m_count = 0;
 | |
| 	}
 | |
| 
 | |
| 	enum
 | |
| 	{
 | |
| 		e_vertexCapacity = 3 * 512
 | |
| 	};
 | |
| 
 | |
| 	b3Vec3 m_vertices[e_vertexCapacity];
 | |
| 	b3Color m_colors[e_vertexCapacity];
 | |
| 	b3Vec3 m_normals[e_vertexCapacity];
 | |
| 	u32 m_count;
 | |
| 
 | |
| 	GLuint m_programId;
 | |
| 	GLuint m_projectionUniform;
 | |
| 	GLuint m_vertexAttribute;
 | |
| 	GLuint m_colorAttribute;
 | |
| 	GLuint m_normalAttribute;
 | |
| 
 | |
| 	GLuint m_vboIds[3];
 | |
| 	GLuint m_vaoId;
 | |
| };
 | |
| 
 | |
| struct DrawWireSphere
 | |
| {
 | |
| 	DrawWireSphere()
 | |
| 	{
 | |
| 		smMesh mesh;
 | |
| 		smCreateMesh(mesh, 2);
 | |
| 
 | |
| 		m_vertexCount = mesh.vertexCount;
 | |
| 		m_indexCount = mesh.indexCount;
 | |
| 
 | |
| 		glGenBuffers(1, &m_vboId);
 | |
| 		glGenBuffers(1, &m_iboId);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboId);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, m_vertexCount * sizeof(b3Vec3), mesh.vertices, GL_STATIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iboId);
 | |
| 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(u32), mesh.indices, GL_STATIC_DRAW);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 | |
| 	}
 | |
| 
 | |
| 	~DrawWireSphere()
 | |
| 	{
 | |
| 		glDeleteBuffers(1, &m_vboId);
 | |
| 		glDeleteBuffers(1, &m_iboId);
 | |
| 	}
 | |
| 
 | |
| 	GLuint m_vboId;
 | |
| 	GLuint m_iboId;
 | |
| 	u32 m_vertexCount;
 | |
| 	u32 m_indexCount;
 | |
| };
 | |
| 
 | |
| struct DrawWire
 | |
| {
 | |
| 	DrawWire()
 | |
| 	{
 | |
| 		const char* vs = \
 | |
| 			"#version 400\n"
 | |
| 			"uniform vec4 color;\n"
 | |
| 			"uniform mat4 projectionMatrix;\n"
 | |
| 			"layout(location = 0) in vec3 v_position;\n"
 | |
| 			"out vec4 f_color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	f_color = color;\n"
 | |
| 			"	gl_Position = projectionMatrix * vec4(v_position, 1.0f);\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		const char* fs = \
 | |
| 			"#version 400\n"
 | |
| 			"in vec4 f_color;\n"
 | |
| 			"out vec4 color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	color = f_color;\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		m_programId = CreateShaderProgram(vs, fs);
 | |
| 		m_colorUniform = glGetUniformLocation(m_programId, "color");
 | |
| 		m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
 | |
| 		m_vertexAttribute = 0;
 | |
| 	}
 | |
| 
 | |
| 	~DrawWire()
 | |
| 	{
 | |
| 		glDeleteProgram(m_programId);
 | |
| 	}
 | |
| 
 | |
| 	void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
 | |
| 	{
 | |
| 		if (!g_glDrawLines)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		glUseProgram(m_programId);
 | |
| 
 | |
| 		b3Mat44 m1 = b3TransformMat44(xf);
 | |
| 		m1.x = radius * m1.x;
 | |
| 		m1.y = radius * m1.y;
 | |
| 		m1.z = radius * m1.z;
 | |
| 		b3Mat44 m2 = g_glViewMatrix;
 | |
| 		b3Mat44 m3 = g_glProjectionMatrix;
 | |
| 		b3Mat44 m = m3 * m2 * m1;
 | |
| 
 | |
| 		glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_sphere.m_vboId);
 | |
| 		glVertexAttribPointer(m_vertexAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_vertexAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphere.m_iboId);
 | |
| 		glDrawElements(GL_LINES, m_sphere.m_indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 
 | |
| 		glUseProgram(0);
 | |
| 	}
 | |
| 
 | |
| 	GLuint m_programId;
 | |
| 	GLuint m_colorUniform;
 | |
| 	GLuint m_projectionUniform;
 | |
| 	GLuint m_vertexAttribute;
 | |
| 
 | |
| 	DrawWireSphere m_sphere;
 | |
| };
 | |
| 
 | |
| struct DrawSolidSphere
 | |
| {
 | |
| 	DrawSolidSphere()
 | |
| 	{
 | |
| 		smMesh mesh;
 | |
| 		smCreateMesh(mesh, 2);
 | |
| 
 | |
| 		m_vertexCount = mesh.vertexCount;
 | |
| 		m_indexCount = mesh.indexCount;
 | |
| 
 | |
| 		glGenBuffers(3, m_vboIds);
 | |
| 		glGenBuffers(1, &m_iboId);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, m_vertexCount * sizeof(b3Vec3), mesh.vertices, GL_STATIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, m_vertexCount * sizeof(b3Vec3), mesh.vertices, GL_STATIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iboId);
 | |
| 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(u32), mesh.indices, GL_STATIC_DRAW);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 | |
| 	}
 | |
| 
 | |
| 	~DrawSolidSphere()
 | |
| 	{
 | |
| 		glDeleteBuffers(2, m_vboIds);
 | |
| 		glDeleteBuffers(1, &m_iboId);
 | |
| 	}
 | |
| 
 | |
| 	GLuint m_vboIds[2];
 | |
| 	GLuint m_iboId;
 | |
| 	u32 m_vertexCount;
 | |
| 	u32 m_indexCount;
 | |
| };
 | |
| 
 | |
| struct DrawSolidCylinder
 | |
| {
 | |
| 	DrawSolidCylinder()
 | |
| 	{
 | |
| 		cymMesh mesh;
 | |
| 		cymCreateMesh(mesh, 20);
 | |
| 
 | |
| 		m_vertexCount = mesh.vertexCount;
 | |
| 		m_indexCount = mesh.indexCount;
 | |
| 
 | |
| 		glGenBuffers(2, m_vboIds);
 | |
| 		glGenBuffers(1, &m_iboId);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, m_vertexCount * sizeof(b3Vec3), mesh.vertices, GL_STATIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
 | |
| 		glBufferData(GL_ARRAY_BUFFER, m_vertexCount * sizeof(b3Vec3), mesh.normals, GL_STATIC_DRAW);
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iboId);
 | |
| 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(u32), mesh.indices, GL_STATIC_DRAW);
 | |
| 
 | |
| 		AssertGL();
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 | |
| 	}
 | |
| 
 | |
| 	~DrawSolidCylinder()
 | |
| 	{
 | |
| 		glDeleteBuffers(2, m_vboIds);
 | |
| 		glDeleteBuffers(1, &m_iboId);
 | |
| 	}
 | |
| 
 | |
| 	GLuint m_vboIds[2];
 | |
| 	GLuint m_iboId;
 | |
| 	u32 m_vertexCount;
 | |
| 	u32 m_indexCount;
 | |
| };
 | |
| 
 | |
| struct DrawSolid
 | |
| {
 | |
| 	DrawSolid()
 | |
| 	{
 | |
| 		const char* vs = \
 | |
| 			"#version 400\n"
 | |
| 			"uniform vec4 color;\n"
 | |
| 			"uniform mat4 modelMatrix;\n"
 | |
| 			"uniform mat4 projectionMatrix;\n"
 | |
| 			"layout(location = 0) in vec3 v_position;\n"
 | |
| 			"layout(location = 1) in vec3 v_normal;\n"
 | |
| 			"out vec4 f_color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	vec3 f_normal = normalize( ( modelMatrix * vec4(v_normal, 0.0f) ).xyz );\n"
 | |
| 			"	gl_Position = projectionMatrix * vec4(v_position, 1.0f);\n"
 | |
| 			"	vec3 La = vec3(0.5f, 0.5f, 0.5f);\n"
 | |
| 			"	vec3 Ld = vec3(0.5f, 0.5f, 0.5f);\n"
 | |
| 			"	vec3 L = vec3(0.0f, 0.3f, 0.7f);\n"
 | |
| 			"	vec3 Ma = color.xyz;\n"
 | |
| 			"	vec3 Md = color.xyz;\n"
 | |
| 			"	vec3 a = La * Ma;\n"
 | |
| 			"	vec3 d = max(dot(f_normal, L), 0.0f) * Ld * Md;\n"
 | |
| 			"	f_color = vec4(a + d, color.w);\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		const char* fs = \
 | |
| 			"#version 400\n"
 | |
| 			"in vec4 f_color;\n"
 | |
| 			"out vec4 color;\n"
 | |
| 			"void main(void)\n"
 | |
| 			"{\n"
 | |
| 			"	color = f_color;\n"
 | |
| 			"}\n";
 | |
| 
 | |
| 		m_programId = CreateShaderProgram(vs, fs);
 | |
| 		m_colorUniform = glGetUniformLocation(m_programId, "color");
 | |
| 		m_modelUniform = glGetUniformLocation(m_programId, "modelMatrix");
 | |
| 		m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
 | |
| 		m_vertexAttribute = 0;
 | |
| 		m_normalAttribute = 1;
 | |
| 	}
 | |
| 
 | |
| 	~DrawSolid()
 | |
| 	{
 | |
| 	}
 | |
| 
 | |
| 	void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
 | |
| 	{
 | |
| 		if (!g_glDrawTriangles)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		glUseProgram(m_programId);
 | |
| 
 | |
| 		b3Mat44 m1 = b3TransformMat44(xf);
 | |
| 		m1.x = radius * m1.x;
 | |
| 		m1.y = height * m1.y;
 | |
| 		m1.z = radius * m1.z;
 | |
| 
 | |
| 		b3Mat44 m2 = g_glViewMatrix;
 | |
| 		b3Mat44 m3 = g_glProjectionMatrix;
 | |
| 		b3Mat44 m = m3 * m2 * m1;
 | |
| 
 | |
| 		glUniform4fv(m_colorUniform, 1, &c.r);
 | |
| 		glUniformMatrix4fv(m_modelUniform, 1, GL_FALSE, &m1.x.x);
 | |
| 		glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_cylinder.m_vboIds[0]);
 | |
| 		glVertexAttribPointer(m_vertexAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_vertexAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_cylinder.m_vboIds[1]);
 | |
| 		glVertexAttribPointer(m_normalAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_normalAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_cylinder.m_iboId);
 | |
| 		glDrawElements(GL_TRIANGLES, m_cylinder.m_indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 
 | |
| 		glUseProgram(0);
 | |
| 	}
 | |
| 
 | |
| 	void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
 | |
| 	{
 | |
| 		if (!g_glDrawTriangles)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		glUseProgram(m_programId);
 | |
| 
 | |
| 		b3Mat44 m1 = b3TransformMat44(xf);
 | |
| 		m1.x = radius * m1.x;
 | |
| 		m1.y = radius * m1.y;
 | |
| 		m1.z = radius * m1.z;
 | |
| 
 | |
| 		b3Mat44 m2 = g_glViewMatrix;
 | |
| 		b3Mat44 m3 = g_glProjectionMatrix;
 | |
| 		b3Mat44 m = m3 * m2 * m1;
 | |
| 
 | |
| 		glUniform4fv(m_colorUniform, 1, &c.r);
 | |
| 		glUniformMatrix4fv(m_modelUniform, 1, GL_FALSE, &m1.x.x);
 | |
| 		glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_sphere.m_vboIds[0]);
 | |
| 		glVertexAttribPointer(m_vertexAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_vertexAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, m_sphere.m_vboIds[1]);
 | |
| 		glVertexAttribPointer(m_normalAttribute, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 | |
| 		glEnableVertexAttribArray(m_normalAttribute);
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphere.m_iboId);
 | |
| 		glDrawElements(GL_TRIANGLES, m_sphere.m_indexCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
 | |
| 
 | |
| 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 | |
| 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 | |
| 
 | |
| 		glUseProgram(0);
 | |
| 	}
 | |
| 
 | |
| 	GLuint m_programId;
 | |
| 	GLuint m_colorUniform;
 | |
| 	GLuint m_modelUniform;
 | |
| 	GLuint m_projectionUniform;
 | |
| 	GLuint m_vertexAttribute;
 | |
| 	GLuint m_normalAttribute;
 | |
| 
 | |
| 	DrawSolidSphere m_sphere;
 | |
| 	DrawSolidCylinder m_cylinder;
 | |
| };
 | |
| 
 | |
| #endif |