Fix rotation on triangles

This commit is contained in:
Doyle Thai 2017-05-16 17:36:51 +10:00
parent 51342122b9
commit 3ec64da44c
2 changed files with 126 additions and 160 deletions

View File

@ -46,6 +46,8 @@ typedef struct DRState
typedef struct DRDebug typedef struct DRDebug
{ {
DRFont *font; DRFont *font;
PlatformRenderBuffer *renderBuffer;
DqnV2 displayP; DqnV2 displayP;
i32 displayYOffset; i32 displayYOffset;
@ -186,11 +188,13 @@ FILE_SCOPE void DrawText(PlatformRenderBuffer *const renderBuffer,
} }
} }
FILE_SCOPE void DebugPushText(PlatformRenderBuffer *const renderBuffer, FILE_SCOPE void DebugPushText(const char *const formatStr, ...)
const char *const formatStr, ...) {
if (DR_DEBUG)
{ {
#ifdef DR_DEBUG
DRDebug *const debug = &globalDebug; DRDebug *const debug = &globalDebug;
if (!debug->renderBuffer) return;
char str[1024] = {}; char str[1024] = {};
va_list argList; va_list argList;
@ -201,9 +205,9 @@ FILE_SCOPE void DebugPushText(PlatformRenderBuffer *const renderBuffer,
} }
va_end(argList); va_end(argList);
DrawText(renderBuffer, *debug->font, debug->displayP, str); DrawText(debug->renderBuffer, *debug->font, debug->displayP, str);
debug->displayP.y += globalDebug.displayYOffset; debug->displayP.y += globalDebug.displayYOffset;
#endif }
} }
FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a, FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
@ -284,64 +288,50 @@ FILE_SCOPE void TransformVertexes(const DqnV2 origin, DqnV2 *const vertexList,
} }
} }
FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
DqnV2 min, DqnV2 max, DqnV4 color,
const DqnV2 scale = DqnV2_1f(1.0f),
const f32 rotation = 0,
const DqnV2 anchor = DqnV2_1f(0.5f));
FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1, FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
DqnV2 p2, DqnV2 p3, DqnV4 color, DqnV2 p2, DqnV2 p3, DqnV4 color,
DqnV2 scale = DqnV2_1f(1.0f), f32 rotation = 0, DqnV2 scale = DqnV2_1f(1.0f), f32 rotation = 0,
DqnV2 anchor = DqnV2_1f(0.5f)) DqnV2 anchor = DqnV2_1f(0.33f))
{ {
f32 area2Times = ((p2.x - p1.x) * (p2.y + p1.y)) + f32 area2Times = ((p2.x - p1.x) * (p2.y + p1.y)) +
((p3.x - p2.x) * (p3.y + p2.y)) + ((p3.x - p2.x) * (p3.y + p2.y)) +
((p1.x - p3.x) * (p1.y + p3.y)); ((p1.x - p3.x) * (p1.y + p3.y));
if (area2Times < 0) if (area2Times > 0)
{
// Counter-clockwise, do nothing this is what we want.
}
else
{ {
// Clockwise swap any point to make it clockwise // Clockwise swap any point to make it clockwise
DQN_SWAP(DqnV2, p2, p3); DQN_SWAP(DqnV2, p2, p3);
} }
// Transform vertexes // Transform vertexes
#if 1 DqnV2 p1p2 = p2 - p1;
{ DqnV2 p1p3 = p3 - p1;
DqnV2 max = DqnV2_2f(DQN_MAX(DQN_MAX(p1.x, p2.x), p3.x), DqnV2 p1p2Anchored = p1p2 * anchor;
DQN_MAX(DQN_MAX(p1.y, p2.y), p3.y)); DqnV2 p1p3Anchored = p1p3 * anchor;
DqnV2 min = DqnV2_2f(DQN_MIN(DQN_MIN(p1.x, p2.x), p3.x),
DQN_MIN(DQN_MIN(p1.y, p2.y), p3.y));
DqnV2 boundsDim = DqnV2_2f(max.x - min.x, max.y - min.y);
DQN_ASSERT(boundsDim.w > 0 && boundsDim.h > 0);
DqnV2 origin = DqnV2_2f(min.x + (anchor.x * boundsDim.w), min.y + (anchor.y * boundsDim.h));
DqnV2 origin = p1 + p1p2Anchored + p1p3Anchored;
DqnV2 vertexList[3] = {p1 - origin, p2 - origin, p3 - origin}; DqnV2 vertexList[3] = {p1 - origin, p2 - origin, p3 - origin};
TransformVertexes(origin, vertexList, DQN_ARRAY_COUNT(vertexList), TransformVertexes(origin, vertexList, DQN_ARRAY_COUNT(vertexList), scale,
scale, rotation); rotation);
p1 = vertexList[0]; p1 = vertexList[0];
p2 = vertexList[1]; p2 = vertexList[1];
p3 = vertexList[2]; p3 = vertexList[2];
}
#endif
color = PreMultiplyAlpha(color); color = PreMultiplyAlpha(color);
DqnV2i max = DqnV2i_2f(DQN_MAX(DQN_MAX(p1.x, p2.x), p3.x), DqnV2i max = DqnV2i_2f(DQN_MAX(DQN_MAX(p1.x, p2.x), p3.x),
DQN_MAX(DQN_MAX(p1.y, p2.y), p3.y)); DQN_MAX(DQN_MAX(p1.y, p2.y), p3.y));
DqnV2i min = DqnV2i_2f(DQN_MIN(DQN_MIN(p1.x, p2.x), p3.x), DqnV2i min = DqnV2i_2f(DQN_MIN(DQN_MIN(p1.x, p2.x), p3.x),
DQN_MIN(DQN_MIN(p1.y, p2.y), p3.y)); DQN_MIN(DQN_MIN(p1.y, p2.y), p3.y));
min.x = DQN_MAX(min.x, 0); min.x = DQN_MAX(min.x, 0);
min.y = DQN_MAX(min.y, 0); min.y = DQN_MAX(min.y, 0);
max.x = DQN_MIN(max.x, renderBuffer->width - 1); max.x = DQN_MIN(max.x, renderBuffer->width - 1);
max.y = DQN_MIN(max.y, renderBuffer->height - 1); max.y = DQN_MIN(max.y, renderBuffer->height - 1);
#if 1
DrawLine(renderBuffer, DqnV2i_2i(min.x, min.y), DqnV2i_2i(min.x, max.y), color);
DrawLine(renderBuffer, DqnV2i_2i(min.x, max.y), DqnV2i_2i(max.x, max.y), color);
DrawLine(renderBuffer, DqnV2i_2i(max.x, max.y), DqnV2i_2i(max.x, min.y), color);
DrawLine(renderBuffer, DqnV2i_2i(max.x, min.y), DqnV2i_2i(min.x, min.y), color);
#endif
/* /*
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// Rearranging the Determinant // Rearranging the Determinant
@ -350,12 +340,6 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
determine whether a point lies on the line, or is to the left or right of determine whether a point lies on the line, or is to the left or right of
a the line. a the line.
Then you can imagine if we iterate over the triangle vertexes, 2 at at
time and a last point P, being the point we want to test if it's inside
the triangle, then if the point is considered to lie on the side of the
line forming the interior of the triangle for all 3 vertexes then the
point is inside the triangle. We can do this using the determinant.
First forming a 3x3 matrix of our terms with a, b being from the triangle First forming a 3x3 matrix of our terms with a, b being from the triangle
and test point c, we can derive a 2x2 matrix by subtracting the 1st and test point c, we can derive a 2x2 matrix by subtracting the 1st
column from the 2nd and 1st column from the third. column from the 2nd and 1st column from the third.
@ -491,41 +475,43 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
signedArea3 += signedArea3DeltaY; signedArea3 += signedArea3DeltaY;
} }
#if 1 if (DR_DEBUG)
{
// Draw Bounding box
{
DrawLine(renderBuffer, DqnV2i_2i(min.x, min.y), DqnV2i_2i(min.x, max.y), color);
DrawLine(renderBuffer, DqnV2i_2i(min.x, max.y), DqnV2i_2i(max.x, max.y), color);
DrawLine(renderBuffer, DqnV2i_2i(max.x, max.y), DqnV2i_2i(max.x, min.y), color);
DrawLine(renderBuffer, DqnV2i_2i(max.x, min.y), DqnV2i_2i(min.x, min.y), color);
}
// Draw Triangle Coordinate Basis
{ {
DqnV2 xAxis = DqnV2_2f(cosf(rotation), sinf(rotation)) * scale.x; DqnV2 xAxis = DqnV2_2f(cosf(rotation), sinf(rotation)) * scale.x;
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x) * scale.y; DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x) * scale.y;
DqnV2 vertexList[3] = {p1, p2, p3};
DqnRect bounds = {};
bounds.min = vertexList[0];
bounds.max = vertexList[0];
for (i32 i = 1; i < DQN_ARRAY_COUNT(vertexList); i++)
{
const DqnV2 p = vertexList[i];
bounds.min = DqnV2_2f(DQN_MIN(p.x, bounds.min.x),
DQN_MIN(p.y, bounds.min.y));
bounds.max = DqnV2_2f(DQN_MAX(p.x, bounds.max.x),
DQN_MAX(p.y, bounds.max.y));
}
DqnV2 boundsDim = DqnRect_GetSizeV2(bounds);
DqnV2 origin = DqnV2_2f(bounds.min.x + (anchor.x * boundsDim.w),
bounds.min.y + (anchor.y * boundsDim.h));
DqnV4 coordSysColor = DqnV4_4f(0, 255, 255, 255); DqnV4 coordSysColor = DqnV4_4f(0, 255, 255, 255);
i32 axisLen = 50; i32 axisLen = 50;
DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(xAxis * axisLen), coordSysColor); DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(xAxis * axisLen), coordSysColor);
DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(yAxis * axisLen), coordSysColor); DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(yAxis * axisLen), coordSysColor);
} }
#endif
// Draw axis point
{
DqnV4 green = DqnV4_4f(0, 255, 0, 255);
DqnV4 blue = DqnV4_4f(0, 0, 255, 255);
DqnV4 purple = DqnV4_4f(255, 0, 255, 255);
DrawRectangle(renderBuffer, p1 - DqnV2_1f(5), p1 + DqnV2_1f(5), green);
DrawRectangle(renderBuffer, p2 - DqnV2_1f(5), p2 + DqnV2_1f(5), blue);
DrawRectangle(renderBuffer, p3 - DqnV2_1f(5), p3 + DqnV2_1f(5), purple);
}
}
} }
FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer, FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
DqnV2 min, DqnV2 max, DqnV4 color, DqnV2 min, DqnV2 max, DqnV4 color,
const DqnV2 scale = DqnV2_1f(1.0f), const DqnV2 scale, const f32 rotation,
const f32 rotation = 0, const DqnV2 anchor)
const DqnV2 anchor = DqnV2_1f(0.5f))
{ {
// TODO(doyle): Do edge test for quads // TODO(doyle): Do edge test for quads
if (rotation > 0) if (rotation > 0)
@ -562,7 +548,6 @@ FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
DqnRect clippedRect = DqnRect_ClipRect(rect, clip); DqnRect clippedRect = DqnRect_ClipRect(rect, clip);
DqnV2 clippedSize = DqnRect_GetSizeV2(clippedRect); DqnV2 clippedSize = DqnRect_GetSizeV2(clippedRect);
DebugPushText(renderBuffer, "ClippedSized: %5.2f, %5.2f", clippedSize.w, clippedSize.h);
for (i32 y = 0; y < clippedSize.w; y++) for (i32 y = 0; y < clippedSize.w; y++)
{ {
i32 bufferY = (i32)clippedRect.min.y + y; i32 bufferY = (i32)clippedRect.min.y + y;
@ -622,9 +607,7 @@ FILE_SCOPE void BitmapFontCreate(const PlatformAPI api,
stbtt_fontinfo fontInfo = {}; stbtt_fontinfo fontInfo = {};
DQN_ASSERT(stbtt_InitFont(&fontInfo, fontBuf, 0) != 0); DQN_ASSERT(stbtt_InitFont(&fontInfo, fontBuf, 0) != 0);
#if DR_DEBUG if (DR_DEBUG) DQN_ASSERT(stbtt_GetNumberOfFonts(fontBuf) == 1);
DQN_ASSERT(stbtt_GetNumberOfFonts(fontBuf) == 1);
#endif
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Pack font data to bitmap // Pack font data to bitmap
@ -806,12 +789,23 @@ void DebugDisplayMemBuffer(PlatformRenderBuffer *const renderBuffer,
debugP->y += globalDebug.displayYOffset; debugP->y += globalDebug.displayYOffset;
} }
void DebugUpdate(PlatformRenderBuffer *const renderBuffer, void DebugUpdate(DRState *const state, PlatformRenderBuffer *const renderBuffer,
PlatformInput *const input, PlatformMemory *const memory) PlatformInput *const input, PlatformMemory *const memory)
{ {
#ifdef DR_DEBUG if (DR_DEBUG)
{
DRDebug *const debug = &globalDebug; DRDebug *const debug = &globalDebug;
if (input->executableReloaded || !memory->isInit)
{
debug->font = &state->font;
debug->displayYOffset = -(i32)(state->font.sizeInPt + 0.5f);
debug->displayP =
DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset);
DQN_ASSERT(globalDebug.displayYOffset < 0);
debug->renderBuffer = renderBuffer;
}
debug->totalSetPixels += debug->setPixelsPerFrame; debug->totalSetPixels += debug->setPixelsPerFrame;
debug->totalSetPixels = DQN_MAX(0, debug->totalSetPixels); debug->totalSetPixels = DQN_MAX(0, debug->totalSetPixels);
@ -819,7 +813,7 @@ void DebugUpdate(PlatformRenderBuffer *const renderBuffer,
{ {
char str[128] = {}; char str[128] = {};
Dqn_sprintf(str, "%s: %'lld", "TotalSetPixels", debug->totalSetPixels); Dqn_sprintf(str, "%s: %'lld", "TotalSetPixels", debug->totalSetPixels);
DrawText(renderBuffer, *debug->font, debug->displayP, str); DrawText(debug->renderBuffer, *debug->font, debug->displayP, str);
debug->displayP.y += globalDebug.displayYOffset; debug->displayP.y += globalDebug.displayYOffset;
} }
@ -827,22 +821,22 @@ void DebugUpdate(PlatformRenderBuffer *const renderBuffer,
{ {
char str[128] = {}; char str[128] = {};
Dqn_sprintf(str, "%s: %'lld", "SetPixelsPerFrame", debug->setPixelsPerFrame); Dqn_sprintf(str, "%s: %'lld", "SetPixelsPerFrame", debug->setPixelsPerFrame);
DrawText(renderBuffer, *debug->font, debug->displayP, str); DrawText(debug->renderBuffer, *debug->font, debug->displayP, str);
debug->displayP.y += globalDebug.displayYOffset; debug->displayP.y += globalDebug.displayYOffset;
} }
// memory // memory
{ {
DebugDisplayMemBuffer(renderBuffer, "PermBuffer", DebugDisplayMemBuffer(debug->renderBuffer, "PermBuffer",
&memory->permanentBuffer, &debug->displayP, *debug->font); &memory->permanentBuffer, &debug->displayP, *debug->font);
DebugDisplayMemBuffer(renderBuffer, "TransBuffer", DebugDisplayMemBuffer(debug->renderBuffer, "TransBuffer",
&memory->transientBuffer, &debug->displayP, *debug->font); &memory->transientBuffer, &debug->displayP, *debug->font);
} }
debug->setPixelsPerFrame = 0; debug->setPixelsPerFrame = 0;
debug->displayP = debug->displayP =
DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset); DqnV2_2i(0, debug->renderBuffer->height + globalDebug.displayYOffset);
#endif }
} }
extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer, extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
@ -865,20 +859,10 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
&memory->transientBuffer)); &memory->transientBuffer));
} }
#ifdef DR_DEBUG
if (input->executableReloaded || !memory->isInit)
{
globalDebug.font = &state->font;
globalDebug.displayYOffset = -(i32)(state->font.sizeInPt + 0.5f);
globalDebug.displayP =
DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset);
DQN_ASSERT(globalDebug.displayYOffset < 0);
}
#endif
ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 0, 0)); ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 0, 0));
DqnV4 colorRed = DqnV4_4i(50, 0, 0, 255); DqnV4 colorRed = DqnV4_4i(50, 0, 0, 255);
DqnV2i bufferMidP = DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f); DqnV2i bufferMidP =
DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
i32 boundsOffset = 100; i32 boundsOffset = 100;
DqnV2 t0[3] = {DqnV2_2i(10, 70), DqnV2_2i(50, 160), DqnV2_2i(70, 80)}; DqnV2 t0[3] = {DqnV2_2i(10, 70), DqnV2_2i(50, 160), DqnV2_2i(70, 80)};
@ -889,41 +873,24 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
DqnV2_2i(bufferMidP.w, renderBuffer->height - boundsOffset), DqnV2_2i(bufferMidP.w, renderBuffer->height - boundsOffset),
DqnV2_2i(renderBuffer->width - boundsOffset, boundsOffset)}; DqnV2_2i(renderBuffer->width - boundsOffset, boundsOffset)};
f32 minX = (f32)(renderBuffer->width - 1); #if 0
f32 maxX = 0;
for (i32 i = 0; i < DQN_ARRAY_COUNT(t3); i++)
{
// t3[i].x += input->deltaForFrame * 2.0f;
minX = DQN_MIN(t3[i].x, minX);
maxX = DQN_MAX(t3[i].x, maxX);
}
if (minX >= renderBuffer->width - 1)
{
f32 triangleWidth = maxX - minX;
for (i32 i = 0; i < DQN_ARRAY_COUNT(t3); i++)
{
t3[i].x -= (minX + triangleWidth);
}
}
DrawTriangle(renderBuffer, t0[0], t0[1], t0[2], colorRed); DrawTriangle(renderBuffer, t0[0], t0[1], t0[2], colorRed);
DrawTriangle(renderBuffer, t1[0], t1[1], t1[2], colorRed); DrawTriangle(renderBuffer, t1[0], t1[1], t1[2], colorRed);
DrawTriangle(renderBuffer, t2[0], t2[1], t2[2], colorRed); DrawTriangle(renderBuffer, t2[0], t2[1], t2[2], colorRed);
#endif
DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 190); DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 190);
LOCAL_PERSIST f32 rotation = 0; LOCAL_PERSIST f32 rotation = 0;
rotation += input->deltaForFrame * 0.25f; rotation += input->deltaForFrame * 0.25f;
DqnV2 scale = DqnV2_1f(1.0f); DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA,
DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA, scale, DqnV2_1f(1.0f), rotation, DqnV2_2f(0.33f, 0.33f));
rotation, DqnV2_1f(0.5f));
DrawRectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f), colorRed, DrawRectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f),
DqnV2_1f(1.0f), rotation); colorRed, DqnV2_1f(1.0f), rotation);
DqnV2 fontP = DqnV2_2i(200, 180); DqnV2 fontP = DqnV2_2i(200, 180);
DrawText(renderBuffer, state->font, fontP, "hello world!"); DrawText(renderBuffer, state->font, fontP, "hello world!");
DrawBitmap(renderBuffer, &state->bitmap, 300, 250); // DrawBitmap(renderBuffer, &state->bitmap, 300, 250);
DebugUpdate(renderBuffer, input, memory); DebugUpdate(state, renderBuffer, input, memory);
} }

View File

@ -2282,25 +2282,24 @@ DQN_FILE_SCOPE DqnRect DqnRect_Init(DqnV2 origin, DqnV2 size)
DQN_FILE_SCOPE void DqnRect_GetSize2f(DqnRect rect, f32 *width, f32 *height) DQN_FILE_SCOPE void DqnRect_GetSize2f(DqnRect rect, f32 *width, f32 *height)
{ {
*width = DQN_ABS(rect.max.x - rect.min.x); *width = rect.max.x - rect.min.x;
*height = DQN_ABS(rect.max.y - rect.min.y); *height = rect.max.y - rect.min.y;
} }
DQN_FILE_SCOPE void DqnRect_GetSize2i(DqnRect rect, i32 *width, i32 *height) DQN_FILE_SCOPE void DqnRect_GetSize2i(DqnRect rect, i32 *width, i32 *height)
{ {
*width = (i32)DQN_ABS(rect.max.x - rect.min.x); *width = (i32)(rect.max.x - rect.min.x);
*height = (i32)DQN_ABS(rect.max.y - rect.min.y); *height = (i32)(rect.max.y - rect.min.y);
} }
DQN_FILE_SCOPE DqnV2 DqnRect_GetSizeV2(DqnRect rect) DQN_FILE_SCOPE DqnV2 DqnRect_GetSizeV2(DqnRect rect)
{ {
f32 width = DQN_ABS(rect.max.x - rect.min.x); f32 width = rect.max.x - rect.min.x;
f32 height = DQN_ABS(rect.max.y - rect.min.y); f32 height = rect.max.y - rect.min.y;
DqnV2 result = DqnV2_2f(width, height); DqnV2 result = DqnV2_2f(width, height);
return result; return result;
} }
DQN_FILE_SCOPE DqnV2 DqnRect_GetCentre(DqnRect rect) DQN_FILE_SCOPE DqnV2 DqnRect_GetCentre(DqnRect rect)
{ {
f32 sumX = rect.min.x + rect.max.x; f32 sumX = rect.min.x + rect.max.x;