diff --git a/pixelGameEngine.h b/pixelGameEngine.h index 87f8813..cdbde54 100644 --- a/pixelGameEngine.h +++ b/pixelGameEngine.h @@ -3,7 +3,7 @@ olcPixelGameEngine.h +-------------------------------------------------------------+ - | OneLoneCoder Pixel Game Engine v2.23 | + | OneLoneCoder Pixel Game Engine v2.25 | | "What do you need? Pixels... Lots of Pixels..." - javidx9 | +-------------------------------------------------------------+ @@ -193,11 +193,11 @@ Special thanks to my Patreons too - I wont name you on here, but I've certainly enjoyed my tea and flapjacks :D - + - In Memory of SaladinAkara 25.06.2023 - Author ~~~~~~ - David Barr, aka javidx9, (c) OneLoneCoder 2018, 2019, 2020, 2021, 2022 + David Barr, aka javidx9, (c) OneLoneCoder 2018, 2019, 2020, 2021, 2022, 2023, 2024 */ #pragma endregion @@ -315,11 +315,11 @@ +FillTexturedTriangle() - Software rasterizes a textured, coloured, triangle +FillTexturedPolygon() - Hijacks DecalStructure for configuration +olc::vf2d arguments for Sprite::Sample() functions - - SIG Updates: - The following additions are included in Sig's version of the PGE header (this is a sig version) - +GetAnyKey() - Returns when a key is activated - +GetAnyKeyPress() - Returns when a key is pressed down (and if a keyboard key, which key it was) + 2.22: = Fix typo on dragged file buffers for unicode builds + 2.23: Fixed Emscripten host sizing errors - Thanks Moros + Fixed v2d_generic.clamp() function + 2.24: Fix FillTexturedTriangle() to remove const-ref + 2.25: +DrawPolygonDecal(pos, tex, w, col) !! Apple Platforms will not see these updates immediately - Sorry, I dont have a mac to test... !! !! Volunteers willing to help appreciated, though PRs are manually integrated with credit !! @@ -399,7 +399,7 @@ int main() #include #pragma endregion -#define PGE_VER 223 +#define PGE_VER 225 // O------------------------------------------------------------------------------O // | COMPILER CONFIGURATION ODDITIES | @@ -580,6 +580,7 @@ namespace olc // O------------------------------------------------------------------------------O // | olc::Pixel - Represents a 32-Bit RGBA colour | // O------------------------------------------------------------------------------O +#if !defined(OLC_IGNORE_PIXEL) struct Pixel { union @@ -625,7 +626,7 @@ namespace olc BLUE(0, 0, 255), DARK_BLUE(0, 0, 128), VERY_DARK_BLUE(0, 0, 64), MAGENTA(255, 0, 255), DARK_MAGENTA(128, 0, 128), VERY_DARK_MAGENTA(64, 0, 64), WHITE(255, 255, 255), BLACK(0, 0, 0), BLANK(0, 0, 0, 0); - +#endif // Thanks to scripticuk and others for updating the key maps // NOTE: The GLUT platform will need updating, open to contributions ;) enum Key @@ -851,7 +852,6 @@ namespace olc STENCIL, ILLUMINATE, WIREFRAME, - MODEL3D, }; enum class DecalStructure @@ -892,10 +892,12 @@ namespace olc std::vector pos; std::vector uv; std::vector w; + std::vector z; std::vector tint; olc::DecalMode mode = olc::DecalMode::NORMAL; olc::DecalStructure structure = olc::DecalStructure::FAN; uint32_t points = 0; + bool depth = false; }; struct LayerDesc @@ -976,8 +978,6 @@ namespace olc virtual bool OnUserUpdate(float fElapsedTime); // Called once on application termination, so you can be one clean coder virtual bool OnUserDestroy(); - virtual void GetAnyKey(); - virtual void GetAnyKeyPress(olc::Key pressedKey); // Called when a text entry is confirmed with "enter" key virtual void OnTextEntryComplete(const std::string& sText); @@ -1090,7 +1090,7 @@ namespace olc void FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE); void FillTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p = olc::WHITE); // Fill a textured and coloured triangle - void FillTexturedTriangle(const std::vector& vPoints, std::vector vTex, std::vector vColour, olc::Sprite* sprTex); + void FillTexturedTriangle(std::vector vPoints, std::vector vTex, std::vector vColour, olc::Sprite* sprTex); void FillTexturedPolygon(const std::vector& vPoints, const std::vector& vTex, const std::vector& vColour, olc::Sprite* sprTex, olc::DecalStructure structure = olc::DecalStructure::LIST); // Draws an entire sprite at location (x,y) void DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE); @@ -1142,6 +1142,8 @@ namespace olc void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& depth, const std::vector& uv, const olc::Pixel tint = olc::WHITE); void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const std::vector& tint); void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const std::vector& colours, const olc::Pixel tint); + void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& depth, const std::vector& uv, const std::vector& colours, const olc::Pixel tint); + // Draws a line in Decal Space void DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE); void DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); @@ -1191,6 +1193,7 @@ namespace olc // Draws a vector of vertices, interprted as individual triangles void LW3D_DrawTriangles(olc::Decal* decal, const std::vector>& pos, const std::vector& tex, const std::vector& col); + void LW3D_DrawWarpedDecal(olc::Decal* decal, const std::vector>& pos, const olc::Pixel& tint); void LW3D_ModelTranslate(const float x, const float y, const float z); @@ -1460,6 +1463,7 @@ namespace olc // O------------------------------------------------------------------------------O // | olc::Pixel IMPLEMENTATION | // O------------------------------------------------------------------------------O +#if !defined(OLC_IGNORE_PIXEL) Pixel::Pixel() { r = 0; g = 0; b = 0; a = nDefaultAlpha; } @@ -1570,7 +1574,7 @@ namespace olc Pixel PixelLerp(const olc::Pixel& p1, const olc::Pixel& p2, float t) { return (p2 * t) + p1 * (1.0f - t); } - +#endif // O------------------------------------------------------------------------------O // | olc::Sprite IMPLEMENTATION | // O------------------------------------------------------------------------------O @@ -2191,8 +2195,8 @@ namespace olc auto rol = [&](void) { pattern = (pattern << 1) | (pattern >> 31); return pattern & 1; }; olc::vi2d p1(x1, y1), p2(x2, y2); - //if (!ClipLineToScreen(p1, p2)) - // return; + if (!ClipLineToScreen(p1, p2)) + return; x1 = p1.x; y1 = p1.y; x2 = p2.x; y2 = p2.y; @@ -2584,7 +2588,7 @@ namespace olc } } - void PixelGameEngine::FillTexturedTriangle(const std::vector& vPoints, std::vector vTex, std::vector vColour, olc::Sprite* sprTex) + void PixelGameEngine::FillTexturedTriangle(std::vector vPoints, std::vector vTex, std::vector vColour, olc::Sprite* sprTex) { olc::vi2d p1 = vPoints[0]; olc::vi2d p2 = vPoints[1]; @@ -3000,7 +3004,28 @@ namespace olc di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; di.uv[i] = uv[i]; di.tint[i] = tint; - di.w[i] = 1.0f; + di.w[i] = depth[i]; + } + di.mode = nDecalMode; + di.structure = nDecalStructure; + vLayers[nTargetLayer].vecDecalInstance.push_back(di); + } + + void PixelGameEngine::DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& depth, const std::vector& uv, const std::vector& colours, const olc::Pixel tint) + { + DecalInstance di; + di.decal = decal; + di.points = uint32_t(pos.size()); + di.pos.resize(di.points); + di.uv.resize(di.points); + di.w.resize(di.points); + di.tint.resize(di.points); + for (uint32_t i = 0; i < di.points; i++) + { + di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; + di.uv[i] = uv[i]; + di.tint[i] = colours[i] * tint; + di.w[i] = depth[i]; } di.mode = nDecalMode; di.structure = nDecalStructure; @@ -3017,17 +3042,64 @@ namespace olc di.pos.resize(di.points); di.uv.resize(di.points); di.w.resize(di.points); + di.z.resize(di.points); di.tint.resize(di.points); for (uint32_t i = 0; i < di.points; i++) { di.pos[i] = { pos[i][0], pos[i][1] }; di.w[i] = pos[i][2]; + di.z[i] = pos[i][2]; di.uv[i] = tex[i]; di.tint[i] = col[i]; } - di.mode = DecalMode::MODEL3D; + di.mode = nDecalMode; + di.structure = DecalStructure::LIST; + di.depth = true; vLayers[nTargetLayer].vecDecalInstance.push_back(di); } + + void PixelGameEngine::LW3D_DrawWarpedDecal(olc::Decal* decal, const std::vector>& pos, const olc::Pixel& tint) + { + // Thanks Nathan Reed, a brilliant article explaining whats going on here + // http://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/ + DecalInstance di; + di.points = 4; + di.decal = decal; + di.tint = { tint, tint, tint, tint }; + di.w = { 1, 1, 1, 1 }; + di.z = { 1, 1, 1, 1 }; + di.pos.resize(4); + di.uv = { { 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; + olc::vf2d center; + float rd = ((pos[2][0] - pos[0][0]) * (pos[3][1] - pos[1][1]) - (pos[3][0] - pos[1][0]) * (pos[2][1] - pos[0][1])); + if (rd != 0) + { + rd = 1.0f / rd; + float rn = ((pos[3][0] - pos[1][0]) * (pos[0][1] - pos[1][1]) - (pos[3][1] - pos[1][1]) * (pos[0][0] - pos[1][0])) * rd; + float sn = ((pos[2][0] - pos[0][0]) * (pos[0][1] - pos[1][1]) - (pos[2][1] - pos[0][1]) * (pos[0][0] - pos[1][0])) * rd; + if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) + { + center.x = pos[0][0] + rn * (pos[2][0] - pos[0][0]); + center.y = pos[0][1] + rn * (pos[2][1] - pos[0][1]); + } + float d[4]; + for (int i = 0; i < 4; i++) + d[i] = std::sqrt((pos[i][0] - center.x) * (pos[i][0] - center.x) + (pos[i][1] - center.y) * (pos[i][1] - center.y)); + + for (int i = 0; i < 4; i++) + { + float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3]; + di.uv[i] *= q; + di.w[i] *= q; + di.z[i] = pos[i][2]; + di.pos[i] = { (pos[i][0] * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i][1] * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; + } + di.mode = nDecalMode; + di.structure = nDecalStructure; + di.depth = true; + vLayers[nTargetLayer].vecDecalInstance.push_back(di); + } + } #endif void PixelGameEngine::DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p) @@ -3682,9 +3754,6 @@ namespace olc bool PixelGameEngine::OnUserDestroy() { return true; } - void PixelGameEngine::GetAnyKey(){}; - void PixelGameEngine::GetAnyKeyPress(olc::Key pressedKey){}; - void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); } bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; } @@ -3842,10 +3911,8 @@ namespace olc platform->HandleSystemEvent(); // Compare hardware input states from previous frame - auto ScanHardware = [&](HWButton* pKeys, bool* pStateOld, bool* pStateNew, uint32_t nKeyCount,bool keyboard=true) + auto ScanHardware = [&](HWButton* pKeys, bool* pStateOld, bool* pStateNew, uint32_t nKeyCount) { - bool pressed=false; - int key; for (uint32_t i = 0; i < nKeyCount; i++) { pKeys[i].bPressed = false; @@ -3854,8 +3921,6 @@ namespace olc { if (pStateNew[i]) { - pressed=true; - key=i; pKeys[i].bPressed = !pKeys[i].bHeld; pKeys[i].bHeld = true; } @@ -3864,18 +3929,13 @@ namespace olc pKeys[i].bReleased = true; pKeys[i].bHeld = false; } - GetAnyKey(); } pStateOld[i] = pStateNew[i]; } - if (pressed) { - if (keyboard) {GetAnyKeyPress((olc::Key)key);} - else {GetAnyKeyPress(olc::Key::NONE);} - } }; ScanHardware(pKeyboardState, pKeyOldState, pKeyNewState, 256); - ScanHardware(pMouseState, pMouseOldState, pMouseNewState, nMouseButtons, false); + ScanHardware(pMouseState, pMouseOldState, pMouseNewState, nMouseButtons); // Cache mouse coordinates so they remain consistent during frame vMousePos = vMousePosCache; @@ -4382,7 +4442,6 @@ namespace olc switch (mode) { case olc::DecalMode::NORMAL: - case olc::DecalMode::MODEL3D: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; case olc::DecalMode::ADDITIVE: @@ -4430,59 +4489,36 @@ namespace olc else glBindTexture(GL_TEXTURE_2D, decal.decal->id); - if (nDecalMode == DecalMode::MODEL3D) + if (decal.depth) { -#ifdef OLC_ENABLE_EXPERIMENTAL - glMatrixMode(GL_PROJECTION); glPushMatrix(); - glMatrixMode(GL_MODELVIEW); glPushMatrix(); - glEnable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-1.0f, 1.0f, -1.0f, 1.0f, 1, 1000); - - #pragma comment (lib, "winmm.lib") + } - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0, -40, -200); - glRotatef(float(clock()) * 0.1f, 1, 0, 0); - glRotatef(float(clock()) * 0.1f * 2, 0, 1, 0); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (nDecalMode == DecalMode::WIREFRAME) + glBegin(GL_LINE_LOOP); + else + { + if(decal.structure == olc::DecalStructure::FAN) + glBegin(GL_TRIANGLE_FAN); + else if(decal.structure == olc::DecalStructure::STRIP) + glBegin(GL_TRIANGLE_STRIP); + else if(decal.structure == olc::DecalStructure::LIST) + glBegin(GL_TRIANGLES); + } - glBegin(GL_TRIANGLES); - + if (decal.depth) + { // Render as 3D Spatial Entity for (uint32_t n = 0; n < decal.points; n++) { glColor4ub(decal.tint[n].r, decal.tint[n].g, decal.tint[n].b, decal.tint[n].a); - glTexCoord2f(decal.uv[n].x, decal.uv[n].y); - glVertex3f(decal.pos[n].x, decal.pos[n].y, decal.w[n]); + glTexCoord4f(decal.uv[n].x, decal.uv[n].y, 0.0f, decal.w[n]); + glVertex3f(decal.pos[n].x, decal.pos[n].y, decal.z[n]); } - - glEnd(); - - glMatrixMode(GL_PROJECTION); glPopMatrix(); - glMatrixMode(GL_MODELVIEW); glPopMatrix(); - glDisable(GL_DEPTH_TEST); -#endif } else { - if (nDecalMode == DecalMode::WIREFRAME) - glBegin(GL_LINE_LOOP); - else - { - if(decal.structure == olc::DecalStructure::FAN) - glBegin(GL_TRIANGLE_FAN); - else if(decal.structure == olc::DecalStructure::STRIP) - glBegin(GL_TRIANGLE_STRIP); - else if(decal.structure == olc::DecalStructure::LIST) - glBegin(GL_TRIANGLES); - } - // Render as 2D Spatial entity for (uint32_t n = 0; n < decal.points; n++) { @@ -4490,12 +4526,15 @@ namespace olc glTexCoord4f(decal.uv[n].x, decal.uv[n].y, 0.0f, decal.w[n]); glVertex2f(decal.pos[n].x, decal.pos[n].y); } - - glEnd(); } - - //glDisable(GL_DEPTH_TEST); + glEnd(); + + if (decal.depth) + { + glDisable(GL_DEPTH_TEST); + } + } uint32_t CreateTexture(const uint32_t width, const uint32_t height, const bool filtered, const bool clamp) override diff --git a/pixelGameEngine.o b/pixelGameEngine.o deleted file mode 100644 index 4f5be2d..0000000 Binary files a/pixelGameEngine.o and /dev/null differ diff --git a/pixelGameEngine_wasm.o b/pixelGameEngine_wasm.o deleted file mode 100644 index 5c80e82..0000000 Binary files a/pixelGameEngine_wasm.o and /dev/null differ