Initial code for UV Spheres

master
Martin Felis 2020-10-26 22:27:05 +01:00
parent d7a5507774
commit 0622c53d29
2 changed files with 137 additions and 12 deletions

View File

@ -17,7 +17,6 @@ typedef enum {
SRndrCmdTypeFrame = 0, SRndrCmdTypeFrame = 0,
SRndrCmdTypeGrid, SRndrCmdTypeGrid,
SRndrCmdTypeCube, SRndrCmdTypeCube,
SRndrCmdTypeLight,
SRndrCmdTypeSphere SRndrCmdTypeSphere
} SRndrCmdType; } SRndrCmdType;
@ -131,6 +130,7 @@ typedef struct srmeshdata {
static srmeshdata gCoordFrameMesh = {0}; static srmeshdata gCoordFrameMesh = {0};
static srmeshdata gGridMesh = {0}; static srmeshdata gGridMesh = {0};
static srmeshdata gCubeMesh = {0}; static srmeshdata gCubeMesh = {0};
static srmeshdata gUVSphereMesh = {0};
typedef struct srshader { typedef struct srshader {
const char* vert_fname; const char* vert_fname;
@ -477,14 +477,14 @@ void init_debug_meshes() {
dbg_vbuf_offset += sizeof(srvrtxdata) * 24; dbg_vbuf_offset += sizeof(srvrtxdata) * 24;
GLuint cube_indices[] = { GLuint cube_indices[] = {
// clang-format off // clang-format off
0, 1, 2, 0, 2, 3, 0, 1, 2, 0, 2, 3,
4, 5, 6, 4, 6, 7, 4, 5, 6, 4, 6, 7,
8, 9, 10, 8, 10, 11, 8, 9, 10, 8, 10, 11,
12, 13, 14, 12, 14, 15, 12, 13, 14, 12, 14, 15,
16, 17, 18, 16, 18, 19, 16, 17, 18, 16, 18, 19,
20, 21, 22, 20, 22, 23 20, 21, 22, 20, 22, 23
// clang-format on // clang-format on
}; };
for (int i = 0; i < 36; i++) { for (int i = 0; i < 36; i++) {
@ -502,6 +502,119 @@ void init_debug_meshes() {
gCubeMesh.mode = GL_TRIANGLES; gCubeMesh.mode = GL_TRIANGLES;
gCubeMesh.count = 36; 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); glBindVertexArray(0);
}; };
@ -668,6 +781,20 @@ void srndr_run_cube_command(const srcmd* cmd) {
glBindVertexArray(0); 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) { void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sview->mFrameBufferId); 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); glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); // glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); // glCullFace(GL_BACK);
glUseProgram(gDefaultShader.program_id); glUseProgram(gDefaultShader.program_id);
GLint view_mat_loc = GLint view_mat_loc =
@ -708,6 +834,9 @@ void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) {
case SRndrCmdTypeCube: case SRndrCmdTypeCube:
srndr_run_cube_command(cmd); srndr_run_cube_command(cmd);
break; break;
case SRndrCmdTypeSphere:
srndr_run_sphere_command(cmd);
break;
default: default:
gLog("Invalid command type %d at index %d", cmd->type, i); gLog("Invalid command type %d at index %d", cmd->type, i);
break; break;

View File

@ -165,7 +165,7 @@ void DoRender() {
simd4x4f view; simd4x4f view;
simd4x4f proj; simd4x4f proj;
simd4x4f_translation(&view, 0.1f, 0.1f, -0.5f); 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( simd4x4f_lookat(
&view, &view,
eye, eye,
@ -197,10 +197,6 @@ void DoRender() {
rcmd.type = SRndrCmdTypeFrame; rcmd.type = SRndrCmdTypeFrame;
srcmdbuf_add(gRndrCmds, &rcmd); srcmdbuf_add(gRndrCmds, &rcmd);
rcmd.type = SRndrCmdTypeGrid;
srcmdbuf_add(gRndrCmds, &rcmd);
rcmd.type = SRndrCmdTypeGrid; rcmd.type = SRndrCmdTypeGrid;
simd4x4f_translation(&rcmd.mat, 10.f, 0.f, 10.f); simd4x4f_translation(&rcmd.mat, 10.f, 0.f, 10.f);
srcmdbuf_add(gRndrCmds, &rcmd); srcmdbuf_add(gRndrCmds, &rcmd);
@ -224,7 +220,7 @@ void DoRender() {
srcmdbuf_add(gRndrCmds, &rcmd); srcmdbuf_add(gRndrCmds, &rcmd);
srcmd_clear(&rcmd); srcmd_clear(&rcmd);
rcmd.type = SRndrCmdTypeCube; rcmd.type = SRndrCmdTypeSphere;
srcmdbuf_add(gRndrCmds, &rcmd); srcmdbuf_add(gRndrCmds, &rcmd);
// Perform the actual render // Perform the actual render