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); }