From 0c7824bf18f123b4d8cc2e70ed74f7ea8002fb75 Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Wed, 23 Nov 2016 13:42:46 +1100 Subject: [PATCH] Move rotation step outside of inner rendering loop We need to generate interim vertex points during the collision detection loop that includes rotation to check for collision. During collision detection, vertex points are rotated and positioned in placed for checking. We also re-create this vertex list in the renderer suggesting that we could cache the list in the entity or look at coupling rendering and collision detection. --- src/Asteroid.c | 147 ++++++++++++++++----------- src/Entity.c | 21 ++++ src/Renderer.c | 177 +++++++++++++++++---------------- src/include/Dengine/Entity.h | 5 +- src/include/Dengine/Math.h | 33 ++++++ src/include/Dengine/Renderer.h | 10 +- 6 files changed, 245 insertions(+), 148 deletions(-) diff --git a/src/Asteroid.c b/src/Asteroid.c index 36b2b5f..6928e45 100644 --- a/src/Asteroid.c +++ b/src/Asteroid.c @@ -83,7 +83,7 @@ void initRenderer(GameState *state, v2 windowSize) { glEnableVertexAttribArray(0); u32 numVertexElements = 4; - u32 stride = sizeof(Vertex); + u32 stride = sizeof(RenderVertex); glVertexAttribPointer(0, numVertexElements, GL_FLOAT, GL_FALSE, stride, (GLvoid *)0); @@ -98,8 +98,9 @@ void initRenderer(GameState *state, v2 windowSize) { renderer->groupCapacity = 4096; for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++) { - renderer->groups[i].vertexList = memory_pushBytes( - &state->persistentArena, renderer->groupCapacity * sizeof(Vertex)); + renderer->groups[i].vertexList = + memory_pushBytes(&state->persistentArena, + renderer->groupCapacity * sizeof(RenderVertex)); } } @@ -221,38 +222,36 @@ v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations, return result; } -v2 *createEntityEdgeList(MemoryArena_ *transientArena, Entity *entity) +v2 *createNormalEdgeList(MemoryArena_ *transientArena, v2 *vertexList, + i32 vertexListSize) { - v2 *result = memory_pushBytes(transientArena, - sizeof(v2) * entity->numVertexPoints); - - i32 numVertexes = entity->numVertexPoints; - for (i32 i = 0; i < numVertexes - 1; i++) + v2 *result = memory_pushBytes(transientArena, sizeof(v2) * vertexListSize); + for (i32 i = 0; i < vertexListSize - 1; i++) { - ASSERT((i + 1) < numVertexes); - result[i] = - v2_sub(entity->vertexPoints[i + 1], entity->vertexPoints[i]); + ASSERT((i + 1) < vertexListSize); + result[i] = v2_sub(vertexList[i + 1], vertexList[i]); + result[i] = v2_perpendicular(result[i]); } // NOTE(doyle): Creating the last edge requires using the first // vertex point which is at index 0 - result[numVertexes - 1] = - v2_sub(entity->vertexPoints[0], entity->vertexPoints[numVertexes - 1]); + result[vertexListSize - 1] = + v2_sub(vertexList[0], vertexList[vertexListSize - 1]); + result[vertexListSize - 1] = v2_perpendicular(result[vertexListSize - 1]); return result; } -v2 calculateProjectionRangeForEdge(Entity *entity, v2 edgeNormal) +v2 calculateProjectionRangeForEdge(v2 *vertexList, i32 vertexListSize, + v2 edgeNormal) { v2 result = {0}; - result.max = v2_dot(entity->vertexPoints[0], edgeNormal); + result.min = v2_dot(vertexList[0], edgeNormal); result.max = result.min; - for (i32 vertexIndex = 0; vertexIndex < entity->numVertexPoints; - vertexIndex++) + for (i32 vertexIndex = 0; vertexIndex < vertexListSize; vertexIndex++) { - f32 dist = - v2_dot(entity->vertexPoints[vertexIndex], edgeNormal); + f32 dist = v2_dot(vertexList[vertexIndex], edgeNormal); if (dist < result.min) result.min = dist; @@ -263,20 +262,20 @@ v2 calculateProjectionRangeForEdge(Entity *entity, v2 edgeNormal) return result; } -b32 checkEntityProjectionOverlap(Entity *entity, Entity *checkEntity, - v2 *entityEdges) +b32 checkEdgeProjectionOverlap(v2 *vertexList, i32 listSize, + v2 *checkVertexList, i32 checkListSize, + v2 *edgeList, i32 totalNumEdges) { b32 result = TRUE; - for (i32 edgeIndex = 0; edgeIndex < entity->numVertexPoints && result; - edgeIndex++) + for (i32 edgeIndex = 0; edgeIndex < totalNumEdges && result; edgeIndex++) { - v2 entityProjectionRange = - calculateProjectionRangeForEdge(entity, entityEdges[edgeIndex]); - v2 checkEntityProjectionRange = calculateProjectionRangeForEdge( - checkEntity, entityEdges[edgeIndex]); + v2 projectionRange = calculateProjectionRangeForEdge( + vertexList, listSize, edgeList[edgeIndex]); - if (!v2_intervalsOverlap(entityProjectionRange, - checkEntityProjectionRange)) + v2 checkProjectionRange = calculateProjectionRangeForEdge( + checkVertexList, checkListSize, edgeList[edgeIndex]); + + if (!v2_intervalsOverlap(projectionRange, checkProjectionRange)) { result = FALSE; return result; @@ -286,7 +285,7 @@ b32 checkEntityProjectionOverlap(Entity *entity, Entity *checkEntity, return result; } -void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed) +b32 moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed) { ASSERT(ABS(ddP.x) <= 1.0f && ABS(ddP.y) <= 1.0f); /* @@ -311,7 +310,8 @@ void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed) v2 newPos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos); b32 willCollide = FALSE; -#if 0 + +#if 1 if (entity->renderMode == rendermode_polygon && entity->collides) { for (i32 i = 0; i < state->entityIndex; i++) @@ -322,31 +322,40 @@ void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed) if (checkEntity->renderMode == rendermode_polygon && checkEntity->collides) { - i32 numEntityEdges = entity->numVertexPoints; - i32 numCheckEntityEdges = checkEntity->numVertexPoints; - v2 *entityEdges = - createEntityEdgeList(&state->transientArena, entity); - v2 *checkEntityEdges = - createEntityEdgeList(&state->transientArena, entity); + /* Create entity edge lists */ + v2 *entityVertexListOffsetToP = + entity_createVertexList(&state->transientArena, entity); + v2 *checkEntityVertexListOffsetToP = entity_createVertexList( + &state->transientArena, checkEntity); - // Convert inplace the vector normal of the edges - for (i32 i = 0; i < numEntityEdges; i++) + v2 *entityEdgeList = createNormalEdgeList( + &state->transientArena, entityVertexListOffsetToP, + entity->numVertexPoints); + + v2 *checkEntityEdgeList = createNormalEdgeList( + &state->transientArena, checkEntityVertexListOffsetToP, + checkEntity->numVertexPoints); + + /* Combine both edge lists into one */ + i32 totalNumEdges = + checkEntity->numVertexPoints + entity->numVertexPoints; + v2 *edgeList = memory_pushBytes(&state->transientArena, + totalNumEdges * sizeof(v2)); + for (i32 i = 0; i < entity->numVertexPoints; i++) { - entityEdges[i] = v2_perpendicular(entityEdges[i]); - entityEdges[i] = v2_add(entityEdges[i], entity->pos); + edgeList[i] = entityEdgeList[i]; } - for (i32 i = 0; i < numCheckEntityEdges; i++) + for (i32 i = 0; i < checkEntity->numVertexPoints; i++) { - checkEntityEdges[i] = v2_perpendicular(checkEntityEdges[i]); - checkEntityEdges[i] = - v2_add(checkEntityEdges[i], checkEntity->pos); + edgeList[i + entity->numVertexPoints] = + checkEntityEdgeList[i]; } - if ((checkEntityProjectionOverlap(entity, checkEntity, - entityEdges) && - checkEntityProjectionOverlap(entity, checkEntity, - checkEntityEdges))) + if (checkEdgeProjectionOverlap( + entityVertexListOffsetToP, entity->numVertexPoints, + checkEntityVertexListOffsetToP, + checkEntity->numVertexPoints, edgeList, totalNumEdges)) { willCollide = TRUE; } @@ -364,13 +373,17 @@ void moveEntity(GameState *state, Entity *entity, v2 ddP, f32 dt, f32 ddPSpeed) entity->dP = newDp; entity->pos = newPos; } + else + { + entity->dP = v2_scale(newDp, -1.0f); + } + + return willCollide; } void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, v2 windowSize, f32 dt) { - i32 iterations = 16; - memory_arenaInit(&state->transientArena, memory->transient, memory->transientSize); @@ -387,8 +400,9 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, { // Init ship entity Entity *ship = &state->entityList[state->entityIndex]; ship->id = state->entityIndex++; - ship->pos = V2(0, 0); + ship->pos = V2(100, 100); ship->size = V2(25.0f, 50.0f); + ship->rotation = 90.0f; ship->hitbox = ship->size; ship->offset = v2_scale(ship->size, 0.5f); @@ -411,7 +425,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, ship->tex = NULL; ship->collides = TRUE; - i32 numAsteroids = 8; + i32 numAsteroids = 1; for (i32 i = 0; i < numAsteroids; i++) { Entity *asteroid = &state->entityList[state->entityIndex]; @@ -420,7 +434,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, i32 randValue = rand(); i32 randX = (randValue % (i32)windowSize.w); i32 randY = (randValue % (i32)windowSize.h); - asteroid->pos = V2i(randX, randY); + asteroid->pos = V2i(500, 500); asteroid->size = V2(100.0f, 100.0f); asteroid->hitbox = asteroid->size; @@ -438,6 +452,19 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, asteroid->tex = NULL; asteroid->collides = TRUE; } + + Entity *square = &state->entityList[state->entityIndex]; + square->id = state->entityIndex++; + square->pos = V2(350, 350); + square->size = V2(75.0f, 75.0f); + square->hitbox = square->size; + square->offset = v2_scale(square->size, 0.5f); + square->scale = 1; + square->type = entitytype_asteroid; + square->direction = direction_null; + square->renderMode = rendermode_quad; + square->tex = NULL; + square->collides = TRUE; } state->camera.min = V2(0, 0); @@ -546,6 +573,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, } v2 ddP = {0}; +#if 0 switch (entity->direction) { case direction_north: @@ -613,15 +641,20 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, // NOTE(doyle): Make asteroids start and move at constant speed ddPSpeedInMs = 2; entity->dP = v2_scale(ddP, state->pixelsPerMeter * ddPSpeedInMs); +#endif entity->rotation += (randValue % 20) * dt; } - moveEntity(state, entity, ddP, dt, ddPSpeedInMs); + b32 willCollide = moveEntity(state, entity, ddP, dt, ddPSpeedInMs); + + v4 entityCollisionColor = V4(1.0f, 1.0f, 1.0f, 1.0f); + + if (willCollide) entityCollisionColor = V4(1.0f, 0, 0, 1.0f); RenderFlags flags = renderflag_wireframe | renderflag_no_texture; renderer_entity(&state->renderer, &state->transientArena, state->camera, entity, V2(0, 0), 0, - V4(0.4f, 0.8f, 1.0f, 1.0f), flags); + entityCollisionColor, flags); } debug_drawUi(state, dt); diff --git a/src/Entity.c b/src/Entity.c index 4a77d1e..9795ba6 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -1,6 +1,8 @@ #include "Dengine/Entity.h" #include "Dengine/AssetManager.h" #include "Dengine/Debug.h" +#include "Dengine/Math.h" +#include "Dengine/MemoryArena.h" SubTexture entity_getActiveSubTexture(Entity *const entity) { @@ -86,3 +88,22 @@ void entity_addAnim(AssetManager *const assetManager, Entity *const entity, DEBUG_LOG("No more free entity animation slots"); } + +v2 *entity_createVertexList(MemoryArena_ *transientArena, Entity *entity) +{ + v2 *result = + memory_pushBytes(transientArena, entity->numVertexPoints * sizeof(v2)); + + for (i32 i = 0; i < entity->numVertexPoints; i++) + { + result[i] = v2_sub(entity->vertexPoints[i], entity->offset); + result[i] = v2_add(result[i], entity->pos); + } + + math_applyRotationToVertexes(result[0], entity->offset, + DEGREES_TO_RADIANS(entity->rotation), result, + entity->numVertexPoints); + + return result; +} + diff --git a/src/Renderer.c b/src/Renderer.c index 8da2815..fc3d604 100644 --- a/src/Renderer.c +++ b/src/Renderer.c @@ -10,8 +10,8 @@ typedef struct RenderQuad { - Vertex vertex[4]; -} RenderQuad_; + RenderVertex vertexList[4]; +} RenderQuad; // NOTE(doyle): A vertex batch is the batch of vertexes comprised to make one // shape @@ -56,7 +56,8 @@ INTERNAL void endVertexBatch(Renderer *renderer) i32 freeVertexSlots = renderer->groupCapacity - group->vertexIndex; if (numDegenerateVertexes < freeVertexSlots) { - Vertex degenerateVertex = group->vertexList[group->vertexIndex-1]; + RenderVertex degenerateVertex = + group->vertexList[group->vertexIndex - 1]; group->vertexList[group->vertexIndex++] = degenerateVertex; group->vertexList[group->vertexIndex++] = degenerateVertex; } @@ -65,8 +66,38 @@ INTERNAL void endVertexBatch(Renderer *renderer) renderer->groupIndexForVertexBatch = -1; } +INTERNAL void applyRotationToVertexes(v2 pos, v2 pivotPoint, Radians rotate, + RenderVertex *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. + v2 pointOfRotation = v2_add(pivotPoint, pos); + + mat4 rotateMat = mat4_translate(pointOfRotation.x, pointOfRotation.y, 0.0f); + rotateMat = mat4_mul(rotateMat, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f)); + rotateMat = mat4_mul(rotateMat, mat4_translate(-pointOfRotation.x, + -pointOfRotation.y, 0.0f)); + for (i32 i = 0; i < vertexListSize; i++) + { + // NOTE(doyle): Manual matrix multiplication since vertex pos is 2D and + // matrix is 4D + v2 oldP = vertexList[i].pos; + v2 newP = {0}; + + newP.x = (oldP.x * rotateMat.e[0][0]) + (oldP.y * rotateMat.e[1][0]) + + (rotateMat.e[3][0]); + newP.y = (oldP.x * rotateMat.e[0][1]) + (oldP.y * rotateMat.e[1][1]) + + (rotateMat.e[3][1]); + + vertexList[i].pos = newP; + } +} + INTERNAL void addVertexToRenderGroup_(Renderer *renderer, Texture *tex, - v4 color, Vertex *vertexList, + v4 color, RenderVertex *vertexList, i32 numVertexes, enum RenderMode targetRenderMode, RenderFlags flags) @@ -208,46 +239,17 @@ INTERNAL inline void flipTexCoord(v4 *texCoords, b32 flipX, b32 flipY) INTERNAL void bufferRenderGroupToGL(Renderer *renderer, RenderGroup *group) { - Vertex *vertexList = group->vertexList; + RenderVertex *vertexList = group->vertexList; i32 numVertex = group->vertexIndex; // TODO(doyle): We assume that vbo and vao are assigned renderer->numVertexesInVbo = numVertex; glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo[group->mode]); - glBufferData(GL_ARRAY_BUFFER, numVertex * sizeof(Vertex), vertexList, + glBufferData(GL_ARRAY_BUFFER, numVertex * sizeof(RenderVertex), vertexList, GL_STREAM_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } -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. - v2 pointOfRotation = v2_add(pivotPoint, pos); - - mat4 rotateMat = mat4_translate(pointOfRotation.x, pointOfRotation.y, 0.0f); - rotateMat = mat4_mul(rotateMat, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f)); - rotateMat = mat4_mul(rotateMat, mat4_translate(-pointOfRotation.x, - -pointOfRotation.y, 0.0f)); - for (i32 i = 0; i < vertexListSize; i++) - { - // NOTE(doyle): Manual matrix multiplication since vertex pos is 2D and - // matrix is 4D - v2 oldP = vertexList[i].pos; - v2 newP = {0}; - - newP.x = (oldP.x * rotateMat.e[0][0]) + (oldP.y * rotateMat.e[1][0]) + - (rotateMat.e[3][0]); - newP.y = (oldP.x * rotateMat.e[0][1]) + (oldP.y * rotateMat.e[1][1]) + - (rotateMat.e[3][1]); - - vertexList[i].pos = newP; - } -} - INTERNAL v4 getTexRectNormaliseDeviceCoords(RenderTex renderTex) { /* Convert texture coordinates to normalised texture coordinates */ @@ -266,9 +268,9 @@ INTERNAL v4 getTexRectNormaliseDeviceCoords(RenderTex renderTex) } -INTERNAL RenderQuad_ createRenderQuad(Renderer *renderer, v2 pos, v2 size, - v2 pivotPoint, Radians rotate, - RenderTex renderTex) +INTERNAL RenderQuad createRenderQuad(Renderer *renderer, v2 pos, v2 size, + v2 pivotPoint, Radians rotate, + RenderTex renderTex) { /* * Rendering order @@ -291,33 +293,50 @@ INTERNAL RenderQuad_ createRenderQuad(Renderer *renderer, v2 pos, v2 size, // NOTE(doyle): Create a quad composed of 4 vertexes to be rendered as // a triangle strip using vertices v0, v1, v2, then v2, v1, v3 (note the // order) - RenderQuad_ result = {0}; - result.vertex[0].pos = V2(vertexPair.x, vertexPair.w); // Top left - result.vertex[0].texCoord = V2(texRectNdc.x, texRectNdc.w); + v2 vertexList[4] = {0}; + v2 texCoordList[4] = {0}; - result.vertex[1].pos = V2(vertexPair.x, vertexPair.y); // Bottom left - result.vertex[1].texCoord = V2(texRectNdc.x, texRectNdc.y); + // Top left + vertexList[0] = V2(vertexPair.x, vertexPair.w); + texCoordList[0] = V2(texRectNdc.x, texRectNdc.w); - result.vertex[2].pos = V2(vertexPair.z, vertexPair.w); // Top right - result.vertex[2].texCoord = V2(texRectNdc.z, texRectNdc.w); + // Bottom left + vertexList[1] = V2(vertexPair.x, vertexPair.y); + texCoordList[1] = V2(texRectNdc.x, texRectNdc.y); - result.vertex[3].pos = V2(vertexPair.z, vertexPair.y); // Bottom right - result.vertex[3].texCoord = V2(texRectNdc.z, texRectNdc.y); + // Top right + vertexList[2] = V2(vertexPair.z, vertexPair.w); + texCoordList[2] = V2(texRectNdc.z, texRectNdc.w); + + // Bottom right + vertexList[3] = V2(vertexPair.z, vertexPair.y); + texCoordList[3] = V2(texRectNdc.z, texRectNdc.y); // NOTE(doyle): Precalculate rotation on vertex positions // NOTE(doyle): No translation/scale matrix as we pre-calculate it from // entity data and work in world space until GLSL uses the projection matrix - applyRotationToVertexes(pos, pivotPoint, rotate, result.vertex, - ARRAY_COUNT(result.vertex)); + + math_applyRotationToVertexes(pos, pivotPoint, rotate, vertexList, + ARRAY_COUNT(vertexList)); + + RenderQuad result = {0}; + + ASSERT(ARRAY_COUNT(vertexList) == ARRAY_COUNT(result.vertexList)); + for (i32 i = 0; i < ARRAY_COUNT(vertexList); i++) + { + result.vertexList[i].pos = vertexList[i]; + result.vertexList[i].texCoord = texCoordList[i]; + } + return result; } -INTERNAL inline RenderQuad_ +INTERNAL inline RenderQuad createDefaultTexQuad(Renderer *renderer, RenderTex *renderTex) { - RenderQuad_ result = {0}; - result = createRenderQuad(renderer, V2(0, 0), V2(0, 0), V2(0, 0), - 0.0f, *renderTex); + RenderQuad result = {0}; + result = createRenderQuad(renderer, V2(0, 0), V2(0, 0), V2(0, 0), 0.0f, + *renderTex); return result; } @@ -384,12 +403,13 @@ void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size, RenderTex emptyRenderTex = {0}; if (!renderTex) renderTex = &emptyRenderTex; - RenderQuad_ quad = createRenderQuad(renderer, posInCameraSpace, size, - pivotPoint, rotate, *renderTex); + RenderQuad quad = createRenderQuad(renderer, posInCameraSpace, size, + pivotPoint, rotate, *renderTex); beginVertexBatch(renderer); - addVertexToRenderGroup_(renderer, renderTex->tex, color, quad.vertex, - ARRAY_COUNT(quad.vertex), rendermode_quad, flags); + addVertexToRenderGroup_(renderer, renderTex->tex, color, quad.vertexList, + ARRAY_COUNT(quad.vertexList), rendermode_quad, + flags); endVertexBatch(renderer); } @@ -408,7 +428,7 @@ void renderer_polygon(Renderer *const renderer, Rect camera, if (!renderTex) renderTex = &emptyRenderTex; v2 triangulationBaseP = polygonPoints[0]; - Vertex triangulationBaseVertex = {0}; + RenderVertex triangulationBaseVertex = {0}; triangulationBaseVertex.pos = triangulationBaseP; i32 numTrisInTriangulation = numPoints - 2; @@ -418,13 +438,11 @@ void renderer_polygon(Renderer *const renderer, Rect camera, { ASSERT((i + 1) < numPoints); - Vertex triangle[3] = {0}; - triangle[0].pos = triangulationBaseP; - triangle[1].pos = polygonPoints[i]; - triangle[2].pos = polygonPoints[i + 1]; + RenderVertex triangle[3] = {0}; + triangle[0].pos = triangulationBaseP; + triangle[1].pos = polygonPoints[i]; + triangle[2].pos = polygonPoints[i + 1]; - applyRotationToVertexes(triangulationBaseP, pivotPoint, rotate, - triangle, ARRAY_COUNT(triangle)); addVertexToRenderGroup_(renderer, renderTex->tex, color, triangle, ARRAY_COUNT(triangle), rendermode_polygon, flags); @@ -453,8 +471,8 @@ void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera, i32 vertexIndex = 0; i32 numVertexPerQuad = 4; i32 numVertexesToAlloc = (strLen * (numVertexPerQuad + 2)); - Vertex *vertexList = - memory_pushBytes(arena, numVertexesToAlloc * sizeof(Vertex)); + RenderVertex *vertexList = + memory_pushBytes(arena, numVertexesToAlloc * sizeof(RenderVertex)); v2 posInCameraSpace = v2_sub(pos, camera.min); pos = posInCameraSpace; @@ -480,13 +498,13 @@ void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera, flipTexCoord(&charTexRect, FALSE, TRUE); RenderTex renderTex = {tex, charTexRect}; - RenderQuad_ quad = createRenderQuad(renderer, pos, font->maxSize, - pivotPoint, rotate, renderTex); + RenderQuad quad = createRenderQuad(renderer, pos, font->maxSize, + pivotPoint, rotate, renderTex); beginVertexBatch(renderer); - addVertexToRenderGroup_(renderer, tex, color, quad.vertex, - ARRAY_COUNT(quad.vertex), rendermode_quad, - flags); + addVertexToRenderGroup_(renderer, tex, color, quad.vertexList, + ARRAY_COUNT(quad.vertexList), + rendermode_quad, flags); endVertexBatch(renderer); pos.x += metric.advance; } @@ -531,24 +549,17 @@ void renderer_entity(Renderer *renderer, MemoryArena_ *transientArena, if (entity->renderMode == rendermode_quad) { - renderer_rect(renderer, camera, entity->pos, entity->size, pivotPoint, - totalRotation, &renderTex, color, flags); + renderer_rect(renderer, camera, entity->pos, entity->size, + v2_add(entity->offset, pivotPoint), totalRotation, + &renderTex, color, flags); } else if (entity->renderMode == rendermode_polygon) { ASSERT(entity->numVertexPoints >= 3); ASSERT(entity->vertexPoints); - v2 *offsetVertexPoints = memory_pushBytes( - transientArena, entity->numVertexPoints * sizeof(v2)); - - for (i32 i = 0; i < entity->numVertexPoints; i++) - { - offsetVertexPoints[i] = - v2_add(entity->vertexPoints[i], entity->offset); - offsetVertexPoints[i] = v2_add(offsetVertexPoints[i], entity->pos); - } - + v2 *offsetVertexPoints = + entity_createVertexList(transientArena, entity); renderer_polygon(renderer, camera, offsetVertexPoints, entity->numVertexPoints, v2_add(entity->offset, pivotPoint), totalRotation, diff --git a/src/include/Dengine/Entity.h b/src/include/Dengine/Entity.h index 44252cf..4d08392 100644 --- a/src/include/Dengine/Entity.h +++ b/src/include/Dengine/Entity.h @@ -6,6 +6,7 @@ #include "Dengine/Renderer.h" typedef struct AudioRenderer AudioRenderer; +typedef struct MemoryArena_ MemoryArena; enum Direction { @@ -66,8 +67,6 @@ typedef struct Entity f32 scale; Degrees rotation; - b32 invisible; - enum EntityType type; enum Direction direction; @@ -95,4 +94,6 @@ void entity_setActiveAnim(Entity *const entity, const char *const animName); void entity_updateAnim(Entity *const entity, const f32 dt); void entity_addAnim(AssetManager *const assetManager, Entity *const entity, const char *const animName); + +v2 *entity_createVertexList(MemoryArena_ *transientArena, Entity *entity); #endif diff --git a/src/include/Dengine/Math.h b/src/include/Dengine/Math.h index 5307a88..877c822 100644 --- a/src/include/Dengine/Math.h +++ b/src/include/Dengine/Math.h @@ -367,4 +367,37 @@ INTERNAL inline v2 math_getRectSize(v4 rect) return result; } +INTERNAL inline void math_applyRotationToVertexes(v2 pos, v2 pivotPoint, + Radians rotate, + v2 *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. + v2 pointOfRotation = v2_add(pivotPoint, pos); + + mat4 rotateMat = mat4_translate(pointOfRotation.x, pointOfRotation.y, 0.0f); + rotateMat = mat4_mul(rotateMat, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f)); + rotateMat = mat4_mul(rotateMat, mat4_translate(-pointOfRotation.x, + -pointOfRotation.y, 0.0f)); + + // TODO(doyle): Make it nice for 2d vector, stop using mat4 + for (i32 i = 0; i < vertexListSize; i++) + { + // NOTE(doyle): Manual matrix multiplication since vertex pos is 2D and + // matrix is 4D + v2 oldP = vertexList[i]; + v2 newP = {0}; + + newP.x = (oldP.x * rotateMat.e[0][0]) + (oldP.y * rotateMat.e[1][0]) + + (rotateMat.e[3][0]); + newP.y = (oldP.x * rotateMat.e[0][1]) + (oldP.y * rotateMat.e[1][1]) + + (rotateMat.e[3][1]); + + vertexList[i] = newP; + } +} + #endif diff --git a/src/include/Dengine/Renderer.h b/src/include/Dengine/Renderer.h index fa342b2..efc4b1d 100644 --- a/src/include/Dengine/Renderer.h +++ b/src/include/Dengine/Renderer.h @@ -13,11 +13,11 @@ typedef struct MemoryArena MemoryArena_; typedef struct Shader Shader; typedef struct Texture Texture; -typedef struct Vertex +typedef struct RenderVertex { v2 pos; v2 texCoord; -} Vertex; +} RenderVertex; typedef struct RenderTex { @@ -51,7 +51,7 @@ typedef struct RenderGroup Texture *tex; v4 color; - Vertex *vertexList; + RenderVertex *vertexList; i32 vertexIndex; } RenderGroup; @@ -82,9 +82,7 @@ typedef struct Renderer } Renderer; -// TODO(doyle): Use z-index occluding for rendering -RenderTex -renderer_createNullRenderTex(AssetManager *const assetManager); +RenderTex renderer_createNullRenderTex(AssetManager *const assetManager); // TODO(doyle): Clean up lines // Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }