Start of SSE vector math library. Fixed compiler warnings. Removed rasterizer and Doom map loader from CosmicGL.

This commit is contained in:
TempleProgramming 2021-07-01 06:27:22 -04:00
parent e5596ee2bf
commit e912217325
30 changed files with 1050 additions and 2077 deletions

Binary file not shown.

View file

@ -1,83 +0,0 @@
/* This demo renders a BSP. Put DOOM1.WAD in the directory to try this. */
Cd(__DIR__);;
"\n\n\n\n"; // Seperate from annoying warnings
I64 wWC = 90; // Window width in columns
I64 wHC = 90; // Window height in rows
I64 wW = wWC * 8;
I64 wH = wHC * 8;
I64 wXC = 1; // Window x in columns
I64 wYC = 2; // Window y in rows
I64 wX = wXC * 8;
I64 wY = wYC * 8;
SettingsPush;
WinHorz(wXC, wXC + wWC - 1);
WinVert(wYC, wYC + wHC - 1);
DocClear;
// Prepare framebuffer
CTex2D frameBuf;
Tex2DInit(&frameBuf, TEX2D_RAW, wW, wH);
Tex2DColorFill(&frameBuf, gr_palette[WHITE]);
// Load BSP and render
CWAD doom1;
WADLoad(&doom1, "DOOM1.WAD");
CDoomMap map;
DoomMapLoad(&map, &doom1, "E1M1");
// Sprite loading
CTex2D sprite;
Tex2DLoadWADSprite(&sprite, &doom1, "POSSF2F8");
WADFree(&doom1);
CBGR24 cRed;
cRed.r = 255; cRed.b = cRed.g = 0;
I64 i, a, b, c, d;
for (i = 0; i < map.nLines; i++)
{
a = map.lines[i].v1->x >> 32;
b = map.lines[i].v1->y >> 32;
c = map.lines[i].v2->x >> 32;
d = map.lines[i].v2->y >> 32;
a /= 8;
b /= 8;
c /= 8;
d /= 8;
a += 200;
b += 650;
c += 200;
d += 650;
if (a < 0 || b < 0 || c < 0 || d < 0 ||
a >= wW || b >= wH || c >= wW || d >= wH)
{
// One coordinate outside window
}
else
{
DrawLine(&frameBuf, a, b, c, d, cRed);
}
}
DrawTexture(&frameBuf, &sprite, 200, 200, TRUE);
while (CharScan() == 0)
{
Tex2DDebugDisp(&frameBuf, wX, wY);
Sleep(1);
}
DoomMapFree(&doom1);
Tex2DFree(&sprite);
Tex2DFree(&framebuf);
SettingsPop;
Exit;

View file

@ -17,37 +17,37 @@ WinVert(wYC, wYC + wHC - 1);
DocClear;
// Prepare framebuffer
CTex2D frameBuf;
Tex2DInit(&frameBuf, TEX2D_RAW, wW, wH);
Tex2DColorFill(&frameBuf, gr_palette[WHITE]);
CGLTex2D frameBuf;
GLTex2DInit(&frameBuf, TEX2D_RAW, wW, wH);
GLTex2DColorFill(&frameBuf, gr_palette[WHITE]);
// Draw Rectangles
DrawRectFill(&frameBuf, 32, 32, 128, 96, gr_palette[CYAN]);
GLDrawRectFill(&frameBuf, 32, 32, 128, 96, gr_palette[CYAN]);
DrawRectVertGradient(&frameBuf, 64, 128, 96, 256, gr_palette[CYAN],
GLDrawRectVertGradient(&frameBuf, 64, 128, 96, 256, gr_palette[CYAN],
gr_palette[BLUE]);
// Gradient's starting transition points can also be modified:
DrawRectVertGradient(&frameBuf, 160, 32, 224, 96, gr_palette[BLACK],
GLDrawRectVertGradient(&frameBuf, 160, 32, 224, 96, gr_palette[BLACK],
gr_palette[WHITE], 0.65, 0.7);
DrawRectOutline(&frameBuf, 55, 300, 75, 310, gr_palette[LTGRAY]);
GLDrawRectOutline(&frameBuf, 55, 300, 75, 310, gr_palette[LTGRAY]);
// You can also define a second color for adding button-like shading
DrawRectSoftOutline(&frameBuf, 100, 200, 130, 210, gr_palette[LTGRAY],
GLDrawRectSoftOutline(&frameBuf, 100, 200, 130, 210, gr_palette[LTGRAY],
gr_palette[DKGRAY]);
// Drawing text
DrawChar(&frameBuf, 48, 48, '!', gr_palette[WHITE]);
DrawString(&frameBuf, 16, 104, "When I wrote this, God said:
GLDrawChar(&frameBuf, 48, 48, '!', gr_palette[WHITE]);
GLDrawString(&frameBuf, 16, 104, "When I wrote this, God said:
calls singing moist days excellence.", gr_palette[GREEN]);
while (CharScan() == 0)
{
Tex2DDebugDisp(&frameBuf, wX, wY);
GLTex2DDebugDisp(&frameBuf, wX, wY);
Sleep(1);
}
Tex2DFree(&frameBuf);
GLTex2DFree(&frameBuf);
SettingsPop;
Exit;

View file

@ -1,247 +0,0 @@
/* This demo shows how to load a custom model (created based on the .obj format
using a converstion script). It uses WAD textures rather than BMP textures
unlike most of the other demos. The model is not transformed in any way and
is rendered directly, so scaling the window will also scale the resulting
render. */
Cd(__DIR__);;
I64 wWC = 80; // Window width in columns (Drop to under 80 for 640x480 displays)
I64 wHC = 45; // Window height in rows (Drop to under 60 for 640x480 displays)
I64 wW = wWC * 8;
I64 wH = wHC * 8;
I64 wXC = 1; // Window x in columns
I64 wYC = 2; // Window y in rows
I64 wX = wXC * 8;
I64 wY = (wYC + 0) * 8;
SettingsPush;
WinHorz(wXC, wXC + wWC - 1);
WinVert(wYC, wYC + wHC - 1);
DocClear;
// Framebuffer Initialization
CTex2D frameBuf;
CTex2D depthBuf;
Tex2DInit(&frameBuf, TEX2D_RAW, wW, wH);
Tex2DInit(&depthBuf, TEX2D_DEPTH, wW, wH);
// Colors
CBGR24 cBlack;
cBlack.r = 0; cBlack.g = 0; cBlack.b = 0;
CBGR24 cRed;
cRed.r = 255; cRed.g = 20; cRed.b = 20;
CBGR24 cWhite;
cWhite.r = 255; cWhite.g = 255; cWhite.b = 255;
Tex2DColorFill(&frameBuf, cBlack);
// Texture Intitalization
CWAD wad;
WADLoad(&wad, "KingTerry.wad");
CTex2D TexRevelation;
Tex2DLoadWAD(&TexRevelation, &wad, "Revelation");
CTex2D TexKingTerrySkin;
Tex2DLoadWAD(&TexKingTerrySkin, &wad, "KingTerry_Skin");
CTex2D TexKingTerryBody;
Tex2DLoadWAD(&TexKingTerryBody, &wad, "KingTerry_Body");
CTex2D TexNebula;
Tex2DLoadWAD(&TexNebula, &wad, "Nebula");
WADFree(&wad);
// Generate our own page texture
CTex2D TexPages;
Tex2DInit(&TexPages, TEX2D_RAW, 256, 256);
Tex2DColorFill(&TexPages, cWhite);
DrawString(&TexPages, 16, 20, "I should fix", cBlack);
DrawString(&TexPages, 16, 35, "the UVs on this", cBlack);
DrawString(&TexPages, 16, 50, "book model.", cBlack);
class CMat
{
U8 name[32];
U32 nOffset; // Offset to first triangle
U32 nTris; // Number of triangles
};
class CZMHeader
{
I32 nMats; // Number of materials
U32 nTriOffset; // Triangle array offset
U32 nVertOffset; // Vertex array offset
U32 nUVOffset; // UV array offset
U32 nNormOffset; // Normal array offset
};
class CZMTri
{
U32 iV1; // Vertices
U32 iV2;
U32 iV3;
U32 iN1; // Normals
U32 iN2;
U32 iN3;
U32 iT1; // UVs
U32 iT2;
U32 iT3;
};
class CZModel
{
CMat *mat;
CZMTri *tri;
CVec3 *vert;
CVec2 *uv;
CVec3 *norm;
};
class UniformTex
{
I64 mat; // Material index of model to render
CTex2D *tex;
};
class UniformCol
{
I64 mat;
CBGR24 col;
};
// Load model
U8 *MdlHandle = FileRead("TerryTruth.ZM");
CZMHeader *header = MdlHandle;
CZModel MdlTerry;
MdlTerry.mat = MdlHandle + 20;
MdlTerry.tri = MdlHandle + header->nTriOffset;
MdlTerry.vert = MdlHandle + header->nVertOffset;
MdlTerry.uv = MdlHandle + header->nUVOffset;
MdlTerry.norm = MdlHandle + header->nNormOffset;
// Prepare uniforms (unchanging parameters) to feed into shader
// Book cover is red
UniformCol UniCover;
UniCover.col.r = 150;
UniCover.col.g = 0;
UniCover.col.b = 0;
UniCover.mat = 0;
// Skin uses skin texture
UniformTex UniKingTerry_Skin;
UniKingTerry_Skin.tex = &TexKingTerrySkin;
UniKingTerry_Skin.mat = 1;
// Body uses body texture
UniformTex UniKingTerry_Body;
UniKingTerry_Body.tex = &TexKingTerryBody;
UniKingTerry_Body.mat = 2;
// Hat is black (dark gray)
UniformCol UniHat;
UniHat.col.r = 20;
UniHat.col.g = 20;
UniHat.col.b = 20;
UniHat.mat = 3;
// Pages uses WAD texture
UniformTex UniPages;
UniPages.tex = &TexPages; // Set this to &TexRevelation for original.
UniPages.mat = 4;
// Nebula uses WAD texture
UniformTex UniNebula;
UniNebula.tex = &TexNebula;
UniNebula.mat = 5;
// Generate a texure and color shader
CShader ShdTex, ShdCol;
ShdTex.vertValues = MAlloc(2 * sizeof(I64));
ShdTex.vertValues[0] = SHD_CVEC2; // UV
ShdTex.vertValues[1] = SHD_CVEC3; // Normal
ShdCol.vertValues = MAlloc(2 * sizeof(I64));
ShdCol.vertValues[0] = SHD_CVEC2; // UV
ShdCol.vertValues[1] = SHD_CVEC3; // Normal
ShdTex.nVertValues = 2;
ShdCol.nVertValues = 2;
U0 vShaderTex(CTri *tri, F64 *vertOutBuf, U8 *mdlPtr, U8 *uniforms, I64 iTri, I64 nTris)
{
CZModel *mdl = mdlPtr;
UniformTex *uni = uniforms;
nTris++; // So I don't have to see the unused warning.
I64 t = mdl->mat[uni->mat].nOffset + iTri; // Triangle index in triangle array
// Copy model directly into the triangle, I won't even transform for this demo.
MemCopy(&tri->p[0], &mdl->vert[mdl->tri[t].iV1 - 1], sizeof(CVec3));
MemCopy(&tri->p[1], &mdl->vert[mdl->tri[t].iV2 - 1], sizeof(CVec3));
MemCopy(&tri->p[2], &mdl->vert[mdl->tri[t].iV3 - 1], sizeof(CVec3));
tri->p[0].z = -1 * tri->p[0].z;
tri->p[1].z = -1 * tri->p[1].z;
tri->p[2].z = -1 * tri->p[2].z;
// Copy uv and normals into vertOutBuf to be interpolated for the vertex shader.
MemCopy(&vertOutBuf[0], &mdl->uv[mdl->tri[t].iT1 - 1], sizeof(CVec2));
MemCopy(&vertOutBuf[2], &mdl->norm[mdl->tri[t].iN1 - 1], sizeof(CVec3));
MemCopy(&vertOutBuf[5], &mdl->uv[mdl->tri[t].iT2 - 1], sizeof(CVec2));
MemCopy(&vertOutBuf[7], &mdl->norm[mdl->tri[t].iN2 - 1], sizeof(CVec3));
MemCopy(&vertOutBuf[10], &mdl->uv[mdl->tri[t].iT3 - 1], sizeof(CVec2));
MemCopy(&vertOutBuf[12], &mdl->norm[mdl->tri[t].iN3 - 1], sizeof(CVec3));
}
U0 fShaderTex(CBGR24 *color, F64 *fragInBuf, U8 *uniforms)
{
UniformTex *uni = uniforms;
Tex2DSampleNorm(color, uni->tex, fragInBuf[0], 1.0-fragInBuf[1]);
// Debug, display normals
// color->r=fragInBuf[2]*255.0; color->g=fragInBuf[3]*255.0; color->b=fragInBuf[4]*255.0;
}
U0 fShaderCol(CBGR24 *color, F64 *fragInBuf, U8 *uniforms)
{
UniformCol *uni = uniforms;
color->r = uni->col.r;
color->g = uni->col.g;
color->b = uni->col.b;
}
ShdTex.FragShd = &fShaderTex;
ShdTex.VertShd = &vShaderTex;
ShdCol.FragShd = &fShaderCol;
ShdCol.VertShd = &vShaderTex;
Tex2DDepthReset(&depthBuf);
RenderTris(&ShdCol, &frameBuf, &depthBuf, &MdlTerry, &UniCover, MdlTerry.mat[0].nTris);
RenderTris(&ShdTex, &frameBuf, &depthBuf, &MdlTerry, &UniKingTerry_Skin, MdlTerry.mat[1].nTris);
RenderTris(&ShdTex, &frameBuf, &depthBuf, &MdlTerry, &UniKingTerry_Body, MdlTerry.mat[2].nTris);
RenderTris(&ShdCol, &frameBuf, &depthBuf, &MdlTerry, &UniHat, MdlTerry.mat[3].nTris);
RenderTris(&ShdTex, &frameBuf, &depthBuf, &MdlTerry, &UniPages, MdlTerry.mat[4].nTris);
RenderTris(&ShdTex, &frameBuf, $ER$&depthBuf, &MdlTerry, &UniNebula, MdlTerry.mat[5].nTris);
while (CharScan() == 0)
{
Tex2DDebugDisp(&frameBuf, wX, wY);
Sleep(1);
}
Tex2DFree(&frameBuf);
Tex2DFree(&depthBuf);
Tex2DFree(&TexPages);
Tex2DFree(&TexRevelation);
Tex2DFree(&TexKingTerrySkin);
Tex2DFree(&TexKingTerryBody);
Tex2DFree(&TexNebula);
SettingsPop;
Exit;

View file

@ -16,15 +16,15 @@ WinHorz(wXC, wXC + wWC - 1);
WinVert(wYC, wYC + wHC - 1);
DocClear;
CTex2D texture;
Tex2DLoadBMP(&texture, "SaintTerry.bmp");
CGLTex2D texture;
GLTex2DLoadBMP(&texture, "SaintTerry.bmp");
while (CharScan() == 0)
{
Tex2DDebugDisp(&texture, wX, wY);
GLTex2DDebugDisp(&texture, wX, wY);
Sleep(1);
}
Tex2DFree(&texture);
GLTex2DFree(&texture);
SettingsPop;
Exit;

Binary file not shown.

Before

(image error) Size: 192 KiB

View file

@ -1,119 +0,0 @@
/* This demo shows how to create a custom model format, import a texture, and
program a shader to render a triangle. */
Cd(__DIR__);;
I64 wWC = 32; // Window width in columns (512px)
I64 wHC = 32; // Window height in rows (512px)
I64 wW = wWC * 8;
I64 wH = wHC * 8;
I64 wXC = 1; // Window x in columns
I64 wYC = 2; // Window y in rows
I64 wX = wXC * 8;
I64 wY = (wYC + 4) * 8;
SettingsPush;
WinHorz(wXC, wXC + wWC - 1);
WinVert(wYC, wYC + wHC + 3);
DocClear;
// Framebuffer Initialization
CTex2D frameBuf;
CTex2D depthBuf;
Tex2DInit(&frameBuf, TEX2D_RAW, wW, wH);
Tex2DInit(&depthBuf, TEX2D_DEPTH, wW, wH);
// Clear framebuffer texture with black background
CBGR24 cBlack;
cBlack.r = 0; cBlack.g = 0; cBlack.b = 0;
Tex2DColorFill(&frameBuf, cBlack);
// Importing BMP texture
CTex2D texture;
Tex2DLoadBMP(&texture, "MrGod.bmp");
// Create custom model format that is quite straightforward
class MDL
{
I64 nTris;
CTri *tri;
CVec2 *uv;
};
// Load it with a texture mapped triangle.
MDL model;
model.nTris = 1;
model.tri = MAlloc(sizeof(CTri));
model.tri[0].p[0].x = 0.0;
model.tri[0].p[0].y = 0.8;
model.tri[0].p[0].z = 0.0;
model.tri[0].p[1].x = -0.8;
model.tri[0].p[1].y = -0.4;
model.tri[0].p[1].z = 0.0;
model.tri[0].p[2].x = 0.8;
model.tri[0].p[2].y = -0.4;
model.tri[0].p[2].z = 0.0;
model.uv = MAlloc(sizeof(CVec2)*3);
// UVs commonly use coordinates of 0.0-1.0, although you can use direct pixel
// coordinates if you use the pixel coordinate sampler in the shader.
model.uv[0].x = 0.5;
model.uv[0].y = 0.0898;
model.uv[1].x = 0.07421875;
model.uv[1].y = 0.73046875;
model.uv[2].x = 0.9375;
model.uv[2].y = 0.7305;
// In this example a class is not needed for the uniforms (unchanging
// parameters), we only feed the pointer for the texture we want to sample.
// to the shader.
// Generate a shader. Each vertex has a UV coordinate (coordinate that
// maps to the texture), so we only need to pass one CVEC2 attribute
// from the vertex shader to the fragment shader.
CShader shd, shdB;
shd.vertValues = MAlloc(sizeof(I64));
shd.vertValues[0] = SHD_CVEC2; // UV coordinate
shd.nVertValues = 1;
// The vertex shader gives the normalized device coordinates (screen coordinates
// from -1.0 to 1.0) of each vertex of a specified triangle. Normally you would
// do translations and perspective transforms, but here our model is already in
// NDC. It also passes the UV coordinates of each vertex to the vertOutBuf to
// be interpolated for the fragment shader.
U0 vShader(CTri *tri, F64 *vertOutBuf, U8 *mdlPtr, U8 *uniforms, I64 iTri, I64 nTris)
{
MDL *mdl = mdlPtr;
MemCopy(tri, &mdl->tri[iTri], sizeof(CTri));
MemCopy(vertOutBuf, &mdl->uv[iTri*3], sizeof(CVec2)*3);
}
// The fragment shader calculates what color an individual fragment (pixel)
// should be. Here we use the interpolated UV coordinate from the fragInBuf to
// sample the color from the texture.
U0 fShader(CBGR24 *color, F64 *fragInBuf, U8 *uniforms)
{
// We will pass in the texture pointer through the uniform later
// when we render.
Tex2DSampleNorm(color, uniforms, fragInBuf[0], fragInBuf[1]);
}
// Attach vertex and fragment shader
shd.FragShd = &fShader;
shd.VertShd = &vShader;
while (CharScan() == 0)
{
// Where &texture is you would usually feed in a pointer to uniforms,
// however since the texture is the only value the shader needs,
// we simply pass in that pointer.
RenderTris(&shd, &frameBuf, &depthBuf, &model, &texture, 1);
Tex2DDebugDisp(&frameBuf, wX, wY);
Sleep(1);
}
Tex2DFree(&frameBuf);
Tex2DFree(&depthBuf);
Tex2DFree(&texture);
SettingsPop;
Exit;

13
src/Home/MakeHome.CC Normal file
View file

@ -0,0 +1,13 @@
Cd(__DIR__);;
//If these are not present in /Home, it uses the version in the root dir. You
//can make your own, modified, version of these files in your /Home directory.
#include "~/HomeLocalize"
#include "/Zenith/Boot/MakeBoot"
#include "/Zenith/Utils/MakeUtils"
#include "~/HomeWrappers"
MapFileLoad("::/Kernel/Kernel");
MapFileLoad("::/Compiler/Compiler");
#include "~/HomeKeyPlugIns"
#include "~/HomeSys"
Cd("..");;

View file

@ -1,10 +1,10 @@
/**
@defgroup Draw Draw
@defgroup GLDraw Draw
@brief Functions for drawing to textures.
*/
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw pixel on color texture. Does not check boundaries, point
must be fully inside texture.
@ -13,14 +13,14 @@
@param[in] y Y position.
@param[in] color Color of point.
*/
U0 DrawPixel(CTex2D *tex, I64 x, I64 y, CBGR24 color)
U0 GLDrawPixel(CGLTex2D *tex, I64 x, I64 y, CBGR24 color)
{
tex->rawBuf[x + y * tex->w] = color;
}
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw line on color texture. Does not check boundaries, line must
be fully inside texture.
@ -31,11 +31,14 @@ U0 DrawPixel(CTex2D *tex, I64 x, I64 y, CBGR24 color)
@param[in] y1 End y.
@param[in] color Color of line.
*/
U0 DrawLine(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
U0 GLDrawLine(CGLTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
{
Bool steep = (Abs(y1 - y0) > Abs(x1 - x0));
Bool steep;
I64 temp,
delta_x, delta_y, error,
step_y, x, y;
I64 temp;
steep = Abs(y1 - y0) > Abs(x1 - x0);
if (steep == TRUE)
{
@ -57,11 +60,11 @@ U0 DrawLine(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
y1 = temp;
}
I64 delta_x = x1 - x0;
I64 delta_y = Abs(y1 - y0);
I64 error = delta_x / 2;
delta_x = x1 - x0;
delta_y = Abs(y1 - y0);
error = delta_x / 2;
I64 step_y;
step_y;
if (y0 < y1)
{
@ -72,11 +75,9 @@ U0 DrawLine(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
step_y = -1;
}
I64 y = y0;
y = y0;
I64 x;
for (x = x0; x < (x1 + 1); x++)
for (x = x0; x < x1 + 1; x++)
{
if (steep == TRUE)
{
@ -98,7 +99,7 @@ U0 DrawLine(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
}
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw single color triangle to color texture. Does not check
boundaries, triangle must be fully inside texture.
@ -111,11 +112,18 @@ U0 DrawLine(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
@param[in] y2 Third vertex y.
@param[in] color Color of triangle.
*/
U0 DrawTriangle(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, I64 x2, I64 y2,
U0 GLDrawTriangle(CGLTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, I64 x2, I64 y2,
CBGR24 color)
{
Bool middle_line_drawn;
I64 temp;
F64 ftemp;
F64 ftemp,
x_delta, y_delta,
left_delta, right_delta,
left_x, right_x,
y, lX, rX,
left_index, right_index,
width;
if (y0 > y1)
{
@ -147,25 +155,16 @@ U0 DrawTriangle(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, I64 x2, I64 y2,
y2 = temp;
}
Bool middle_line_drawn = FALSE;
F64 x_delta;
F64 y_delta;
F64 left_delta;
F64 right_delta;
F64 left_x;
F64 right_x;
I64 y, lX, rX;
I64 left_index, right_index;
I64 width;
middle_line_drawn = FALSE;
// Bottom Half
if (y0 != y1)
{
x_delta = (x1 - x0);
y_delta = (y1 - y0);
x_delta = x1 - x0;
y_delta = y1 - y0;
left_delta = x_delta / y_delta;
x_delta = (x2 - x0);
y_delta = (y2 - y0);
x_delta = x2 - x0;
y_delta = y2 - y0;
right_delta = x_delta / y_delta;
if (left_delta > right_delta)
@ -180,7 +179,7 @@ U0 DrawTriangle(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, I64 x2, I64 y2,
middle_line_drawn = TRUE;
for (y = y0; y < (y1 + 1); y++)
for (y = y0; y < y1 + 1; y++)
{
lX = left_x + 0.5;
rX = right_x + 0.5;
@ -196,11 +195,11 @@ U0 DrawTriangle(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, I64 x2, I64 y2,
// Top Half
if (y1 != y2)
{
x_delta = -(x1 - x2);
y_delta = (y1 - y2);
x_delta = -x1 - x2;
y_delta = y1 - y2;
left_delta = x_delta / y_delta;
x_delta = -(x0 - x2);
y_delta = (y0 - y2);
x_delta = -x0 - x2;
y_delta = y0 - y2;
right_delta = x_delta / y_delta;
if (left_delta > right_delta)
@ -218,7 +217,7 @@ U0 DrawTriangle(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, I64 x2, I64 y2,
y1 += 1;
}
for (y = y2; y > (y1 - 1); y--)
for (y = y2; y > y1 - 1; y--)
{
lX = left_x + 0.5;
rX = right_x + 0.5;

View file

@ -1,6 +1,6 @@
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw single color rectangle.
@param[in,out] tex Texture to draw to.
@ -10,17 +10,21 @@
@param[in] y1 End corner y.
@param[in] color Color of rectangle.
*/
U0 DrawRectFill(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
U0 GLDrawRectFill(CGLTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
{
I64 xMaxIndex = tex->w - 1;
I64 yMaxIndex = tex->h - 1;
I64 xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
I64 xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
I64 yMin = Clamp(Min(y0, y1), 0, yMaxIndex);
I64 yMax = Clamp(Max(y0, y1), 0, yMaxIndex);
I64 xLen = xMax - xMin;
I64 xMaxIndex, yMaxIndex,
xMin, xMax,
yMin, yMax,
xLen, y;
xMaxIndex = tex->w - 1;
yMaxIndex = tex->h - 1;
xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
yMin = Clamp(Min(y0, y1), 0, yMaxIndex);
yMax = Clamp(Max(y0, y1), 0, yMaxIndex);
xLen = xMax - xMin;
I64 y;
for (y = yMin; y < yMax; y++)
{
MemSetU32(&tex->rawBuf[xMin + y * tex->w], color, xLen);
@ -28,8 +32,8 @@ U0 DrawRectFill(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
}
/**
@ingroup Draw
@brief Draw 1px soft rectangle outline (corners not filled).
@ingroup GLDraw
@brief Draw 1px soft rectangle outline (corners not filled).
@param[in,out] tex Texture to draw to.
@param[in] x0 Start corner x.
@ -40,19 +44,24 @@ U0 DrawRectFill(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1, CBGR24 color)
@param[in] shadeColor (Optional) color of bottom right corner
for shading effect.
*/
U0 DrawRectSoftOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
U0 GLDrawRectSoftOutline(CGLTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
CBGR24 color, CBGR24 shadeColor = 0x7FFFFFFF)
{
I64 xMaxIndex, yMaxIndex,
xMin, xMax,
yMin, yMax,
xLen, y;
if (shadeColor == 0x7FFFFFFF)
shadeColor = color;
I64 xMaxIndex = tex->w - 1;
I64 yMaxIndex = tex->w - 1;
I64 xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
I64 xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
I64 yMin = Clamp(Min(y0, y1), 0, yMaxIndex);
I64 yMax = Clamp(Max(y0, y1), 0, yMaxIndex);
I64 xLen = xMax - xMin - 1;
xMaxIndex = tex->w - 1;
yMaxIndex = tex->w - 1;
xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
yMin = Clamp(Min(y0, y1), 0, yMaxIndex);
yMax = Clamp(Max(y0, y1), 0, yMaxIndex);
xLen = xMax - xMin - 1;
// Top border
MemSetU32(&tex->rawBuf[xMin + 1 + yMin * tex->w], color, xLen);
@ -61,7 +70,6 @@ U0 DrawRectSoftOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
MemSetU32(&tex->rawBuf[xMin + 1 + yMax * tex->w], shadeColor, xLen);
// Left/Right border
I64 y;
for (y = yMin + 1; y < yMax; y++)
{
tex->rawBuf[xMin + y * tex->w] = color;
@ -70,7 +78,7 @@ U0 DrawRectSoftOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
}
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw 1px rectangle outline.
@param[in,out] tex Texture to draw to.
@ -82,19 +90,24 @@ U0 DrawRectSoftOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
@param[in] shadeColor (Optional) color of bottom right corner
for shading effect.
*/
U0 DrawRectOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
U0 GLDrawRectOutline(CGLTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
CBGR24 color, CBGR24 shadeColor = 0x7FFFFFFF)
{
I64 xMaxIndex, yMaxIndex,
xMin, xMax,
yMin, yMax,
xLen, y;
if (shadeColor == 0x7FFFFFFF)
shadeColor = color;
I64 xMaxIndex = tex->w - 1;
I64 yMaxIndex = tex->w - 1;
I64 xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
I64 xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
I64 yMin = Clamp(Min(y0, y1), 0, yMaxIndex);
I64 yMax = Clamp(Max(y0, y1), 0, yMaxIndex);
I64 xLen = xMax - xMin + 1;
xMaxIndex = tex->w - 1;
yMaxIndex = tex->w - 1;
xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
yMin = Clamp(Min(y0, y1), 0, yMaxIndex);
yMax = Clamp(Max(y0, y1), 0, yMaxIndex);
xLen = xMax - xMin + 1;
// Top border
MemSetU32(&tex->rawBuf[xMin + yMin * tex->w], color, xLen);
@ -103,7 +116,6 @@ U0 DrawRectOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
MemSetU32(&tex->rawBuf[xMin + yMax * tex->w], shadeColor, xLen);
// Left/Right border
I64 y;
for (y = yMin + 1; y < yMax; y++)
{
tex->rawBuf[xMin + y * tex->w] = color;
@ -112,9 +124,11 @@ U0 DrawRectOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
}
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw two color vertical gradient rectangle.
Should be optimized to avoid such heavy use of F64's.
@param[in,out] tex Texture to draw to.
@param[in] x0 Start corner x.
@param[in] y0 Start corner y.
@ -127,30 +141,35 @@ U0 DrawRectOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
@param[in] tStart (Optional) start of gradient.
@param[in] tEnd (Optional) end of gradient.
*/
U0 DrawRectVertGradient(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
U0 GLDrawRectVertGradient(CGLTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
CBGR24 colorTop, CBGR24 colorBottom, F64 tStart = 0.0, F64 tEnd = 1.0)
{
I64 xMaxIndex = tex->w - 1;
I64 yMaxIndex = tex->h - 1;
I64 xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
I64 xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
I64 yMinReal = Min(y0, y1);
I64 yMin = Clamp(yMinReal, 0, yMaxIndex);
I64 yMaxReal = Max(y0, y1);
I64 yMax = Clamp(yMaxReal, 0, yMaxIndex);
I64 xLen = xMax - xMin;
F64 yHeight = yMaxReal - yMinReal + 1;
F64 t;
F64 rDiff = colorBottom.r - colorTop.r;
F64 gDiff = colorBottom.g - colorTop.g;
F64 bDiff = colorBottom.b - colorTop.b;
F64 r, g, b;
I64 y;
CBGR24 color;
I64 xMaxIndex, yMaxIndex,
xMin, xMax,
yMin, yMax,
yMinReal, yMaxReal,
xLen, y;
F64 yHeight, t,
rDiff, gDiff, bDiff,
r, g, b;
xMaxIndex = tex->w - 1;
yMaxIndex = tex->h - 1;
xMin = Clamp(Min(x0, x1), 0, xMaxIndex);
xMax = Clamp(Max(x0, x1), 0, xMaxIndex);
yMinReal = Min(y0, y1);
yMin = Clamp(yMinReal, 0, yMaxIndex);
yMaxReal = Max(y0, y1);
yMax = Clamp(yMaxReal, 0, yMaxIndex);
xLen = xMax - xMin;
yHeight = yMaxReal - yMinReal + 1;
rDiff = colorBottom.r - colorTop.r;
gDiff = colorBottom.g - colorTop.g;
bDiff = colorBottom.b - colorTop.b;
for (y = yMin; y < yMax; y++)
{
t = Clamp((y - yMinReal) / yHeight, tStart, tEnd);

View file

@ -1,12 +1,14 @@
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw a single color character to color texture.
Will not draw character if partially off-screen.
@param[in,out] tex Texture to draw to.
@param[in] x X position to draw character at.
@param[in] y Y position to draw character at.
*/
U0 DrawChar(CTex2D *tex, I64 x, I64 y, U8 char, CBGR24 color,
U0 GLDrawChar(CGLTex2D *tex, I64 x, I64 y, U8 char, CBGR24 color,
U64 *font = text.font)
{
// Check if off-screen
@ -18,28 +20,32 @@ U0 DrawChar(CTex2D *tex, I64 x, I64 y, U8 char, CBGR24 color,
{
for (i = 0; i < FONT_WIDTH; i++)
{
if (font[char].u8[j] & (1 << i))
if (font[char].u8[j] & 1 << i)
tex->rawBuf[x + i + (y + j) * tex->w] = color;
}
}
}
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw a single color string to color texture.
Escape sequences are not working correctly.
@param[in,out] tex Texture to draw to.
@param[in] x X position to draw text at.
@param[in] y Y position to draw text at.
@param[in] color Color of text.
@param[in] font Pointer to font buffer. System font by default.
*/
U0 DrawString(CTex2D *tex, I64 x, I64 y, U8 *str, CBGR24 color,
U0 GLDrawString(CGLTex2D *tex, I64 x, I64 y, U8 *str, CBGR24 color,
U64 *font = text.font)
{
I64 cur = 0; // String cursor
I64 xCur = x; // Screen cursors
I64 yCur = y;
I64 cur = 0, // String cursor
xCur, yCur; // Screen cursors
xCur = x;
yCur = y;
while (str[cur] != NULL)
{
@ -47,7 +53,6 @@ U0 DrawString(CTex2D *tex, I64 x, I64 y, U8 *str, CBGR24 color,
{
// Escape sequence
case '\\':
"ESCAPE SEQ\n";
switch (str[cur + 1])
{
case 'n':
@ -62,7 +67,7 @@ U0 DrawString(CTex2D *tex, I64 x, I64 y, U8 *str, CBGR24 color,
break;
case '\\':
DrawChar(tex, xCur, yCur, '\\', color, font);
GLDrawChar(tex, xCur, yCur, '\\', color, font);
xCur += FONT_WIDTH;
break;
@ -76,7 +81,7 @@ U0 DrawString(CTex2D *tex, I64 x, I64 y, U8 *str, CBGR24 color,
break;
default:
DrawChar(tex, xCur, yCur, str[cur], color, font);
GLDrawChar(tex, xCur, yCur, str[cur], color, font);
cur++;
xCur += FONT_WIDTH;
break;

View file

@ -1,6 +1,6 @@
/**
@ingroup Draw
@ingroup GLDraw
@brief Draw non-transformed color texture with blit operation.
Does not yet check if texture being drawn is entirely inside the texture
@ -12,14 +12,15 @@
@param[in] y Y location to draw texture.
@param[in] transparent (optional) use alpha as mask. False by default.
*/
U0 DrawTexture(CTex2D *dst, CTex2D *src, I64 x, I64 y,
U0 GLDrawTexture(CGLTex2D *dst, CGLTex2D *src, I64 x, I64 y,
Bool transparent = FALSE)
{
I64 xC, yC; // Current width/height position being copied from
I64 xC, yC, // Current width/height position being copied from
srcW, srcH, dstW;
I64 srcW = src->w; // Don't think the compiler is optimizing this so I am
I64 srcH = src->h;
I64 dstW = dst->w;
srcW = src->w;
srcH = src->h;
dstW = dst->w;
if (transparent)
{
@ -30,7 +31,7 @@ U0 DrawTexture(CTex2D *dst, CTex2D *src, I64 x, I64 y,
if (src->rawBuf[xC + yC * srcW].pad == 255)
{
// Assume target doesn't care about alpha byte being copied
dst->rawBuf[(x + xC) + (y + yC) * dstW] =
dst->rawBuf[x + xC + (y + yC) * dstW] =
src->rawBuf[xC + yC * srcW];
}
}

View file

@ -1,16 +1,18 @@
/* Include this file to rebuild the CosmicGL library. */
Option(OPTf_WARN_PAREN, ON);
Option(OPTf_WARN_DUP_TYPES, ON);
Cd(__DIR__);;
#include "Math/Math"
#include "Math/Types"
#include "Math/Vec4"
#include "Math/Vec3"
#include "Math/Conversion"
#include "Texture/Texture"
#include "Draw/Primitive"
#include "Draw/Texture"
#include "Draw/Rectangle"
#include "Draw/Text"
#include "Render/Shader"
#include "Render/Rasterize"
#include "WAD/WADTypes"
#include "WAD/WAD"
#include "Texture/TextureImport"
#include "WAD/DoomTypes"
#include "WAD/DoomMap"
#include "Texture/TextureImport"

View file

@ -0,0 +1,19 @@
asm
{
_DOUBLE_TO_SINGLE::
PUSH RBP
MOV RBP, RSP
//
POP RBP
RET1 8
}
/**
@ingroup gfxmath
@brief Convert double-precision scalar to single-precision.
@param[in] d Double-precision scalar.
@return Single-precision scalar.
*/
_extern _DOUBLE_TO_SINGLE I32 DoubleToSingle(F64 d);

View file

@ -1,141 +0,0 @@
/* Legacy math library. Is being replaced, however the few functions
still used will remain until SIMD math library is finished. */
/**
@defgroup math Math
@brief Legacy math stuff that is still being used.
*/
class CVec4
{
F64 x;
F64 y;
F64 z;
F64 w;
};
class CVec3
{
F64 x;
F64 y;
F64 z;
};
class CVec2
{
F64 x;
F64 y;
};
class CIVec2
{
I64 x;
I64 y;
};
class CTri
{
CVec3 p[3];
};
/**
@ingroup math
@brief Subtract vector b from a.
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination vector.
*/
U0 Vec2Sub(CVec2 *a, CVec2 *b, CVec2 *dest)
{
dest->x = a->x - b->x;
dest->y = a->y - b->y;
}
/**
@ingroup math
@brief Dot product of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@return Dot product.
*/
F64 Vec2Dot(CVec2 *a, CVec2 *b)
{
return a->x * b->x + a->y * b->y;
}
/**
@ingroup math
@brief Calculates barycentric coordinates for point p from triangle
vertices a, b, and c.
@param[in] p Point
@param[in] a Vertex 1
@param[in] b Vertex 2
@param[in] c Vertex 3
@param[in,out] u U coordinate.
@param[in,out] b V coordinate.
@param[in,out] w W coordinate.
*/
U0 Vec2Barycentric(CVec2 *p, CVec2 *a, CVec2 *b, CVec2 *c, F64 *u, F64 *v, F64 *w)
{
CVec2 v0, v1, v2;
Vec2Sub(b, a, &v0);
Vec2Sub(c, a, &v1);
Vec2Sub(p, a, &v2);
F64 d00 = Vec2Dot(&v0, &v0);
F64 d01 = Vec2Dot(&v0, &v1);
F64 d11 = Vec2Dot(&v1, &v1);
F64 d20 = Vec2Dot(&v2, &v0);
F64 d21 = Vec2Dot(&v2, &v1);
F64 denom = d00 * d11 - d01 * d01;
F64 tempV, tempW;
tempV = (d11 * d20 - d01 * d21)/denom;
tempW = (d00 * d21 - d01 * d20)/denom;
*u = 1.0 - tempV - tempW;
*v = tempV;
*w = tempW;
}
/**
@ingroup math
@brief Converts float at address to double and writes to given address.
Useful for parsing standard model formats.
@param[in] float Float
@param[in,out] double Double
*/
U0 Float2Double(U32 *float, U64 *double)
{
double->u32[1] = *float;
// Isolate parts of F32
U64 MASK_SIGN = 0b1000000000000000000000000000000000000000000000000000000000000000;
U64 MASK_EXP = 0b0111111110000000000000000000000000000000000000000000000000000000;
U64 MASK_MANT = 0b0000000001111111111111111111111100000000000000000000000000000000;
U64 EXP = *double & MASK_EXP;
U64 MANT = *double & MASK_MANT;
// Clear original F64 so that the masked values can be OR'd in
*double = *double & MASK_SIGN;
// Exponent of F64 is 11 bits instead of 8, shift mantissa by 3 and OR it back in
MANT = MANT >> 3;
*double = *double | MANT;
// Shift exponent to regular int format
// F32: [1 bit sign][8 bit exponent][23 bit mantissa]
EXP = EXP >> 55; // 23 + 32 to get it in regular int format
if (EXP != 0)
{
EXP += 896; // -127, +1023
EXP = EXP << 52;
}
*double = *double | EXP;
}

View file

@ -0,0 +1,49 @@
/**
@defgroup gfxmath Graphics Math
@brief SSE accelerated graphics math.
*/
/**
@ingroup gfxmath
@brief Single-precision floating point 2D vector.
Must be kept on 16-byte alignment in memory.
*/
class CVec2
{
I32 x, y, z, w;
};
/**
@ingroup gfxmath
@brief Single-precision floating point 3D vector.
Must be kept on 16-byte alignment in memory.
*/
class CVec3
{
I32 x, y, z, w;
};
/**
@ingroup gfxmath
@brief Single-precision floating point 4D vector.
Must be kept on 16-byte alignment in memory.
*/
class CVec4
{
I32 x, y, z, w;
};
/**
@ingroup gfxmath
@brief Single-precision floating point 4x4 matrix.
Must be kept on 16 byte alignment in memory.
*/
class CMat4
{
U32 e[16];
};

View file

@ -0,0 +1,216 @@
asm
{
_VEC3::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG4[RBP] // = *dest
// CVTSD2SS XMM0, SF_ARG1[RBP]
DU8 0xF2, 0x0F, 0x5A, 0x45, 0x10;
// MOVSS [RAX], XMM0
DU8 0xF3, 0x0F, 0x11, 0x00;
// CVTSD2SS XMM0, SF_ARG1[RBP]
DU8 0xF2, 0x0F, 0x5A, 0x45, 0x18;
// MOVSS 4[RAX], XMM0
DU8 0xF3, 0x0F, 0x11, 0x40, 0x04;
// CVTSD2SS XMM0, SF_ARG1[RBP]
DU8 0xF2, 0x0F, 0x5A, 0x45, 0x20;
// MOVSS 8[RAX], XMM0
DU8 0xF3, 0x0F, 0x11, 0x40, 0x08;
POP RBP
RET1 32
}
/**
@ingroup gfxmath
@brief Initialize members of a vector with double-precision floats.
@param[in] x X component.
@param[in] y Y component.
@param[in] z Z component.
@param[in,out] dest Destination
*/
_extern _VEC3 U0 Vec3(F64 x, F64 y, F64 z, CVec3 *dest);
asm
{
_VEC3_PRINT::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP] // = *v
SUB RSP, 24
// CVTSS2SD XMM0, 8[RAX] // (F64) v->z
DU8 0xF3, 0x0F, 0x5A, 0x40, 0x08;
// MOVSD 16[RSP], XMM0 // Push v->z
DU8 0xF2, 0x0F, 0x11, 0x44, 0x24, 0x10;
// CVTSS2SD XMM0, 4[RAX] // (F64) v->y
DU8 0xF3, 0x0F, 0x5A, 0x40, 0x04;
// MOVSD 8[RSP], XMM0 // Push v->y
DU8 0xF2, 0x0F, 0x11, 0x44, 0x24, 0x08;
// CVTSS2SD XMM0, [RAX] // (F64) v->x
DU8 0xF3, 0x0f, 0x5A, 0x00;
// MOVSD [RSP], XMM0 // Push v->x
DU8 0xF2, 0x0F, 0x11, 0x04, 0x24;
PUSH 3 // # of varargs
PUSH "X: %n | Y: %n | Z: %n\n"
CALL &Print
ADD RSP, 40
POP RBP
RET1 8
}
/**
@ingroup gfxmath
@brief Print members of a vector.
@param[in] v Vector
*/
_extern _VEC3_PRINT U0 Vec3Print(CVec3 *v);
/**
@ingroup gfxmath
@brief Copy all members of a vector to destination.
@param[in] src Source
@param[in,out] dest Destination
*/
_extern _VEC4_COPY U0 Vec3Copy(CVec3 *src, CVec3 *dest);
asm
{
_VEC3_IS_EQUAL::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP] // = *a
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
MOV RAX, SF_ARG2[RBP] // = *b
// MOVAPS XMM1, [RAX]
DU8 0x0F, 0x28, 0x08;
// CMPPS XMM0, XMM1, 0 // CMPEQPS
DU8 0x0F, 0xC2, 0xC1, 0x00;
// PMOVMSKB RAX, XMM0
DU8 0x66, 0x0F, 0xD7, 0xC0;
AND RAX, 0xFFF
CMP RAX, 0xFFF
JNZ _is_not_equal
MOV RAX, 1
JMP _return
_is_not_equal:
MOV RAX, 0
_return:
POP RBP
RET1 16
}
/**
@ingroup gfxmath
@brief Checks if two vectors are equal.
@param[in] a Vector 1
@param[in] b Vector 2
*/
_extern _VEC3_IS_EQUAL Bool Vec3IsEqual(CVec3 *a, CVec3 *b);
/**
@ingroup gfxmath
@brief Sum of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_ADD U0 Vec3Add(CVec3 *a, CVec3 *b, CVec3 *dest);
/**
@ingroup gfxmath
@brief Add a scalar to a vector.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_ADDS U0 Vec3AddS(CVec3 *v, I32 *s, CVec3 *dest);
/**
@ingroup gfxmath
@brief Difference of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_SUB U0 Vec3Sub(CVec3 *a, CVec3 *b, CVec3 *dest);
/**
@ingroup gfxmath
@brief Subtract a scalar from a vector.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_SUBS U0 Vec3SubS(CVec3 *v, I32 *s, CVec3 *dest);
/**
@ingroup gfxmath
@brief Product of two vectors (element multiplication).
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_MUL U0 Vec3Mul(CVec3 *a, CVec3 *b, CVec3 *dest);
/**
@ingroup gfxmath
@brief Scale a vector by a scalar.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_MULS U0 Vec3MulS(CVec3 *v, I32 *s, CVec3 *dest);
/**
@ingroup gfxmath
@brief Quotient of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_DIV U0 Vec3Div(CVec3 *a, CVec3 *b, CVec3 *dest);
/**
@ingroup gfxmath
@brief Divide a vector by a scalar.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_DIVS U0 Vec3DivS(CVec3 *v, I32 *s, CVec3 *dest);

View file

@ -0,0 +1,436 @@
asm
{
_VEC4::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG5[RBP] // = *dest
// CVTSD2SS XMM0, SF_ARG1[RBP]
DU8 0xF2, 0x0F, 0x5A, 0x45, 0x10;
// MOVSS [RAX], XMM0
DU8 0xF3, 0x0F, 0x11, 0x00;
// CVTSD2SS XMM0, SF_ARG2[RBP]
DU8 0xF2, 0x0F, 0x5A, 0x45, 0x18;
// MOVSS 4[RAX], XMM0
DU8 0xF3, 0x0F, 0x11, 0x40, 0x04;
// CVTSD2SS XMM0, SF_ARG3[RBP]
DU8 0xF2, 0x0F, 0x5A, 0x45, 0x20;
// MOVSS 8[RAX], XMM0
DU8 0xF3, 0x0F, 0x11, 0x40, 0x08;
// CVTSD2SS XMM0, SF_ARG4[RBP]
DU8 0xF2, 0x0F, 0x5A, 0x45, 0x28;
// MOVSS 16[RAX], XMM0
DU8 0xF3, 0x0F, 0x11, 0x40, 0x10;
POP RBP
RET1 40
}
/**
@ingroup gfxmath
@brief Initialize members of a vector with double-precision floats.
@param[in] x X component.
@param[in] y Y component.
@param[in] z Z component.
@param[in,out] dest Destination
*/
_extern _VEC4 U0 Vec4(F64 x, F64 y, F64 z, F64 w, CVec4 *dest);
asm
{
_VEC4_PRINT::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP] // = *v
SUB RSP, 32
// CVTSS2SD XMM0, 12[RAX] // (F64) v->w
DU8 0xF3, 0x0F, 0x5A, 0x40, 0x0C;
// MOVSD 24[RSP], XMM0 // Push v->w
DU8 0xF2, 0x0F, 0x11, 0x44, 0x24, 0x18;
// CVTSS2SD XMM0, 8[RAX] // (F64) v->z
DU8 0xF3, 0x0F, 0x5A, 0x40, 0x08;
// MOVSD 16[RSP], XMM0 // Push v->z
DU8 0xF2, 0x0F, 0x11, 0x44, 0x24, 0x10;
// CVTSS2SD XMM0, 4[RAX] // (F64) v->y
DU8 0xF3, 0x0F, 0x5A, 0x40, 0x04;
// MOVSD 8[RSP], XMM0 // Push v->y
DU8 0xF2, 0x0F, 0x11, 0x44, 0x24, 0x08;
// CVTSS2SD XMM0, [RAX] // (F64) v->x
DU8 0xF3, 0x0f, 0x5A, 0x00;
// MOVSD [RSP], XMM0 // Push v->x
DU8 0xF2, 0x0F, 0x11, 0x04, 0x24;
PUSH 4 // # of varargs
PUSH "X: %n | Y: %n | Z: %n | W: %n\n"
CALL &Print
ADD RSP, 48
POP RBP
RET1 8
}
/**
@ingroup gfxmath
@brief Print members of a vector.
@param[in] v Vector
*/
_extern _VEC4_PRINT U0 Vec4Print(CVec4 *v);
asm
{
_VEC4_COPY::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP] // = *src
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
MOV RAX, SF_ARG2[RBP] // = *dest
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 16
}
/**
@ingroup gfxmath
@brief Copy all members of a vector to destination.
@param[in] src Source
@param[in,out] dest Destination
*/
_extern _VEC4_COPY U0 Vec4Copy(CVec4 *src, CVec4 *dest);
/**
@ingroup gfxmath
@brief Checks if two vectors are equal.
@param[in] a Vector 1
@param[in] b Vector 2
@return TRUE if equal.
*/
Bool Vec4IsEqual(CVec4 *a, CVec4 *b)
{
U64 *c, *d;
c = a;
d = b;
if (c[0] == d[0] && c[1] == d[1])
return 1;
else
return 0;
}
asm
{
_VEC4_ADD::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
MOV RAX, SF_ARG2[RBP]
// MOVAPS XMM1, [RAX]
DU8 0x0F, 0x28, 0x08;
// ADDPS XMM0, XMM1
DU8 0x0F, 0x58, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Sum of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_ADD U0 Vec4Add(CVec4 *a, CVec4 *b, CVec4 *dest);
asm
{
_VEC4_ADDS::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
// MOVSS XMM1, SF_ARG2[RBP]
DU8 0xF3, 0x0F, 0x10, 0x4D, 0x18;
// SHUFPS XMM1, XMM1, 0
DU8 0x0F, 0xC6, 0xC9, 0x00;
// ADDPS XMM0, XMM1
DU8 0x0F, 0x58, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Add a scalar to a vector.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_ADDS U0 Vec4AddS(CVec4 *v, I32 *s, CVec4 *dest);
asm
{
_VEC4_SUB::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
MOV RAX, SF_ARG2[RBP]
// MOVAPS XMM1, [RAX]
DU8 0x0F, 0x28, 0x08;
// SUBPS XMM0, XMM1
DU8 0x0F, 0x5C, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Difference of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_SUB U0 Vec4Sub(CVec4 *a, CVec4 *b, CVec4 *dest);
asm
{
_VEC4_SUBS::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
// MOVSS XMM1, SF_ARG2[RBP]
DU8 0xF3, 0x0F, 0x10, 0x4D, 0x18;
// SHUFPS XMM1, XMM1, 0
DU8 0x0F, 0xC6, 0xC9, 0x00;
// SUBPS XMM0, XMM1
DU8 0x0F, 0x5C, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Subtract a scalar from a vector.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_SUBS U0 Vec4SubS(CVec4 *v, I32 *s, CVec4 *dest);
asm
{
_VEC4_MUL::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
MOV RAX, SF_ARG2[RBP]
// MOVAPS XMM1, [RAX]
DU8 0x0F, 0x28, 0x08;
// MULPS XMM0, XMM1
DU8 0x0F, 0x59, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Product of two vectors (element multiplication).
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_MUL U0 Vec4Mul(CVec4 *a, CVec4 *b, CVec4 *dest);
asm
{
_VEC4_MULS::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
// MOVSS XMM1, SF_ARG2[RBP]
DU8 0xF3, 0x0F, 0x10, 0x4D, 0x18;
// SHUFPS XMM1, XMM1, 0
DU8 0x0F, 0xC6, 0xC9, 0x00;
// MULPS XMM0, XMM1
DU8 0x0F, 0x59, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Scale a vector by a scalar.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_MULS U0 Vec4MulS(CVec4 *v, I32 *s, CVec4 *dest);
asm
{
_VEC4_DIV::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
MOV RAX, SF_ARG2[RBP]
// MOVAPS XMM1, [RAX]
DU8 0x0F, 0x28, 0x08;
// DIVPS XMM0, XMM1
DU8 0x0F, 0x5E, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Quotient of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@param[in,out] dest Destination
*/
_extern _VEC4_DIV U0 Vec4Div(CVec4 *a, CVec4 *b, CVec4 *dest);
asm
{
_VEC4_DIVS::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
// MOVSS XMM1, SF_ARG2[RBP]
DU8 0xF3, 0x0F, 0x10, 0x4D, 0x18;
// SHUFPS XMM1, XMM1, 0
DU8 0x0F, 0xC6, 0xC9, 0x00;
// DIVPS XMM0, XMM1
DU8 0x0F, 0x5E, 0xC1;
MOV RAX, SF_ARG3[RBP]
// MOVAPS [RAX], XMM0
DU8 0x0F, 0x29, 0x00;
POP RBP
RET1 24
}
/**
@ingroup gfxmath
@brief Scale a vector by a scalar.
@param[in] v Vector
@param[in] s Scalar
@param[in,out] dest Destination
*/
_extern _VEC4_DIVS U0 Vec4DivS(CVec4 *v, I32 *s, CVec4 *dest);
asm
{
_VEC4_DOT::
PUSH RBP
MOV RBP, RSP
MOV RAX, SF_ARG1[RBP]
// MOVAPS XMM0, [RAX]
DU8 0x0F, 0x28, 0x00;
MOV RAX, SF_ARG2[RBP]
// MOVAPS XMM1, [RAX]
DU8 0x0F, 0x29, 0x08;
// MULPS XMM0, XMM1
DU8 0x0F, 0x59, 0xC1;
// MOVHLPS XMM1, XMM0
DU8 0x0F, 0x12, 0xC8;
// ADDPS XMM0, XMM1
DU8 0x0F, 0x58, 0xC1;
// MOVSS XMM1, XMM0
DU8 0xF3, 0x0F, 0x10, 0xC8;
// SHUFPS XMM1, XMM1, 0
DU8 0x0F, 0xC6, 0xC9, 0x00;
// ADDSS XMM0, XMM1
DU8 0xF3, 0x0F, 0x58, 0xC1;
// MOVQ RAX, XMM0
DU8 0x66, 0x48, 0x0F, 0x7E, 0xC0;
POP RBP
RET1 16
}
/**
@ingroup gfxmath
@brief Dot product of two vectors.
@param[in] a Vector 1
@param[in] b Vector 2
@return Dot product.
*/
_extern _VEC4_DOT I32 Vec4Dot(CVec4 *a, CVec4 *b);

View file

@ -1,323 +0,0 @@
/**
@ingroup Render
@brief Renders triangles to texture.
Limitations: Triangles must be clipped to NDC.
@param[in] shd Shader.
@param[in,out] frameBuf Color texture to render to.
@param[in,out] depthBuf Depth texture to render to and check against.
@param[in] mdl Model buffer, shader defines how to read this.
@param[in] uniforms Buffer of unchanging values for shader.
@param[in] nTris Number of triangles to render.
*/
U0 RenderTris(CShader *shd, CTex2D *frameBuf, CTex2D *depthBuf, U8 *mdl,
U8 *uniforms, I64 nTris)
{
Bool middle_line_drawn = FALSE;
F64 x_delta;
F64 y_delta;
F64 left_delta;
F64 right_delta;
F64 left_x;
F64 right_x;
I64 y, lX, rX;
I64 left_index, right_index;
I64 i, j, temp;
F64 ftemp;
F64 z; // Interpolated value to depth check
// Stores baryocentric coordinates for current fragment
F64 bc[3];
// Vertex coordinates. P is the point to get baryocentric coordinate for
CVec2 p, a, b, c;
CBGR24 fragColor; // Final color to write to fragment
// Calculate dimensions and allocate vertex attributes buffer
// to pass interpolated per-frag values to the fragment
// shader from the vertex shader:
F64 *vOut; // This would be like Out from GLSL, it is 3x the size of fIn (3 vertices)
F64 *fIn; // This would be like In from GLSL
I64 attrBufSize = 0;
for (i = 0; i < shd->nVertValues; i++)
{
switch (shd->vertValues[i])
{
case SHD_F64:
attrBufSize += 1;
break;
case SHD_CVEC2:
attrBufSize += 2;
break;
case SHD_CVEC3:
attrBufSize += 3;
break;
case SHD_CMat4:
attrBufSize += 16;
break;
}
}
vOut = MAlloc(attrBufSize * sizeof(F64) * 3); // 3x for 3 vertexes
fIn = MAlloc(attrBufSize * sizeof(F64)); // Single set of interpolated values
CTri cTri; // Current Triangle in NDC
CIVec2 cTriPx[3]; // Current Triangle in pixels
I64 tri; // Current Triangle Index
I64 VI[3]; // Vertex Indices
for (tri = 0; tri < nTris; tri++)
{
// Get current triangle in NDC from vertex shader
shd->VertShd(&cTri, vOut, mdl, uniforms, tri, nTris);
ftemp = 0;
ftemp += Abs(cTri.p[0].x);
ftemp += Abs(cTri.p[0].y);
ftemp += Abs(cTri.p[1].x);
ftemp += Abs(cTri.p[1].y);
ftemp += Abs(cTri.p[2].x);
ftemp += Abs(cTri.p[2].y);
// Triangle is not outside NDC range, it is on screen
//if (ftemp =< 6)
if (1 == 1)
{
// This triangle may not be in the correct order.
// y0 should be lowest in texture coordinates, then y1 and y2.
// This means y0 should be the highest in NDC coordinates.
// In VI (Vertex Indices), the array index is the index of the final point,
// and it's value is the point from the original tri it get's it's
// coordinates from.
VI[0] = 0;
VI[1] = 1;
VI[2] = 2;
if (cTri.p[VI[0]].y < cTri.p[VI[1]].y)
{
temp = VI[0];
VI[0] = VI[1];
VI[1] = temp;
}
if (cTri.p[VI[0]].y < cTri.p[VI[2]].y)
{
temp = VI[0];
VI[0] = VI[2];
VI[2] = temp;
}
if (cTri.p[VI[1]].y < cTri.p[VI[2]].y)
{
temp = VI[1];
VI[1] = VI[2];
VI[2] = temp;
}
// By now, VI[0] points to the point with the lowest
// y in texture coordinates, and VI[2] points to the highest
// Convert NDC coordinates into tex coordinates for rasterization process
cTriPx[0].x = ToI64(((cTri.p[VI[0]].x * 0.5) + 0.5) * ToF64(frameBuf->w));
cTriPx[0].y = ToI64(((-cTri.p[VI[0]].y * 0.5) + 0.5) * ToF64(frameBuf->h));
cTriPx[1].x = ToI64(((cTri.p[VI[1]].x * 0.5) + 0.5) * ToF64(frameBuf->w));
cTriPx[1].y = ToI64(((-cTri.p[VI[1]].y * 0.5) + 0.5) * ToF64(frameBuf->h));
cTriPx[2].x = ToI64(((cTri.p[VI[2]].x * 0.5) + 0.5) * ToF64(frameBuf->w));
cTriPx[2].y = ToI64(((-cTri.p[VI[2]].y * 0.5) + 0.5) * ToF64(frameBuf->h));
// Prepare F64 triangle point vectors for calculating barycentric coords later
//Userd to use VI[0]
a.x = cTriPx[0].x;
a.y = cTriPx[0].y;
b.x = cTriPx[1].x;
b.y = cTriPx[1].y;
c.x = cTriPx[2].x;
c.y = cTriPx[2].y;
// Rasterize Bottom Half (Tex coordinates, not NDC)
if (cTriPx[0].y != cTriPx[1].y)
{
x_delta = (cTriPx[1].x - cTriPx[0].x);
y_delta = (cTriPx[1].y - cTriPx[0].y);
left_delta = x_delta / y_delta;
x_delta = (cTriPx[2].x - cTriPx[0].x);
y_delta = (cTriPx[2].y - cTriPx[0].y);
right_delta = x_delta / y_delta;
if (left_delta > right_delta)
{
ftemp = left_delta;
left_delta = right_delta;
right_delta = ftemp;
}
left_x = cTriPx[0].x;
right_x = cTriPx[0].x;
middle_line_drawn = TRUE;
for (y = cTriPx[0].y; y < (cTriPx[1].y + 1); y++)
{
lX = left_x + 0.5;
rX = right_x + 0.5;
left_index = y * frameBuf->w + lX;
right_index = y * frameBuf->w + rX;
// Temporary fix, the y should just be clipped and left_x/right_x adjusted accordingly
if (TRUE)
{
// Check if x coordinate is off screen and clip it.
if (lX < 0)
{
lX = 0;
}
if (lX > frameBuf->w)
{
lX = frameBuf->w;
}
if (rX > frameBuf->w)
{
rX = frameBuf->w;
}
if (rX < 0)
{
rX = 0;
}
// For every pixel along the line, set it's color
for (i = lX; i < rX; i++)
{
// Get barycentric coordinates (u, v, w)
p.x = i;
p.y = y;
Vec2Barycentric(&p, &a, &b, &c, &bc[VI[0]], &bc[VI[1]], &bc[VI[2]]);
z = (bc[VI[0]] * cTri.p[VI[0]].z) + (bc[VI[1]] * cTri.p[VI[1]].z) + (bc[VI[2]] * cTri.p[VI[2]].z);
if (z <= depthBuf->depthBuf[y * frameBuf->w + i])
{
// Interpolate all vOut values to fIn values for the fragment shader
for (j = 0; j < attrBufSize; j++)
{
fIn[j] = (vOut[j] * bc[0]) + (vOut[j+attrBufSize] * bc[1]) + (vOut[j+(2*attrBufSize)] * bc[2]);
}
left_index = y * frameBuf->w + i;
depthBuf->depthBuf[left_index] = z;
shd->FragShd(&fragColor, fIn, uniforms);
frameBuf->rawBuf[left_index] = fragColor;
}
}
}
left_x += left_delta;
right_x += right_delta;
}
}
// Rasterize Top Half (Tex coordinates, not NDC)
if (cTriPx[1].y != cTriPx[2].y)
{
x_delta = -(cTriPx[1].x - cTriPx[2].x);
y_delta = (cTriPx[1].y - cTriPx[2].y);
left_delta = x_delta / y_delta;
x_delta = -(cTriPx[0].x - cTriPx[2].x);
y_delta = (cTriPx[0].y - cTriPx[2].y);
right_delta = x_delta / y_delta;
if (left_delta > right_delta)
{
ftemp = left_delta;
left_delta = right_delta;
right_delta = ftemp;
}
left_x = cTriPx[2].x;
right_x = cTriPx[2].x;
if (middle_line_drawn == TRUE)
{
cTriPx[1].y += 1;
}
a.x = cTriPx[0].x;
a.y = cTriPx[0].y;
b.x = cTriPx[1].x;
b.y = cTriPx[1].y;
c.x = cTriPx[2].x;
c.y = cTriPx[2].y;
for (y = cTriPx[2].y; y > (cTriPx[1].y - 1); y--)
{
lX = left_x + 0.5;
rX = right_x + 0.5;
left_index = y * frameBuf->w + lX;
right_index = y * frameBuf->w + rX;
// Temporary fix, the y should just be clipped and left_x/right_x adjusted accordingly
if (TRUE)
{
if (lX < 0)
{
lX = 0;
}
if (lX > frameBuf->w)
{
lX = frameBuf->w;
}
if (rX > frameBuf->w)
{
rX = frameBuf->w;
}
if (rX < 0)
{
rX = 0;
}
// For every pixel along the line, set it's color
for (i = lX; i < rX; i++)
{
// Get barycentric coordinates (u, v, w)
p.x = i;
p.y = y;
Vec2Barycentric(&p, &a, &b, &c, &bc[VI[0]], &bc[VI[1]], &bc[VI[2]]);
z = (bc[VI[0]] * cTri.p[VI[0]].z) + (bc[VI[1]] * cTri.p[VI[1]].z) + (bc[VI[2]] * cTri.p[VI[2]].z);
if (z <= depthBuf->depthBuf[y * frameBuf->w + i])
{
// Interpolate all vOut values to fIn values for the fragment shader
for (j = 0; j < attrBufSize; j++)
{
fIn[j] = (vOut[j] * bc[0]) + (vOut[j+attrBufSize] * bc[1]) + (vOut[j+(2*attrBufSize)] * bc[2]);
}
left_index = y * frameBuf->w + i;
depthBuf->depthBuf[left_index] = z;
shd->FragShd(&fragColor, fIn, uniforms);
frameBuf->rawBuf[left_index] = fragColor;
}
}
}
left_x += left_delta;
right_x += right_delta;
}
}
}
}
Free(vOut);
Free(fIn);
}

View file

@ -1,97 +0,0 @@
/**
@defgroup Render Render
@brief For rendering triangle arrays using vertex/fragment shaders.
*/
#define SHD_F64 1 /// @ingroup Render
#define SHD_CVEC2 2 /// @ingroup Render
#define SHD_CVEC3 3 /// @ingroup Render
#define SHD_CVEC4 4 /// @ingroup Render
#define SHD_CMat4 5 /// @ingroup Render
/**
@ingroup Render
@brief User-programmed and passed to renderer. Calculates on-screen
coordinates of every triangle vertex, as well as the color for any given
pixel being rasterized.
Render Pipeline:
1) Vertex shader feeds in triangle coordinates in NDC format
(Normalized Device Coordinates), as well as other
per-vertex values it would like to interpolate and later
feed to the frag shader.
2) Using these NDC triangle coordinates, the rasterizer
calculates pixel positions of the triangles on the texture,
and interpolates the per-vertex values given by the vertex
shader into values for the particular fragment (pixel).
3) The fragment shader is called, with the interpolated
fragment values fed in, and it calculates the color to
be drawn at that particular fragment.
*/
class CShader
{
/**
@brief The number of vertex attributes to interpolate and pass between
the vertex and fragment shader.
For example if you wanted to pass an interpolated position and UV
coordinate to the fragment shader, this value would be 2.
*/
I64 nVertValues;
/**
@brief Array of vertex attribute types that describes the format of
the vertex attributes. See SHD_ macros for types.
For example if you wanted to pass an interpolated position and UV
coordinate to the fragment shader, this array would be
{SHD_CVEC2, SHD_CVEC3}.
*/
I64 *vertValues;
/**
@brief The vertex shader serves the purpose of returning
a triangle in NDC (normalized device coordinates), as well as
returning a buffer containing other vertex attributes such as
position/normals/UVs.
@param[in,out] tri Returned triangle (in NDC).
@param[in,out] vertOutBuf Vertex attributes to be interpolated
for the frag shader. These are in format:
Vertex 0 values, Vertex 1 values, Vertex
2 values, where values has the format
defined by vertValues in CShader.
@param[in] mdlPtr The pointer to the model to calculate
the output triangle from. There is no
predefined model format, the user can
give the renderer any model they want
and interpret it in this function.
@param[in] uniforms Unchanging variables throughout the render
(ie: perspective/lighting/textures).
@param[in] iTri Index of triangle to calculate.
@param[in] nTris Total triangles being rendered. This
function only calculates one triangle
but this is given if accessing a triangle
in your model depends on this value.
*/
U0 (*VertShd)(CTri *tri, F64 *vertOutBuf, U8 *mdlPtr, U8 *uniforms,
I64 iTri, I64 nTris);
/**
@brief The fragment shader serves the purpose of calculating
the color for the current fragment (pixel) using the passed-in
interpolated vertex attributes, as well as anything else given in
the uniform buffer.
@param[in] vertBuf Interpolated vertex attributes at that frag
(ie: position, uv, normal).
@param[in] uniforms Unchanging variables throughout the render
(ie: perspective/lighting/textures).
@param[in,out] color Color calculated for this fragment.
*/
U0 (*FragShd)(CBGR24 *color, F64 *fragInBuf, U8 *uniforms);
};

View file

@ -0,0 +1,44 @@
Cd(__DIR__);;
#include "../Math/Types"
#include "../Math/Vec4"
#include "../Math/Vec3"
CVec4 *a = MAllocAligned(sizeof(CVec4), 16);
CVec4 *b = MAllocAligned(sizeof(CVec4), 16);
CVec4 *dest = MAllocAligned(sizeof(CVec4), 16);
CVec4 *trueRes = MAllocAligned(sizeof(CVec4), 16);
// Note that some smaller vector functions are identical to larger vector
// functions so they do not get tested.
//-----------------------------------------------------------------------------
// Vec4Copy
Vec4(1.25, 2.5, 3.75, 5.0, a);
Vec4(0.0, 0.0, 0.0, 0.0, dest);
Vec4Copy(a, dest);
if (!Vec4IsEqual(a, dest))
{
"[WARNING] Vec4Copy NOT WORKING CORRECTLY! RESULT VECTOR:\n";
Vec4Print(dest);
}
//-----------------------------------------------------------------------------
// Vec4Add
Vec4(1.25, -2.5, 3.75, -5.0, a);
Vec4(-1.0, 2.0, -3.0, 4.0, b);
Vec4(0.25, -0.5, 0.75, -1.0, trueRes);
Vec4Add(a, b, dest);
// Looks like I have to use actual float compare and not direct
// equal compare. I'll fix Vec4IsEqual to do this.
if (!Vec3IsEqual(dest, trueRes))
{
"[WARNING] Vec4Add NOT WORKING CORRECTLY! RESULT VECTOR:\n";
Vec3Print(dest);
}
//-----------------------------------------------------------------------------
Free(a);
Free(b);
Free(dest);

View file

@ -1,29 +1,28 @@
/**
@defgroup Tex2D Texture
@defgroup GLTex2D Texture
@brief The core of the library, almost all functions either read from
or write to textures.
*/
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Raw format is a CBGR24 rawBuf array of size w * h in row-major
order.
*/
#define TEX2D_RAW 1
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Depth format is a F64 depthBuf array of size w * h in row-major
order.
*/
#define TEX2D_DEPTH 2
/**
@ingroup Tex2D
@brief The CTex2D class
@ingroup GLTex2D
@brief The texture class, just about everything reads from or writes to this.
*/
class CTex2D
class CGLTex2D
{
I64 type; // Type, see TEX2D_ macros above
I64 w; // Width
@ -36,7 +35,7 @@ class CTex2D
};
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Initialize texture.
@param[in,out] tex Uninitialized texture to initialize.
@ -46,7 +45,7 @@ class CTex2D
@param[in] l (Optional) left offset for use with sprite textures.
@param[in] t (Optional) top offset for use with sprite textures.
*/
U0 Tex2DInit(CTex2D *tex, I64 type, I64 w, I64 h, I64 l = 0, I64 t = 0)
U0 GLTex2DInit(CGLTex2D *tex, I64 type, I64 w, I64 h, I64 l = 0, I64 t = 0)
{
tex->w = w;
tex->h = h;
@ -56,23 +55,23 @@ U0 Tex2DInit(CTex2D *tex, I64 type, I64 w, I64 h, I64 l = 0, I64 t = 0)
switch (type)
{
case (TEX2D_RAW):
case TEX2D_RAW:
tex->rawBuf = MAlloc(4 * tex->w * tex->h);
break;
case (TEX2D_DEPTH):
case TEX2D_DEPTH:
tex->depthBuf = MAlloc(sizeof(F64) * tex->w * tex->h);
break;
}
}
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Free texture.
@param[in,out] tex Texture to free.
*/
U0 Tex2DFree(CTex2D *tex)
U0 GLTex2DFree(CGLTex2D *tex)
{
switch (tex->type)
{
@ -87,24 +86,24 @@ U0 Tex2DFree(CTex2D *tex)
}
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Fill texture with color. Only works with raw textures.
@param[in,out] tex Texture to color fill.
@param[in] color Color to fill texture with.
*/
U0 Tex2DColorFill(CTex2D *tex, CBGR24 color)
U0 GLTex2DColorFill(CGLTex2D *tex, CBGR24 color)
{
MemSetU32(tex->rawBuf, color, tex->w * tex->h);
}
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Reset depth texture. Set all pixels to far depth.
@param[in,out] tex Depth texture to reset.
*/
U0 Tex2DDepthReset(CTex2D *tex)
U0 GLTex2DDepthReset(CGLTex2D *tex)
{
F64 depth = 2.0;
I64 *iDepth = &depth;
@ -112,7 +111,7 @@ U0 Tex2DDepthReset(CTex2D *tex)
}
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Draw texture directly to display buffer. Maps non-visible textures
like depth to a visible palette when drawing for visual debugging.
@ -125,7 +124,7 @@ U0 Tex2DDepthReset(CTex2D *tex)
@param[in] x X position on screen to draw texture.
@param[in] y Y position on screen to draw texture.
*/
U0 Tex2DDebugDisp(CTex2D *tex, I64 x, I64 y)
U0 GLTex2DDebugDisp(CGLTex2D *tex, I64 x, I64 y)
{
// i, j = sampling x, y position on texture
I64 i, j;
@ -141,7 +140,7 @@ U0 Tex2DDebugDisp(CTex2D *tex, I64 x, I64 y)
switch (tex->type)
{
case TEX2D_RAW:
text.fb_alias[(x + i) + (y + j) * GR_WIDTH]
text.fb_alias[x + i + (y + j) * GR_WIDTH]
= tex->rawBuf[i + j * tex->w];
break;
@ -151,7 +150,7 @@ U0 Tex2DDebugDisp(CTex2D *tex, I64 x, I64 y)
color.r = scaled;
color.g = scaled;
color.b = scaled;
text.fb_alias[(x + i) + (y + j) * GR_WIDTH] = color;
text.fb_alias[x + i + (y + j) * GR_WIDTH] = color;
break;
}
}
@ -159,7 +158,7 @@ U0 Tex2DDebugDisp(CTex2D *tex, I64 x, I64 y)
}
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Sample color from color textures at normalized UV coordinate
(0.0-1.0). Coordinates over 1.0 loop causing a repeating texture effect.
@ -170,10 +169,12 @@ U0 Tex2DDebugDisp(CTex2D *tex, I64 x, I64 y)
@param[in] u Normalized (0.0-1.0) x coordinate to sample from.
@param[in] v Normalized (0.0-1.0) y coordinate to sample from.
*/
U0 Tex2DSampleNorm(CBGR24 *col, CTex2D *tex, F64 u, F64 v)
U0 GLTex2DSampleNorm(CBGR24 *col, CGLTex2D *tex, F64 u, F64 v)
{
I64 x = u * tex->w;
I64 y = v * tex->h;
I64 x, y;
x = u * tex->w;
y = v * tex->h;
x %= tex->w;
y %= tex->h;
@ -181,7 +182,7 @@ U0 Tex2DSampleNorm(CBGR24 *col, CTex2D *tex, F64 u, F64 v)
}
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Sample color from color textures at UV coordinate. Coordinates
over texture dimensions loop causing a repeating texture effect.
@ -189,7 +190,7 @@ U0 Tex2DSampleNorm(CBGR24 *col, CTex2D *tex, F64 u, F64 v)
@param[in] u X coordinate to sample from.
@param[in] v Y coordinate to sample from.
*/
U0 Tex2DSampleCoord(CBGR24 *col, CTex2D *tex, I64 u, I64 v)
U0 GLTex2DSampleCoord(CBGR24 *col, CGLTex2D *tex, I64 u, I64 v)
{
u %= tex->w;
v %= tex->h;

View file

@ -1,23 +1,21 @@
/**
@ingroup Tex2D
@brief Loads Half-Life texture from WAD file.
@ingroup GLTex2D
@brief Loads texture from Half-Life WAD file.
@param[in,out] tex Unitialized texture to load into.
@param[in] wad WAD file to load from.
@param[in] texName Name of texture lump in WAD file to load.
*/
U0 Tex2DLoadWAD(CTex2D *tex, CWAD *wad, U8 *texName)
U0 GLTex2DLoadWAD(CGLTex2D *tex, CGLWAD *wad, U8 *texName)
{
if (wad->type != WAD_TYPE_HL)
{
"[ERROR] CAN NOT LOAD %s TEXTURE FROM NON-HALF-LIFE WAD %s. USE LOAD
SPRITE/FLAT/WALL FOR DOOM WADS.\n", texName, wad->name;
return;
}
I64 i, texIndex;
U8 *pixel, *palette;
CGLWADFileLump *lump;
CGLWADTex *wadTex;
CBGR24 color;
// Get lump handle
CWADFileLumpHL *lump;
I64 texIndex = WADFindLump(wad, texName, &lump);
texIndex = GLWADFindLump(wad, texName, &lump);
if (texIndex < 0)
{
@ -26,28 +24,26 @@ U0 Tex2DLoadWAD(CTex2D *tex, CWAD *wad, U8 *texName)
}
// Map texture class to WAD file buffer
CWADTexHL *wadTex = wad->fileBuf + lump->filePos;
wadTex = wad->fileBuf + lump->filePos;
Tex2DInit(tex, TEX2D_RAW, wadTex->w, wadTex->h);
GLTex2DInit(tex, TEX2D_RAW, wadTex->w, wadTex->h);
// Map pixel array
U8 *pixel = wad->fileBuf + lump->filePos + wadTex->offsets[0];
pixel = wad->fileBuf + lump->filePos + wadTex->offsets[0];
// After the last byte of the fourth mipmap, there are two padding bytes,
// then a palette of 24-bit color (R, G, B).
U8 *palette = wad->fileBuf + lump->filePos + wadTex->offsets[3] +
((wadTex->w * wadTex->h) / 64) + 2;
palette = wad->fileBuf + lump->filePos + wadTex->offsets[3] +
wadTex->w * wadTex->h / 64 + 2;
// 1/64 here is the relative size of 4th mip map
I64 i;
CBGR24 color;
color.pad = 255; // Alpha
for (i = 0; i < wadTex->w * wadTex->h; i++)
{
color.r = palette[pixel[i] * 3];
color.g = palette[(pixel[i] * 3) + 1];
color.b = palette[(pixel[i] * 3) + 2];
color.g = palette[pixel[i] * 3 + 1];
color.b = palette[pixel[i] * 3 + 2];
tex->rawBuf[i] = color;
@ -59,108 +55,10 @@ U0 Tex2DLoadWAD(CTex2D *tex, CWAD *wad, U8 *texName)
/**
@internal
@ingroup Tex2D
@brief Loads DOOM patch at memory location into position on texture.
Relevant locations on texture should be initialized with a transparent
alpha byte.
@param[in,out] tex Initialized texture to load into.
@param[in] patch Memory location of patch to load from.
@param[in] palette Array of 256 colors.
@param[in] l Left (x) offset.
@param[in] t Top (y) offset.
*/
U0 Tex2DLoadWADPatch(CTex2D *tex, CWADPatch *patch, CBGR24 *palette,
I64 l, I64 t)
{
I64 x, y;
CWADPost *post; // Current post being parsed.
// Direct pointer addition gives wierd results so these are
// intermediate pointers:
I64 patchAddr = patch;
I64 cursor;
// Iterate through every column in patch
for (x = 0; x < patch->w; x++)
{
// Point post to first post in current column
cursor = patchAddr + patch->columnOffsets[x];
post = cursor;
// Post with offset 255 is last post in column and is empty
while (post->yOffset != 255)
{
// Draw every pixel in post to texture buffer
for (y = 0; y < post->length; y++)
{
tex->rawBuf[(x + l) + (y + t + post->yOffset) * tex->w]
= palette[post->pixels[y]];
}
// Point post to next post in column
cursor += post->length + 4; // 3 starting bytes + last pad byte
post = cursor;
}
}
}
/**
@ingroup Tex2D
@brief Loads DOOM sprite from WAD file.
@param[in,out] tex Unitialized texture to load into.
@param[in] wad WAD file to load from.
@param[in] sprName Name of sprite in WAD file to load.
*/
U0 Tex2DLoadWADSprite(CTex2D *tex, CWAD *wad, U8 *sprName)
{
if (wad->type != WAD_TYPE_DOOM)
{
"[ERROR] CAN NOT LOAD %s SPRITE FROM NON-DOOM %s\n", sprName, wad->name;
return;
}
// Get lump handle
CWADFileLumpDoom *lump;
I64 sprIndex = WADFindLump(wad, sprName, &lump);
if (sprIndex < 0)
{
"[ERROR] CAN NOT FIND %s SPRITE IN %s\n", sprName, wad->name;
return;
}
// Map patch class to sprite lump (which is in patch format)
CWADPatch *patch = wad->fileBuf + lump->filePos;
Tex2DInit(tex, TEX2D_RAW, patch->w, patch->h, patch->l, patch->t);
Tex2DColorFill(tex, 0); // To set alpha to 0 since patch's don't draw
// the transparent pixels, only opaque ones.
Tex2DLoadWADPatch(tex, patch, wad->paletteBuf, 0, 0);
}
/**
@ingroup Tex2D
@brief Loads DOOM wall texture from WAD file.
@param[in,out] tex Uninitialized texture to load into.
@param[in] wad WAD file to load from.
@param[in] wallName Name of wall in WAD file to load.
U0 Tex2DLoadWADWall(CTex2D *tex, CWAD *wad, U8 *wallName)
{
}
*/
/**
@internal
@ingroup Tex2D
@ingroup GLTex2D
@brief BMP file header.
*/
class CBMPHeader
class CGLBMPHeader
{
U8 szVersion[2]; // Should have 'BM' signature
U32 nSize; // File size in bytes
@ -190,7 +88,7 @@ class CBMPHeader
};
/**
@ingroup Tex2D
@ingroup GLTex2D
@brief Loads BMP image.
Supports standard uncompressed 24-bit color BMP images.
@ -198,12 +96,16 @@ class CBMPHeader
@param[in,out] tex Uninitialized texture to load into.
@param[in] fname File name of BMP.
*/
U0 Tex2DLoadBMP(CTex2D *tex, U8 *fname, Bool mask = FALSE)
U0 GLTex2DLoadBMP(CGLTex2D *tex, U8 *fname)
{
U8 *bmp = FileRead(fname);
I64 imgPointer,
xPx, yPx;
U8 *bmp;
bmp = FileRead(fname);
// Map locations in buffer;
CBMPHeader *info = bmp;
CGLBMPHeader *info = bmp;
//if (StrMatch(bmp->szVersion, "BM") == 0)
if (info->szVersion[0] != 'B' && info->szVersion[1] != 'M')
@ -221,48 +123,21 @@ U0 Tex2DLoadBMP(CTex2D *tex, U8 *fname, Bool mask = FALSE)
// Each pixel is 3 bytes in 24-bit BMP, however CTex2D uses CBGR24
// which contains a final padding bit (32-bits per pixel). The rows
// also increment in the opposite direction.
I64 imgPointer = bmp + info->nOffset;
I64 xPx, yPx;
imgPointer = bmp + info->nOffset;
// Initialize with RAW format for 24-bit non-compressed color
GLTex2DInit(tex, TEX2D_RAW, info->nWidth, info->nHeight);
// For checking if a color channel is greater than 0 for masks
// U8 channel;
if (mask)
for (yPx = 0; yPx < info->nHeight; yPx++)
{
/*
// Initialize with MASK format for 1-bit non-compressed color
Tex2DInit(tex, TEX2D_MASK, info->nWidth, info->nHeight);
for (yPx = 0; yPx < info->nHeight; yPx++)
for (xPx = 0; xPx < info->nWidth; xPx++)
{
for (xPx = 0; xPx < info->nWidth; xPx++)
{
channel = *(imgPointer + (xPx + info->nWidth *
(info->nHeight - yPx)) * 3);
if ((channel == 0 && invert = TRUE) ||
(channel > 0 && invert = FALSE))
{
tex->maskBuf[(xPx + info->nWidth * yPx) / 8] | (1 << (xPx % 8));
}
}
}
*/
}
else
{
// Initialize with RAW format for 24-bit non-compressed color
Tex2DInit(tex, TEX2D_RAW, info->nWidth, info->nHeight);
for (yPx = 0; yPx < info->nHeight; yPx++)
{
for (xPx = 0; xPx < info->nWidth; xPx++)
{
MemCopy(&tex->rawBuf[xPx + info->nWidth * yPx],
imgPointer + (xPx + info->nWidth * (info->nHeight - yPx))
* 3, 3);
}
MemCopy(&tex->rawBuf[xPx + info->nWidth * yPx],
imgPointer + (xPx + info->nWidth * (info->nHeight - yPx))
* 3, 3);
}
}
Free(bmp);
}

View file

@ -1,267 +0,0 @@
/**
@internal
@ingroup Doom
@brief Hash table type for Doom texture hash.
*/
#define HTT_DOOM_TEX 420
/**
@internal
@ingroup Doom
@brief Doom texture hash table size.
*/
#define DOOM_TEX_TABLE_SIZE 256
/**
@internal
@ingroup Doom
@brief Hash for quick access of textures by name.
*/
class CHashDoomTex : CHash
{
CTex2D tex;
};
/**
@ingroup Doom
@brief Runtime Doom map.
*/
class CDoomMap
{
I64 pad;
CDoomVertex *vertexes;
I64 nVertexes;
CDoomSide *sides;
I64 nSides;
CDoomLine *lines;
I64 nLines;
// CHashTable *texTable; // Hash table for quick access of textures
};
/**
@internal
@ingroup Doom
@brief Load blockmap from WAD into Doom map. See CDoomBBox.
@param[in,out] map Doom map to load into.
@param[in] wad WAD to load from.
@param[in] lumpIndex Index of BLOCKMAP lump in WAD.
U0 DoomMapLoadBlockmap(CDoomMap *map, CWAD *wad, I64 lumpIndex)
{
}
*/
/**
@internal
@ingroup Doom
Load vertexes from WAD into Doom map. See CDoomVertex.
@param[in,out] map Doom map to load into.
@param[in] wad WAD to load from.
@param[in] lumpIndex Index of VERTEXES lump in WAD.
*/
U0 DoomMapLoadVertexes(CDoomMap *map, CWAD *wad, I64 lumpIndex)
{
CWADFileLumpDoom *lump = &wad->doomLumps[lumpIndex];
if (StrNICompare("VERTEXES", lump->name, 8) != 0)
{
"[ERROR] EXPECTED VERTEXES LUMP INDEX DOES NOT POINT TO A
VERTEXES LUMP\n";
return;
}
// Map WAD vertex array
CWADVertex *verts = wad->fileBuf + lump->filePos;
// Calculate and update number of vertexes
I64 nVerts = lump->size / sizeof(CWADVertex);
map->nVertexes = nVerts;
// Allocate memory for map vertexes
map->vertexes = MAlloc(sizeof(CDoomVertex) * nVerts);
// Load I16 vertexes to I64 fixed point
I32 xIntermediate;
I32 yIntermediate;
I64 i;
for (i = 0; i < nVerts; i++)
{
// Load I16 to I32 to preserve sign at MSB when shifting 32 bits left
// for I64 fixed point conversion.
xIntermediate = verts[i].x;
yIntermediate = verts[i].y;
map->vertexes[i].x = xIntermediate << 32;
map->vertexes[i].y = yIntermediate << 32;
}
}
/**
@internal
@ingroup Doom
@brief Load sectors from WAD into Doom map. See CDoomSector.
@param[in,out] map Doom map to load into.
@param[in] wad WAD to load from.
@param[in] lumpIndex Index of SECTORS lump in WAD.
U0 DoomMapLoadSectors(CDoomMap *map, CWAD *wad, I64 lumpIndex)
{
}
*/
/**
@internal
@ingroup Doom
@brief Load sides from WAD into Doom map. See CDoomSide.
@param[in,out] map Doom map to load into.
@param[in] wad WAD to load from.
@param[in] lumpIndex Index of SIDEDEFS lump in WAD.
*/
U0 DoomMapLoadSides(CDoomMap *map, CWAD *wad, I64 lumpIndex)
{
CWADFileLumpDoom *lump = &wad->doomLumps[lumpIndex];
if (StrNICompare("SIDEDEFS", lump->name, 8) != 0)
{
"[ERROR] EXPECTED SIDEDEFS LUMP INDEX DOES NOT POINT TO A
SIDEDEFS LUMP\n";
return;
}
// Map WAD sidedef array
CWADSidedef *sidedefs = wad->fileBuf + lump->filePos;
// Calculate and update number of sidedefs
I64 nSidedefs = lump->size / sizeof(CWADSidedef);
map->nSides = nSidedefs;
// Allocate memory for map sides
map->sides = MAlloc(sizeof(CDoomSide) * nSidedefs);
I64 i;
for (i = 0; i < nSidedefs; i++)
{
map->sides[i].xOffset = sidedefs[i].xOffset;
map->sides[i].yOffset = sidedefs[i].yOffset;
/* Todo - Handle wall texture loading */
}
}
/**
@internal
@ingroup Doom
@brief Load lines from WAD into Doom map. See CDoomLine.
@param[in,out] map Doom map to load into.
@param[in] wad WAD to load from.
@param[in] lumpIndex Index of LINEDEFS lump in WAD.
*/
U0 DoomMapLoadLines(CDoomMap *map, CWAD *wad, I64 lumpIndex)
{
CWADFileLumpDoom *lump = &wad->doomLumps[lumpIndex];
if (StrNICompare("LINEDEFS", lump->name, 8) != 0)
{
"[ERROR] EXPECTED LINEDEFS LUMP INDEX DOES NOT POINT TO A
LINEDEFS LUMP\n";
return;
}
// Map WAD linedefs array
CWADLinedef *linedefs = wad->fileBuf + lump->filePos;
// Calculate and update number of linedefs
I64 nLinedefs = lump->size / sizeof(CWADLinedef);
map->nLines = nLinedefs;
// Allocate memory for map linedefs
map->lines = MAlloc(sizeof(CDoomLine) * nLinedefs);
I64 i;
for (i = 0; i < nLinedefs; i++)
{
map->lines[i].v1 = &map->vertexes[linedefs[i].v1];
map->lines[i].v2 = &map->vertexes[linedefs[i].v2];
map->lines[i].frontSide = &map->sides[linedefs[i].frontSidedef];
map->lines[i].backSide = &map->sides[linedefs[i].backSidedef];
}
}
/**
@internal
@ingroup Doom
@brief Builds sector line lists and subsector numbers. Finds block
bounding boxes for sectors.
@param[in,out] map Map to modify.
U0 DoomMapGroupLines(CDoomMap *map)
{
// Look up sector number for each subsector
}
*/
/**
@ingroup Doom
@brief Load DOOM map from WAD file.
@param[in,out] map Uninitialized Doom map to load into.
@param[in] wad WAD to load from.
@param[in] mapName Map from WAD to load (max length is 8 characters).
*/
U0 DoomMapLoad(CDoomMap *map, CWAD *wad, U8 *mapName)
{
I64 mapLumpIndex = WADFindLump(wad, mapName, NULL);
if (mapLumpIndex < 0)
{
"[ERROR] UNABLE TO FIND MAP %s IN WAD\n", mapName;
return;
}
// Prepare texture hash table
// map->texTable = HashTableNew(DOOM_TEX_TABLE_SIZE);
//I64 thingsIndex = mapLumpIndex + 1;
I64 vertexesIndex = mapLumpIndex + 4;
DoomMapLoadVertexes(map, wad, vertexesIndex);
I64 sidedefsIndex = mapLumpIndex + 3;
DoomMapLoadSides(map, wad, sidedefsIndex);
I64 linedefsIndex = mapLumpIndex + 2;
DoomMapLoadLines(map, wad, linedefsIndex);
//I64 segsIndex = mapLumpIndex + 5;
//I64 subsectorsIndex = mapLumpIndex + 6;
//I64 rejectIndex = mapLumpIndex + 7;
//I64 blockmapIndex = mapLumpIndex + 8;
}
/**
@ingroup Doom
@brief Free Doom map.
@param[in,out] map Doom map to free.
U0 DoomMapFree(CDoomMap *map)
{
// Free(map->vertexes);
// Free(map->lines);
// Free(map->sides);
}
*/

View file

@ -1,125 +0,0 @@
/**
@defgroup Doom Doom
@brief Functions for loading Doom maps from WADs and rendering them.
*/
/**
@ingroup Doom
@brief Fixed point 2D vertex.
*/
class CDoomVertex
{
I64 x;
I64 y;
};
/**
@internal
@ingroup Doom
@brief Fixed point 2D bounding box.
*/
class CDoomBBox
{
I64 x1;
I64 y1;
I64 x2;
I64 y2;
};
/**
@internal
@ingroup Doom
@brief A sector is a 2D section of the map.
*/
class CDoomSector
{
I64 floorH; // Floor height
I64 ceilingH; // Ceiling height
CTex2D *floorTex;
CTex2D *ceilingTex;
I64 lightLevel;
I64 special;
I16 tag;
I64 nLines; // Total lines associated with sector
//CDoomLine **lines; // Array of line pointers
CDoomBBox blockBox[4]; // Bounding box for height changes
};
/**
@internal
@ingroup Doom
@brief A side contains the textures applied to a line (wall).
*/
class CDoomSide
{
I64 xOffset;
I64 yOffset;
CTex2D *upperTex;
CTex2D *lowerTex;
CTex2D *middleTex;
CDoomSector *sectorFacing;
};
/**
@internal
@ingroup Doom
@brief Lines make up the shape of the map. A one sided wall is a
solid wall, while a two sided wall is a boundary between sectors.
*/
class CDoomLine
{
CDoomVertex *v1;
CDoomVertex *v2;
CDoomSide *frontSide;
CDoomSide *backSide;
};
/**
@internal
@ingroup Doom
@brief Clipped line that is used to make up subsectors.
*/
class CDoomSeg
{
}
/**
@internal
@ingroup Doom
@brief List of segs indicating some or all visible walls that define
a convex BSP leaf.
*/
class CDoomSubSector
{
CDoomSector *sector;
I64 nLines;
I64 firstLine;
};
#define NF_SUBSECTOR 0x8000
/**
@internal
@ingroup Doom
@brief Splits level down a line. On either side of the line is either
another child node or a BSP leaf (subsector).
*/
class CDoomNode
{
I64 x; // Partition start coordinates
I64 y;
I64 xChange; // Change from start to end of partition line
I64 yChange;
CDoomBBox rightBox;
CDoomBBox leftBox;
CDoomNode *rightChild;
CDoomNode *leftChild;
};

View file

@ -1,58 +1,41 @@
/**
@internal
@ingroup WAD
@brief Half-Life WAD type.
*/
#define WAD_TYPE_HL 1
/**
@internal
@ingroup WAD
@brief Doom WAD type.
*/
#define WAD_TYPE_DOOM 2
/**
@internal
@ingroup WAD
@ingroup GLWAD
@brief Hash table type for lump hash.
*/
#define HTT_LUMP 69
/**
@internal
@ingroup WAD
@ingroup GLWAD
@brief Hash for quick access of lump pointer and index by name.
*/
class CHashLump : CHash
class CHashGLWADLump : CHash
{
CWADFileLump *lump; // Pointer to lump
// Access with lump->doom/lump->hl
I64 lumpIndex; // Index of lump in WAD
CGLWADFileLump *lump;
I64 lumpIndex;
};
/**
@ingroup WAD
@ingroup GLWAD
@brief Class for WAD currently in memory.
Has easy access handles and a hash table to quickly find lumps.
*/
class CWAD
class CGLWAD
{
U8 *name;
U8 *fileBuf;
CWADInfo *info; // Type, size, pointer to lumps
CWADFileLumpDoom *doomLumps;// Quick access doom lumps
CWADFileLumpHL *hlLumps; // Quick access half life lumps
I64 type; // WAD type
CGLWADInfo *info; // WAD info header handle
CGLWADFileLump *lumps; // File lumps array handle
CHashTable *lumpTable; // Hash table for quick access of
// lumps by name.
CHashLump *hashLumps; // Hashes for lumpTable.
CBGR24 *paletteBuf; // Color palette 0 for texture loading if doom
CHashGLWADLump *hashLumps; // Hashes for lumpTable.
};
/**
@ingroup WAD
@ingroup GLWAD
@brief Finds lump with name and returns it's index in the WAD. Also
points input lump pointer to it if found.
@ -61,9 +44,9 @@ class CWAD
@param[in,out] lump Points to lump if found.
@return Lump index in WAD. -1 if not found.
*/
I64 WADFindLump(CWAD *wad, U8 *name, CWADFileLump **lump = NULL)
I64 GLWADFindLump(CGLWAD *wad, U8 *name, CGLWADFileLump **lump = NULL)
{
CHashLump *lumpHash;
CHashGLWADLump *lumpHash;
lumpHash = HashFind(name, wad->lumpTable, HTT_LUMP);
if (lumpHash != NULL)
@ -80,54 +63,48 @@ I64 WADFindLump(CWAD *wad, U8 *name, CWADFileLump **lump = NULL)
}
/**
@ingroup WAD
@brief Loads WAD file.
@ingroup GLWAD
@brief Loads Half-Life WAD file.
@param[in,out] wad Uninitialized WAD to initialize.
@param[in,out] wad Uninitialized WAD to load into.
@param[in] fname File name of WAD.
*/
U0 WADLoad(CWAD *wad, U8 *fname)
U0 GLWADLoad(CGLWAD *wad, U8 *fname)
{
I64 i;
U32 *type;
wad->fileBuf = FileRead(fname);
wad->name = StrNew(fname);
// For palette loading if doom WAD
CWADFileLumpDoom *paletteLump;
U8 *paletteColor;
// Map locations in buffer
// Map info handle to buffer
wad->info = wad->fileBuf;
// Allocate hash table
wad->lumpTable = HashTableNew(wad->info->nLumps); // Table
wad->hashLumps = CAlloc(wad->info->nLumps * // Hashes
sizeof(CHashLump));
sizeof(CHashGLWADLump));
I64 i;
// Check version and proceed accordingly
U32 *type = wad->info->type; // Cast to U32
// Check version
type = wad->info->type; // Cast to U32
// 'WAD3': Half Life 'WAD2': Quake
if (*type == 0x33444157 || *type == 0x32444157)
{
wad->type = WAD_TYPE_HL;
// Map lumps to buffer
wad->hlLumps = wad->fileBuf + wad->info->lumpOffset;
wad->lumps = wad->fileBuf + wad->info->lumpOffset;
for (i = 0; i < wad->info->nLumps; i++)
{
// Copy name to hash
wad->hashLumps[i].str = CAlloc(17); // 16 + NULL
MemCopy(wad->hashLumps[i].str,
wad->hlLumps[i].name, 16);
wad->hashLumps[i].str = CAlloc(17);
MemCopy(wad->hashLumps[i].str, wad->lumps[i].name, 16);
// Set hash type
wad->hashLumps[i].type = HTT_LUMP;
// Link lump to hash
wad->hashLumps[i].lump = &wad->hlLumps[i];
wad->hashLumps[i].lump = &wad->lumps[i];
// Set lump index in hash to this index
wad->hashLumps[i].lumpIndex = i;
@ -137,71 +114,28 @@ U0 WADLoad(CWAD *wad, U8 *fname)
}
return;
}
// 'IWAD': Doom Internal 'PWAD': Doom Patch
if (*type == 0x44415749 || *type == 0x44415750)
{
wad->type = WAD_TYPE_DOOM;
// Map lumps to buffer
wad->doomLumps = wad->fileBuf + wad->info->lumpOffset;
for (i = 0; i < wad->info->nLumps - 10; i++)
{
// Copy name to hash
wad->hashLumps[i].str = CAlloc(9); // 8 + NULL
MemCopy(wad->hashLumps[i].str,
wad->doomLumps[i].name, 8);
// Set hash type
wad->hashLumps[i].type = HTT_LUMP;
// Link lump to hash
wad->hashLumps[i].lump = &wad->doomLumps[i];
// Set lump index in hash to this index
wad->hashLumps[i].lumpIndex = i;
// Add hash to table
HashAdd(&wad->hashLumps[i], wad->lumpTable);
}
// Load palette 0 for texture loading later if it exists
if (WADFindLump(wad, "PLAYPAL", &paletteLump) != -1)
{
wad->paletteBuf = MAlloc(sizeof(CBGR24) * 256);
paletteColor = wad->fileBuf + paletteLump->filePos;
// Load each 3-byte RGB color into 4 byte BGRA palette
for (i = 0; i < 256; i++)
{
wad->paletteBuf[i].r = paletteColor[i * 3];
wad->paletteBuf[i].g = paletteColor[i * 3 + 1];
wad->paletteBuf[i].b = paletteColor[i * 3 + 2];
wad->paletteBuf[i].pad = 255; // Alpha
}
}
return;
}
// Type not recognized
U64 typeStr = 0;
MemCopy(&typeStr, wad->type, 4);
"[ERROR] %s WAD TYPE NOT RECOGNIZED: %s\n", typeStr;
"[ERROR] %s WAD TYPE NOT RECOGNIZED: %4ts\n", fname, type;
}
/**
@ingroup WAD
@ingroup GLWAD
@brief Free WAD.
@param[in,out] wad WAD to free.
*/
U0 WADFree(CWAD *wad)
U0 GLWADFree(CGLWAD *wad)
{
I64 i;
Free(wad->name);
Free(wad->lumpTable->body);
Free(wad->lumpTable);
Free(wad->hashLumps);
Free(wad->fileBuf);
}
for (i = 0; i < wad->info->nLumps; i++)
{
Free(wad->hashLumps[i].str);
}
Free(wad->hashLumps);
Free(wad->fileBuf);
}

View file

@ -1,15 +1,14 @@
/**
@defgroup WAD WAD
@brief WAD file format management and parsing. Supports DOOM and
Half-Life WADs.
@defgroup GLWAD WAD File Loading
@brief Half-Life WAD file format management and parsing.
*/
/**
@internal
@ingroup WAD
@ingroup GLWAD
@brief WAD file header.
*/
class CWADInfo
class CGLWADInfo
{
U8 type[4]; // Type of WAD, like IWAD/PWAD/WAD3
I32 nLumps; // Number of lumps
@ -17,22 +16,11 @@ class CWADInfo
};
/**
@ingroup WAD
@brief DOOM file lump. These point to "lumps" or directories in the WAD.
@ingroup GLWAD
@brief Half-Life WAD file lump. These point to "lumps" or directories in
the WAD.
*/
class CWADFileLumpDoom
{
I32 filePos; // Relative offset
I32 size;
U8 name[8];
};
/**
@ingroup WAD
@brief Half-Life file lump. These point to "lumps" or directories in the
WAD.
*/
class CWADFileLumpHL
class CGLWADFileLump
{
I32 filePos; // Relative offset
I32 diskSize; // Size of lump (compressed)
@ -43,238 +31,12 @@ class CWADFileLumpHL
U8 name[16];
};
/**
@ingroup WAD
@brief Union of Half-Life and DOOM lump classes to return as a pointer
from general purpose WAD functions like WADFindLump.
*/
union CWADFileLump
{
CWADFileLumpDoom doom;
CWADFileLumpHL hl;
};
/**
@internal
@ingroup WAD
@brief Thing element from a DOOM WAD THINGS lump.
Describes an entity.
*/
class CWADThing
{
I16 x;
I64 y;
I16 angle;
I16 type;
I16 flags;
};
/**
@internal
@ingroup WAD
@brief Linedef element from a DOOM WAD LINEDEFS lump.
Describes a line that makes up a wall/sector boundary on the map.
*/
class CWADLinedef
{
I16 v1; // Vertex 1
I16 v2; // Vertex 2
I16 flags;
I16 type;
I16 sectorTag;
I16 frontSidedef; // Sidedefs hold texture data for each side of linedef
I16 backSidedef;
};
/**
@internal
@ingroup WAD
@brief Sidedef element from a DOOM WAD SIDEDEFS lump.
Describes a side of a line (wall) and what textures it uses as well as
what sector it faces.
*/
class CWADSidedef
{
I16 xOffset; // Texture x offset
I16 yOffset; // Texture y offset
U8 upperTex[8]; // These are found in TEXTUREx lumps
U8 lowerTex[8];
U8 middleTex[8];
I16 sectorFaces; // Sector this sidedef faces
};
/**
@internal
@ingroup WAD
@brief Vertex element from a DOOM WAD VERTEXES lump.
*/
class CWADVertex
{
I16 x;
I16 y;
};
/**
@internal
@ingroup WAD
@brief Segment element from a DOOM WAD SEGS lump.
Describes a segment of a line that makes up the outline of a subsector
(convex BSP leaf).
*/
class CWADSeg
{
I16 v1;
I16 v2;
I16 angle;
I16 linedef;
I16 direction;
I16 offset;
};
/**
@internal
@ingroup WAD
@brief Sector element from a DOOM WAD SECTORS lump.
Describes a 2D region of the map.
*/
class CWADSector
{
I16 floorHeight;
I16 ceilingHeight;
U8 floorTex[8];
U8 ceilingTex[8];
I16 lightLevel;
I16 flags;
I16 tag;
};
/**
@internal
@ingroup WAD
@brief Sub-sector element from a DOOM WAD SSECTORS lump.
Describes a convex BSP leaf, meaning a convex sub section of a sector.
*/
class CWADSubSector
{
I16 nLinedefs;
I16 firstLinedef;
};
/**
@internal
@ingroup WAD
@brief Node element from a DOOM WAD NODES lump
Describes a node on a BSP tree. Each node splits a region of the map into
two along a line, with a left/right side child which can either be another
node or a subsector.
*/
class CWADNode
{
I16 x;
I16 y;
};
/**
@internal
@ingroup WAD
@brief DOOM Patch texture header.
Points to columns which are variable size arrays of CWADPost. This is a
variable length class.
*/
class CWADPatch
{
U16 w;
U16 h;
I16 l; // Offsets to shift origin point when drawing
I16 t;
U32 columnOffsets[1]; // Array of offsets (relative to header) of size
// width. If columns are identical they may point
// to the same column in the file.
};
/**
@internal
@ingroup WAD
@brief DOOM Post.
A post is a vertical segment of opaque pixels in the column of a patch
texture. There may be multiple of these posts in a column, one after the
other, with the end of a column being signifiged by a post with an offset
of 255. This is a variable length class.
*/
class CWADPost
{
U8 yOffset; // Offset from start of column. This is 255 if
// signaling end of column.
U8 length; // Length is bytes/pixels
U8 pad;
U8 pixels[1]; // Size is equal to length. Each pixel points to a color
// in the color palette.
// Technically another U8 pad comes here but pixels is variable length
};
/**
@internal
@ingroup WAD
@brief Header to DOOM TEXTUREx lumps.
*/
class CWADTexHeader
{
I32 nTextures; // Number of textures in TEXTUREx lump
I32 offsets[1]; // Offsets to CWADMapTex's from start of this class
};
/**
@internal
@ingroup WAD
@brief Information about DOOM patch and where to find it in the PNAMES
lump.
*/
class CWADMapPatch
{
I16 l; // Left offset (x origin)
I16 t; // Top offset (y origin)
I16 patch; // Patch number listed in PNAMES lump
I16 stepdir; // Obsolete, ignored by all DOOM versions
I16 colormap; // Obsolete, ignored by all DOOM versions
};
/**
@internal
@ingroup WAD
@brief Texture in a DOOM TEXTUREx lump.
A texture is composed of multiple patches. However it would have been
too simple for this to point to these patches directly, instead it points
to CWADMapPatch which describes where the patch is found in the PNAMES
lump.
*/
class CWADMapTex
{
U8 name[8];
I32 masked; // Boolean
I16 width;
U16 height;
U8 columnDir[4]; // Obsolete, ignored by all DOOM versions
I16 patchCount; // Number of patches that make up texture
CWADMapPatch patches[1]; // Size dependent on patchCount
};
/**
@internal
@ingroup WAD
@ingroup GLWAD
@brief Header to a Half-Life texture lump.
*/
class CWADTexHL
class CGLWADTex
{
U8 name[16];
U32 w;