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;
@ -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