mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2025-03-28 10:55:10 +00:00
Added CosmicGL.
This commit is contained in:
parent
9a30b7f1a0
commit
1cbc72e57b
34 changed files with 4329 additions and 1 deletions
README.mdZenith-latest-2021-06-26-04_03_37.iso
src
|
@ -15,7 +15,7 @@ Features in development include:
|
|||
- Fully-functional AHCI support
|
||||
- ~~VBE support~~ 32-bit color VBE graphics
|
||||
- A new GUI framework in 32-bit color
|
||||
- [Gr2](https://github.com/TempleProgramming/Gr2)
|
||||
- CosmicGL renderer
|
||||
- Compiler optimizations for speed improvements
|
||||
- SSE2+ instruction support in compiler and assembler
|
||||
- Network card drivers and a networking stack
|
||||
|
|
BIN
Zenith-latest-2021-06-25-21_34_44.iso → Zenith-latest-2021-06-26-04_03_37.iso
Executable file → Normal file
BIN
Zenith-latest-2021-06-25-21_34_44.iso → Zenith-latest-2021-06-26-04_03_37.iso
Executable file → Normal file
Binary file not shown.
BIN
src/Home/CosmicGLDemos/DrawBSP/DOOM1.WAD
Normal file
BIN
src/Home/CosmicGLDemos/DrawBSP/DOOM1.WAD
Normal file
Binary file not shown.
83
src/Home/CosmicGLDemos/DrawBSP/DrawBSP.CC
Normal file
83
src/Home/CosmicGLDemos/DrawBSP/DrawBSP.CC
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* 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;
|
53
src/Home/CosmicGLDemos/DrawPrimitives/DrawPrimitives.CC
Normal file
53
src/Home/CosmicGLDemos/DrawPrimitives/DrawPrimitives.CC
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* This demo shows how to draw primitives to textures. */
|
||||
|
||||
Cd(__DIR__);;
|
||||
|
||||
I64 wWC = 64; // Window width in columns (512px)
|
||||
I64 wHC = 48; // Window height in rows (384px)
|
||||
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]);
|
||||
|
||||
// Draw Rectangles
|
||||
DrawRectFill(&frameBuf, 32, 32, 128, 96, gr_palette[CYAN]);
|
||||
|
||||
DrawRectVertGradient(&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],
|
||||
gr_palette[WHITE], 0.65, 0.7);
|
||||
|
||||
DrawRectOutline(&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],
|
||||
gr_palette[DKGRAY]);
|
||||
|
||||
// Drawing text
|
||||
DrawChar(&frameBuf, 48, 48, '!', gr_palette[WHITE]);
|
||||
DrawString(&frameBuf, 16, 104, "When I wrote this, God said:
|
||||
calls singing moist days excellence.", gr_palette[GREEN]);
|
||||
|
||||
while (CharScan() == 0)
|
||||
{
|
||||
Tex2DDebugDisp(&frameBuf, wX, wY);
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
Tex2DFree(&frameBuf);
|
||||
SettingsPop;
|
||||
Exit;
|
BIN
src/Home/CosmicGLDemos/ModelLoading/KingTerry.wad
Normal file
BIN
src/Home/CosmicGLDemos/ModelLoading/KingTerry.wad
Normal file
Binary file not shown.
247
src/Home/CosmicGLDemos/ModelLoading/TerryTruth.CC
Normal file
247
src/Home/CosmicGLDemos/ModelLoading/TerryTruth.CC
Normal file
|
@ -0,0 +1,247 @@
|
|||
/* 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;
|
BIN
src/Home/CosmicGLDemos/ModelLoading/TerryTruth.ZM
Normal file
BIN
src/Home/CosmicGLDemos/ModelLoading/TerryTruth.ZM
Normal file
Binary file not shown.
30
src/Home/CosmicGLDemos/TextureLoading/RenderTextures.CC
Normal file
30
src/Home/CosmicGLDemos/TextureLoading/RenderTextures.CC
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* This demo shows how to initialize, import, and render textures. */
|
||||
|
||||
Cd(__DIR__);;
|
||||
|
||||
I64 wWC = 32; // Window width in columns (256px)
|
||||
I64 wHC = 32; // Window height in rows (256px)
|
||||
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;
|
||||
|
||||
CTex2D texture;
|
||||
Tex2DLoadBMP(&texture, "SaintTerry.bmp");
|
||||
|
||||
while (CharScan() == 0)
|
||||
{
|
||||
Tex2DDebugDisp(&texture, wX, wY);
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
Tex2DFree(&texture);
|
||||
SettingsPop;
|
||||
Exit;
|
BIN
src/Home/CosmicGLDemos/TextureLoading/SaintTerry.bmp
Normal file
BIN
src/Home/CosmicGLDemos/TextureLoading/SaintTerry.bmp
Normal file
Binary file not shown.
After ![]() (image error) Size: 192 KiB |
BIN
src/Home/CosmicGLDemos/TexturedTriangle/MrGod.bmp
Normal file
BIN
src/Home/CosmicGLDemos/TexturedTriangle/MrGod.bmp
Normal file
Binary file not shown.
After ![]() (image error) Size: 192 KiB |
119
src/Home/CosmicGLDemos/TexturedTriangle/UVMappedShader.CC
Normal file
119
src/Home/CosmicGLDemos/TexturedTriangle/UVMappedShader.CC
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* 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;
|
10
src/Home/Registry.CC
Normal file
10
src/Home/Registry.CC
Normal file
|
@ -0,0 +1,10 @@
|
|||
$TR,"Zenith"$
|
||||
$ID,2$$TR,"SysMessageFlags"$
|
||||
$ID,2$sys_message_flags[0]=0;
|
||||
$ID,-2$$TR,"SysRegVer"$
|
||||
$ID,2$registry_version=2.010;
|
||||
$ID,-2$$ID,-2$$TR,"Once"$
|
||||
$ID,2$$TR,"Zenith"$
|
||||
$ID,2$$ID,-2$$TR,"User"$
|
||||
$ID,2$$ID,-2$$ID,-2$$TR,"AutoComplete"$
|
||||
$ID,2$ac.col=98;ac.row=23;$ID,-2$
|
247
src/Zenith/CosmicGL/Docs/CosmicGLOverview.DD
Normal file
247
src/Zenith/CosmicGL/Docs/CosmicGLOverview.DD
Normal file
|
@ -0,0 +1,247 @@
|
|||
|
||||
$FG,5$Using this Library$FG$
|
||||
$HL,1$#include "MakeCosmicGL"$HL,0$
|
||||
$FG,2$Simply include MakeCosmicGL.CC located at the root of this repository in your
|
||||
project. The #include's beneath each title in the documentation are to help
|
||||
you find where these functions/classes are implemented.
|
||||
|
||||
$FG,5$Creating/Freeing Textures and Framebuffers$FG$
|
||||
$HL,1$#include "Texture"
|
||||
$HL,0$
|
||||
$FG,2$CTex2D is used for both textures and framebuffers:$FG$
|
||||
|
||||
$HL,1$U0 Tex2DInit(CTex2D *tex, I64 type, I64 w, I64 h);
|
||||
U0 Tex2DFree(CTex2D *tex);$HL,0$
|
||||
|
||||
$FG,2$Where $FG$$FG,9$type$FG$ $FG,2$can be:$FG$
|
||||
$FG,3$
|
||||
TEX2D_RAW$FG$ $FG,2$CBGR24 format$FG$
|
||||
$FG,3$TEX2D_DEPTH$FG$ $FG,2$F64 format$FG$
|
||||
$FG,3$TEX2D_WAD$FG$ $FG,2$WAD/BMP 8-bit 256-CBGR24 palette compression$FG$
|
||||
|
||||
$FG,2$Textures must be made for the frame and depth buffer, which can later be drawn
|
||||
to a window after the image is rendered onto them. Textures that you intend to
|
||||
use as render targets such as framebuffers can not be compressed:$FG$
|
||||
|
||||
$HL,1$CTex2D frameBuf, depthBuf;
|
||||
Tex2DInit(&frameBuf, TEX2D_RAW, 640, 480);
|
||||
Tex2DInit(&depthBuf, TEX2D_DEPTH, 640, 480);$HL,0$
|
||||
|
||||
$FG,5$Loading/Clearing Textures$FG$
|
||||
$FG,2$Tex2DInit merely allocates space, you can then clear the textures with the
|
||||
following:$FG$
|
||||
|
||||
$HL,1$U0 Tex2DColorFill(CTex2D *tex, CBGR24 color);
|
||||
U0 Tex2DDepthReset(CTex2D *tex);
|
||||
U0 Tex2DLoadWAD(CTex2D *tex, CWAD *wad, U8 *texName);
|
||||
$HL,0$
|
||||
$FG,5$Sampling Textures$FG$
|
||||
$FG,2$To sample a texture location (such as when texture mapping in a fragment
|
||||
shader), the following are available:$FG$
|
||||
|
||||
$HL,1$U0 Tex2DSampleNorm(CBGR24 *col, CTex2D *tex, F64 u, F64 v);$HL,0$ $FG,2$Samples with normalized 0.0-1.0 uv coordinates.$FG$
|
||||
$HL,1$U0 Tex2DSampleCoord(CBGR24 *col, CTex2D *tex, I64 u, I64 v);$HL,0$ $FG,2$Samples with raw pixel uv coordinates.$FG$
|
||||
|
||||
$FG,5$Displaying Textures$FG$
|
||||
$FG,2$All texture types can be rendered to the OS framebuffer. Textures and
|
||||
non-color data (depth) are rendered in grayscale.$FG$
|
||||
|
||||
$HL,1$U0 Tex2DDebugDisp(CTex2D *tex, I64 x, I64 y);$HL,0$ $FG,2$Copies directly to OS display buffer rather than window, will be replaced.$FG$
|
||||
|
||||
$FG,5$Loading Textures From Common Formats$FG$
|
||||
$HL,1$#include "TextureImport"
|
||||
$HL,0$
|
||||
$FG,5$WAD Textures$FG$
|
||||
$FG,2$WAD files were a common method of storing textures in early game engines,
|
||||
popularized by the DOOM/Quake/GldSrc engines. Textures are compressed with
|
||||
8-bit color pointing to a 256 24-bit color palette. See the WAD section to
|
||||
learn how to load the CWAD object to pass to this function.
|
||||
|
||||
$FG,2$Example WAD loading:$FG$
|
||||
$HL,1$
|
||||
CWAD wad;
|
||||
CTex2D tex;
|
||||
WADLoad(&wad, "Assets/Textures/HALFLIFE.WAD");
|
||||
Tex2DLoadWAD(&tex, &wad, "!waterblue");$HL,1$$HL,0$ $FG,2$The loader will initialize the texture.$FG$
|
||||
WADFree(&wad);
|
||||
$HL,0$
|
||||
$FG,5$BMP Images$FG$
|
||||
$FG,2$BMP images are an extremely simple format to read. You can load 24-bit uncompressed
|
||||
BMPs like so:$FG$
|
||||
|
||||
$HL,1$CTex2D tex;
|
||||
Tex2DLoadBMP(&tex, "SaintTerry.bmp");$HL,0$ $FG,2$The loader will initialize the texture.$FG$
|
||||
|
||||
$FG,5$Loading and Reading WAD Files$FG$
|
||||
$HL,1$#include "WAD/WADTypes"
|
||||
#include "WAD/WAD"$HL,0$
|
||||
$FG,2$WAD files are a general purpose format for storing a flat hierarchy of
|
||||
directories called "lumps." They were first used by the DOOM engine to hold
|
||||
game assets, however they have been used by subsequent engines such as Quake
|
||||
and GldSrc to hold textures. The general purpose WAD manipulation functions
|
||||
below can be used to access all WAD formats, although some functionality from
|
||||
other functions may be limited to specific WAD types.$FG$
|
||||
$HL,1$
|
||||
U0 WADLoad(CWAD *wad, U8 *fname);
|
||||
U0 WADFree(CWAD *wad);
|
||||
$HL,0$
|
||||
$FG,2$WAD types:$FG$$FG,3$
|
||||
WAD_TYPE_HL
|
||||
WAD_TYPE_DOOM
|
||||
$FG$
|
||||
$FG,5$Lumps$FG$
|
||||
$FG,2$These are named directories with no hierarchy. The format for lumps is slightly
|
||||
different for DOOM and Quake/Half-Life WADs, so a CWADFileLump union is available
|
||||
to pass general purpose lump pointers.
|
||||
|
||||
Lump classes:$FG$
|
||||
$HL,1$class CWADFileLumpDoom;
|
||||
class CWADFileLumpHL;
|
||||
class CWADFileLump;$HL,0$
|
||||
|
||||
$FG,2$CWADFileLump can be "interpreted" as either with:$FG$
|
||||
CWADFileLump.doom
|
||||
CWADFileLump.hl
|
||||
|
||||
$FG,2$CWAD has an internal hash file for fast lump reading. To find a lump by name, use:$FG$
|
||||
|
||||
$HL,1$I64 WADFindLump(CWAD *wad, U8 *name, CWADFileLump **lump=NULL);$HL,0$
|
||||
|
||||
$FG,2$It returns the lump index, or -1 if not found. **lump can be optionally used to get
|
||||
the handle to the target lump.$FG$
|
||||
|
||||
$FG,5$Shaders$FG$
|
||||
$HL,1$#include "Shader"
|
||||
$HL,0$
|
||||
$FG,2$Shaders are functions that calculate the vertex positions of each triangle in
|
||||
NDC (normalized device coordinates), and then calculate the color of each
|
||||
individual fragment (pixel) within the triangles. You can use any model format
|
||||
you like, as you get to decide what vertex coordinates are returned for each
|
||||
triangle. $FG$
|
||||
|
||||
$FG,5$Uniforms$FG$
|
||||
$FG,2$Uniforms are unchanging values that will be used by the shader for every
|
||||
triangle in the model. These are often values like transformation matrices,
|
||||
texture pointers, or any other material parameters you need. You can provide a
|
||||
pointer to your uniforms to use in the shader.$FG$
|
||||
|
||||
$FG,5$Vertex to Fragment Vertex Attributes$FG$
|
||||
$FG,2$The vertex shader returns not only the coordinates of the vertices for each
|
||||
triangle, but also other attributes such as UV coordinates, normals, colors,
|
||||
etc. Every time the fragment shader is called, the interpolated attributes
|
||||
for that frag (pixel) are given to the shader.)
|
||||
|
||||
$FG,2$You can choose the structure of the F64 array of attributes to be interpolated
|
||||
by setting the nVertValues and *vertValues from CShader:$FG$
|
||||
$HL,1$
|
||||
CShader shd;
|
||||
shd.nVertValues = 2; $FG,2$In this example, the vertex shader will pass two attributes.$FG$
|
||||
shd.vertValues = MAlloc(2 * sizeof(I64));
|
||||
shd.vertValues[0] = SHD_CVEC2; $FG,2$For passing UV coordinate to fragment shader.$FG$
|
||||
shd.vertValues[1] = SHD_CVEC3;$HL,0$ $FG,2$For passing normal to fragment shader.$FG$
|
||||
|
||||
$FG,2$Where the vertValues can be of type:$FG$
|
||||
$FG,3$
|
||||
SHD_F64
|
||||
SHD_CVEC2
|
||||
SHD_CVEC3
|
||||
SHD_CVEC4
|
||||
SHD_CMat4
|
||||
$FG$
|
||||
$FG,5$Vertex Shader$FG$
|
||||
$FG,2$The purpose of the vertex shader is to calculate each triangle's vertex
|
||||
coordinates in NDC (noramalized device coordinates). The renderer will "plot"
|
||||
or rasterize these coordinates to the specified render target texture.
|
||||
Fragments outside of the -1:1 range will not be rendered (as they are
|
||||
off-texture). $FG$
|
||||
|
||||
$SP,"NDC Coordinates:",BI=1$
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$HL,1$U0 (*VertShd)(CTri *tri, F64 *vertOutBuf,, U8 *mdlPtr, U8 *uniforms, I64 iTri, i64 nTris);$HL,0$
|
||||
|
||||
$FG,3$*tri$FG$ $FG,2$OUTPUT: Final triangle coordinates in NDC$FG$
|
||||
$FG,3$*mdlPtr$FG$ $FG,2$INPUT: Pointer to model data.$FG$
|
||||
$FG,3$*vertOutBuf$FG$ $FG,2$OUTPUT: Array of attributes to be interpolated for the frag shader. In order of: [V0 Attr, V1 Attr, V2 Attr] $FG$
|
||||
$FG,3$*uniforms$FG$ $FG,2$INPUT: Pointer to uniforms.$FG$
|
||||
$FG,3$iTri$FG$ $FG,2$INPUT: Current triangle.$FG$
|
||||
$FG,3$nTris$FG$ $FG,2$INPUT: Total number of triangles in model.$FG$
|
||||
|
||||
$FG,2$Example of creating and attaching a vertex shader to a CShader:$FG$
|
||||
|
||||
$HL,1$CShader shd;
|
||||
U0 vShader(CTri *tri, F64 *vertOutBuf, U8 *mdlPtr, U8 *uniforms, I64 iTri, I64 nTris)
|
||||
{
|
||||
// Set *tri with the iTri from mdlPtr.
|
||||
}
|
||||
shd.VertShd = &vShader;$HL,0$
|
||||
|
||||
$FG,5$Fragment Shader$FG$
|
||||
$FG,2$The fragment shader returns the CBGR24 color for a particular fragment (pixel).
|
||||
It takes uniforms as well as interpolated values from the vertex shader to
|
||||
calculate each frag's color.
|
||||
|
||||
For example, each vertex of a triangle may have a UV coordinate pointing to the
|
||||
part of the texture it maps to. The three UV coordinate attributes from the
|
||||
vertex shader will be interpolated into one UV coordinate sent to the fragment
|
||||
shader. The fragment shader can then sample that pixel color from the texture
|
||||
included in the uniforms and return that color. Fragment shaders can be used
|
||||
for all sorts of purposes, including rendering lighting, shadows, warping,
|
||||
color filtering, etc.$FG$
|
||||
|
||||
$HL,1$U0 (*FragShd)(CBGR24 *color, F64 *fragInBuf, U8 *uniforms);$HL,0$
|
||||
|
||||
$FG,2$Fragment shaders can be created and attached in the same way as vertex shaders:$FG$
|
||||
|
||||
$HL,1$CShader shd;
|
||||
U0 fShader(CBGR24 *color, F64 *fragInBuf, U8 *uniforms)
|
||||
{
|
||||
// Set *color using interpolated F64's from fragInBuf and uniforms
|
||||
}
|
||||
shd.FragShd = &fShader;$HL,0$
|
||||
|
||||
|
||||
|
||||
$FG,5$Rendering$FG$
|
||||
$HL,1$#include "Math"
|
||||
#include "Rasterize"
|
||||
$HL,0$
|
||||
$FG,2$After models, textures, and shaders are initialized, you can render with these
|
||||
functions. Currently only triangles can be rendered, however support for all
|
||||
sprite primitives will be added for performance and ease of use (saves the
|
||||
steps of rendering textured triangles to draw 2D primitives like in GPU
|
||||
libraries).$FG$
|
||||
$HL,1$
|
||||
U0 RenderTris(CShader *shd, CTex2D *frameBuf, CTex2D *depthBuf, U8 *mdl, U8 *uniforms, I64 nTris);
|
||||
$HL,0$
|
||||
|
||||
õ
|
||||
¢ÿÿÿ4·ÿÿÿ#ÿ
|
||||
”ÿÿÿÔÿÿÿ
|
||||
”ÿÿÿWÔÿÿÿW
|
||||
”ÿÿÿ”ÿÿÿW
|
||||
ÔÿÿÿÔÿÿÿW´ÿÿÿ7´ÿÿÿ´ÿÿÿ7Óÿÿÿ7´ÿÿÿ7Ëÿÿÿ ¡ÿÿÿY: +1Ùÿÿÿ4X: +1ÐÿÿÿZ: +1ÿÿÿ[-1„ÿÿÿ4-1šÿÿÿJ-1
ANDC maps to texture
|
||||
coordinates when
|
||||
rasterizing.
|
||||
8£8
|
||||
·¸P
|
||||
¸P
P
|
||||
P
|
||||
¸
|
||||
œÿÿÿ*§ÿÿÿB
|
||||
§ÿÿÿBÁÿÿÿ>
|
||||
Áÿÿÿ>œÿÿÿ*
|
||||
Ä+ú=
|
||||
ú=ÎC
|
||||
ÎCÄ+
|
233
src/Zenith/CosmicGL/Draw/Primitive.CC
Normal file
233
src/Zenith/CosmicGL/Draw/Primitive.CC
Normal file
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
@defgroup Draw Draw
|
||||
@brief Functions for drawing to textures.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw pixel on color texture. Does not check boundaries, point
|
||||
must be fully inside texture.
|
||||
|
||||
@param[in,out] tex Color texture to draw to.
|
||||
@param[in] x X position.
|
||||
@param[in] y Y position.
|
||||
@param[in] color Color of point.
|
||||
*/
|
||||
U0 DrawPixel(CTex2D *tex, I64 x, I64 y, CBGR24 color)
|
||||
{
|
||||
tex->rawBuf[x + y * tex->w] = color;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw line on color texture. Does not check boundaries, line must
|
||||
be fully inside texture.
|
||||
|
||||
@param[in,out] tex Color texture to draw to.
|
||||
@param[in] x0 Start x.
|
||||
@param[in] y0 Start y.
|
||||
@param[in] x1 End x.
|
||||
@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)
|
||||
{
|
||||
Bool steep = (Abs(y1 - y0) > Abs(x1 - x0));
|
||||
|
||||
I64 temp;
|
||||
|
||||
if (steep == TRUE)
|
||||
{
|
||||
temp = x0;
|
||||
x0 = y0;
|
||||
y0 = temp;
|
||||
temp = x1;
|
||||
x1 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
if (x0 > x1)
|
||||
{
|
||||
temp = x0;
|
||||
x0 = x1;
|
||||
x1 = temp;
|
||||
temp = y0;
|
||||
y0 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
I64 delta_x = x1 - x0;
|
||||
I64 delta_y = Abs(y1 - y0);
|
||||
I64 error = delta_x / 2;
|
||||
|
||||
I64 step_y;
|
||||
|
||||
if (y0 < y1)
|
||||
{
|
||||
step_y = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
step_y = -1;
|
||||
}
|
||||
|
||||
I64 y = y0;
|
||||
|
||||
|
||||
I64 x;
|
||||
for (x = x0; x < (x1 + 1); x++)
|
||||
{
|
||||
if (steep == TRUE)
|
||||
{
|
||||
tex->rawBuf[y + x * tex->w] = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
tex->rawBuf[x + y * tex->w] = color;
|
||||
}
|
||||
|
||||
error -= delta_y;
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
y += step_y;
|
||||
error += delta_x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw single color triangle to color texture. Does not check
|
||||
boundaries, triangle must be fully inside texture.
|
||||
|
||||
@param[in,out] tex Color texture to draw to.
|
||||
@param[in] x0 First vertex x.
|
||||
@param[in] y0 First vertex y.
|
||||
@param[in] x1 Second vertex x.
|
||||
@param[in] y1 Second vertex y.
|
||||
@param[in] x2 Third vertex x.
|
||||
@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,
|
||||
CBGR24 color)
|
||||
{
|
||||
I64 temp;
|
||||
F64 ftemp;
|
||||
|
||||
if (y0 > y1)
|
||||
{
|
||||
temp = x0;
|
||||
x0 = x1;
|
||||
x1 = temp;
|
||||
temp = y0;
|
||||
y0 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
if (y0 > y2)
|
||||
{
|
||||
temp = x0;
|
||||
x0 = x2;
|
||||
x2 = temp;
|
||||
temp = y0;
|
||||
y0 = y2;
|
||||
y2 = temp;
|
||||
}
|
||||
|
||||
if (y1 > y2)
|
||||
{
|
||||
temp = x1;
|
||||
x1 = x2;
|
||||
x2 = temp;
|
||||
temp = y1;
|
||||
y1 = 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;
|
||||
|
||||
// Bottom Half
|
||||
if (y0 != y1)
|
||||
{
|
||||
x_delta = (x1 - x0);
|
||||
y_delta = (y1 - y0);
|
||||
left_delta = x_delta / y_delta;
|
||||
x_delta = (x2 - x0);
|
||||
y_delta = (y2 - y0);
|
||||
right_delta = x_delta / y_delta;
|
||||
|
||||
if (left_delta > right_delta)
|
||||
{
|
||||
ftemp = left_delta;
|
||||
left_delta = right_delta;
|
||||
right_delta = ftemp;
|
||||
}
|
||||
|
||||
left_x = x0;
|
||||
right_x = x0;
|
||||
|
||||
middle_line_drawn = TRUE;
|
||||
|
||||
for (y = y0; y < (y1 + 1); y++)
|
||||
{
|
||||
lX = left_x + 0.5;
|
||||
rX = right_x + 0.5;
|
||||
left_index = y * tex->w + lX;
|
||||
right_index = y * tex->w + rX;
|
||||
width = right_index - left_index;
|
||||
MemSetU32(tex->rawBuf + left_index, color, width);
|
||||
left_x += left_delta;
|
||||
right_x += right_delta;
|
||||
}
|
||||
}
|
||||
|
||||
// Top Half
|
||||
if (y1 != y2)
|
||||
{
|
||||
x_delta = -(x1 - x2);
|
||||
y_delta = (y1 - y2);
|
||||
left_delta = x_delta / y_delta;
|
||||
x_delta = -(x0 - x2);
|
||||
y_delta = (y0 - y2);
|
||||
right_delta = x_delta / y_delta;
|
||||
|
||||
if (left_delta > right_delta)
|
||||
{
|
||||
ftemp = left_delta;
|
||||
left_delta = right_delta;
|
||||
right_delta = ftemp;
|
||||
}
|
||||
|
||||
left_x = x2;
|
||||
right_x = x2;
|
||||
|
||||
if (middle_line_drawn == TRUE)
|
||||
{
|
||||
y1 += 1;
|
||||
}
|
||||
|
||||
for (y = y2; y > (y1 - 1); y--)
|
||||
{
|
||||
lX = left_x + 0.5;
|
||||
rX = right_x + 0.5;
|
||||
left_index = y * tex->w + lX;
|
||||
right_index = y * tex->w + rX;
|
||||
width = right_index - left_index;
|
||||
MemSetU32(tex->rawBuf + left_index, color, width);
|
||||
left_x += left_delta;
|
||||
right_x += right_delta;
|
||||
}
|
||||
}
|
||||
}
|
165
src/Zenith/CosmicGL/Draw/Rectangle.CC
Normal file
165
src/Zenith/CosmicGL/Draw/Rectangle.CC
Normal file
|
@ -0,0 +1,165 @@
|
|||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw single color rectangle.
|
||||
|
||||
@param[in,out] tex Texture to draw to.
|
||||
@param[in] x0 Start corner x.
|
||||
@param[in] y0 Start corner y.
|
||||
@param[in] x1 End corner x.
|
||||
@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)
|
||||
{
|
||||
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 y;
|
||||
for (y = yMin; y < yMax; y++)
|
||||
{
|
||||
MemSetU32(&tex->rawBuf[xMin + y * tex->w], color, xLen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw 1px soft rectangle outline (corners not filled).
|
||||
|
||||
@param[in,out] tex Texture to draw to.
|
||||
@param[in] x0 Start corner x.
|
||||
@param[in] y0 Start corner y.
|
||||
@param[in] x1 End corner x.
|
||||
@param[in] y1 End corner y.
|
||||
@param[in] color Color of rectangle.
|
||||
@param[in] shadeColor (Optional) color of bottom right corner
|
||||
for shading effect.
|
||||
*/
|
||||
U0 DrawRectSoftOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
|
||||
CBGR24 color, CBGR24 shadeColor = 0x7FFFFFFF)
|
||||
{
|
||||
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;
|
||||
|
||||
// Top border
|
||||
MemSetU32(&tex->rawBuf[xMin + 1 + yMin * tex->w], color, xLen);
|
||||
|
||||
// Bottom border
|
||||
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;
|
||||
tex->rawBuf[xMax + y * tex->w] = shadeColor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw 1px rectangle outline.
|
||||
|
||||
@param[in,out] tex Texture to draw to.
|
||||
@param[in] x0 Start corner x.
|
||||
@param[in] y0 Start corner y.
|
||||
@param[in] x1 End corner x.
|
||||
@param[in] y1 End corner y.
|
||||
@param[in] color Color of rectangle.
|
||||
@param[in] shadeColor (Optional) color of bottom right corner
|
||||
for shading effect.
|
||||
*/
|
||||
U0 DrawRectOutline(CTex2D *tex, I64 x0, I64 y0, I64 x1, I64 y1,
|
||||
CBGR24 color, CBGR24 shadeColor = 0x7FFFFFFF)
|
||||
{
|
||||
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;
|
||||
|
||||
// Top border
|
||||
MemSetU32(&tex->rawBuf[xMin + yMin * tex->w], color, xLen);
|
||||
|
||||
// Bottom border
|
||||
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;
|
||||
tex->rawBuf[xMax + y * tex->w] = shadeColor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw two color vertical gradient rectangle.
|
||||
|
||||
@param[in,out] tex Texture to draw to.
|
||||
@param[in] x0 Start corner x.
|
||||
@param[in] y0 Start corner y.
|
||||
@param[in] x1 End corner x.
|
||||
@param[in] y1 End corner y.
|
||||
@param[in] colorTop Top color of gradient.
|
||||
@param[in] colorBottom Bottom color of gradient.
|
||||
@param[in] shadeColor (Optional) color of bottom right corner
|
||||
for shading effect.
|
||||
@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,
|
||||
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;
|
||||
for (y = yMin; y < yMax; y++)
|
||||
{
|
||||
t = Clamp((y - yMinReal) / yHeight, tStart, tEnd);
|
||||
r = t * rDiff;
|
||||
g = t * gDiff;
|
||||
b = t * bDiff;
|
||||
color.r = colorTop.r + r;
|
||||
color.g = colorTop.g + g;
|
||||
color.b = colorTop.b + b;
|
||||
MemSetU32(&tex->rawBuf[xMin + y * tex->w], color, xLen);
|
||||
}
|
||||
}
|
86
src/Zenith/CosmicGL/Draw/Text.CC
Normal file
86
src/Zenith/CosmicGL/Draw/Text.CC
Normal file
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw a single color character to color texture.
|
||||
|
||||
@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,
|
||||
U64 *font = text.font)
|
||||
{
|
||||
// Check if off-screen
|
||||
if (x >= tex->w || x <= -FONT_WIDTH)
|
||||
return;
|
||||
|
||||
I64 i, j;
|
||||
for (j = 0; j < FONT_HEIGHT; j++)
|
||||
{
|
||||
for (i = 0; i < FONT_WIDTH; i++)
|
||||
{
|
||||
if (font[char].u8[j] & (1 << i))
|
||||
tex->rawBuf[x + i + (y + j) * tex->w] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw a single color string to color texture.
|
||||
|
||||
@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,
|
||||
U64 *font = text.font)
|
||||
{
|
||||
I64 cur = 0; // String cursor
|
||||
I64 xCur = x; // Screen cursors
|
||||
I64 yCur = y;
|
||||
U8 char = 0; // Character to draw
|
||||
|
||||
while (str[cur] != NULL)
|
||||
{
|
||||
switch (str[cur])
|
||||
{
|
||||
// Escape sequence
|
||||
case '\\':
|
||||
"ESCAPE SEQ\n";
|
||||
switch (str[cur + 1])
|
||||
{
|
||||
case 'n':
|
||||
xCur = x;
|
||||
yCur += FONT_HEIGHT;
|
||||
"NEWLINE\n";
|
||||
break;
|
||||
|
||||
// Not a real tab, but what mong uses tabs in labels?
|
||||
case 't':
|
||||
xCur += FONT_WIDTH * 4;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
DrawChar(tex, xCur, yCur, '\\', color, font);
|
||||
xCur += FONT_WIDTH;
|
||||
break;
|
||||
|
||||
}
|
||||
cur += 2;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
cur++;
|
||||
xCur += FONT_WIDTH;
|
||||
break;
|
||||
|
||||
default:
|
||||
DrawChar(tex, xCur, yCur, str[cur], color, font);
|
||||
cur++;
|
||||
xCur += FONT_WIDTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
47
src/Zenith/CosmicGL/Draw/Texture.CC
Normal file
47
src/Zenith/CosmicGL/Draw/Texture.CC
Normal file
|
@ -0,0 +1,47 @@
|
|||
|
||||
/**
|
||||
@ingroup Draw
|
||||
@brief Draw non-transformed color texture with blit operation.
|
||||
|
||||
Does not yet check if texture being drawn is entirely inside the texture
|
||||
being drawn to.
|
||||
|
||||
@param[in,out] dst Destination texture to draw to.
|
||||
@param[in] src Source texture to draw.
|
||||
@param[in] x X location to draw texture.
|
||||
@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,
|
||||
Bool transparent = FALSE)
|
||||
{
|
||||
I64 xC, yC; // Current width/height position being copied from
|
||||
|
||||
I64 srcW = src->w; // Don't think the compiler is optimizing this so I am
|
||||
I64 srcH = src->h;
|
||||
I64 dstW = dst->w;
|
||||
|
||||
if (transparent)
|
||||
{
|
||||
for (yC = 0; yC < srcH; yC++)
|
||||
{
|
||||
for (xC = 0; xC < srcW; xC++)
|
||||
{
|
||||
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] =
|
||||
src->rawBuf[xC + yC * srcW];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (yC = 0; yC < srcH; yC++)
|
||||
{
|
||||
MemCopy(&dst->rawBuf[x + (y + yC) * dstW],
|
||||
&src->rawBuf[yC * srcW], sizeof(CBGR24) * srcW);
|
||||
}
|
||||
}
|
||||
}
|
25
src/Zenith/CosmicGL/Draw/UIIrix.CC
Normal file
25
src/Zenith/CosmicGL/Draw/UIIrix.CC
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
/* Draws text button, returns col/row for next button in nCol/nRow. */
|
||||
U0 DrawTextButton(CTex2D *tex, I64 col, I64 row, U8 *str, I64 size = 0,
|
||||
I64 *nCol = NULL, I64 *nRow = NULL)
|
||||
{
|
||||
if (size == 0)
|
||||
size = StrLen(str);
|
||||
|
||||
I64 x = col * FONT_WIDTH;
|
||||
I64 y = row * FONT_HEIGHT;
|
||||
|
||||
DrawRectSoftOutline(tex, x - 3, y - 3, x + 1 + size * FONT_WIDTH,
|
||||
y + FONT_HEIGHT + 1, gr_palette[DKGRAY]);
|
||||
|
||||
DrawRectVertGradient(tex, x - 2, y - 2, x + 1 + size * FONT_WIDTH,
|
||||
y + FONT_HEIGHT + 1, gr_palette[DKGRAY], gr_palette[WHITE]);
|
||||
|
||||
DrawString(tex, x, y, str, gr_palette[BLACK ]);
|
||||
|
||||
if (nCol != NULL)
|
||||
*nCol += size + 1;
|
||||
|
||||
if (nRow != NULL)
|
||||
*nRow += 2;
|
||||
}
|
42
src/Zenith/CosmicGL/Draw/UISmooth.CC
Normal file
42
src/Zenith/CosmicGL/Draw/UISmooth.CC
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
// Color palette indexing
|
||||
#define C_BCKGND 0
|
||||
#define C_BCKGNDLIGHT 1 // Light for highlights
|
||||
#define C_BCKGNDSHD 2 // Shade for shadows
|
||||
#define C_TEXT 3
|
||||
|
||||
CBGR24 palette[4] =
|
||||
{
|
||||
0x282828, // C_BCKGND
|
||||
0x383838, // C_BCKGNDLIGHT
|
||||
0x101010, // C_BCKGNDSHD
|
||||
0xFFFFFF // C_TEXT
|
||||
};
|
||||
|
||||
|
||||
/* Draws text button, returns col/row for next button in nCol/nRow. */
|
||||
U0 DrawTextButton(CTex2D *tex, I64 col, I64 row, U8 *str, I64 size = 0,
|
||||
I64 *nCol = NULL, I64 *nRow = NULL)
|
||||
{
|
||||
if (size == 0)
|
||||
size = StrLen(str);
|
||||
|
||||
I64 x = col * FONT_WIDTH;
|
||||
I64 y = row * FONT_HEIGHT;
|
||||
|
||||
CBGR24 blue = 0x0000FF;
|
||||
DrawRectSoftOutline(tex, x - 3, y - 3, x + 1 + size * FONT_WIDTH,
|
||||
y + FONT_HEIGHT + 1, palette[C_BCKGNDLIGHT]);
|
||||
|
||||
DrawRectVertGradient(tex, x - 2, y - 2, x + 1 + size * FONT_WIDTH,
|
||||
y + FONT_HEIGHT + 1, palette[C_BCKGNDLIGHT], palette[C_BCKGND]);
|
||||
|
||||
DrawString(tex, x, y, str, palette[C_TEXT]);
|
||||
|
||||
if (nCol != NULL)
|
||||
*nCol += size + 1;
|
||||
|
||||
if (nRow != NULL)
|
||||
*nRow += 2;
|
||||
}
|
||||
|
17
src/Zenith/CosmicGL/MakeCosmicGL.CC
Normal file
17
src/Zenith/CosmicGL/MakeCosmicGL.CC
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* Include this file to rebuild the CosmicGL library. */
|
||||
|
||||
Cd(__DIR__);;
|
||||
#include "Math/Math"
|
||||
#include "Texture/Texture"
|
||||
#include "Draw/Primitive"
|
||||
#include "Draw/Texture"
|
||||
#include "Draw/Rectangle"
|
||||
#include "Draw/Text"
|
||||
#include "Draw/UISmooth"
|
||||
#include "Render/Shader"
|
||||
#include "Render/Rasterize"
|
||||
#include "WAD/WADTypes"
|
||||
#include "WAD/WAD"
|
||||
#include "Texture/TextureImport"
|
||||
#include "WAD/DoomTypes"
|
||||
#include "WAD/DoomMap"
|
382
src/Zenith/CosmicGL/Math/Math.CC
Normal file
382
src/Zenith/CosmicGL/Math/Math.CC
Normal file
|
@ -0,0 +1,382 @@
|
|||
/* Legacy math library. Is being replaced\, however it will remain
|
||||
until Rasterize.CC is ported over to the new math library. */
|
||||
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
class CMat4
|
||||
{
|
||||
F64 e[4][4];
|
||||
};
|
||||
|
||||
CVec3 *Add3(CVec3 *a, CVec3 *b)
|
||||
{
|
||||
CVec3 *c = MAlloc(sizeof(CVec3));
|
||||
c->x = a->x + b->x;
|
||||
c->y = a->y + b->y;
|
||||
c->z = a->z + b->z;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec2 *Add2(CVec2 *a, CVec2 *b)
|
||||
{
|
||||
CVec2 *c = MAlloc(sizeof(CVec2));
|
||||
c->x = a->x + b->x;
|
||||
c->y = a->y + b->y;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec3 *Sub3(CVec3 *a, CVec3 *b)
|
||||
{
|
||||
CVec3 *c = MAlloc(sizeof(CVec3));
|
||||
c->x = a->x - b->x;
|
||||
c->y = a->y - b->y;
|
||||
c->z = a->z - b->z;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec2 *Sub2(CVec2 *a, CVec2 *b)
|
||||
{
|
||||
CVec2 *c = MAlloc(sizeof(CVec2));
|
||||
c->x = a->x - b->x;
|
||||
c->y = a->y - b->y;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec3 *Div3S(CVec3 *a, F64 b)
|
||||
{
|
||||
CVec3 *c = MAlloc(sizeof(CVec3));
|
||||
c->x = a->x / b;
|
||||
c->y = a->y / b;
|
||||
c->z = a->z / b;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec2 *Div2S(CVec2 *a, F64 b)
|
||||
{
|
||||
CVec2 *c = MAlloc(sizeof(CVec2));
|
||||
c->x = a->x / b;
|
||||
c->y = a->y / b;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec4 *Mul4S(CVec4 *a, F64 b)
|
||||
{
|
||||
CVec4 *c = MAlloc(sizeof(CVec4));
|
||||
c->x = a->x * b;
|
||||
c->y = a->y * b;
|
||||
c->z = a->z * b;
|
||||
c->w = a->w * b;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec3 *Mul3S(CVec3 *a, F64 b)
|
||||
{
|
||||
CVec3 *c = MAlloc(sizeof(CVec3));
|
||||
c->x = a->x * b;
|
||||
c->y = a->y * b;
|
||||
c->z = a->z * b;
|
||||
return c;
|
||||
}
|
||||
|
||||
CVec2 *Mul2S(CVec2 *a, F64 b)
|
||||
{
|
||||
CVec2 *c = MAlloc(sizeof(CVec2));
|
||||
c->x = a->x * b;
|
||||
c->y = a->y * b;
|
||||
return c;
|
||||
}
|
||||
|
||||
F64 Dot3(CVec3 *a, CVec3 *b)
|
||||
{
|
||||
return (a->x * b->x) + (a->y * b->y) + (a->z * b->z);
|
||||
}
|
||||
|
||||
F64 Dot2(CVec2 *a, CVec2 *b)
|
||||
{
|
||||
return (a->x * b->x) + (a->y * b->y);
|
||||
}
|
||||
|
||||
CVec3 *Norm3(CVec3 *a)
|
||||
{
|
||||
F64 length = Sqrt(Sqr(a->x) + Sqr(a->y) + Sqr(a->z));
|
||||
a->x /= length;
|
||||
a->y /= length;
|
||||
a->z /= length;
|
||||
return a;
|
||||
}
|
||||
|
||||
CVec2 *Norm2(CVec2 *a)
|
||||
{
|
||||
F64 length = Sqrt(Sqr(a->x) + Sqr(a->y));
|
||||
a->x /= length;
|
||||
a->y /= length;
|
||||
return a;
|
||||
}
|
||||
|
||||
// Create direction Vec4 from Vec3
|
||||
CVec4 *Vec4Dir(CVec3 *a)
|
||||
{
|
||||
CVec4 *b = MAlloc(sizeof(CVec4));
|
||||
MemCopy(b, a, 24);
|
||||
b->w = 0;
|
||||
return b;
|
||||
}
|
||||
|
||||
// Create position Vec4 from Vec3
|
||||
CVec4 *Vec4Pos(CVec3 *a)
|
||||
{
|
||||
CVec4 *b = MAlloc(sizeof(CVec4));
|
||||
MemCopy(b, a, 24);
|
||||
b->w = 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
// Create Vec3 from Vec4
|
||||
CVec3 *Vec3Pos(CVec4 *a)
|
||||
{
|
||||
CVec3 *b = MAlloc(sizeof(CVec3));
|
||||
MemCopy(b, a, 24);
|
||||
return b;
|
||||
}
|
||||
|
||||
CVec4 *MulM44(CMat4 *a, CVec4 *b)
|
||||
{
|
||||
CVec4 *c = MAlloc(sizeof(CVec4));
|
||||
c->x = (a->e[0][0] * b->x) + (a->e[0][1] * b->y) + (a->e[0][2] * b->z) + (a->e[0][3] * b->w);
|
||||
c->y = (a->e[1][0] * b->x) + (a->e[1][1] * b->y) + (a->e[1][2] * b->z) + (a->e[1][3] * b->w);
|
||||
c->z = (a->e[2][0] * b->x) + (a->e[2][1] * b->y) + (a->e[2][2] * b->z) + (a->e[2][3] * b->w);
|
||||
c->w = (a->e[3][0] * b->x) + (a->e[3][1] * b->y) + (a->e[3][2] * b->z) + (a->e[3][3] * b->w);
|
||||
return c;
|
||||
}
|
||||
|
||||
CMat4 *MulM4M4(CMat4 *a, CMat4 *b)
|
||||
{
|
||||
CMat4 *c = MAlloc(sizeof(CMat4));
|
||||
c->e[0][0] = (a->e[0][0] * b->e[0][0])+(a->e[0][1] * b->e[1][0])+(a->e[0][2] * b->e[2][0])+(a->e[0][3] * b->e[3][0]);
|
||||
c->e[0][1] = (a->e[0][0] * b->e[0][1])+(a->e[0][1] * b->e[1][1])+(a->e[0][2] * b->e[2][1])+(a->e[0][3] * b->e[3][1]);
|
||||
c->e[0][2] = (a->e[0][0] * b->e[0][2])+(a->e[0][1] * b->e[1][2])+(a->e[0][2] * b->e[2][2])+(a->e[0][3] * b->e[3][2]);
|
||||
c->e[0][3] = (a->e[0][0] * b->e[0][3])+(a->e[0][1] * b->e[1][3])+(a->e[0][2] * b->e[2][3])+(a->e[0][3] * b->e[3][3]);
|
||||
|
||||
c->e[1][0] = (a->e[1][0] * b->e[0][0])+(a->e[1][1] * b->e[1][0])+(a->e[1][2] * b->e[2][0])+(a->e[1][3] * b->e[3][0]);
|
||||
c->e[1][1] = (a->e[1][0] * b->e[0][1])+(a->e[1][1] * b->e[1][1])+(a->e[1][2] * b->e[2][1])+(a->e[1][3] * b->e[3][1]);
|
||||
c->e[1][2] = (a->e[1][0] * b->e[0][2])+(a->e[1][1] * b->e[1][2])+(a->e[1][2] * b->e[2][2])+(a->e[1][3] * b->e[3][2]);
|
||||
c->e[1][3] = (a->e[1][0] * b->e[0][3])+(a->e[1][1] * b->e[1][3])+(a->e[1][2] * b->e[2][3])+(a->e[1][3] * b->e[3][3]);
|
||||
|
||||
c->e[2][0] = (a->e[2][0] * b->e[0][0])+(a->e[2][1] * b->e[1][0])+(a->e[2][2] * b->e[2][0])+(a->e[2][3] * b->e[3][0]);
|
||||
c->e[2][1] = (a->e[2][0] * b->e[0][1])+(a->e[2][1] * b->e[1][1])+(a->e[2][2] * b->e[2][1])+(a->e[2][3] * b->e[3][1]);
|
||||
c->e[2][2] = (a->e[2][0] * b->e[0][2])+(a->e[2][1] * b->e[1][2])+(a->e[2][2] * b->e[2][2])+(a->e[2][3] * b->e[3][2]);
|
||||
c->e[2][3] = (a->e[2][0] * b->e[0][3])+(a->e[2][1] * b->e[1][3])+(a->e[2][2] * b->e[2][3])+(a->e[2][3] * b->e[3][3]);
|
||||
|
||||
c->e[3][0] = (a->e[3][0] * b->e[0][0])+(a->e[3][1] * b->e[1][0])+(a->e[3][2] * b->e[2][0])+(a->e[3][3] * b->e[3][0]);
|
||||
c->e[3][1] = (a->e[3][0] * b->e[0][1])+(a->e[3][1] * b->e[1][1])+(a->e[3][2] * b->e[2][1])+(a->e[3][3] * b->e[3][1]);
|
||||
c->e[3][2] = (a->e[3][0] * b->e[0][2])+(a->e[3][1] * b->e[1][2])+(a->e[3][2] * b->e[2][2])+(a->e[3][3] * b->e[3][2]);
|
||||
c->e[3][3] = (a->e[3][0] * b->e[0][3])+(a->e[3][1] * b->e[1][3])+(a->e[3][2] * b->e[2][3])+(a->e[3][3] * b->e[3][3]);
|
||||
return c;
|
||||
}
|
||||
|
||||
// Normalized Vec4 to RGBA
|
||||
U0 Vec4Col(CVec4 *col, CBGR24 *bgrcol)
|
||||
{
|
||||
bgrcol->r = (col->x * 255.0);
|
||||
bgrcol->g = (col->y * 255.0);
|
||||
bgrcol->b = (col->z * 255.0);
|
||||
bgrcol->pad = (col->w * 255.0);
|
||||
}
|
||||
|
||||
// Normalized Vec3 to RGBA
|
||||
U0 Vec3Col(CVec3 *col, CBGR24 *bgrcol)
|
||||
{
|
||||
bgrcol->r = (col->x * 255.0);
|
||||
bgrcol->g = (col->y * 255.0);
|
||||
bgrcol->b = (col->z * 255.0);
|
||||
bgrcol->pad = 255.0;
|
||||
}
|
||||
|
||||
U0 Barycentric2(CVec2 *p, CVec2 *a, CVec2 *b, CVec2 *c, F64 *u, F64 *v, F64 *w)
|
||||
{
|
||||
CVec2 *v0 = Sub2(b, a);
|
||||
CVec2 *v1 = Sub2(c, a);
|
||||
CVec2 *v2 = Sub2(p, a);
|
||||
|
||||
F64 d00 = Dot2(v0, v0);
|
||||
F64 d01 = Dot2(v0, v1);
|
||||
F64 d11 = Dot2(v1, v1);
|
||||
F64 d20 = Dot2(v2, v0);
|
||||
F64 d21 = Dot2(v2, v1);
|
||||
F64 denom = d00 * d11 - d01 * d01;
|
||||
*v = (d11 * d20 - d01 * d21)/denom;
|
||||
*w = (d00 * d21 - d01 * d20)/denom;
|
||||
*u = 1.0 - *v - *w;
|
||||
|
||||
Free(v0);
|
||||
Free(v1);
|
||||
Free(v2);
|
||||
}
|
||||
|
||||
CVec2 Ayy,Bee,Cee, P;
|
||||
Ayy.x = 0;
|
||||
Ayy.y = 0;
|
||||
Bee.x = 3;
|
||||
Bee.y = 0;
|
||||
Cee.x = 0;
|
||||
Cee.y = 3;
|
||||
|
||||
U0 SetTranslateM4(CMat4 *mat, CVec3 *translation)
|
||||
{
|
||||
MemSet(mat, 0, sizeof(CMat4));
|
||||
mat->e[0][0] = 1;
|
||||
mat->e[1][1] = 1;
|
||||
mat->e[2][2] = 1;
|
||||
mat->e[3][3] = 1;
|
||||
mat->e[0][3] = translation->x;
|
||||
mat->e[1][3] = translation->y;
|
||||
mat->e[2][3] = translation->z;
|
||||
}
|
||||
|
||||
U0 SetScaleM4(CMat4 *mat, CVec3 *scale)
|
||||
{
|
||||
MemSet(mat, 0, sizeof(CMat4));
|
||||
mat->e[0][0] = scale->x;
|
||||
mat->e[1][1] = scale->y;
|
||||
mat->e[2][2] = scale->z;
|
||||
mat->e[3][3] = 1;
|
||||
}
|
||||
|
||||
U0 SetRotXM4(CMat4 *mat, F64 rot)
|
||||
{
|
||||
MemSet(mat, 0, sizeof(CMat4));
|
||||
mat->e[0][0] = 1;
|
||||
mat->e[3][3] = 1;
|
||||
F64 x = Cos(rot);
|
||||
F64 y = Sin(rot);
|
||||
mat->e[1][1] = x;
|
||||
mat->e[1][2] = -y;
|
||||
mat->e[2][1] = y;
|
||||
mat->e[2][2] = x;
|
||||
}
|
||||
|
||||
U0 SetRotYM4(CMat4 *mat, F64 rot)
|
||||
{
|
||||
MemSet(mat, 0, sizeof(CMat4));
|
||||
mat->e[1][1] = 1;
|
||||
mat->e[3][3] = 1;
|
||||
F64 x = Cos(rot);
|
||||
F64 y = Sin(rot);
|
||||
mat->e[0][0] = x;
|
||||
mat->e[0][2] = y;
|
||||
mat->e[2][0] = -y;
|
||||
mat->e[2][2] = x;
|
||||
}
|
||||
|
||||
U0 SetRotZM4(CMat4 *mat, F64 rot)
|
||||
{
|
||||
MemSet(mat, 0, sizeof(CMat4));
|
||||
mat->e[2][2] = 1;
|
||||
mat->e[3][3] = 1;
|
||||
F64 x = Cos(rot);
|
||||
F64 y = Sin(rot);
|
||||
mat->e[0][0] = x;
|
||||
mat->e[0][1] = -y;
|
||||
mat->e[1][0] = y;
|
||||
mat->e[1][1] = x;
|
||||
}
|
||||
|
||||
U0 TranslateM4(CMat4 *mat, CVec3 *translation)
|
||||
{
|
||||
// Generate CMat4 translation matrix
|
||||
CMat4 *translateMat = MAlloc(sizeof(CMat4));
|
||||
SetTranslateM4(translateMat, translation);
|
||||
|
||||
|
||||
CMat4 *finalMat = MulM4M4(mat, translateMat);
|
||||
MemCopy(mat, finalMat, sizeof(CMat4));
|
||||
Free(finalMat);
|
||||
Free(translateMat);
|
||||
}
|
||||
|
||||
U0 F32toF64(U32 *float, U64 *double)
|
||||
{
|
||||
MemCopy(&double->u32[1], float, 4);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
29
src/Zenith/CosmicGL/Math/Types.CC
Normal file
29
src/Zenith/CosmicGL/Math/Types.CC
Normal file
|
@ -0,0 +1,29 @@
|
|||
class CVec2
|
||||
{
|
||||
F64 x, y;
|
||||
};
|
||||
|
||||
class CIVec2
|
||||
{
|
||||
I64 x, y;
|
||||
};
|
||||
|
||||
class CVec3
|
||||
{
|
||||
F64 x, y, z;
|
||||
};
|
||||
|
||||
class CIVec3
|
||||
{
|
||||
I64 x, y, z;
|
||||
};
|
||||
|
||||
class CVec4
|
||||
{
|
||||
F64 x, y, z, w;
|
||||
};
|
||||
|
||||
class CIVec4
|
||||
{
|
||||
I64 x, y, z, w;
|
||||
};
|
318
src/Zenith/CosmicGL/Math/Vec2.CC
Normal file
318
src/Zenith/CosmicGL/Math/Vec2.CC
Normal file
|
@ -0,0 +1,318 @@
|
|||
/* Initialize CVec2 from F64 pointer. */
|
||||
U0 Vec2(F64 *a, CVec2 *o)
|
||||
{
|
||||
o->x = a[0];
|
||||
o->y = a[1];
|
||||
}
|
||||
|
||||
/* Copy CVec2 into CVec2. */
|
||||
U0 Copy2(CVec2 *a, CVec2 *o)
|
||||
{
|
||||
o->x = a->x;
|
||||
o->y = a->y;
|
||||
}
|
||||
|
||||
/* Fill CVec2 with F64 */
|
||||
U0 Fill2S(CVec2 *v, F64 val)
|
||||
{
|
||||
v->x = v->y = val;
|
||||
}
|
||||
|
||||
/* Fill CIVec2 with I64 */
|
||||
U0 FillI2S(CIVec2 *v, I64 val)
|
||||
{
|
||||
v->x = v->y = val;
|
||||
}
|
||||
|
||||
/* Clear CVec2 with zeros. */
|
||||
U0 Zero2(CVec2 *v)
|
||||
{
|
||||
v->x = v->y = 0.0;
|
||||
}
|
||||
|
||||
/* Clear CVec2 with ones. */
|
||||
U0 One2(CVec2 *v)
|
||||
{
|
||||
v->x = v->y = 1.0;
|
||||
}
|
||||
|
||||
/* Dot product of two CVec2. */
|
||||
U0 Dot2(CVec2 *a, CVec2 *b, F64 *o)
|
||||
{
|
||||
*o = (a->x * b->x) + (a->y * b->y);
|
||||
}
|
||||
|
||||
/* Z component of cross product of two CVec2. */
|
||||
U0 Cross2(CVec2 *a, CVec2 *b, F64 *o)
|
||||
{
|
||||
*o = (a->x * b->y) - (a->y * b->x);
|
||||
}
|
||||
|
||||
/* Norm^2 (magnitude^2) of CVec2. */
|
||||
U0 NormSqr2(CVec2 *a, F64 *o)
|
||||
{
|
||||
*o = Sqr(a->x) + Sqr(a->y);
|
||||
}
|
||||
|
||||
/* Norm (magnitude) of CVec2. */
|
||||
U0 Norm2(CVec2 *a, F64 *o)
|
||||
{
|
||||
*o = Sqrt(Sqr(v->x) + Sqr(v->y));
|
||||
}
|
||||
|
||||
/* Add CVec2 to CVec2. */
|
||||
U0 Add2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x + b->x;
|
||||
o->y = a->y + b->y;
|
||||
}
|
||||
|
||||
/* Add CVec2 to F64. */
|
||||
U0 Add2S(CVec2 *a, F64 b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x + b;
|
||||
o->y = a->y + b;
|
||||
}
|
||||
|
||||
/* Sub CVec2 from CVec2. */
|
||||
U0 Sub2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x - b->x;
|
||||
o->y = a->y - b->y;
|
||||
}
|
||||
|
||||
/* Sub CVec2 from F64. */
|
||||
U0 Sub2S(CVec2 *a, F64 b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x - b;
|
||||
o->y = a->y - b;
|
||||
}
|
||||
|
||||
/* Multiply CVec2 with CVec2. */
|
||||
U0 Mul2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x * b->x;
|
||||
o->y = a->y * b->y;
|
||||
}
|
||||
|
||||
/* Scale CVec2 by F64. */
|
||||
U0 Scale2S(CVec2 *a, F64 b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x * b;
|
||||
o->y = a->y * b;
|
||||
}
|
||||
|
||||
/* Scale CVec2 unit vector by F64. */
|
||||
U0 ScaleUnit2(CVec2 *a, F64 b, CVec2 *o)
|
||||
{
|
||||
// Norm2(a, &norm)
|
||||
F64 norm = Sqrt(Sqr(a->x) + Sqr(a->y));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero2(a)
|
||||
a->x = a->y = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale2(a, b / norm, o);
|
||||
F64 scale = b / norm;
|
||||
o->x = a->x * scale;
|
||||
o->y = a->y * scale;
|
||||
}
|
||||
|
||||
/* Divide CVec2 by CVec2. */
|
||||
U0 Div2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x / b->x;
|
||||
o->y = b->y / b->y;
|
||||
}
|
||||
|
||||
/* Divide CVec2 by F64. */
|
||||
U0 Div2S(CVec2 *a, F64 b, CVec2 *o)
|
||||
{
|
||||
o->x = a->x / b;
|
||||
o->y = a->y / b;
|
||||
}
|
||||
|
||||
/* Square root of CVec2 components. */
|
||||
U0 Sqrt2(CVec2 *a, CVec2 *o)
|
||||
{
|
||||
o->x = Sqrt(a->x);
|
||||
o->y = Sqrt(a->y);
|
||||
}
|
||||
|
||||
/* Sign of components as -1, 0, or 1. */
|
||||
U0 Sign2(CVec2 *a, CVec2 *o)
|
||||
{
|
||||
o->x = ((o->x > 0.0) - (val < 0.0));
|
||||
o->y = ((o->y > 0.0) - (val < 0.0));
|
||||
}
|
||||
|
||||
/* Add CVec2 to CVec2 to output CVec2. */
|
||||
U0 AddAdd2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x += a->x + b->x;
|
||||
o->y += a->y + b->y;
|
||||
}
|
||||
|
||||
/* Subtract CVec2 from CVec2, add to output CVec2. */
|
||||
U0 SubAdd2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x += a->x - b->x;
|
||||
o->y += a->y - b->y;
|
||||
}
|
||||
|
||||
/* Multiply CVec2 by CVec2, add to output CVec2. */
|
||||
U0 MulAdd2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x += a->x * b->x;
|
||||
o->y += a->y * b->y;
|
||||
}
|
||||
/* Multiply CVec2 by F64, add to output CVec2. */
|
||||
U0 MulAdd2S(CVec2 *a, F64 b, CVec2 *o)
|
||||
{
|
||||
o->x += a->x * b;
|
||||
o->y += a->y * b;
|
||||
}
|
||||
|
||||
/* Add maximum of each CVec2 component to output CVec2. */
|
||||
U0 MaxAdd2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x += Max(a->x, b->x);
|
||||
o->y += Max(a->y, b->y);
|
||||
}
|
||||
|
||||
/* Add minimum of each CVec2 component to output CVec2. */
|
||||
U0 MinAdd2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x += Min(a->x, b->x);
|
||||
o->y += Min(a->y, b->y);
|
||||
}
|
||||
|
||||
/* Negate vector components (*-1) to output CVec2. */
|
||||
U0 NegateTo2(CVec2 *a, CVec2 *o)
|
||||
{
|
||||
o->x = -a->x;
|
||||
o->y = -a->y;
|
||||
}
|
||||
|
||||
/* Negate vector components (*-1). */
|
||||
U0 Negate2(CVec2 *v)
|
||||
{
|
||||
v->x = -v->x;
|
||||
v->y = -v->y;
|
||||
}
|
||||
|
||||
/* Normalize CVec2 to output CVec2. */
|
||||
U0 NormalizeTo2(CVec2 *a, CVec2 *o)
|
||||
{
|
||||
// Norm2(a, &norm)
|
||||
F64 norm = Sqrt(Sqr(a->x) + Sqr(a->y));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero2(o)
|
||||
o->x = o->y = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale2(a, 1.0 / norm, o)
|
||||
F64 scale = 1.0 / norm;
|
||||
o->x = a->x * scale;
|
||||
o->y = a->y * scale;
|
||||
}
|
||||
|
||||
/* Normalize CVec2. */
|
||||
U0 Normalize2(CVec2 *v)
|
||||
{
|
||||
// Norm2(v, &norm)
|
||||
F64 norm = Sqrt(Sqr(v->x) + Sqr(v->y));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero2(v)
|
||||
v->x = v->y = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale2(v, 1.0 / norm, v)
|
||||
F64 scale = 1.0 / norm;
|
||||
v->x = v->x * scale;
|
||||
v->y = v->y * scale;
|
||||
}
|
||||
|
||||
/* Rotate CVec2 by angle (F64) to output CVec2. */
|
||||
U0 Rotate2(CVec2 *a, F64 b, CVec2 *o)
|
||||
{
|
||||
F64 c, s;
|
||||
|
||||
c = Cos(b);
|
||||
s = Sin(b);
|
||||
|
||||
o->x = (c * a->x) - (s * a->y);
|
||||
o->y = (s * a->x) - (c * a->y);
|
||||
}
|
||||
|
||||
/* Squared distance between two CVec2. */
|
||||
U0 DistanceSqr2(CVec2 *a, CVec2 *b, F64 *o)
|
||||
{
|
||||
*o = Sqr(b->x - b->y) + Sqr(b->y - a->y);
|
||||
}
|
||||
|
||||
/* Distance between two CVec2. */
|
||||
U0 Distance2(CVec2 *a, CVec2 *b, F64 *o)
|
||||
{
|
||||
*o = Sqrt(Sqr(b->x - b->y) + Sqr(b->y - a->y));
|
||||
}
|
||||
|
||||
/* Minimum components of two CVec2. */
|
||||
U0 MinVec2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x = Min(a->x, b->x);
|
||||
o->y = Min(a->y, b->y);
|
||||
}
|
||||
|
||||
/* Maximum components of two CVec2. */
|
||||
U0 MaxVec2(CVec2 *a, CVec2 *b, CVec2 *o)
|
||||
{
|
||||
o->x = Max(a->x, b->x);
|
||||
o->y = Max(a->y, b->y);
|
||||
}
|
||||
|
||||
/* Minimum component of CVec2. */
|
||||
U0 Min2(CVec2 *a, F64 *o)
|
||||
{
|
||||
*o = Min(a->x, a->y);
|
||||
}
|
||||
|
||||
/* Maximum component of CVec2. */
|
||||
U0 Max2(CVec2 *a, F64 *o)
|
||||
{
|
||||
*o = Max(a->x, a->y);
|
||||
}
|
||||
|
||||
/* Clamp a CVec2 to min and max values. */
|
||||
U0 Clamp2(CVec2 *v, F64 minval, F64 maxval)
|
||||
{
|
||||
v->x = Clamp(v->x, minval, maxval);
|
||||
v->y = Clamp(v->y, minval, maxval);
|
||||
}
|
||||
|
||||
/* Linear interpolation between two CVec2. */
|
||||
U0 Lerp2(CVec2 *a, CVec2 *b, F64 t, CVec2 *o)
|
||||
{
|
||||
CVec2 s, v;
|
||||
|
||||
s.x = s.y = Clamp(t, 0.0, 1.0);
|
||||
// Sub2(b, a, &v)
|
||||
v.x = b->x - a->x;
|
||||
v.y = b->y - a->y;
|
||||
// Mul2(s, v, v)
|
||||
v.x *= s.x;
|
||||
v.y *= s.y;
|
||||
// Add(a, &v, o)
|
||||
o->x = a->x + v.x;
|
||||
o->y = a->y + v.y;
|
||||
}
|
||||
|
429
src/Zenith/CosmicGL/Math/Vec3.CC
Normal file
429
src/Zenith/CosmicGL/Math/Vec3.CC
Normal file
|
@ -0,0 +1,429 @@
|
|||
/* Initialize CVec3 from F64 pointer. */
|
||||
U0 Vec3(F64 *a, CVec3 *o)
|
||||
{
|
||||
o->x = a[0];
|
||||
o->y = a[1];
|
||||
o->z = a[2];
|
||||
}
|
||||
|
||||
/* Copy CVec3 into CVec3. */
|
||||
U0 Copy3(CVec3 *a, CVec3 *o)
|
||||
{
|
||||
o->x = a->x;
|
||||
o->y = a->y;
|
||||
o->z = a->z;
|
||||
}
|
||||
|
||||
/* Fill CVec3 with F64 */
|
||||
U0 Fill3S(CVec3 *v, F64 val)
|
||||
{
|
||||
v->x = v->y = v->z = val;
|
||||
}
|
||||
|
||||
/* Fill CIVec3 with I64 */
|
||||
U0 FillI3S(CIVec3 *v, I64 val)
|
||||
{
|
||||
v->x = v->y = v->z = val;
|
||||
}
|
||||
|
||||
/* Clear CVec2 with zeros. */
|
||||
U0 Zero3(CVec3 *v)
|
||||
{
|
||||
v->x = v->y = v->z = 0.0;
|
||||
}
|
||||
|
||||
/* Clear CVec3 with ones. */
|
||||
U0 One3(CVec3 *v)
|
||||
{
|
||||
v->x = v->y = v->z = 1.0;
|
||||
}
|
||||
|
||||
/* Dot product of two CVec3. */
|
||||
U0 Dot3(CVec3 *a, CVec3 *b, F64 *o)
|
||||
{
|
||||
*o = (a->x * b->x) + (a->y * b->y) + (a->z * b->z);
|
||||
}
|
||||
|
||||
/* Norm^2 (magnitude^2) of CVec3. */
|
||||
U0 NormSqr3(CVec2 *a, F64 *o)
|
||||
{
|
||||
*o = Sqr(a->x) + Sqr(a->y) + Sqr(a->z);
|
||||
}
|
||||
|
||||
/* Norm (magnitude) of CVec3. */
|
||||
U0 Norm3(CVec3 *a, F64 *o)
|
||||
{
|
||||
*o = Sqrt(Sqr(v->x) + Sqr(v->y) + Sqr(v->z));
|
||||
}
|
||||
|
||||
/* Manhattan Distance/Taxicab Norm, sum of component magnitudes of CVec3. */
|
||||
U0 ManhattanNorm3(CVec3 *a, F64 *o)
|
||||
{
|
||||
*o = Abs(a->x) + Abs(a->y) + Abs(a->z);
|
||||
}
|
||||
|
||||
/* Maximum norm (magnitude), largest magnitude of all CVec3 components. */
|
||||
U0 MaxNorm3(CVec3 *a, F64 *o)
|
||||
{
|
||||
*o = Max(Max(Abs(a->x), Abs(a->y)), Abs(a->z));
|
||||
}
|
||||
|
||||
/* Add CVec3 to CVec3. */
|
||||
U0 Add3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x + b->x;
|
||||
o->y = a->y + b->y;
|
||||
o->z = a->z + b->z;
|
||||
}
|
||||
|
||||
/* Add CVec3 to F64. */
|
||||
U0 Add3S(CVec3 *a, F64 b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x + b;
|
||||
o->y = a->y + b;
|
||||
o->z = a->z + b;
|
||||
}
|
||||
|
||||
/* Sub CVec3 from CVec3. */
|
||||
U0 Sub3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x - b->x;
|
||||
o->y = a->y - b->y;
|
||||
o->z = a->z - b->z;
|
||||
}
|
||||
|
||||
/* Sub CVec3 from F64. */
|
||||
U0 Sub3S(CVec3 *a, F64 b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x - b;
|
||||
o->y = a->y - b;
|
||||
o->z = a->z - b;
|
||||
}
|
||||
|
||||
/* Multiply CVec3 with CVec3. */
|
||||
U0 Mul3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x * b->x;
|
||||
o->y = a->y * b->y;
|
||||
o->z = a->z * b->z;
|
||||
}
|
||||
|
||||
/* Scale CVec3 by F64. */
|
||||
U0 Scale3S(CVec3 *a, F64 b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x * b;
|
||||
o->y = a->y * b;
|
||||
o->z = a->z * b;
|
||||
}
|
||||
|
||||
/* Scale CVec3 unit vector by F64. */
|
||||
U0 ScaleUnit3(CVec3 *a, F64 b, CVec3 *o)
|
||||
{
|
||||
// Norm3(a, &norm)
|
||||
F64 norm = Sqrt(Sqr(a->x) + Sqr(a->y) + Sqr(a->z));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero3(a)
|
||||
a->x = 0.0;
|
||||
a->y = 0.0;
|
||||
a->z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale3(a, b / norm, o);
|
||||
F64 scale = b / norm;
|
||||
o->x = a->x * scale;
|
||||
o->y = a->y * scale;
|
||||
o->z = a->z * scale;
|
||||
}
|
||||
|
||||
/* Divide CVec3 by CVec3. */
|
||||
U0 Div3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x / b->x;
|
||||
o->y = b->y / b->y;
|
||||
o->z = b->z / b->z;
|
||||
}
|
||||
|
||||
/* Divide CVec3 by F64. */
|
||||
U0 Div3S(CVec3 *a, F64 b, CVec3 *o)
|
||||
{
|
||||
o->x = a->x / b;
|
||||
o->y = a->y / b;
|
||||
o->z = a->z / b;
|
||||
}
|
||||
|
||||
/* Square root of CVec3 components. */
|
||||
U0 Sqrt3(CVec3 *a, CVec3 *o)
|
||||
{
|
||||
o->x = Sqrt(a->x);
|
||||
o->y = Sqrt(a->y);
|
||||
o->z = Sqrt(a->z);
|
||||
}
|
||||
|
||||
/* Sign of components as -1, 0, or 1. */
|
||||
U0 Sign3(CVec3 *a, CVec3 *o)
|
||||
{
|
||||
o->x = ((o->x > 0.0) - (val < 0.0));
|
||||
o->y = ((o->y > 0.0) - (val < 0.0));
|
||||
o->z = ((o->z > 0.0) - (val < 0.0));
|
||||
}
|
||||
|
||||
/* Add CVec3 to CVec3 to output CVec3. */
|
||||
U0 AddAdd3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x += a->x + b->x;
|
||||
o->y += a->y + b->y;
|
||||
o->z += a->z + b->z;
|
||||
}
|
||||
|
||||
/* Subtract CVec3 from CVec3, add to output CVec3. */
|
||||
U0 SubAdd3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x += a->x - b->x;
|
||||
o->y += a->y - b->y;
|
||||
o->z += a->z - b->z;
|
||||
}
|
||||
|
||||
/* Multiply CVec3 by CVec3, add to output CVec3. */
|
||||
U0 MulAdd2(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x += a->x * b->x;
|
||||
o->y += a->y * b->y;
|
||||
o->z += a->z * b->z;
|
||||
}
|
||||
/* Multiply CVec3 by F64, add to output CVec3. */
|
||||
U0 MulAdd3S(CVec3 *a, F64 b, CVec3 *o)
|
||||
{
|
||||
o->x += a->x * b;
|
||||
o->y += a->y * b;
|
||||
o->z += a->z * b;
|
||||
}
|
||||
|
||||
/* Add maximum of each CVec3 component to output CVec3. */
|
||||
U0 MaxAdd3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x += Max(a->x, b->x);
|
||||
o->y += Max(a->y, b->y);
|
||||
o->z += Max(a->z, b->z);
|
||||
}
|
||||
|
||||
/* Add minimum of each CVec3 component to output CVec3. */
|
||||
U0 MinAdd2(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x += Min(a->x, b->x);
|
||||
o->y += Min(a->y, b->y);
|
||||
o->z == Min(a->z, b->z);
|
||||
}
|
||||
|
||||
/* Negate vector components (*-1) to output CVec3. */
|
||||
U0 NegateTo2(CVec3 *a, CVec3 *o)
|
||||
{
|
||||
o->x = -a->x;
|
||||
o->y = -a->y;
|
||||
o->z = -a->z;
|
||||
}
|
||||
|
||||
/* Negate vector components (*-1). */
|
||||
U0 Negate2(CVec3 *v)
|
||||
{
|
||||
v->x = -v->x;
|
||||
v->y = -v->y;
|
||||
v->z = -v->z;
|
||||
}
|
||||
|
||||
/* Normalize CVec3 to output CVec3. */
|
||||
U0 NormalizeTo3(CVec3 *a, CVec3 *o)
|
||||
{
|
||||
// Norm3(a, &norm)
|
||||
F64 norm = Sqrt(Sqr(a->x) + Sqr(a->y) + Sqr(a->z));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero3(o)
|
||||
o->x = 0.0;
|
||||
o->y = 0.0;
|
||||
o->z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale3(a, 1.0 / norm, o)
|
||||
F64 scale = 1.0 / norm;
|
||||
o->x = a->x * scale;
|
||||
o->y = a->y * scale;
|
||||
o->z = a->z * scale;
|
||||
}
|
||||
|
||||
/* Normalize CVec3. */
|
||||
U0 Normalize3(CVec3 *v)
|
||||
{
|
||||
// Norm3(v, &norm)
|
||||
F64 norm = Sqrt(Sqr(v->x) + Sqr(v->y) + Sqr(v->z));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero2(v)
|
||||
v->x = 0.0;
|
||||
v->y = 0.0;
|
||||
v->z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale3(v, 1.0 / norm, v)
|
||||
F64 scale = 1.0 / norm;
|
||||
v->x = v->x * scale;
|
||||
v->y = v->y * scale;
|
||||
v->z = v->z * scale;
|
||||
}
|
||||
|
||||
/* Cross product of two CVec3. */
|
||||
U0 Cross3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
o->x = (a->y * b->z) - (a->z * b->y);
|
||||
o->y = (a->z * b->x) - (a->x * b->z);
|
||||
o->z = (a->x * b->y) - (a->y * b->x);
|
||||
}
|
||||
|
||||
/* Cross product then normalize two CVec3. */
|
||||
U0 CrossNormalize3(CVec3 *a, CVec3 *b, CVec3 *o)
|
||||
{
|
||||
// Cross3(a, b, o)
|
||||
o->x = (a->y * b->z) - (a->z * b->y);
|
||||
o->y = (a->z * b->x) - (a->x * b->z);
|
||||
o->z = (a->x * b->y) - (a->y * b->x);
|
||||
// Normalize3(o)
|
||||
// Norm3(o, &norm)
|
||||
F64 norm = Sqrt(Sqr(o->x) + Sqr(o->y) + Sqr(o->z));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero2(o)
|
||||
o->x = o->y = o->z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale3(o, 1.0 / norm, o)
|
||||
F64 scale = 1.0 / norm;
|
||||
o->x = o->x * scale;
|
||||
o->y = o->y * scale;
|
||||
o->z = o->z * scale;
|
||||
}
|
||||
|
||||
/* Angle between two vectors. */
|
||||
U0 Angle3(CVec3 *a, CVec3 *b, F64 *o)
|
||||
{
|
||||
F64 norm, normA, normB, dot;
|
||||
|
||||
// Norm3(a, &normA)
|
||||
normA = Sqrt(Sqr(a->x) + Sqr(a->y) + Sqr(a->z));
|
||||
// Norm3(b, &normB)
|
||||
normB = Sqrt(Sqr(b->x) + Sqr(v->y) + Sqr(b->z));
|
||||
norm = 1.0 / (normA * normB);
|
||||
// Dot(a, b, &dot)
|
||||
dot = (a->x * b->x) + (a->y * b->y) + (a->z * b->z);
|
||||
dot *= norm;
|
||||
|
||||
if (dot > 1.0)
|
||||
{
|
||||
*o = 0.0;
|
||||
return;
|
||||
}
|
||||
else if (dot < -1.0)
|
||||
{
|
||||
*o = Pi;
|
||||
return;
|
||||
}
|
||||
|
||||
*o = ArcCos(dot);
|
||||
}
|
||||
|
||||
/* Rotate CVec3 by angle (F64) through CVec3 axis. */
|
||||
U0 Rotate3(CVec3 *a, F64 angle, CVec3 *axis, CVec3 *o)
|
||||
{
|
||||
CVec3 v1, v2, k;
|
||||
F64 c, s, temp;
|
||||
|
||||
c = Cos(angle);
|
||||
s = Sin(angle);
|
||||
|
||||
// NormalizeTo3(axis, &k);
|
||||
// Norm3(axis, &temp)
|
||||
temp = Sqrt(Sqr(axis->x) + Sqr(axis->y) + Sqr(axis->z));
|
||||
|
||||
if (temp == 0.0)
|
||||
{
|
||||
// Zero3(&k)
|
||||
k.x = k.y = k.z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale3(axis, 1.0 / temp, &k)
|
||||
F64 scale = 1.0 / temp;
|
||||
k.x = axis->x * scale;
|
||||
k.y = axis->y * scale;
|
||||
k.z = axis->z * scale;
|
||||
|
||||
// Right Hand, Rodrigues' rotation formula:
|
||||
// v = v*Cos(t) + (kxv)sin(t) + k*(k.v)(1-cos(t))
|
||||
|
||||
// Scale3(a, c, &v1)
|
||||
v1.x = a->x * c;
|
||||
v1.y = a->y * c;
|
||||
v1.z = a->z * c;
|
||||
|
||||
// Cross3(&k, a, v2)
|
||||
v2.x = (k.y * a->z) - (k.z * a->y);
|
||||
v2.y = (k.z * a->x) - (k.x * a->z);
|
||||
v2.z = (k.x * a->y) - (k.y * a->x);
|
||||
|
||||
// Scale3(&v1, s, &v2)
|
||||
v2.x = v1.x * s;
|
||||
v2.y = v1.y * s;
|
||||
v2.z = v1.z * s;
|
||||
|
||||
// Add3(&v1, &v2, &v1)
|
||||
v1.x += v2.x;
|
||||
v1.y += v2.y;
|
||||
v1.z += v2.z;
|
||||
|
||||
// Dot3(&k, &v, &temp)
|
||||
temp = (k.x * v.x) + (k.y * v.y) + (k.z * v.z);
|
||||
|
||||
// Scale3(&k, temp * (1.0 - c), &v2)
|
||||
temp *= (1.0 - c);
|
||||
v2.x = k.x * temp;
|
||||
v2.y = k.y * temp;
|
||||
v2.z = k.z * temp;
|
||||
|
||||
// Add3(&v1, &v2, o)
|
||||
o->x = v1.x + v2.x;
|
||||
o->y = v1.y + v2.y;
|
||||
o->z = v1.z + v2.z;
|
||||
}
|
||||
|
||||
/* Apply Mat4 rotation matrix to CVec3. */
|
||||
Rotate3M4(CVec3 *a, F64 *m, CVec3 *o)
|
||||
{
|
||||
CVec4 x, y, z, res;
|
||||
F64 norm, scale;
|
||||
|
||||
// NormalizeTo4(&m[0], &x)
|
||||
norm = Sqrt(Sqr(m[0][0]) + Sqr(m[0][1]) + Sqr(m[0][2]) + Sqr(m[0][3]));
|
||||
|
||||
if (norm == 0.0)
|
||||
{
|
||||
// Zero4(&x)
|
||||
x.x = x.y = x.z = x.w = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale3(v, 1.0 / norm, v)
|
||||
F64 scale = 1.0 / norm;
|
||||
v->x = v->x * scale;
|
||||
v->y = v->y * scale;
|
||||
v->z = v->z * scale;
|
||||
// TODO: FINISH!!!!
|
||||
}
|
||||
|
||||
|
323
src/Zenith/CosmicGL/Render/Rasterize.CC
Normal file
323
src/Zenith/CosmicGL/Render/Rasterize.CC
Normal file
|
@ -0,0 +1,323 @@
|
|||
/**
|
||||
@ingroup Render
|
||||
@brief Renders triangles to texture.
|
||||
|
||||
@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 width;
|
||||
|
||||
I64 i, j, temp;
|
||||
F64 ftemp;
|
||||
F64 z; // Interpolated value to depth check
|
||||
|
||||
// Stores baryocentric coordinates for current fragment
|
||||
F64 u, v, w;
|
||||
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;
|
||||
Barycentric2(&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]);
|
||||
}
|
||||
|
||||
depthBuf->depthBuf[y * frameBuf->w + i] = z;
|
||||
shd->FragShd(&fragColor, fIn, uniforms);
|
||||
left_index = y * frameBuf->w + i;
|
||||
MemSetU32(frameBuf->rawBuf + left_index, fragColor, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
Barycentric2(&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]);
|
||||
}
|
||||
|
||||
depthBuf->depthBuf[y * frameBuf->w + i] = z;
|
||||
shd->FragShd(&fragColor, fIn, uniforms);
|
||||
left_index = y * frameBuf->w + i;
|
||||
MemSetU32(frameBuf->rawBuf + left_index, fragColor, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
left_x += left_delta;
|
||||
right_x += right_delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Free(vOut);
|
||||
Free(fIn);
|
||||
}
|
97
src/Zenith/CosmicGL/Render/Shader.CC
Normal file
97
src/Zenith/CosmicGL/Render/Shader.CC
Normal file
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
@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);
|
||||
};
|
199
src/Zenith/CosmicGL/Texture/Texture.CC
Normal file
199
src/Zenith/CosmicGL/Texture/Texture.CC
Normal file
|
@ -0,0 +1,199 @@
|
|||
/**
|
||||
@defgroup Tex2D Texture
|
||||
@brief The core of the library, almost all functions either read from
|
||||
or write to textures.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Raw format is a CBGR24 rawBuf array of size w * h in row-major
|
||||
order.
|
||||
*/
|
||||
#define TEX2D_RAW 1
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@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
|
||||
*/
|
||||
class CTex2D
|
||||
{
|
||||
I64 type; // Type, see TEX2D_ macros above
|
||||
I64 w; // Width
|
||||
I64 h; // Height
|
||||
I64 l; // Left offset if applicable (for use with sprite textures)
|
||||
I64 t; // Top offset if applicable (for use with sprite textures)
|
||||
I64 mipmaps; // Mipmaps, not currently being used
|
||||
CBGR24 *rawBuf; // Raw color buffer. Size: w * h
|
||||
F64 *depthBuf; // Depth buffer. Size: w * h, pixels are depth.
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Initialize texture.
|
||||
|
||||
@param[in,out] tex Uninitialized texture to initialize.
|
||||
@param[in] type Type of texture. See TEX2D_ macros for options.
|
||||
@param[in] w Width
|
||||
@param[in] h Height
|
||||
@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)
|
||||
{
|
||||
tex->w = w;
|
||||
tex->h = h;
|
||||
tex->l = l;
|
||||
tex->t = t;
|
||||
tex->type = type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case (TEX2D_RAW):
|
||||
tex->rawBuf = MAlloc(4 * tex->w * tex->h);
|
||||
break;
|
||||
|
||||
case (TEX2D_DEPTH):
|
||||
tex->depthBuf = MAlloc(sizeof(F64) * tex->w * tex->h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Free texture.
|
||||
|
||||
@param[in,out] tex Texture to free.
|
||||
*/
|
||||
U0 Tex2DFree(CTex2D *tex)
|
||||
{
|
||||
switch (tex->type)
|
||||
{
|
||||
case TEX2D_RAW:
|
||||
Free(tex->rawBuf);
|
||||
break;
|
||||
|
||||
case TEX2D_DEPTH:
|
||||
Free(tex->depthBuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@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)
|
||||
{
|
||||
MemSetU32(tex->rawBuf, color, tex->w * tex->h);
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Reset depth texture. Set all pixels to far depth.
|
||||
|
||||
@param[in,out] tex Depth texture to reset.
|
||||
*/
|
||||
U0 Tex2DDepthReset(CTex2D *tex)
|
||||
{
|
||||
F64 depth = 2.0;
|
||||
I64 *iDepth = &depth;
|
||||
MemSetI64(tex->depthBuf, *iDepth, tex->w * tex->h);
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Draw texture directly to display buffer. Maps non-visible textures
|
||||
like depth to a visible palette when drawing for visual debugging.
|
||||
|
||||
This may cause fighting with the operating system and flashing/text or
|
||||
other visual updates might show through. If using this for an application,
|
||||
be sure to disable the operating system from drawing to the display buffer
|
||||
in GrWinUpdate32.
|
||||
|
||||
@param[in] tex Texture to draw to display buffer.
|
||||
@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)
|
||||
{
|
||||
// i, j = sampling x, y position on texture
|
||||
I64 i, j;
|
||||
|
||||
// For scaling depth buffer to 8 bit color
|
||||
F64 scaled;
|
||||
CBGR24 color;
|
||||
|
||||
for (j = 0; j < tex->h; j++)
|
||||
{
|
||||
for (i = 0; i < tex->w; i++)
|
||||
{
|
||||
switch (tex->type)
|
||||
{
|
||||
case TEX2D_RAW:
|
||||
text.fb_alias[(x + i) + (y + j) * GR_WIDTH]
|
||||
= tex->rawBuf[i + j * tex->w];
|
||||
break;
|
||||
|
||||
case TEX2D_DEPTH:
|
||||
// Scaled to display 0-1024 depth
|
||||
scaled = tex->depthBuf[i + j * tex->w] / 4;
|
||||
color.r = scaled;
|
||||
color.g = scaled;
|
||||
color.b = scaled;
|
||||
text.fb_alias[(x + i) + (y + j) * GR_WIDTH] = color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Sample color from color textures at normalized UV coordinate
|
||||
(0.0-1.0). Coordinates over 1.0 loop causing a repeating texture effect.
|
||||
|
||||
Does not handle filtering or mip maps (yet). The MemCopy's are dumb
|
||||
I will replace with simply returning the color soon.
|
||||
|
||||
@param[in,out] col Sets color at this address to sampled color.
|
||||
@param[in] tex Texture to sample from.
|
||||
@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)
|
||||
{
|
||||
I64 x = u * tex->w;
|
||||
I64 y = v * tex->h;
|
||||
x %= tex->w;
|
||||
y %= tex->h;
|
||||
|
||||
MemCopy(col, &tex->rawBuf[x + y * tex->w], sizeof(CBGR24));
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Sample color from color textures at UV coordinate. Coordinates
|
||||
over texture dimensions loop causing a repeating texture effect.
|
||||
|
||||
@param[in,out] col Sets color at this address to sampled color.
|
||||
@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)
|
||||
{
|
||||
u %= tex->w;
|
||||
v %= tex->h;
|
||||
|
||||
MemCopy(col, &tex->rawBuf[u + v * tex->w], sizeof(CBGR24));
|
||||
}
|
268
src/Zenith/CosmicGL/Texture/TextureImport.CC
Normal file
268
src/Zenith/CosmicGL/Texture/TextureImport.CC
Normal file
|
@ -0,0 +1,268 @@
|
|||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Loads Half-Life texture from 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Get lump handle
|
||||
CWADFileLumpHL *lump;
|
||||
I64 texIndex = WADFindLump(wad, texName, &lump);
|
||||
|
||||
if (texIndex < 0)
|
||||
{
|
||||
"[ERROR] CAN NOT FIND %s TEXTURE IN WAD %s\n", texName, wad->name;
|
||||
return;
|
||||
}
|
||||
|
||||
// Map texture class to WAD file buffer
|
||||
CWADTexHL *wadTex = wad->fileBuf + lump->filePos;
|
||||
|
||||
Tex2DInit(tex, TEX2D_RAW, wadTex->w, wadTex->h);
|
||||
|
||||
// Map pixel array
|
||||
U8 *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;
|
||||
// 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];
|
||||
|
||||
tex->rawBuf[i] = color;
|
||||
|
||||
// Full blue pixels are transparent
|
||||
if (color == 0xFF0000FF)
|
||||
tex->rawBuf[i].pad = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@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
|
||||
@brief BMP file header.
|
||||
*/
|
||||
class CBMPHeader
|
||||
{
|
||||
U8 szVersion[2]; // Should have 'BM' signature
|
||||
U32 nSize; // File size in bytes
|
||||
U32 pad; // Unused
|
||||
U32 nOffset; // Offset from beginning of file to data;
|
||||
|
||||
/* Info header is right after first header, so it is merged into this class */
|
||||
U32 nInfoSize; // Size of this info part of the header (=40)
|
||||
U32 nWidth; // Image width in pixels
|
||||
U32 nHeight; // Image height in pixels
|
||||
U16 nPlanes; // Number of planes (=1)
|
||||
U16 nPxBits; // Number of bits per pixel. This also indicates palette method:
|
||||
// 1-bit: Monochrome
|
||||
// 4-bit: 16-color palette
|
||||
// 8-bit: 256-color palette
|
||||
// 16-bit: 65565 colors
|
||||
// 24-bit: 16M colors
|
||||
U32 nCompression; // Type of compression:
|
||||
// 0: BI_RGB no-compression
|
||||
// 1: BI_RLE8 8-bit RLE encoding
|
||||
// 2: BI_RLE4 4-bit RLE encoding
|
||||
U32 nImageSize; // Size of image if compressed, (can =0 if not compressed)
|
||||
U32 nXPxPerM; // Horizontal resolution, pixels per meter
|
||||
U32 nYPxPerM; // Vertical resolution, pixels per meter
|
||||
U32 nColors; // Number of actually used colors (ie. 256 for 8-bit color)
|
||||
U32 nImptColors; // Number of important colors (=0 for all)
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup Tex2D
|
||||
@brief Loads BMP image.
|
||||
|
||||
Supports standard uncompressed 24-bit color BMP images.
|
||||
|
||||
@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,
|
||||
Bool invert = TRUE)
|
||||
{
|
||||
U8 *bmp = FileRead(fname);
|
||||
|
||||
// Map locations in buffer;
|
||||
CBMPHeader *info = bmp;
|
||||
|
||||
//if (StrMatch(bmp->szVersion, "BM") == 0)
|
||||
if (info->szVersion[0] != 'B' && info->szVersion[1] != 'M')
|
||||
{
|
||||
"[ERROR] %s IS NOT A VALID BMP FILE!\n", fname;
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->nPxBits != 24 || info->nCompression != 0)
|
||||
{
|
||||
"[ERROR] %s IS NOT A 24-BIT UNCOMPRESSED BMP!\n", fname;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// For checking if a color channel is greater than 0 for masks
|
||||
U8 channel;
|
||||
|
||||
if (mask)
|
||||
{
|
||||
/*
|
||||
// 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++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
263
src/Zenith/CosmicGL/WAD/DoomMap.CC
Normal file
263
src/Zenith/CosmicGL/WAD/DoomMap.CC
Normal file
|
@ -0,0 +1,263 @@
|
|||
/**
|
||||
@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);
|
||||
}
|
125
src/Zenith/CosmicGL/WAD/DoomTypes.CC
Normal file
125
src/Zenith/CosmicGL/WAD/DoomTypes.CC
Normal file
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
@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;
|
||||
};
|
||||
|
207
src/Zenith/CosmicGL/WAD/WAD.CC
Normal file
207
src/Zenith/CosmicGL/WAD/WAD.CC
Normal file
|
@ -0,0 +1,207 @@
|
|||
/**
|
||||
@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
|
||||
@brief Hash table type for lump hash.
|
||||
*/
|
||||
#define HTT_LUMP 69
|
||||
|
||||
/**
|
||||
@internal
|
||||
@ingroup WAD
|
||||
@brief Hash for quick access of lump pointer and index by name.
|
||||
*/
|
||||
class CHashLump : CHash
|
||||
{
|
||||
CWADFileLump *lump; // Pointer to lump
|
||||
// Access with lump->doom/lump->hl
|
||||
I64 lumpIndex; // Index of lump in WAD
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup WAD
|
||||
@brief Class for WAD currently in memory.
|
||||
|
||||
Has easy access handles and a hash table to quickly find lumps.
|
||||
*/
|
||||
class CWAD
|
||||
{
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup WAD
|
||||
@brief Finds lump with name and returns it's index in the WAD. Also
|
||||
points input lump pointer to it if found.
|
||||
|
||||
@param[in] wad WAD to search.
|
||||
@param[in] name Lump name to find.
|
||||
@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)
|
||||
{
|
||||
CHashLump *lumpHash;
|
||||
lumpHash = HashFind(name, wad->lumpTable, HTT_LUMP);
|
||||
|
||||
if (lumpHash != NULL)
|
||||
{
|
||||
if (lump != NULL)
|
||||
*lump = lumpHash->lump;
|
||||
|
||||
return lumpHash->lumpIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup WAD
|
||||
@brief Loads WAD file.
|
||||
|
||||
@param[in,out] wad Uninitialized WAD to initialize.
|
||||
@param[in] fname File name of WAD.
|
||||
*/
|
||||
U0 WADLoad(CWAD *wad, U8 *fname)
|
||||
{
|
||||
wad->fileBuf = FileRead(fname);
|
||||
wad->name = StrNew(fname);
|
||||
|
||||
// For palette loading if doom WAD
|
||||
CWADFileLumpDoom *paletteLump;
|
||||
U8 *paletteColor;
|
||||
|
||||
// Map locations in buffer
|
||||
wad->info = wad->fileBuf;
|
||||
|
||||
// Allocate hash table
|
||||
wad->lumpTable = HashTableNew(wad->info->nLumps); // Table
|
||||
wad->hashLumps = CAlloc(wad->info->nLumps * // Hashes
|
||||
sizeof(CHashLump));
|
||||
|
||||
I64 i;
|
||||
|
||||
// Check version and proceed accordingly
|
||||
U32 *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;
|
||||
|
||||
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);
|
||||
|
||||
// Set hash type
|
||||
wad->hashLumps[i].type = HTT_LUMP;
|
||||
|
||||
// Link lump to hash
|
||||
wad->hashLumps[i].lump = &wad->hlLumps[i];
|
||||
|
||||
// Set lump index in hash to this index
|
||||
wad->hashLumps[i].lumpIndex = i;
|
||||
|
||||
// Add hash to table
|
||||
HashAdd(&wad->hashLumps[i], wad->lumpTable);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup WAD
|
||||
@brief Free WAD.
|
||||
|
||||
@param[in,out] wad WAD to free.
|
||||
*/
|
||||
U0 WADFree(CWAD *wad)
|
||||
{
|
||||
Free(wad->lumpTable->body);
|
||||
Free(wad->lumpTable);
|
||||
Free(wad->hashLumps);
|
||||
Free(wad->fileBuf);
|
||||
}
|
||||
|
283
src/Zenith/CosmicGL/WAD/WADTypes.CC
Normal file
283
src/Zenith/CosmicGL/WAD/WADTypes.CC
Normal file
|
@ -0,0 +1,283 @@
|
|||
/**
|
||||
@defgroup WAD WAD
|
||||
@brief WAD file format management and parsing. Supports DOOM and
|
||||
Half-Life WADs.
|
||||
*/
|
||||
|
||||
/**
|
||||
@internal
|
||||
@ingroup WAD
|
||||
@brief WAD file header.
|
||||
*/
|
||||
class CWADInfo
|
||||
{
|
||||
U8 type[4]; // Type of WAD, like IWAD/PWAD/WAD3
|
||||
I32 nLumps; // Number of lumps
|
||||
I32 lumpOffset; // Offset to lump
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup WAD
|
||||
@brief DOOM 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
|
||||
{
|
||||
I32 filePos; // Relative offset
|
||||
I32 diskSize; // Size of lump (compressed)
|
||||
I32 size; // Uncompressed lump size
|
||||
I8 type;
|
||||
I8 compression; // 0 if none
|
||||
I16 pad;
|
||||
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
|
||||
@brief Header to a Half-Life texture lump.
|
||||
*/
|
||||
class CWADTexHL
|
||||
{
|
||||
U8 name[16];
|
||||
U32 w;
|
||||
U32 h;
|
||||
U32 offsets[4]; // Relative offset to each mip map
|
||||
};
|
|
@ -24,4 +24,5 @@ LBts(&sys_run_level, RLf_DOC);
|
|||
#include "ZDefine"
|
||||
#include "WallPaper"
|
||||
#include "ZMouse"
|
||||
#include "CosmicGL/MakeCosmicGL"
|
||||
Cd("..");;
|
||||
|
|
Loading…
Reference in a new issue