Fix triangle rendering and wireframe

This commit is contained in:
Doyle Thai 2016-11-16 13:00:59 +11:00
parent 339ae38b38
commit 21bf650298
8 changed files with 210 additions and 127 deletions

View File

@ -42,10 +42,7 @@ void initAssetManager(GameState *state)
i32 result =
asset_loadTTFont(assetManager, arena, "C:/Windows/Fonts/Arialbd.ttf");
if (result) {
ASSERT(TRUE);
}
if (result) ASSERT(TRUE);
}
void initRenderer(GameState *state, v2 windowSize) {
@ -76,11 +73,12 @@ void initRenderer(GameState *state, v2 windowSize) {
glGenBuffers(ARRAY_COUNT(renderer->vbo), renderer->vbo);
GL_CHECK_ERROR();
{
// Bind buffers and configure vao, vao automatically intercepts
// glBindCalls and associates the state with that buffer for us
glBindVertexArray(renderer->vao[rendermode_quad]);
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo[rendermode_quad]);
for (enum RenderMode mode = 0; mode < rendermode_count; mode++)
{
glBindVertexArray(renderer->vao[mode]);
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo[mode]);
glEnableVertexAttribArray(0);
u32 numVertexElements = 4;
@ -92,20 +90,6 @@ void initRenderer(GameState *state, v2 windowSize) {
glBindVertexArray(0);
}
{
glBindVertexArray(renderer->vao[rendermode_triangle]);
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo[rendermode_triangle]);
glEnableVertexAttribArray(0);
u32 numVertexElements = 3;
u32 stride = sizeof(Vertex);
glVertexAttribPointer(0, numVertexElements, GL_FLOAT,
GL_FALSE, stride, (GLvoid *)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
/* Unbind */
GL_CHECK_ERROR();
@ -183,13 +167,11 @@ INTERNAL b32 getKeyStatus(KeyState *key, enum ReadKeyType readType,
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
v2 windowSize, f32 dt)
{
if (!state->init) {
if (!state->init)
{
memory_arenaInit(&state->persistentArena, memory->persistent,
memory->persistentSize);
memory_arenaInit(&state->transientArena, memory->transient,
memory->transientSize);
initAssetManager(state);
initRenderer(state, windowSize);
@ -198,22 +180,31 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
{ // Init ship entity
Entity *ship = &state->entityList[state->entityIndex++];
ship->id = 0;
ship->pos = V2(100.0f, 100.0f);
ship->hitbox = V2(100.0f, 100.0f);
ship->size = V2(100.0f, 100.0f);
ship->pos = V2(100, 100);
ship->size = V2(25.0f, 50.0f);
ship->hitbox = ship->size;
ship->offset = v2_scale(ship->size, 0.5f);
ship->scale = 1;
ship->type = entitytype_ship;
ship->direction = direction_null;
ship->renderMode = rendermode_triangle;
ship->tex = NULL;
ship->collides = FALSE;
}
state->camera.pos = V2(0, 0);
state->camera.size = state->renderer.size;
state->init = TRUE;
state->worldSize = windowSize;
debug_init(&state->persistentArena, windowSize,
state->assetManager.font);
}
memory_arenaInit(&state->transientArena, memory->transient,
memory->transientSize);
{
KeyState *keys = state->input.keys;
for (enum KeyCode code = 0; code < keycode_count; code++)
@ -244,40 +235,40 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
Entity *entity = &state->entityList[i];
ASSERT(entity->type != entitytype_invalid);
v2 pivotPoint = {0};
if (entity->type == entitytype_ship) {
v2 acceleration = {0};
v2 ddP = {0};
if (getKeyStatus(&state->input.keys[keycode_up], readkeytype_repeat,
0.0f, dt))
{
acceleration.y = 1.0f;
}
// TODO(doyle): Renderer creates upfacing triangles by default,
// but we need to offset rotation so that our base "0 degrees"
// is right facing for trig to work
Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f));
v2 direction = V2(math_cosf(rotation), math_sinf(rotation));
if (getKeyStatus(&state->input.keys[keycode_down],
readkeytype_repeat, 0.0f, dt))
{
acceleration.y = -1.0f;
ddP = v2_normalise(direction);
}
if (getKeyStatus(&state->input.keys[keycode_left],
readkeytype_repeat, 0.0f, dt))
{
acceleration.x = -1.0f;
entity->rotation += (120.0f) * dt;
}
if (getKeyStatus(&state->input.keys[keycode_right],
readkeytype_repeat, 0.0f, dt))
{
acceleration.x = 1.0f;
entity->rotation -= (120.0f) * dt;
}
if (acceleration.x != 0.0f && acceleration.y != 0.0f)
if (ddP.x != 0.0f && ddP.y != 0.0f)
{
// NOTE(doyle): Cheese it and pre-compute the vector for
// diagonal using pythagoras theorem on a unit triangle 1^2
// + 1^2 = c^2
acceleration = v2_scale(acceleration, 0.70710678118f);
ddP = v2_scale(ddP, 0.70710678118f);
}
/*
@ -285,41 +276,77 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
newVelocity = a*t + oldVelocity
newPos = (a*t^2)/2 + oldVelocity*t + oldPos
*/
acceleration = v2_scale(acceleration, state->pixelsPerMeter * 25);
ddP = v2_scale(ddP, state->pixelsPerMeter * 25);
v2 oldVelocity = entity->velocity;
v2 resistance = v2_scale(oldVelocity, 4.0f);
acceleration = v2_sub(acceleration, resistance);
v2 oldDp = entity->dP;
v2 resistance = v2_scale(oldDp, 2.0f);
ddP = v2_sub(ddP, resistance);
entity->velocity = v2_add(v2_scale(acceleration, dt), oldVelocity);
entity->dP = v2_add(v2_scale(ddP, dt), oldDp);
v2 halfAcceleration = v2_scale(acceleration, 0.5f);
v2 halfAccelerationDtSquared =
v2_scale(halfAcceleration, (SQUARED(dt)));
v2 oldVelocityDt = v2_scale(oldVelocity, dt);
v2 ddPHalf = v2_scale(ddP, 0.5f);
v2 ddPHalfDtSquared = v2_scale(ddPHalf, (SQUARED(dt)));
v2 oldDpDt = v2_scale(oldDp, dt);
v2 oldPos = entity->pos;
entity->pos = v2_add(
v2_add(halfAccelerationDtSquared, oldVelocityDt), oldPos);
entity->pos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos);
pivotPoint = v2_scale(entity->size, 0.5f);
}
RenderFlags flags = renderflag_wireframe;
renderer_entity(&state->renderer, state->camera, entity, V2(0, 0),
0, V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
if (entity->pos.y >= state->worldSize.h)
{
entity->pos.y = 0;
}
else if (entity->pos.y < 0)
{
entity->pos.y = state->worldSize.h;
}
if (entity->pos.x >= state->worldSize.w)
{
entity->pos.x = 0;
}
else if (entity->pos.x < 0)
{
entity->pos.x = state->worldSize.w;
}
DEBUG_PUSH_VAR("Pos: %5.2f, %5.2f", entity->pos, "v2");
DEBUG_PUSH_VAR("Velocity: %5.2f, %5.2f", entity->dP, "v2");
DEBUG_PUSH_VAR("Rotation: %5.2f", entity->rotation, "f32");
RenderFlags flags = renderflag_wireframe | renderflag_no_texture;
renderer_entity(&state->renderer, state->camera, entity, pivotPoint, 0,
V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
v2 rightAlignedP = v2_add(entity->pos, entity->hitbox);
renderer_rect(&state->renderer, state->camera, rightAlignedP, V2(10, 10),
V2(0, 0), DEGREES_TO_RADIANS(entity->rotation), NULL,
V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
v2 leftAlignedP = entity->pos;
renderer_rect(&state->renderer, state->camera, leftAlignedP, V2(10, 10),
V2(0, 0), DEGREES_TO_RADIANS(entity->rotation), NULL,
V4(0.4f, 0.8f, 1.0f, 1.0f), flags);
}
TrianglePoints triangle = {0};
triangle.points[0] = V2(100, 200);
triangle.points[2] = V2(100, 300);
triangle.points[1] = V2(200, 100);
triangle.points[2] = V2(100, 300);
LOCAL_PERSIST Radians rotation = 0.0f;
rotation += DEGREES_TO_RADIANS(((60.0f) * dt));
RenderFlags flags = renderflag_wireframe;
RenderFlags flags = renderflag_wireframe | renderflag_no_texture;
renderer_triangle(&state->renderer, state->camera, triangle, V2(0, 0),
rotation, NULL, V4(1, 1, 1, 1), flags);
debug_drawUi(state, dt);
debug_clearCounter();
renderer_renderGroups(&state->renderer);
}

View File

@ -228,7 +228,7 @@ INTERNAL void updateAndRenderDebugStack(Renderer *renderer, MemoryArena_ *arena,
for (i32 i = 0; i < GLOBAL_debug.numDebugStrings; i++)
{
f32 rotate = 0;
v4 color = V4(0, 0, 0, 1);
v4 color = V4(1, 1, 1, 1);
renderer_staticString(
renderer, arena, &GLOBAL_debug.font, GLOBAL_debug.debugStrings[i],
GLOBAL_debug.currStringP, V2(0, 0), rotate, color, 0);
@ -270,5 +270,7 @@ INTERNAL void renderConsole(Renderer *renderer, MemoryArena_ *arena)
void debug_drawUi(GameState *state, f32 dt)
{
updateAndRenderDebugStack(&state->renderer, &state->transientArena, dt);
renderConsole(&state->renderer, &state->transientArena);
debug_clearCounter();
}

View File

@ -75,7 +75,7 @@ INTERNAL void addVertexToRenderGroup(Renderer *renderer, Texture *tex, v4 color,
// NOTE(doyle): Mark first vertex as degenerate vertex, but where we
// request wireframe mode- we can't use degenerate vertexes for line
// mode
if (!(flags & renderflag_wireframe)) group->vertexIndex++;
group->vertexIndex++;
group->init = TRUE;
group->tex = tex;
group->color = color;
@ -158,6 +158,7 @@ INTERNAL void bufferRenderGroupToGL(Renderer *renderer, RenderGroup *group)
INTERNAL void applyRotationToVertexes(v2 pos, v2 pivotPoint, Radians rotate,
Vertex *vertexList, i32 vertexListSize)
{
if (rotate == 0) return;
// NOTE(doyle): Move the world origin to the base position of the object.
// Then move the origin to the pivot point (e.g. center of object) and
// rotate from that point.
@ -238,7 +239,6 @@ INTERNAL RenderQuad_ createRenderQuad(Renderer *renderer, v2 pos, v2 size,
result.vertex[3].pos = V2(vertexPair.z, vertexPair.y); // Bottom right
result.vertex[3].texCoord = V2(texRectNdc.z, texRectNdc.y);
if (rotate == 0) return result;
// NOTE(doyle): Precalculate rotation on vertex positions
// NOTE(doyle): No translation/scale matrix as we pre-calculate it from
@ -266,7 +266,6 @@ INTERNAL RenderTriangle_ createRenderTriangle(Renderer *renderer,
result.vertex[2].pos = triangle.points[2];
result.vertex[2].texCoord = V2(texRectNdc.z, texRectNdc.w);
if (rotate == 0) return result;
applyRotationToVertexes(triangle.points[0], pivotPoint, rotate,
result.vertex, ARRAY_COUNT(result.vertex));
@ -286,35 +285,38 @@ INTERNAL void renderGLBufferedData(Renderer *renderer, RenderGroup *group)
{
ASSERT(group->mode < rendermode_invalid);
u32 drawMethod = GL_TRIANGLE_STRIP;
if (group->flags & renderflag_wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
GL_CHECK_ERROR();
if (group->flags & renderflag_no_texture)
{
drawMethod = GL_LINE_LOOP;
renderer->activeShaderId =
renderer->shaderList[shaderlist_default_no_tex];
shader_use(renderer->activeShaderId);
}
else
{
renderer->activeShaderId = renderer->shaderList[shaderlist_default];
}
shader_use(renderer->activeShaderId);
/* Set color modulation value */
shader_uniformSetVec4f(renderer->activeShaderId, "spriteColor",
group->color);
GL_CHECK_ERROR();
Texture *tex = group->tex;
if (tex)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex->id);
shader_uniformSet1i(renderer->activeShaderId, "tex", 0);
GL_CHECK_ERROR();
}
}
/* Set color modulation value */
shader_uniformSetVec4f(renderer->activeShaderId, "spriteColor",
group->color);
glBindVertexArray(renderer->vao[group->mode]);
glDrawArrays(drawMethod, 0, renderer->numVertexesInVbo);
glDrawArrays(GL_TRIANGLE_STRIP, 0, renderer->numVertexesInVbo);
GL_CHECK_ERROR();
debug_countIncrement(debugcount_drawArrays);
@ -322,6 +324,7 @@ INTERNAL void renderGLBufferedData(Renderer *renderer, RenderGroup *group)
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
GL_CHECK_ERROR();
}
RenderTex renderer_createNullRenderTex(AssetManager *const assetManager)
@ -344,17 +347,6 @@ void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size,
RenderQuad_ quad = createRenderQuad(renderer, posInCameraSpace, size,
pivotPoint, rotate, *renderTex);
// addRenderQuadToRenderGroup
if (flags & renderflag_wireframe)
{
Vertex vertexList[4] = {quad.vertex[0], quad.vertex[1], quad.vertex[3],
quad.vertex[2]};
addVertexToRenderGroup(renderer, renderTex->tex, color, vertexList,
ARRAY_COUNT(vertexList), rendermode_quad,
flags);
}
else
{
/*
NOTE(doyle): Entity rendering is always done in two pairs of
triangles, i.e. quad. To batch render quads as a triangle strip, we
@ -377,12 +369,12 @@ void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size,
1 degenerate vertex at the start of each render group.
*/
Vertex vertexList[6] = {quad.vertex[0], quad.vertex[0], quad.vertex[1],
quad.vertex[2], quad.vertex[3], quad.vertex[3]};
addVertexToRenderGroup(renderer, renderTex->tex, color, vertexList,
ARRAY_COUNT(vertexList), rendermode_quad, flags);
}
}
void renderer_triangle(Renderer *const renderer, Rect camera,
TrianglePoints triangle, v2 pivotPoint, Radians rotate,
@ -401,9 +393,13 @@ void renderer_triangle(Renderer *const renderer, Rect camera,
RenderTriangle_ renderTriangle = createRenderTriangle(
renderer, triangleInCamSpace, pivotPoint, rotate, *renderTex);
addVertexToRenderGroup(
renderer, renderTex->tex, color, renderTriangle.vertex,
ARRAY_COUNT(renderTriangle.vertex), rendermode_triangle, flags);
// NOTE(doyle): Create degenerate vertex setup
Vertex vertexList[5] = {renderTriangle.vertex[0], renderTriangle.vertex[0],
renderTriangle.vertex[1], renderTriangle.vertex[2],
renderTriangle.vertex[2]};
addVertexToRenderGroup(renderer, renderTex->tex, color, vertexList,
ARRAY_COUNT(vertexList), rendermode_triangle, flags);
}
void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera,
@ -474,7 +470,7 @@ void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera,
}
void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
v2 pivotPoint, Radians rotate, v4 color, RenderFlags flags)
v2 pivotPoint, Degrees rotate, v4 color, RenderFlags flags)
{
// TODO(doyle): Batch into render groups
@ -518,8 +514,36 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
renderTex.texRect = texRect;
}
renderer_rect(renderer, camera, entity->pos, entity->size, pivotPoint,
entity->rotation + rotate, &renderTex, color, flags);
Radians totalRotation = DEGREES_TO_RADIANS((entity->rotation + rotate));
if (entity->renderMode == rendermode_quad)
{
renderer_rect(renderer, camera, entity->pos, entity->size,
pivotPoint, totalRotation, &renderTex,
color, flags);
}
else if (entity->renderMode == rendermode_triangle)
{
TrianglePoints triangle = {0};
v2 entityPWithOffset = v2_add(entity->pos, entity->offset);
v2 triangleTopPoint =
V2(entityPWithOffset.x + (entity->size.w * 0.5f),
entityPWithOffset.y + entity->size.h);
v2 triangleRightSide =
V2(entityPWithOffset.x + entity->size.w, entityPWithOffset.y);
triangle.points[0] = entityPWithOffset;
triangle.points[1] = triangleRightSide;
triangle.points[2] = triangleTopPoint;
renderer_triangle(renderer, camera, triangle, pivotPoint,
totalRotation, &renderTex, color, flags);
}
else
{
ASSERT(INVALID_CODE_PATH);
}
}
}

View File

@ -15,6 +15,8 @@ typedef struct GameState {
i32 entityIndex;
f32 pixelsPerMeter;
v2 worldSize;
Rect camera;
AssetManager assetManager;

View File

@ -27,6 +27,7 @@ void debug_recursivePrintXmlTree(XmlNode *root, i32 levelsDeep);
void debug_countIncrement(enum DebugCount id);
void debug_clearCounter();
#define DEBUG_LOG(string) debug_consoleLog(string, __FILE__, __LINE__);
void debug_consoleLog(char *string, char *file, int lineNum);

View File

@ -3,6 +3,7 @@
#include "Dengine/Assets.h"
#include "Dengine/Common.h"
#include "Dengine/Renderer.h"
typedef struct AudioRenderer AudioRenderer;
@ -40,12 +41,16 @@ typedef struct Entity
i32 numChilds;
v2 pos;
v2 velocity;
v2 dP;
v2 hitbox;
v2 size;
v2 offset;
enum RenderMode renderMode;
f32 scale;
f32 rotation;
Degrees rotation;
b32 invisible;

View File

@ -7,11 +7,12 @@
#define MATH_PI 3.14159265359f
#define SQUARED(x) (x * x)
#define ABS(x) ((x) > 0 ? (x) : -(x))
#define DEGREES_TO_RADIANS(x) (x * (MATH_PI / 180.0f))
#define RADIANS_TO_DEGREES(x) (x * (180.0f / MATH_PI))
#define DEGREES_TO_RADIANS(x) ((x * (MATH_PI / 180.0f)))
#define RADIANS_TO_DEGREES(x) ((x * (180.0f / MATH_PI)))
#define SQRT(x) (sqrtf(x))
typedef f32 Radians;
typedef f32 Degrees;
INTERNAL inline f32 math_acosf(f32 a)
{
@ -19,12 +20,31 @@ INTERNAL inline f32 math_acosf(f32 a)
return result;
}
INTERNAL inline Radians math_cosf(Radians a)
{
Radians result = cosf(a);
return result;
}
INTERNAL inline Radians math_sinf(Radians a)
{
Radians result = sinf(a);
return result;
}
INTERNAL inline f32 math_atan2f(f32 y, f32 x)
{
f32 result = atan2f(y, x);
return result;
}
INTERNAL inline f32 math_tanf(Radians angle)
{
f32 result = tanf(angle);
return result;
}
/* VECTORS */
typedef union v2
{

View File

@ -32,6 +32,7 @@ typedef struct TrianglePoints {
typedef u32 RenderFlags;
enum RenderFlag {
renderflag_wireframe = 0x1,
renderflag_no_texture = 0x2,
};
enum RenderMode
@ -47,6 +48,7 @@ typedef struct RenderGroup
b32 init;
RenderFlags flags;
enum RenderMode mode;
u32 glRenderMode;
Texture *tex;
v4 color;
@ -112,7 +114,7 @@ inline void renderer_staticString(Renderer *const renderer, MemoryArena_ *arena,
}
void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
v2 pivotPoint, Radians rotate, v4 color,
v2 pivotPoint, Degrees rotate, v4 color,
RenderFlags flags);
void renderer_renderGroups(Renderer *renderer);