diff --git a/src/srender.h b/src/srender.h index 60f8a04..301ebb5 100644 --- a/src/srender.h +++ b/src/srender.h @@ -17,7 +17,6 @@ typedef enum { SRndrCmdTypeFrame = 0, SRndrCmdTypeGrid, SRndrCmdTypeCube, - SRndrCmdTypeLight, SRndrCmdTypeSphere } SRndrCmdType; @@ -131,6 +130,7 @@ typedef struct srmeshdata { static srmeshdata gCoordFrameMesh = {0}; static srmeshdata gGridMesh = {0}; static srmeshdata gCubeMesh = {0}; +static srmeshdata gUVSphereMesh = {0}; typedef struct srshader { const char* vert_fname; @@ -477,14 +477,14 @@ void init_debug_meshes() { dbg_vbuf_offset += sizeof(srvrtxdata) * 24; GLuint cube_indices[] = { - // clang-format off + // clang-format off 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23 - // clang-format on + // clang-format on }; for (int i = 0; i < 36; i++) { @@ -502,6 +502,119 @@ void init_debug_meshes() { gCubeMesh.mode = GL_TRIANGLES; gCubeMesh.count = 36; + // + // UVSphere + // + gUVSphereMesh.vao_id = gDebugShapesVAId; + gUVSphereMesh.vb_id = gDebugShapesVBOId; + + // loosely based on http://www.songho.ca/opengl/gl_sphere.html + int stack_count = 4; + int sector_count = 4; + gUVSphereMesh.nvertices = (stack_count + 1) * (sector_count + 1); + gLog("UVsphere vertices: %d", gUVSphereMesh.nvertices); + + srvrtxdata* uvsphere_vertices = + calloc(sizeof(srvrtxdata), gUVSphereMesh.nvertices); + + float sector_step = 2.f * M_PI / sector_count; + float stack_step = M_PI / stack_count; + float sector_angle, stack_angle; + + for (int i = 0; i <= stack_count; ++i) { + stack_angle = M_PI / 2 - i * stack_step; // starting from pi/2 to -pi/2 + float xy = cosf(stack_angle); // r * cos(u) + float z = sinf(stack_angle); // r * sin(u) + + // add (sector_count+1) vertices per stack + // the first and last vertices have same position and normal, but different tex coords + for (int j = 0; j <= sector_count; ++j) { + int vertex_index = (i * (sector_count + 1)) + j; + gLog("vertex_index %d", vertex_index); + srvrtxdata* vertex = &uvsphere_vertices[vertex_index]; + sector_angle = j * sector_step; // starting from 0 to 2pi + + // vertex position (x, y, z) + vertex->x = xy * cosf(sector_angle); // r * cos(u) * cos(v) + vertex->y = xy * sinf(sector_angle); // r * cos(u) * sin(v) + vertex->z = z; + vertex->w = 1.f; + + // normalized vertex normal (nx, ny, nz) + vertex->nx = vertex->x; + vertex->ny = vertex->y; + vertex->nz = vertex->z; + + // vertex tex coord (s, t) range between [0, 1] + vertex->s = (float)j / sector_count; + vertex->t = (float)i / stack_count; + + vertex->r = 128; + vertex->g = 128; + vertex->b = 128; + vertex->a = 255; + } + } + + glBindBuffer(GL_ARRAY_BUFFER, gDebugShapesVBOId); + glBufferSubData( + GL_ARRAY_BUFFER, + dbg_vbuf_offset, + sizeof(srvrtxdata) * gUVSphereMesh.nvertices, + uvsphere_vertices); + dbg_vbuf_offset += sizeof(srvrtxdata) * gUVSphereMesh.nvertices; + free(uvsphere_vertices); + + gUVSphereMesh.nindices = + stack_count * sector_count * 3 * 2 - sector_count * 2 * 3; + GLuint* uvsphere_indices = calloc(sizeof(GLuint), gUVSphereMesh.nindices); + + gLog("nindices = %d", gUVSphereMesh.nindices); + // generate CCW index list of sphere triangles + int k1, k2; + GLuint tri_index = 0; + for (int i = 0; i < stack_count; ++i) { + k1 = i * (sector_count + 1); // beginning of current stack + k2 = k1 + sector_count + 1; // beginning of next stack + + for (int j = 0; j < sector_count; ++j, ++k1, ++k2) { + // 2 triangles per sector excluding first and last stacks + // k1 => k2 => k1+1 + if (i != 0) { + uvsphere_indices[++tri_index] = k1; + uvsphere_indices[++tri_index] = k2; + uvsphere_indices[++tri_index] = k1 + 1; + } + + // k1+1 => k2 => k2+1 + if (i != (stack_count - 1)) { + uvsphere_indices[++tri_index] = k1 + 1; + uvsphere_indices[++tri_index] = k2; + uvsphere_indices[++tri_index] = k2 + 1; + } + + gLog("tri_index = %d", tri_index); + } + } + + for (int i = 0; i < gUVSphereMesh.nindices; i++) { + uvsphere_indices[i] += + gCoordFrameMesh.nvertices + gGridMesh.nvertices + gCubeMesh.nvertices; + } + + glGenBuffers(1, &gUVSphereMesh.idb_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gUVSphereMesh.idb_id); + glBufferData( + GL_ELEMENT_ARRAY_BUFFER, + sizeof(GLuint) * gUVSphereMesh.nindices, + uvsphere_indices, + GL_STATIC_DRAW); + + free(uvsphere_indices); + + gUVSphereMesh.mode = GL_TRIANGLES; + gUVSphereMesh.count = gUVSphereMesh.nindices; + glBindVertexArray(0); }; @@ -668,6 +781,20 @@ void srndr_run_cube_command(const srcmd* cmd) { glBindVertexArray(0); } +void srndr_run_sphere_command(const srcmd* cmd) { + glBindVertexArray(gCubeMesh.vao_id); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gUVSphereMesh.idb_id); + glDrawElements( + gUVSphereMesh.mode, + gUVSphereMesh.count, + GL_UNSIGNED_INT, + (void*)0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sview->mFrameBufferId); @@ -675,9 +802,8 @@ void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) { glClearColor(0.1f, 0.1f, 0.1f, 0.1f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); glUseProgram(gDefaultShader.program_id); GLint view_mat_loc = @@ -708,6 +834,9 @@ void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) { case SRndrCmdTypeCube: srndr_run_cube_command(cmd); break; + case SRndrCmdTypeSphere: + srndr_run_sphere_command(cmd); + break; default: gLog("Invalid command type %d at index %d", cmd->type, i); break; diff --git a/src/vissim.cc b/src/vissim.cc index c6d978c..a708e90 100644 --- a/src/vissim.cc +++ b/src/vissim.cc @@ -165,7 +165,7 @@ void DoRender() { simd4x4f view; simd4x4f proj; simd4x4f_translation(&view, 0.1f, 0.1f, -0.5f); - simd4f eye = simd4f_create (2.f * sin(gTimer->mCurrentTime), 1.f, 2.f * cos (gTimer->mCurrentTime), 1.f); + simd4f eye = simd4f_create (2.f * sin(gTimer->mCurrentTime), sin(gTimer->mCurrentTime * 0.5f), 2.f * cos (gTimer->mCurrentTime), 1.f); simd4x4f_lookat( &view, eye, @@ -197,10 +197,6 @@ void DoRender() { rcmd.type = SRndrCmdTypeFrame; srcmdbuf_add(gRndrCmds, &rcmd); - rcmd.type = SRndrCmdTypeGrid; - srcmdbuf_add(gRndrCmds, &rcmd); - - rcmd.type = SRndrCmdTypeGrid; simd4x4f_translation(&rcmd.mat, 10.f, 0.f, 10.f); srcmdbuf_add(gRndrCmds, &rcmd); @@ -224,7 +220,7 @@ void DoRender() { srcmdbuf_add(gRndrCmds, &rcmd); srcmd_clear(&rcmd); - rcmd.type = SRndrCmdTypeCube; + rcmd.type = SRndrCmdTypeSphere; srcmdbuf_add(gRndrCmds, &rcmd); // Perform the actual render