Add proper rectangle rotation
This commit is contained in:
parent
3ec64da44c
commit
75f23b6d66
@ -53,7 +53,6 @@ typedef struct DRDebug
|
|||||||
|
|
||||||
u64 setPixelsPerFrame;
|
u64 setPixelsPerFrame;
|
||||||
u64 totalSetPixels;
|
u64 totalSetPixels;
|
||||||
|
|
||||||
} DRDebug;
|
} DRDebug;
|
||||||
|
|
||||||
FILE_SCOPE inline DqnV4 PreMultiplyAlpha(DqnV4 color)
|
FILE_SCOPE inline DqnV4 PreMultiplyAlpha(DqnV4 color)
|
||||||
@ -270,44 +269,152 @@ FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_SCOPE void TransformVertexes(const DqnV2 origin, DqnV2 *const vertexList,
|
FILE_SCOPE void TransformPoints(const DqnV2 origin, DqnV2 *const pList,
|
||||||
const i32 numVertexes, const DqnV2 scale,
|
const i32 numP, const DqnV2 scale,
|
||||||
const f32 rotation)
|
const f32 rotation)
|
||||||
{
|
{
|
||||||
if (!vertexList || numVertexes == 0) return;
|
if (!pList || numP == 0) return;
|
||||||
|
|
||||||
DqnV2 xAxis = (DqnV2_2f(cosf(rotation), sinf(rotation)));
|
DqnV2 xAxis = (DqnV2_2f(cosf(rotation), sinf(rotation)));
|
||||||
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x);
|
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x);
|
||||||
xAxis *= scale.x;
|
xAxis *= scale.x;
|
||||||
yAxis *= scale.y;
|
yAxis *= scale.y;
|
||||||
|
|
||||||
for (i32 i = 0; i < numVertexes; i++)
|
for (i32 i = 0; i < numP; i++)
|
||||||
{
|
{
|
||||||
DqnV2 p = vertexList[i];
|
DqnV2 p = pList[i];
|
||||||
vertexList[i] = origin + (xAxis * p.x) + (yAxis * p.y);
|
pList[i] = origin + (xAxis * p.x) + (yAxis * p.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = DqnV2_1f(1.0f),
|
||||||
const f32 rotation = 0,
|
f32 rotation = 0,
|
||||||
const DqnV2 anchor = DqnV2_1f(0.5f));
|
const DqnV2 anchor = DqnV2_1f(0.5f))
|
||||||
|
{
|
||||||
|
// TODO(doyle): Do edge test for quads
|
||||||
|
#if 0
|
||||||
|
if (rotation > 0)
|
||||||
|
{
|
||||||
|
DqnV2 p1 = min;
|
||||||
|
DqnV2 p2 = DqnV2_2f(max.x, min.y);
|
||||||
|
DqnV2 p3 = max;
|
||||||
|
DqnV2 p4 = DqnV2_2f(min.x, max.y);
|
||||||
|
DrawTriangle(renderBuffer, p1, p2, p3, color, scale, rotation, anchor);
|
||||||
|
DrawTriangle(renderBuffer, p1, p3, p4, color, scale, rotation, anchor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Transform vertexes
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
DqnV2 dim = DqnV2_2f(max.x - min.x, max.y - min.y);
|
||||||
|
DQN_ASSERT(dim.w > 0 && dim.h > 0);
|
||||||
|
DqnV2 initOrigin = DqnV2_2f(min.x + (anchor.x * dim.w), min.y + (anchor.y * dim.h));
|
||||||
|
|
||||||
|
DqnV2 p1 = min - initOrigin;
|
||||||
|
DqnV2 p2 = DqnV2_2f(max.x, min.y) - initOrigin;
|
||||||
|
DqnV2 p3 = max - initOrigin;
|
||||||
|
DqnV2 p4 = DqnV2_2f(min.x, max.y) - initOrigin;
|
||||||
|
DqnV2 pList[] = {p1, p2, p3, p4};
|
||||||
|
|
||||||
|
TransformPoints(initOrigin, pList, DQN_ARRAY_COUNT(pList), scale, rotation);
|
||||||
|
min = pList[0];
|
||||||
|
max = pList[0];
|
||||||
|
for (i32 i = 1; i < DQN_ARRAY_COUNT(pList); i++)
|
||||||
|
{
|
||||||
|
DqnV2 checkP = pList[i];
|
||||||
|
min.x = DQN_MIN(min.x, checkP.x);
|
||||||
|
min.y = DQN_MIN(min.y, checkP.y);
|
||||||
|
max.x = DQN_MAX(max.x, checkP.x);
|
||||||
|
max.y = DQN_MAX(max.y, checkP.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
color = PreMultiplyAlpha(color);
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Clip Drawing Space
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
DqnRect rect = DqnRect_4f(min.x, min.y, max.x, max.y);
|
||||||
|
DqnRect clip = DqnRect_4i(0, 0, renderBuffer->width, renderBuffer->height);
|
||||||
|
|
||||||
|
DqnRect clippedRect = DqnRect_ClipRect(rect, clip);
|
||||||
|
DqnV2 clippedSize = DqnRect_GetSizeV2(clippedRect);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Render
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
if (rotation != 0)
|
||||||
|
{
|
||||||
|
for (i32 y = 0; y < clippedSize.w; y++)
|
||||||
|
{
|
||||||
|
i32 bufferY = (i32)clippedRect.min.y + y;
|
||||||
|
for (i32 x = 0; x < clippedSize.h; x++)
|
||||||
|
{
|
||||||
|
i32 bufferX = (i32)clippedRect.min.x + x;
|
||||||
|
bool pIsInside = true;
|
||||||
|
|
||||||
|
for (i32 pIndex = 0; pIndex < DQN_ARRAY_COUNT(pList);
|
||||||
|
pIndex++)
|
||||||
|
{
|
||||||
|
DqnV2 origin = pList[pIndex];
|
||||||
|
DqnV2 line = pList[(pIndex + 1) % DQN_ARRAY_COUNT(pList)] - origin;
|
||||||
|
DqnV2 axis = DqnV2_2i(bufferX, bufferY) - origin;
|
||||||
|
f32 dotResult = DqnV2_Dot(line, axis);
|
||||||
|
|
||||||
|
if (dotResult < 0)
|
||||||
|
{
|
||||||
|
pIsInside = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pIsInside) SetPixel(renderBuffer, bufferX, bufferY, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i32 y = 0; y < clippedSize.w; y++)
|
||||||
|
{
|
||||||
|
i32 bufferY = (i32)clippedRect.min.y + y;
|
||||||
|
for (i32 x = 0; x < clippedSize.h; x++)
|
||||||
|
{
|
||||||
|
i32 bufferX = (i32)clippedRect.min.x + x;
|
||||||
|
SetPixel(renderBuffer, bufferX, bufferY, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DR_DEBUG)
|
||||||
|
{
|
||||||
|
// Draw Bounding box
|
||||||
|
{
|
||||||
|
DrawLine(renderBuffer, DqnV2i_2f(min.x, min.y), DqnV2i_2f(min.x, max.y), color);
|
||||||
|
DrawLine(renderBuffer, DqnV2i_2f(min.x, max.y), DqnV2i_2f(max.x, max.y), color);
|
||||||
|
DrawLine(renderBuffer, DqnV2i_2f(max.x, max.y), DqnV2i_2f(max.x, min.y), color);
|
||||||
|
DrawLine(renderBuffer, DqnV2i_2f(max.x, min.y), DqnV2i_2f(min.x, min.y), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw rotating outline
|
||||||
|
if (rotation > 0)
|
||||||
|
{
|
||||||
|
DqnV4 green = DqnV4_4f(0, 255, 0, 255);
|
||||||
|
DrawLine(renderBuffer, DqnV2i_V2(pList[0]), DqnV2i_V2(pList[1]), green);
|
||||||
|
DrawLine(renderBuffer, DqnV2i_V2(pList[1]), DqnV2i_V2(pList[2]), green);
|
||||||
|
DrawLine(renderBuffer, DqnV2i_V2(pList[2]), DqnV2i_V2(pList[3]), green);
|
||||||
|
DrawLine(renderBuffer, DqnV2i_V2(pList[3]), DqnV2i_V2(pList[0]), green);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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.33f))
|
DqnV2 anchor = DqnV2_1f(0.33f))
|
||||||
{
|
{
|
||||||
f32 area2Times = ((p2.x - p1.x) * (p2.y + p1.y)) +
|
|
||||||
((p3.x - p2.x) * (p3.y + p2.y)) +
|
|
||||||
((p1.x - p3.x) * (p1.y + p3.y));
|
|
||||||
if (area2Times > 0)
|
|
||||||
{
|
|
||||||
// Clockwise swap any point to make it clockwise
|
|
||||||
DQN_SWAP(DqnV2, p2, p3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform vertexes
|
// Transform vertexes
|
||||||
DqnV2 p1p2 = p2 - p1;
|
DqnV2 p1p2 = p2 - p1;
|
||||||
DqnV2 p1p3 = p3 - p1;
|
DqnV2 p1p3 = p3 - p1;
|
||||||
@ -315,12 +422,11 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
|||||||
DqnV2 p1p3Anchored = p1p3 * anchor;
|
DqnV2 p1p3Anchored = p1p3 * anchor;
|
||||||
|
|
||||||
DqnV2 origin = p1 + p1p2Anchored + p1p3Anchored;
|
DqnV2 origin = p1 + p1p2Anchored + p1p3Anchored;
|
||||||
DqnV2 vertexList[3] = {p1 - origin, p2 - origin, p3 - origin};
|
DqnV2 pList[3] = {p1 - origin, p2 - origin, p3 - origin};
|
||||||
TransformVertexes(origin, vertexList, DQN_ARRAY_COUNT(vertexList), scale,
|
TransformPoints(origin, pList, DQN_ARRAY_COUNT(pList), scale, rotation);
|
||||||
rotation);
|
p1 = pList[0];
|
||||||
p1 = vertexList[0];
|
p2 = pList[1];
|
||||||
p2 = vertexList[1];
|
p3 = pList[2];
|
||||||
p3 = vertexList[2];
|
|
||||||
|
|
||||||
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),
|
||||||
@ -432,6 +538,15 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
|||||||
BaryCentricB(P) = (SignedArea(P) with vertex C and A)/SignedArea(with the orig triangle vertex)
|
BaryCentricB(P) = (SignedArea(P) with vertex C and A)/SignedArea(with the orig triangle vertex)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
f32 area2Times = ((p2.x - p1.x) * (p2.y + p1.y)) +
|
||||||
|
((p3.x - p2.x) * (p3.y + p2.y)) +
|
||||||
|
((p1.x - p3.x) * (p1.y + p3.y));
|
||||||
|
if (area2Times > 0)
|
||||||
|
{
|
||||||
|
// Clockwise swap any point to make it clockwise
|
||||||
|
DQN_SWAP(DqnV2, p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
const DqnV2 a = p1;
|
const DqnV2 a = p1;
|
||||||
const DqnV2 b = p2;
|
const DqnV2 b = p2;
|
||||||
const DqnV2 c = p3;
|
const DqnV2 c = p3;
|
||||||
@ -508,58 +623,8 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
|
FILE_SCOPE void ClearRenderBuffer(PlatformRenderBuffer *const renderBuffer,
|
||||||
DqnV2 min, DqnV2 max, DqnV4 color,
|
DqnV3 color)
|
||||||
const DqnV2 scale, const f32 rotation,
|
|
||||||
const DqnV2 anchor)
|
|
||||||
{
|
|
||||||
// TODO(doyle): Do edge test for quads
|
|
||||||
if (rotation > 0)
|
|
||||||
{
|
|
||||||
DqnV2 p1 = min;
|
|
||||||
DqnV2 p2 = DqnV2_2f(max.x, min.y);
|
|
||||||
DqnV2 p3 = max;
|
|
||||||
DqnV2 p4 = DqnV2_2f(min.x, max.y);
|
|
||||||
DrawTriangle(renderBuffer, p1, p2, p3, color, scale, rotation, anchor);
|
|
||||||
DrawTriangle(renderBuffer, p1, p3, p4, color, scale, rotation, anchor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform vertexes
|
|
||||||
{
|
|
||||||
DqnV2 dim = DqnV2_2f(max.x - min.x, max.y - min.y);
|
|
||||||
DQN_ASSERT(dim.w > 0 && dim.h > 0);
|
|
||||||
DqnV2 origin = DqnV2_2f(min.x + (anchor.x * dim.w), min.y + (anchor.y * dim.h));
|
|
||||||
|
|
||||||
DqnV2 p1 = min - origin;
|
|
||||||
DqnV2 p2 = max - origin;
|
|
||||||
DqnV2 vertexList[4] = {p1, p2};
|
|
||||||
TransformVertexes(origin, vertexList, DQN_ARRAY_COUNT(vertexList),
|
|
||||||
scale, rotation);
|
|
||||||
min = vertexList[0];
|
|
||||||
max = vertexList[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
color = PreMultiplyAlpha(color);
|
|
||||||
|
|
||||||
DqnRect rect = DqnRect_4f(min.x, min.y, max.x, max.y);
|
|
||||||
DqnRect clip = DqnRect_4i(0, 0, renderBuffer->width, renderBuffer->height);
|
|
||||||
|
|
||||||
DqnRect clippedRect = DqnRect_ClipRect(rect, clip);
|
|
||||||
DqnV2 clippedSize = DqnRect_GetSizeV2(clippedRect);
|
|
||||||
|
|
||||||
for (i32 y = 0; y < clippedSize.w; y++)
|
|
||||||
{
|
|
||||||
i32 bufferY = (i32)clippedRect.min.y + y;
|
|
||||||
for (i32 x = 0; x < clippedSize.h; x++)
|
|
||||||
{
|
|
||||||
i32 bufferX = (i32)clippedRect.min.x + x;
|
|
||||||
SetPixel(renderBuffer, bufferX, bufferY, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE_SCOPE void ClearRenderBuffer(PlatformRenderBuffer *const renderBuffer, DqnV3 color)
|
|
||||||
{
|
{
|
||||||
if (!renderBuffer) return;
|
if (!renderBuffer) return;
|
||||||
|
|
||||||
@ -828,9 +893,11 @@ void DebugUpdate(DRState *const state, PlatformRenderBuffer *const renderBuffer,
|
|||||||
// memory
|
// memory
|
||||||
{
|
{
|
||||||
DebugDisplayMemBuffer(debug->renderBuffer, "PermBuffer",
|
DebugDisplayMemBuffer(debug->renderBuffer, "PermBuffer",
|
||||||
&memory->permanentBuffer, &debug->displayP, *debug->font);
|
&memory->permanentBuffer, &debug->displayP,
|
||||||
|
*debug->font);
|
||||||
DebugDisplayMemBuffer(debug->renderBuffer, "TransBuffer",
|
DebugDisplayMemBuffer(debug->renderBuffer, "TransBuffer",
|
||||||
&memory->transientBuffer, &debug->displayP, *debug->font);
|
&memory->transientBuffer, &debug->displayP,
|
||||||
|
*debug->font);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug->setPixelsPerFrame = 0;
|
debug->setPixelsPerFrame = 0;
|
||||||
@ -860,7 +927,7 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(180, 0, 0, 255);
|
||||||
DqnV2i bufferMidP =
|
DqnV2i bufferMidP =
|
||||||
DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
|
DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
|
||||||
i32 boundsOffset = 100;
|
i32 boundsOffset = 100;
|
||||||
@ -873,23 +940,23 @@ 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)};
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
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
|
#endif
|
||||||
|
|
||||||
DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 190);
|
DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 64);
|
||||||
LOCAL_PERSIST f32 rotation = 0;
|
LOCAL_PERSIST f32 rotation = 0;
|
||||||
rotation += input->deltaForFrame * 0.25f;
|
rotation += input->deltaForFrame * 0.25f;
|
||||||
DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA,
|
DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA,
|
||||||
DqnV2_1f(1.0f), rotation, DqnV2_2f(0.33f, 0.33f));
|
DqnV2_1f(1.0f), rotation, DqnV2_2f(0.33f, 0.33f));
|
||||||
|
|
||||||
DrawRectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f),
|
DrawRectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f),
|
||||||
colorRed, DqnV2_1f(1.0f), rotation);
|
colorRed, DqnV2_1f(1.0f), 45 + 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(state, renderBuffer, input, memory);
|
DebugUpdate(state, renderBuffer, input, memory);
|
||||||
|
Loading…
Reference in New Issue
Block a user