Add temp fix for model gaps in tri rasterisation
This commit is contained in:
parent
237e73253a
commit
e922efb897
@ -11,42 +11,15 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef struct WavefrontModelFace
|
||||
{
|
||||
DqnArray<i32> vertexArray;
|
||||
DqnArray<i32> textureArray;
|
||||
DqnArray<i32> normalArray;
|
||||
} WavefrontModelFace;
|
||||
|
||||
FILE_SCOPE inline WavefrontModelFace ObjWavefrontModelFaceInit(i32 capacity = 3)
|
||||
{
|
||||
WavefrontModelFace result = {};
|
||||
DQN_ASSERT(DqnArray_Init(&result.vertexArray, capacity));
|
||||
DQN_ASSERT(DqnArray_Init(&result.vertexArray, capacity));
|
||||
DQN_ASSERT(DqnArray_Init(&result.textureArray, capacity));
|
||||
DQN_ASSERT(DqnArray_Init(&result.normalArray, capacity));
|
||||
DQN_ASSERT(DqnArray_Init(&result.normalArray, capacity));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct WavefrontModel
|
||||
{
|
||||
// TODO(doyle): Fixed size
|
||||
char *groupName[16];
|
||||
i32 groupNameIndex;
|
||||
i32 groupSmoothing;
|
||||
|
||||
DqnArray<WavefrontModelFace> faces;
|
||||
} WavefrontModel;
|
||||
|
||||
typedef struct WavefrontObj
|
||||
{
|
||||
DqnArray<DqnV4> geometryArray;
|
||||
DqnArray<DqnV3> texUVArray;
|
||||
DqnArray<DqnV3> normalArray;
|
||||
|
||||
WavefrontModel model;
|
||||
} WavefrontObj;
|
||||
|
||||
FILE_SCOPE bool ObjWaveFrontInit(WavefrontObj *const obj, const i32 vertexInitCapacity = 1000,
|
||||
const i32 faceInitCapacity = 200)
|
||||
{
|
||||
@ -147,7 +120,7 @@ FILE_SCOPE bool ObjWavefrontLoad(const PlatformAPI api, PlatformMemory *const me
|
||||
}
|
||||
|
||||
i32 f32Len = (i32)((size_t)scan - (size_t)f32StartPtr);
|
||||
v4.e[vIndex++] = Dqn_StrToF32(f32StartPtr, f32Len);
|
||||
v4.e[vIndex++] = (f32)atof(f32StartPtr); // Dqn_StrToF32(f32StartPtr, f32Len);
|
||||
DQN_ASSERT(vIndex < DQN_ARRAY_COUNT(v4.e));
|
||||
|
||||
while (scan && (*scan == ' ' || *scan == '\n')) scan++;
|
||||
@ -1480,7 +1453,6 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||
}
|
||||
|
||||
DTR_DEBUG_TIMED_FUNCTION();
|
||||
LOCAL_PERSIST WavefrontObj waveObj = {};
|
||||
if (!memory->isInit)
|
||||
{
|
||||
TestStrToF32Converter();
|
||||
@ -1504,80 +1476,72 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||
DqnTempMemStack tmp = DqnMemStack_BeginTempRegion(&memory->permMemStack);
|
||||
BitmapLoad(input->api, &test, "byte_read_check.bmp",
|
||||
&memory->transMemStack);
|
||||
int x = 5;
|
||||
DqnMemStack_EndTempRegion(tmp);
|
||||
|
||||
#if 0
|
||||
DQN_ASSERT(ObjWavefrontLoad(input->api, memory, "african_head.obj", &waveObj));
|
||||
#endif
|
||||
DQN_ASSERT(ObjWavefrontLoad(input->api, memory, "african_head.obj", &state->obj));
|
||||
}
|
||||
DTRRender_Clear(renderBuffer, DqnV3_3f(0, 0, 0));
|
||||
DTRRender_Clear(renderBuffer, DqnV3_3f(0.0f, 0.0f, 0.0f));
|
||||
|
||||
#if 1
|
||||
DqnV4 modelCol = DqnV4_4f(1, 1, 1, 1);
|
||||
for (i32 i = 0; i < waveObj.model.faces.count; i++)
|
||||
const DqnV3 LIGHT = DqnV3_3i(0, 0, -1);
|
||||
const f32 MODEL_SCALE = DQN_MIN(renderBuffer->width, renderBuffer->height) * 0.5f;
|
||||
WavefrontObj *const waveObj = &state->obj;
|
||||
DqnV2 modelP = DqnV2_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
|
||||
|
||||
for (i32 i = 0; i < waveObj->model.faces.count; i++)
|
||||
{
|
||||
WavefrontModelFace face = waveObj.model.faces.data[i];
|
||||
WavefrontModelFace face = waveObj->model.faces.data[i];
|
||||
DQN_ASSERT(face.vertexArray.count == 3);
|
||||
|
||||
#if 0
|
||||
i32 vertAIndex = face.vertexArray.data[0];
|
||||
i32 vertBIndex = face.vertexArray.data[1];
|
||||
i32 vertCIndex = face.vertexArray.data[2];
|
||||
|
||||
DqnV4 vertA = waveObj.geometryArray.data[vertAIndex];
|
||||
DqnV4 vertB = waveObj.geometryArray.data[vertBIndex];
|
||||
DqnV4 vertC = waveObj.geometryArray.data[vertCIndex];
|
||||
DqnV4 vertA = waveObj->geometryArray.data[vertAIndex];
|
||||
DqnV4 vertB = waveObj->geometryArray.data[vertBIndex];
|
||||
DqnV4 vertC = waveObj->geometryArray.data[vertCIndex];
|
||||
|
||||
vertA.x *= (renderBuffer->width * 0.5f);
|
||||
vertA.y *= (renderBuffer->height * 0.5f);
|
||||
DqnV4 vertAB = vertB - vertA;
|
||||
DqnV4 vertAC = vertC - vertA;
|
||||
DqnV3 normal = DqnV3_Cross(vertAC.xyz, vertAB.xyz);
|
||||
|
||||
vertB.x *= (renderBuffer->width * 0.5f);
|
||||
vertB.y *= (renderBuffer->height * 0.5f);
|
||||
|
||||
vertC.x *= (renderBuffer->width * 0.5f);
|
||||
vertC.y *= (renderBuffer->height * 0.5f);
|
||||
|
||||
vertA.x += (renderBuffer->width * 0.5f);
|
||||
vertA.y += (renderBuffer->height * 0.5f);
|
||||
|
||||
vertB.x += (renderBuffer->width * 0.5f);
|
||||
vertB.y += (renderBuffer->height * 0.5f);
|
||||
|
||||
vertC.x += (renderBuffer->width * 0.5f);
|
||||
vertC.y += (renderBuffer->height * 0.5f);
|
||||
|
||||
DTRRender_Triangle(renderBuffer, vertA.xy, vertB.xy, vertC.xy, modelCol);
|
||||
#else
|
||||
const i32 NUM_VERTEXES = 3;
|
||||
for (i32 j = 0; j < NUM_VERTEXES; j++)
|
||||
f32 intensity = DqnV3_Dot(DqnV3_Normalise(normal), LIGHT);
|
||||
if (intensity > 0)
|
||||
{
|
||||
i32 vertAIndex = face.vertexArray.data[j];
|
||||
i32 vertBIndex = face.vertexArray.data[(j + 1) % NUM_VERTEXES];
|
||||
DqnV4 modelCol = DqnV4_4f(1, 1, 1, 1);
|
||||
modelCol.rgb *= intensity;
|
||||
|
||||
DqnV4 vertA = waveObj.geometryArray.data[vertAIndex];
|
||||
DqnV4 vertB = waveObj.geometryArray.data[vertBIndex];
|
||||
DqnV2 screenVertA = (vertA.xy * MODEL_SCALE) + modelP;
|
||||
DqnV2 screenVertB = (vertB.xy * MODEL_SCALE) + modelP;
|
||||
DqnV2 screenVertC = (vertC.xy * MODEL_SCALE) + modelP;
|
||||
|
||||
vertA.x = (vertA.x * (renderBuffer->width * 0.5f)) + renderBuffer->width * 0.5f;
|
||||
vertA.y = (vertA.y * (renderBuffer->height * 0.5f)) + renderBuffer->height * 0.5f;
|
||||
// TODO(doyle): Why do we need rounding here? Maybe it's because
|
||||
// I don't do any interpolation in the triangle routine for jagged
|
||||
// edges.
|
||||
screenVertA.x = (f32)(i32)(screenVertA.x + 0.5f);
|
||||
screenVertA.y = (f32)(i32)(screenVertA.y + 0.5f);
|
||||
screenVertB.x = (f32)(i32)(screenVertB.x + 0.5f);
|
||||
screenVertB.y = (f32)(i32)(screenVertB.y + 0.5f);
|
||||
screenVertC.x = (f32)(i32)(screenVertC.x + 0.5f);
|
||||
screenVertC.y = (f32)(i32)(screenVertC.y + 0.5f);
|
||||
|
||||
vertB.x = (vertB.x * (renderBuffer->width * 0.5f)) + renderBuffer->width * 0.5f;
|
||||
vertB.y = (vertB.y * (renderBuffer->height * 0.5f)) + renderBuffer->height * 0.5f;
|
||||
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(vertA.xy), DqnV2i_V2(vertB.xy), modelCol);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
DTRRender_Triangle(renderBuffer, screenVertA, screenVertB, screenVertC, modelCol);
|
||||
|
||||
#if 0
|
||||
DqnV4 wireColor = DqnV4_1f(1.0f);
|
||||
for (i32 j = 0; j < 3; j++)
|
||||
{
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(screenVertA), DqnV2i_V2(screenVertB), wireColor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
DqnV4 colorRed = DqnV4_4f(0.8f, 0, 0, 1);
|
||||
DqnV2i bufferMidP =
|
||||
DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
|
||||
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)};
|
||||
DqnV2 t1[3] = {DqnV2_2i(180, 50), DqnV2_2i(150, 1), DqnV2_2i(70, 180)};
|
||||
DqnV2 t2[3] = {DqnV2_2i(180, 150), DqnV2_2i(120, 160), DqnV2_2i(130, 180)};
|
||||
LOCAL_PERSIST DqnV2 t3[3] = {
|
||||
@ -1589,16 +1553,20 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||
DTRRender_Triangle(renderBuffer, t1[0], t1[1], t1[2], colorRed);
|
||||
DTRRender_Triangle(renderBuffer, t2[0], t2[1], t2[2], colorRed);
|
||||
|
||||
DqnV2 t4[3] = {DqnV2_2i(100, 150), DqnV2_2i(200, 150), DqnV2_2i(200, 250)};
|
||||
DqnV2 t5[3] = {DqnV2_2i(300, 150), DqnV2_2i(201, 150), DqnV2_2i(200, 250)};
|
||||
DTRRender_Triangle(renderBuffer, t4[0], t4[1], t4[2], colorRed);
|
||||
DTRRender_Triangle(renderBuffer, t5[0], t5[1], t5[2], colorRed);
|
||||
|
||||
DqnV4 colorRedHalfA = DqnV4_4f(1, 0, 0, 0.1f);
|
||||
LOCAL_PERSIST f32 rotation = 0;
|
||||
rotation += input->deltaForFrame * 0.25f;
|
||||
|
||||
#if 1
|
||||
DTRRenderTransform defaultTransform = DTRRender_DefaultTransform();
|
||||
defaultTransform.rotation = rotation + 45;
|
||||
|
||||
DTRRender_Rectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 100.0f), DqnV4_4f(0, 1.0f, 1.0f, 1.0f),
|
||||
defaultTransform);
|
||||
#endif
|
||||
|
||||
// Rotating triangle
|
||||
{
|
||||
@ -1624,8 +1592,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||
DTRRender_Bitmap(renderBuffer, &state->bitmap, bitmapP, transform, color);
|
||||
|
||||
#else
|
||||
CompAssignment(renderBuffer, input, memory);
|
||||
#endif
|
||||
// CompAssignment(renderBuffer, input, memory);
|
||||
#endif
|
||||
DTRDebug_Update(state, renderBuffer, input, memory);
|
||||
}
|
||||
|
@ -8,6 +8,32 @@ typedef void DTR_UpdateFunction(struct PlatformRenderBuffer *const renderBuffer,
|
||||
struct PlatformInput *const input,
|
||||
struct PlatformMemory *const memory);
|
||||
|
||||
typedef struct WavefrontModelFace
|
||||
{
|
||||
DqnArray<i32> vertexArray;
|
||||
DqnArray<i32> textureArray;
|
||||
DqnArray<i32> normalArray;
|
||||
} WavefrontModelFace;
|
||||
|
||||
typedef struct WavefrontModel
|
||||
{
|
||||
// TODO(doyle): Fixed size
|
||||
char *groupName[16];
|
||||
i32 groupNameIndex;
|
||||
i32 groupSmoothing;
|
||||
|
||||
DqnArray<WavefrontModelFace> faces;
|
||||
} WavefrontModel;
|
||||
|
||||
typedef struct WavefrontObj
|
||||
{
|
||||
DqnArray<DqnV4> geometryArray;
|
||||
DqnArray<DqnV3> texUVArray;
|
||||
DqnArray<DqnV3> normalArray;
|
||||
|
||||
WavefrontModel model;
|
||||
} WavefrontObj;
|
||||
|
||||
typedef struct DTRFont
|
||||
{
|
||||
u8 *bitmap;
|
||||
@ -27,7 +53,8 @@ typedef struct DTRBitmap
|
||||
|
||||
typedef struct DTRState
|
||||
{
|
||||
DTRFont font;
|
||||
DTRBitmap bitmap;
|
||||
DTRFont font;
|
||||
DTRBitmap bitmap;
|
||||
WavefrontObj obj;
|
||||
} DTRState;
|
||||
#endif
|
||||
|
@ -3,11 +3,11 @@
|
||||
|
||||
#include "dqn.h"
|
||||
#define DTR_DEBUG 1
|
||||
#ifdef DTR_DEBUG
|
||||
#if DTR_DEBUG
|
||||
#define DTR_DEBUG_RENDER 0
|
||||
|
||||
#define DTR_DEBUG_PROFILING 1
|
||||
#ifdef DTR_DEBUG_PROFILING
|
||||
#define DTR_DEBUG_PROFILING 0
|
||||
#if DTR_DEBUG_PROFILING
|
||||
#define BUILD_WITH_EASY_PROFILER 1
|
||||
#include "external/easy/profiler.h"
|
||||
|
||||
|
@ -580,7 +580,7 @@ void DTRRender_Triangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1, DqnV
|
||||
= (bx - ax)(1) = (bx - ax)
|
||||
|
||||
Then we can see that when we progress along x, we only need to change by
|
||||
the value of SignedArea by (ay - by) and similarly for y, (bx - ay)
|
||||
the value of SignedArea by (ay - by) and similarly for y, (bx - ax)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Barycentric Coordinates
|
||||
@ -632,16 +632,16 @@ void DTRRender_Triangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1, DqnV
|
||||
const DqnV2 b = p2;
|
||||
const DqnV2 c = p3;
|
||||
|
||||
DqnV2i scanP = DqnV2i_2i(min.x, min.y);
|
||||
f32 signedArea1 = ((b.x - a.x) * (scanP.y - a.y)) - ((b.y - a.y) * (scanP.x - a.x));
|
||||
DqnV2i startP = min;
|
||||
f32 signedArea1 = ((b.x - a.x) * (startP.y - a.y)) - ((b.y - a.y) * (startP.x - a.x));
|
||||
f32 signedArea1DeltaX = a.y - b.y;
|
||||
f32 signedArea1DeltaY = b.x - a.x;
|
||||
|
||||
f32 signedArea2 = ((c.x - b.x) * (scanP.y - b.y)) - ((c.y - b.y) * (scanP.x - b.x));
|
||||
f32 signedArea2 = ((c.x - b.x) * (startP.y - b.y)) - ((c.y - b.y) * (startP.x - b.x));
|
||||
f32 signedArea2DeltaX = b.y - c.y;
|
||||
f32 signedArea2DeltaY = c.x - b.x;
|
||||
|
||||
f32 signedArea3 = ((a.x - c.x) * (scanP.y - c.y)) - ((a.y - c.y) * (scanP.x - c.x));
|
||||
f32 signedArea3 = ((a.x - c.x) * (startP.y - c.y)) - ((a.y - c.y) * (startP.x - c.x));
|
||||
f32 signedArea3DeltaX = c.y - a.y;
|
||||
f32 signedArea3DeltaY = a.x - c.x;
|
||||
|
||||
@ -650,18 +650,19 @@ void DTRRender_Triangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1, DqnV
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Scan and Render
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
for (scanP.y = min.y; scanP.y < max.y; scanP.y++)
|
||||
color.rgb *= 0.1f;
|
||||
for (i32 bufferY = min.y; bufferY < max.y; bufferY++)
|
||||
{
|
||||
|
||||
f32 signedArea1Row = signedArea1;
|
||||
f32 signedArea2Row = signedArea2;
|
||||
f32 signedArea3Row = signedArea3;
|
||||
|
||||
for (scanP.x = min.x; scanP.x < max.x; scanP.x++)
|
||||
for (i32 bufferX = min.x; bufferX < max.x; bufferX++)
|
||||
{
|
||||
if (signedArea1Row >= 0 && signedArea2Row >= 0 && signedArea3Row >= 0)
|
||||
{
|
||||
SetPixel(renderBuffer, scanP.x, scanP.y, color, ColorSpace_Linear);
|
||||
SetPixel(renderBuffer, bufferX, bufferY, color, ColorSpace_Linear);
|
||||
}
|
||||
|
||||
signedArea1Row += signedArea1DeltaX;
|
||||
|
@ -61,7 +61,8 @@ REM Compile
|
||||
REM ////////////////////////////////////////////////////////////////////////////
|
||||
del *.pdb >NUL 2>NUL
|
||||
cl %CompileFlags% %Win32Flags% ..\src\Win32DTRenderer.cpp /link %LinkLibraries% %LinkFlags%
|
||||
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link ..\src\external\easy\easy_profiler.lib /PDB:%ProjectName%_%TimeStamp%.pdb /export:DTR_Update %LinkFlags%
|
||||
REM cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link ..\src\external\easy\easy_profiler.lib /PDB:%ProjectName%_%TimeStamp%.pdb /export:DTR_Update %LinkFlags%
|
||||
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link /PDB:%ProjectName%_%TimeStamp%.pdb /export:DTR_Update %LinkFlags%
|
||||
|
||||
popd
|
||||
set LastError=%ERRORLEVEL%
|
||||
|
36
src/dqn.h
36
src/dqn.h
@ -504,6 +504,8 @@ DQN_FILE_SCOPE inline bool operator==(DqnV2i a, DqnV2i b) { return DqnV
|
||||
typedef union DqnV3
|
||||
{
|
||||
struct { f32 x, y, z; };
|
||||
DqnV2 xy;
|
||||
|
||||
struct { f32 r, g, b; };
|
||||
f32 e[3];
|
||||
} DqnV3;
|
||||
@ -528,6 +530,8 @@ DQN_FILE_SCOPE f32 DqnV3_Dot (DqnV3 a, DqnV3 b);
|
||||
DQN_FILE_SCOPE bool DqnV3_Equals (DqnV3 a, DqnV3 b);
|
||||
DQN_FILE_SCOPE DqnV3 DqnV3_Cross (DqnV3 a, DqnV3 b);
|
||||
|
||||
DQN_FILE_SCOPE DqnV3 DqnV3_Normalise(DqnV3 a);
|
||||
|
||||
DQN_FILE_SCOPE inline DqnV3 operator- (DqnV3 a, DqnV3 b) { return DqnV3_Sub (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV3 operator+ (DqnV3 a, DqnV3 b) { return DqnV3_Add (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV3 operator* (DqnV3 a, DqnV3 b) { return DqnV3_Hadamard(a, b); }
|
||||
@ -575,17 +579,18 @@ DQN_FILE_SCOPE DqnV4 DqnV4_Hadamard(DqnV4 a, DqnV4 b);
|
||||
DQN_FILE_SCOPE f32 DqnV4_Dot (DqnV4 a, DqnV4 b);
|
||||
DQN_FILE_SCOPE bool DqnV4_Equals (DqnV4 a, DqnV4 b);
|
||||
|
||||
DQN_FILE_SCOPE inline DqnV4 operator- (DqnV4 a, DqnV4 b) { return DqnV4_Sub (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator+ (DqnV4 a, DqnV4 b) { return DqnV4_Add (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, DqnV4 b) { return DqnV4_Hadamard(a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, f32 b) { return DqnV4_Scalef (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, i32 b) { return DqnV4_Scalei (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Hadamard(a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, f32 b) { return (a = DqnV4_Scalef (a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, i32 b) { return (a = DqnV4_Scalei (a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator-=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Sub (a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator+=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Add (a, b)); }
|
||||
DQN_FILE_SCOPE inline bool operator==(DqnV4 a, DqnV4 b) { return DqnV4_Equals (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator- (DqnV4 a, DqnV4 b) { return DqnV4_Sub (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator+ (DqnV4 a, DqnV4 b) { return DqnV4_Add (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator+ (DqnV4 a, f32 b) { return DqnV4_Add (a, DqnV4_1f(b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, DqnV4 b) { return DqnV4_Hadamard(a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, f32 b) { return DqnV4_Scalef (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, i32 b) { return DqnV4_Scalei (a, b); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Hadamard(a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, f32 b) { return (a = DqnV4_Scalef (a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, i32 b) { return (a = DqnV4_Scalei (a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator-=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Sub (a, b)); }
|
||||
DQN_FILE_SCOPE inline DqnV4 &operator+=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Add (a, b)); }
|
||||
DQN_FILE_SCOPE inline bool operator==(DqnV4 a, DqnV4 b) { return DqnV4_Equals (a, b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 4D Matrix Mat4
|
||||
@ -2125,6 +2130,15 @@ DQN_FILE_SCOPE DqnV3 DqnV3_Cross(DqnV3 a, DqnV3 b)
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE DqnV3 DqnV3_Normalise(DqnV3 a)
|
||||
{
|
||||
f32 length = DqnMath_Sqrtf(DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z));
|
||||
f32 invLength = 1 / length;
|
||||
DqnV3 result = a * invLength;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE DqnV3i DqnV3i_3i(i32 x, i32 y, i32 z)
|
||||
{
|
||||
DqnV3i result = {x, y, z};
|
||||
|
Loading…
Reference in New Issue
Block a user