INTERNAL v2 *createNormalEdgeList(MemoryArena_ *transientArena, v2 *vertexList, i32 vertexListSize) { v2 *result = memory_pushBytes(transientArena, sizeof(v2) * vertexListSize); for (i32 i = 0; i < vertexListSize - 1; 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[vertexListSize - 1] = v2_sub(vertexList[0], vertexList[vertexListSize - 1]); result[vertexListSize - 1] = v2_perpendicular(result[vertexListSize - 1]); return result; }
/* Compute the covariance of a set of vectors */ void v2_covariance(int n, v2_t *v, v2_t mean, double *cov) { int i; cov[0] = cov[1] = cov[2] = cov[3] = 0.0; for (i = 0; i < n; i++) { v2_t vzm = v2_sub(v[i], mean); double xy = Vx(vzm) * Vy(vzm); cov[0] += Vx(vzm) * Vx(vzm); cov[1] += xy; cov[2] += xy; cov[3] += Vy(vzm) * Vy(vzm); } cov[0] /= n; cov[1] /= n; cov[2] /= n; cov[3] /= n; }
void ui_spinner_render(ui_spinner* s) { if (!s->active) return; vector2 top_left = s->top_left; vector2 top_right = v2(s->bottom_right.x, s->top_left.y); vector2 bot_left = v2(s->top_left.x, s->bottom_right.y); vector2 bot_right = s->bottom_right; vector2 center; center.x = (top_left.x + top_right.x) / 2; center.y = (top_left.y + bot_left.y) / 2; top_left = v2_sub(top_left, center); top_right = v2_sub(top_right, center); bot_left = v2_sub(bot_left, center); bot_right = v2_sub(bot_right, center); matrix_2x2 rot = m22_rotation(s->rotation); top_left = m22_mul_v2(rot, top_left); top_right = m22_mul_v2(rot, top_right); bot_left = m22_mul_v2(rot, bot_left); bot_right = m22_mul_v2(rot, bot_right); top_left = v2_add(top_left, center); top_right = v2_add(top_right, center); bot_left = v2_add(bot_left, center); bot_right = v2_add(bot_right, center); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, graphics_viewport_width(), graphics_viewport_height(), 0, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, *(s->texture) ); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(s->color.r, s->color.g, s->color.b, s->color.a); glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex3f(top_left.x, top_left.y, 0); glTexCoord2f(1, 1); glVertex3f(bot_left.x, bot_left.y, 0); glTexCoord2f(1, 0); glVertex3f(bot_right.x, bot_right.y, 0); glTexCoord2f(0, 0); glVertex3f(top_right.x, top_right.y, 0); glEnd(); glColor4f(1, 1, 1, 1); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); }
INTERNAL u32 moveEntity(GameWorldState *world, MemoryArena_ *transientArena, Entity *entity, i32 entityIndex, v2 ddP, f32 dt, f32 ddPSpeed) { ASSERT(ABS(ddP.x) <= 1.0f && ABS(ddP.y) <= 1.0f); /* Assuming acceleration A over t time, then integrate twice to get newVelocity = a*t + oldVelocity newPos = (a*t^2)/2 + oldVelocity*t + oldPos */ 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 ddP = v2_scale(ddP, 0.70710678118f); } ddP = v2_scale(ddP, world->pixelsPerMeter * ddPSpeed); v2 oldDp = entity->dP; v2 resistance = v2_scale(oldDp, 2.0f); ddP = v2_sub(ddP, resistance); v2 newDp = v2_add(v2_scale(ddP, dt), oldDp); v2 ddPHalf = v2_scale(ddP, 0.5f); v2 ddPHalfDtSquared = v2_scale(ddPHalf, (SQUARED(dt))); v2 oldDpDt = v2_scale(oldDp, dt); v2 oldPos = entity->pos; v2 newPos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos); i32 collisionIndex = -1; // TODO(doyle): Collision for rects, (need to create vertex list for it) for (i32 i = 1; i < world->entityIndex; i++) { if (i == entityIndex) continue; Entity *checkEntity = &world->entityList[i]; ASSERT(checkEntity->id != entity->id); if (world->collisionTable[entity->type][checkEntity->type]) { ASSERT(entity->vertexPoints); ASSERT(checkEntity->vertexPoints); /* Create entity edge lists */ v2 *entityVertexListOffsetToP = entity_generateUpdatedVertexList(transientArena, entity); v2 *checkEntityVertexListOffsetToP = entity_generateUpdatedVertexList(transientArena, checkEntity); v2 *entityEdgeList = createNormalEdgeList(transientArena, entityVertexListOffsetToP, entity->numVertexPoints); v2 *checkEntityEdgeList = createNormalEdgeList( transientArena, checkEntityVertexListOffsetToP, checkEntity->numVertexPoints); /* Combine both edge lists into one */ i32 totalNumEdges = checkEntity->numVertexPoints + entity->numVertexPoints; v2 *edgeList = memory_pushBytes(transientArena, totalNumEdges * sizeof(v2)); for (i32 i = 0; i < entity->numVertexPoints; i++) { edgeList[i] = entityEdgeList[i]; } for (i32 i = 0; i < checkEntity->numVertexPoints; i++) { edgeList[i + entity->numVertexPoints] = checkEntityEdgeList[i]; } if (checkEdgeProjectionOverlap( entityVertexListOffsetToP, entity->numVertexPoints, checkEntityVertexListOffsetToP, checkEntity->numVertexPoints, edgeList, totalNumEdges)) { collisionIndex = i; } } if (collisionIndex != -1) break; } entity->dP = newDp; entity->pos = newPos; return collisionIndex; }