generated from sigonasr2/CPlusPlusProjectTemplate
Setup 3D example.
This commit is contained in:
parent
7568ba124e
commit
2a1645a35c
@ -12,12 +12,12 @@ source ../emsdk/emsdk_env.sh
|
|||||||
if [ ! -f "pixelGameEngine_wasm.o" ]
|
if [ ! -f "pixelGameEngine_wasm.o" ]
|
||||||
then
|
then
|
||||||
printf "Pixel Game Engine compile object missing. Compiling for the first time..."
|
printf "Pixel Game Engine compile object missing. Compiling for the first time..."
|
||||||
em++ -std=c++17 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 -c pixelGameEngine.cpp -o pixelGameEngine_wasm.o
|
em++ -std=c++17 -O2 -sASSERTIONS -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 -c pixelGameEngine.cpp -o pixelGameEngine_wasm.o
|
||||||
fi
|
fi
|
||||||
if [ -d "assets" ]; then
|
if [ -d "assets" ]; then
|
||||||
em++ -std=c++17 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html --preload-file ./assets
|
em++ -std=c++17 -O2 -sASSERTIONS -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html --preload-file ./assets
|
||||||
else
|
else
|
||||||
em++ -std=c++17 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html
|
em++ -std=c++17 -O2 -sASSERTIONS -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp buildtemplate.html ${PROJECT_NAME}.html
|
cp buildtemplate.html ${PROJECT_NAME}.html
|
||||||
|
BIN
C++ProjectTemplate.data
Normal file
BIN
C++ProjectTemplate.data
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
26
assets/unitcube.obj
Normal file
26
assets/unitcube.obj
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
v 0 0 0
|
||||||
|
v 0 0 1
|
||||||
|
v 0 1 0
|
||||||
|
v 0 1 1
|
||||||
|
v 1 0 0
|
||||||
|
v 1 0 1
|
||||||
|
v 1 1 0
|
||||||
|
v 1 1 1
|
||||||
|
|
||||||
|
vt 0 0 #1
|
||||||
|
vt 0 1 #2
|
||||||
|
vt 1 0 #3
|
||||||
|
vt 1 1 #4
|
||||||
|
|
||||||
|
f 1/2 3/1 7/3 #South/0
|
||||||
|
f 1/2 7/3 5/4 #1
|
||||||
|
f 5/2 7/1 8/3 #East/2
|
||||||
|
f 5/2 8/3 6/4 #3
|
||||||
|
f 6/2 8/1 4/3 #North/4
|
||||||
|
f 6/2 4/3 2/4 #5
|
||||||
|
f 2/2 4/1 3/3 #West/6
|
||||||
|
f 2/2 3/3 1/4 #7
|
||||||
|
f 3/2 4/1 8/3 #Top/8
|
||||||
|
f 3/2 8/3 7/4 #9
|
||||||
|
f 6/2 2/1 1/3 #Bottom/10
|
||||||
|
f 6/2 1/3 5/4 #11
|
89
main.cpp
89
main.cpp
@ -1,49 +1,92 @@
|
|||||||
#include "pixelGameEngine.h"
|
#include "pixelGameEngine.h"
|
||||||
|
#define OLC_PGEX_GRAPHICS3D
|
||||||
|
#include "olcPGEX_Graphics3D.h"
|
||||||
|
|
||||||
using namespace olc;
|
using namespace olc;
|
||||||
|
|
||||||
#define WIDTH 640
|
class Graphics3DPGEX_Example : public olc::PixelGameEngine
|
||||||
#define HEIGHT 480
|
|
||||||
|
|
||||||
class Example : public olc::PixelGameEngine
|
|
||||||
{
|
{
|
||||||
|
GFX3D::mesh cube;
|
||||||
|
GFX3D::PipeLine renderer;
|
||||||
|
|
||||||
|
GFX3D::vec3d vUp = {0,1,0};
|
||||||
|
GFX3D::vec3d vEye = {0,0,-4};
|
||||||
|
GFX3D::vec3d vLookDir = {0,0,1};
|
||||||
|
|
||||||
|
float fTheta=0;
|
||||||
|
|
||||||
|
Sprite*cubeTex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Example()
|
Graphics3DPGEX_Example()
|
||||||
{
|
{
|
||||||
sAppName = "Example";
|
sAppName = "Graphics3D PGEX Example";
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
olc::Key last;
|
|
||||||
bool OnUserCreate() override
|
bool OnUserCreate() override
|
||||||
{
|
{
|
||||||
std::cout<<"Test"<<std::endl;
|
cube.tris =
|
||||||
ConsoleShow(olc::Key::A);
|
{
|
||||||
|
// SOUTH
|
||||||
|
{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, WHITE },
|
||||||
|
{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, WHITE },
|
||||||
|
|
||||||
|
// EAST
|
||||||
|
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, WHITE },
|
||||||
|
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, WHITE },
|
||||||
|
|
||||||
|
// NORTH
|
||||||
|
{ 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, WHITE },
|
||||||
|
{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, WHITE },
|
||||||
|
|
||||||
|
// WEST
|
||||||
|
{ 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, WHITE },
|
||||||
|
{ 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, WHITE },
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
{ 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, WHITE },
|
||||||
|
{ 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, WHITE },
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, WHITE },
|
||||||
|
{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, WHITE },
|
||||||
|
|
||||||
|
};
|
||||||
|
olc::GFX3D::ConfigureDisplay();
|
||||||
|
|
||||||
|
|
||||||
|
renderer.SetProjection(90.0f, (float)ScreenHeight()/(float)ScreenWidth(), 0.1f, 1000.0f, 0.0f, 0.0f, ScreenWidth(), ScreenHeight());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnUserUpdate(float fElapsedTime) override
|
bool OnUserUpdate(float fElapsedTime) override
|
||||||
{
|
{
|
||||||
std::cout<<"Test 4"<<std::endl;
|
fTheta+=fElapsedTime;
|
||||||
ConsoleCaptureStdOut(true);
|
|
||||||
std::cout<<"Test 2"<<std::endl;
|
Clear(VERY_DARK_BLUE);
|
||||||
ConsoleCaptureStdOut(false);
|
|
||||||
std::cout<<"Test 3"<<std::endl;
|
GFX3D::vec3d vLookTarget = GFX3D::Math::Vec_Add(vEye, vLookDir);
|
||||||
std::cout<<"A"<<std::endl;
|
|
||||||
Clear(BLACK);
|
renderer.SetCamera(vEye, vLookTarget, vUp);
|
||||||
DrawString({0,0},std::to_string(last));
|
|
||||||
|
GFX3D::mat4x4 matRotateX=GFX3D::Math::Mat_MakeRotationX(fTheta);
|
||||||
|
GFX3D::mat4x4 matRotateZ=GFX3D::Math::Mat_MakeRotationZ(fTheta/3.0f);
|
||||||
|
GFX3D::mat4x4 matWorld=GFX3D::Math::Mat_MultiplyMatrix(matRotateX,matRotateZ);
|
||||||
|
|
||||||
|
renderer.SetTransform(matWorld);
|
||||||
|
|
||||||
|
renderer.SetTexture(cubeTex);
|
||||||
|
//renderer.Render(cube.tris, GFX3D::RENDER_WIRE);
|
||||||
|
|
||||||
|
renderer.Render(cube.tris);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnUserDestroy()override{
|
bool OnUserDestroy()override{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetAnyKeyPress(olc::Key pressed)override{
|
|
||||||
last=pressed;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Direction{
|
enum Direction{
|
||||||
@ -60,8 +103,8 @@ struct Data{
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Example demo;
|
Graphics3DPGEX_Example demo;
|
||||||
if (demo.Construct(640, 480, 4, 4))
|
if (demo.Construct(768, 480, 2, 2))
|
||||||
demo.Start();
|
demo.Start();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
836
olcPGEX_Graphics3D.h
Normal file
836
olcPGEX_Graphics3D.h
Normal file
@ -0,0 +1,836 @@
|
|||||||
|
/*
|
||||||
|
olcPGEX_Graphics3D.h
|
||||||
|
|
||||||
|
+-------------------------------------------------------------+
|
||||||
|
| OneLoneCoder Pixel Game Engine Extension |
|
||||||
|
| 3D Rendering - v0.1 |
|
||||||
|
+-------------------------------------------------------------+
|
||||||
|
|
||||||
|
What is this?
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
This is an extension to the olcPixelGameEngine, which provides
|
||||||
|
support for software rendering 3D graphics.
|
||||||
|
|
||||||
|
NOTE!!! This file is under development and may change!
|
||||||
|
|
||||||
|
License (OLC-3)
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Copyright 2018-2019 OneLoneCoder.com
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce
|
||||||
|
the above copyright notice. This list of conditions and the following
|
||||||
|
disclaimer must be reproduced in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Links
|
||||||
|
~~~~~
|
||||||
|
YouTube: https://www.youtube.com/javidx9
|
||||||
|
Discord: https://discord.gg/WhwHUMV
|
||||||
|
Twitter: https://www.twitter.com/javidx9
|
||||||
|
Twitch: https://www.twitch.tv/javidx9
|
||||||
|
GitHub: https://www.github.com/onelonecoder
|
||||||
|
Patreon: https://www.patreon.com/javidx9
|
||||||
|
Homepage: https://www.onelonecoder.com
|
||||||
|
|
||||||
|
Author
|
||||||
|
~~~~~~
|
||||||
|
David Barr, aka javidx9, ©OneLoneCoder 2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef OLC_PGEX_GFX3D
|
||||||
|
#define OLC_PGEX_GFX3D
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
namespace olc
|
||||||
|
{
|
||||||
|
// Container class for Advanced 2D Drawing functions
|
||||||
|
class GFX3D : public olc::PGEX
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct vec2d
|
||||||
|
{
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
float z = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vec3d
|
||||||
|
{
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
float z = 0;
|
||||||
|
float w = 1; // Need a 4th term to perform sensible matrix vector multiplication
|
||||||
|
};
|
||||||
|
|
||||||
|
struct triangle
|
||||||
|
{
|
||||||
|
vec3d p[3];
|
||||||
|
vec2d t[3];
|
||||||
|
olc::Pixel col;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat4x4
|
||||||
|
{
|
||||||
|
float m[4][4] = { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mesh
|
||||||
|
{
|
||||||
|
std::vector<triangle> tris;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Math
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline Math();
|
||||||
|
public:
|
||||||
|
inline static vec3d Mat_MultiplyVector(mat4x4 &m, vec3d &i);
|
||||||
|
inline static mat4x4 Mat_MultiplyMatrix(mat4x4 &m1, mat4x4 &m2);
|
||||||
|
inline static mat4x4 Mat_MakeIdentity();
|
||||||
|
inline static mat4x4 Mat_MakeRotationX(float fAngleRad);
|
||||||
|
inline static mat4x4 Mat_MakeRotationY(float fAngleRad);
|
||||||
|
inline static mat4x4 Mat_MakeRotationZ(float fAngleRad);
|
||||||
|
inline static mat4x4 Mat_MakeScale(float x, float y, float z);
|
||||||
|
inline static mat4x4 Mat_MakeTranslation(float x, float y, float z);
|
||||||
|
inline static mat4x4 Mat_MakeProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar);
|
||||||
|
inline static mat4x4 Mat_PointAt(vec3d &pos, vec3d &target, vec3d &up);
|
||||||
|
inline static mat4x4 Mat_QuickInverse(mat4x4 &m); // Only for Rotation/Translation Matrices
|
||||||
|
inline static mat4x4 Mat_Inverse(olc::GFX3D::mat4x4 &m);
|
||||||
|
|
||||||
|
inline static vec3d Vec_Add(vec3d &v1, vec3d &v2);
|
||||||
|
inline static vec3d Vec_Sub(vec3d &v1, vec3d &v2);
|
||||||
|
inline static vec3d Vec_Mul(vec3d &v1, float k);
|
||||||
|
inline static vec3d Vec_Div(vec3d &v1, float k);
|
||||||
|
inline static float Vec_DotProduct(vec3d &v1, vec3d &v2);
|
||||||
|
inline static float Vec_Length(vec3d &v);
|
||||||
|
inline static vec3d Vec_Normalise(vec3d &v);
|
||||||
|
inline static vec3d Vec_CrossProduct(vec3d &v1, vec3d &v2);
|
||||||
|
inline static vec3d Vec_IntersectPlane(vec3d &plane_p, vec3d &plane_n, vec3d &lineStart, vec3d &lineEnd, float &t);
|
||||||
|
|
||||||
|
inline static int Triangle_ClipAgainstPlane(vec3d plane_p, vec3d plane_n, triangle &in_tri, triangle &out_tri1, triangle &out_tri2);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RENDERFLAGS
|
||||||
|
{
|
||||||
|
RENDER_WIRE = 0x01,
|
||||||
|
RENDER_FLAT = 0x02,
|
||||||
|
RENDER_TEXTURED = 0x04,
|
||||||
|
RENDER_CULL_CW = 0x08,
|
||||||
|
RENDER_CULL_CCW = 0x10,
|
||||||
|
RENDER_DEPTH = 0x20,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PipeLine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PipeLine();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void SetProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar, float fLeft, float fTop, float fWidth, float fHeight);
|
||||||
|
void SetCamera(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &lookat, olc::GFX3D::vec3d &up);
|
||||||
|
void SetTransform(olc::GFX3D::mat4x4 &transform);
|
||||||
|
void SetTexture(olc::Sprite *texture);
|
||||||
|
void SetLightSource(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &dir, olc::Pixel &col);
|
||||||
|
uint32_t Render(std::vector<olc::GFX3D::triangle> &triangles, uint32_t flags = RENDER_CULL_CW | RENDER_TEXTURED | RENDER_DEPTH);
|
||||||
|
|
||||||
|
private:
|
||||||
|
olc::GFX3D::mat4x4 matProj;
|
||||||
|
olc::GFX3D::mat4x4 matView;
|
||||||
|
olc::GFX3D::mat4x4 matWorld;
|
||||||
|
olc::Sprite *sprTexture;
|
||||||
|
float fViewX;
|
||||||
|
float fViewY;
|
||||||
|
float fViewW;
|
||||||
|
float fViewH;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//static const int RF_TEXTURE = 0x00000001;
|
||||||
|
//static const int RF_ = 0x00000002;
|
||||||
|
|
||||||
|
inline static void ConfigureDisplay();
|
||||||
|
inline static void ClearDepth();
|
||||||
|
inline static void AddTriangleToScene(olc::GFX3D::triangle &tri);
|
||||||
|
inline static void RenderScene();
|
||||||
|
|
||||||
|
inline static void DrawTriangleFlat(olc::GFX3D::triangle &tri);
|
||||||
|
inline static void DrawTriangleWire(olc::GFX3D::triangle &tri, olc::Pixel col = olc::WHITE);
|
||||||
|
inline static void DrawTriangleTex(olc::GFX3D::triangle &tri, olc::Sprite* spr);
|
||||||
|
inline static void TexturedTriangle(int x1, int y1, float u1, float v1, float w1,
|
||||||
|
int x2, int y2, float u2, float v2, float w2,
|
||||||
|
int x3, int y3, float u3, float v3, float w3, olc::Sprite* spr);
|
||||||
|
|
||||||
|
// Draws a sprite with the transform applied
|
||||||
|
//inline static void DrawSprite(olc::Sprite *sprite, olc::GFX2D::Transform2D &transform);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static float* m_DepthBuffer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace olc
|
||||||
|
{
|
||||||
|
olc::GFX3D::Math::Math()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Mat_MultiplyVector(olc::GFX3D::mat4x4 &m, olc::GFX3D::vec3d &i)
|
||||||
|
{
|
||||||
|
vec3d v;
|
||||||
|
v.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + i.w * m.m[3][0];
|
||||||
|
v.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + i.w * m.m[3][1];
|
||||||
|
v.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + i.w * m.m[3][2];
|
||||||
|
v.w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + i.w * m.m[3][3];
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeIdentity()
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = 1.0f;
|
||||||
|
matrix.m[1][1] = 1.0f;
|
||||||
|
matrix.m[2][2] = 1.0f;
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeRotationX(float fAngleRad)
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = 1.0f;
|
||||||
|
matrix.m[1][1] = cosf(fAngleRad);
|
||||||
|
matrix.m[1][2] = sinf(fAngleRad);
|
||||||
|
matrix.m[2][1] = -sinf(fAngleRad);
|
||||||
|
matrix.m[2][2] = cosf(fAngleRad);
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeRotationY(float fAngleRad)
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = cosf(fAngleRad);
|
||||||
|
matrix.m[0][2] = sinf(fAngleRad);
|
||||||
|
matrix.m[2][0] = -sinf(fAngleRad);
|
||||||
|
matrix.m[1][1] = 1.0f;
|
||||||
|
matrix.m[2][2] = cosf(fAngleRad);
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeRotationZ(float fAngleRad)
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = cosf(fAngleRad);
|
||||||
|
matrix.m[0][1] = sinf(fAngleRad);
|
||||||
|
matrix.m[1][0] = -sinf(fAngleRad);
|
||||||
|
matrix.m[1][1] = cosf(fAngleRad);
|
||||||
|
matrix.m[2][2] = 1.0f;
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeScale(float x, float y, float z)
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = x;
|
||||||
|
matrix.m[1][1] = y;
|
||||||
|
matrix.m[2][2] = z;
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeTranslation(float x, float y, float z)
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = 1.0f;
|
||||||
|
matrix.m[1][1] = 1.0f;
|
||||||
|
matrix.m[2][2] = 1.0f;
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
matrix.m[3][0] = x;
|
||||||
|
matrix.m[3][1] = y;
|
||||||
|
matrix.m[3][2] = z;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar)
|
||||||
|
{
|
||||||
|
float fFovRad = 1.0f / tanf(fFovDegrees * 0.5f / 180.0f * 3.14159f);
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = fAspectRatio * fFovRad;
|
||||||
|
matrix.m[1][1] = fFovRad;
|
||||||
|
matrix.m[2][2] = fFar / (fFar - fNear);
|
||||||
|
matrix.m[3][2] = (-fFar * fNear) / (fFar - fNear);
|
||||||
|
matrix.m[2][3] = 1.0f;
|
||||||
|
matrix.m[3][3] = 0.0f;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MultiplyMatrix(olc::GFX3D::mat4x4 &m1, olc::GFX3D::mat4x4 &m2)
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
for (int c = 0; c < 4; c++)
|
||||||
|
for (int r = 0; r < 4; r++)
|
||||||
|
matrix.m[r][c] = m1.m[r][0] * m2.m[0][c] + m1.m[r][1] * m2.m[1][c] + m1.m[r][2] * m2.m[2][c] + m1.m[r][3] * m2.m[3][c];
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_PointAt(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &target, olc::GFX3D::vec3d &up)
|
||||||
|
{
|
||||||
|
// Calculate new forward direction
|
||||||
|
olc::GFX3D::vec3d newForward = Vec_Sub(target, pos);
|
||||||
|
newForward = Vec_Normalise(newForward);
|
||||||
|
|
||||||
|
// Calculate new Up direction
|
||||||
|
olc::GFX3D::vec3d a = Vec_Mul(newForward, Vec_DotProduct(up, newForward));
|
||||||
|
olc::GFX3D::vec3d newUp = Vec_Sub(up, a);
|
||||||
|
newUp = Vec_Normalise(newUp);
|
||||||
|
|
||||||
|
// New Right direction is easy, its just cross product
|
||||||
|
olc::GFX3D::vec3d newRight = Vec_CrossProduct(newUp, newForward);
|
||||||
|
|
||||||
|
// Construct Dimensioning and Translation Matrix
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = newRight.x; matrix.m[0][1] = newRight.y; matrix.m[0][2] = newRight.z; matrix.m[0][3] = 0.0f;
|
||||||
|
matrix.m[1][0] = newUp.x; matrix.m[1][1] = newUp.y; matrix.m[1][2] = newUp.z; matrix.m[1][3] = 0.0f;
|
||||||
|
matrix.m[2][0] = newForward.x; matrix.m[2][1] = newForward.y; matrix.m[2][2] = newForward.z; matrix.m[2][3] = 0.0f;
|
||||||
|
matrix.m[3][0] = pos.x; matrix.m[3][1] = pos.y; matrix.m[3][2] = pos.z; matrix.m[3][3] = 1.0f;
|
||||||
|
return matrix;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_QuickInverse(olc::GFX3D::mat4x4 &m) // Only for Rotation/Translation Matrices
|
||||||
|
{
|
||||||
|
olc::GFX3D::mat4x4 matrix;
|
||||||
|
matrix.m[0][0] = m.m[0][0]; matrix.m[0][1] = m.m[1][0]; matrix.m[0][2] = m.m[2][0]; matrix.m[0][3] = 0.0f;
|
||||||
|
matrix.m[1][0] = m.m[0][1]; matrix.m[1][1] = m.m[1][1]; matrix.m[1][2] = m.m[2][1]; matrix.m[1][3] = 0.0f;
|
||||||
|
matrix.m[2][0] = m.m[0][2]; matrix.m[2][1] = m.m[1][2]; matrix.m[2][2] = m.m[2][2]; matrix.m[2][3] = 0.0f;
|
||||||
|
matrix.m[3][0] = -(m.m[3][0] * matrix.m[0][0] + m.m[3][1] * matrix.m[1][0] + m.m[3][2] * matrix.m[2][0]);
|
||||||
|
matrix.m[3][1] = -(m.m[3][0] * matrix.m[0][1] + m.m[3][1] * matrix.m[1][1] + m.m[3][2] * matrix.m[2][1]);
|
||||||
|
matrix.m[3][2] = -(m.m[3][0] * matrix.m[0][2] + m.m[3][1] * matrix.m[1][2] + m.m[3][2] * matrix.m[2][2]);
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_Inverse(olc::GFX3D::mat4x4 &m)
|
||||||
|
{
|
||||||
|
double det;
|
||||||
|
|
||||||
|
|
||||||
|
mat4x4 matInv;
|
||||||
|
|
||||||
|
matInv.m[0][0] = m.m[1][1] * m.m[2][2] * m.m[3][3] - m.m[1][1] * m.m[2][3] * m.m[3][2] - m.m[2][1] * m.m[1][2] * m.m[3][3] + m.m[2][1] * m.m[1][3] * m.m[3][2] + m.m[3][1] * m.m[1][2] * m.m[2][3] - m.m[3][1] * m.m[1][3] * m.m[2][2];
|
||||||
|
matInv.m[1][0] = -m.m[1][0] * m.m[2][2] * m.m[3][3] + m.m[1][0] * m.m[2][3] * m.m[3][2] + m.m[2][0] * m.m[1][2] * m.m[3][3] - m.m[2][0] * m.m[1][3] * m.m[3][2] - m.m[3][0] * m.m[1][2] * m.m[2][3] + m.m[3][0] * m.m[1][3] * m.m[2][2];
|
||||||
|
matInv.m[2][0] = m.m[1][0] * m.m[2][1] * m.m[3][3] - m.m[1][0] * m.m[2][3] * m.m[3][1] - m.m[2][0] * m.m[1][1] * m.m[3][3] + m.m[2][0] * m.m[1][3] * m.m[3][1] + m.m[3][0] * m.m[1][1] * m.m[2][3] - m.m[3][0] * m.m[1][3] * m.m[2][1];
|
||||||
|
matInv.m[3][0] = -m.m[1][0] * m.m[2][1] * m.m[3][2] + m.m[1][0] * m.m[2][2] * m.m[3][1] + m.m[2][0] * m.m[1][1] * m.m[3][2] - m.m[2][0] * m.m[1][2] * m.m[3][1] - m.m[3][0] * m.m[1][1] * m.m[2][2] + m.m[3][0] * m.m[1][2] * m.m[2][1];
|
||||||
|
matInv.m[0][1] = -m.m[0][1] * m.m[2][2] * m.m[3][3] + m.m[0][1] * m.m[2][3] * m.m[3][2] + m.m[2][1] * m.m[0][2] * m.m[3][3] - m.m[2][1] * m.m[0][3] * m.m[3][2] - m.m[3][1] * m.m[0][2] * m.m[2][3] + m.m[3][1] * m.m[0][3] * m.m[2][2];
|
||||||
|
matInv.m[1][1] = m.m[0][0] * m.m[2][2] * m.m[3][3] - m.m[0][0] * m.m[2][3] * m.m[3][2] - m.m[2][0] * m.m[0][2] * m.m[3][3] + m.m[2][0] * m.m[0][3] * m.m[3][2] + m.m[3][0] * m.m[0][2] * m.m[2][3] - m.m[3][0] * m.m[0][3] * m.m[2][2];
|
||||||
|
matInv.m[2][1] = -m.m[0][0] * m.m[2][1] * m.m[3][3] + m.m[0][0] * m.m[2][3] * m.m[3][1] + m.m[2][0] * m.m[0][1] * m.m[3][3] - m.m[2][0] * m.m[0][3] * m.m[3][1] - m.m[3][0] * m.m[0][1] * m.m[2][3] + m.m[3][0] * m.m[0][3] * m.m[2][1];
|
||||||
|
matInv.m[3][1] = m.m[0][0] * m.m[2][1] * m.m[3][2] - m.m[0][0] * m.m[2][2] * m.m[3][1] - m.m[2][0] * m.m[0][1] * m.m[3][2] + m.m[2][0] * m.m[0][2] * m.m[3][1] + m.m[3][0] * m.m[0][1] * m.m[2][2] - m.m[3][0] * m.m[0][2] * m.m[2][1];
|
||||||
|
matInv.m[0][2] = m.m[0][1] * m.m[1][2] * m.m[3][3] - m.m[0][1] * m.m[1][3] * m.m[3][2] - m.m[1][1] * m.m[0][2] * m.m[3][3] + m.m[1][1] * m.m[0][3] * m.m[3][2] + m.m[3][1] * m.m[0][2] * m.m[1][3] - m.m[3][1] * m.m[0][3] * m.m[1][2];
|
||||||
|
matInv.m[1][2] = -m.m[0][0] * m.m[1][2] * m.m[3][3] + m.m[0][0] * m.m[1][3] * m.m[3][2] + m.m[1][0] * m.m[0][2] * m.m[3][3] - m.m[1][0] * m.m[0][3] * m.m[3][2] - m.m[3][0] * m.m[0][2] * m.m[1][3] + m.m[3][0] * m.m[0][3] * m.m[1][2];
|
||||||
|
matInv.m[2][2] = m.m[0][0] * m.m[1][1] * m.m[3][3] - m.m[0][0] * m.m[1][3] * m.m[3][1] - m.m[1][0] * m.m[0][1] * m.m[3][3] + m.m[1][0] * m.m[0][3] * m.m[3][1] + m.m[3][0] * m.m[0][1] * m.m[1][3] - m.m[3][0] * m.m[0][3] * m.m[1][1];
|
||||||
|
matInv.m[3][2] = -m.m[0][0] * m.m[1][1] * m.m[3][2] + m.m[0][0] * m.m[1][2] * m.m[3][1] + m.m[1][0] * m.m[0][1] * m.m[3][2] - m.m[1][0] * m.m[0][2] * m.m[3][1] - m.m[3][0] * m.m[0][1] * m.m[1][2] + m.m[3][0] * m.m[0][2] * m.m[1][1];
|
||||||
|
matInv.m[0][3] = -m.m[0][1] * m.m[1][2] * m.m[2][3] + m.m[0][1] * m.m[1][3] * m.m[2][2] + m.m[1][1] * m.m[0][2] * m.m[2][3] - m.m[1][1] * m.m[0][3] * m.m[2][2] - m.m[2][1] * m.m[0][2] * m.m[1][3] + m.m[2][1] * m.m[0][3] * m.m[1][2];
|
||||||
|
matInv.m[1][3] = m.m[0][0] * m.m[1][2] * m.m[2][3] - m.m[0][0] * m.m[1][3] * m.m[2][2] - m.m[1][0] * m.m[0][2] * m.m[2][3] + m.m[1][0] * m.m[0][3] * m.m[2][2] + m.m[2][0] * m.m[0][2] * m.m[1][3] - m.m[2][0] * m.m[0][3] * m.m[1][2];
|
||||||
|
matInv.m[2][3] = -m.m[0][0] * m.m[1][1] * m.m[2][3] + m.m[0][0] * m.m[1][3] * m.m[2][1] + m.m[1][0] * m.m[0][1] * m.m[2][3] - m.m[1][0] * m.m[0][3] * m.m[2][1] - m.m[2][0] * m.m[0][1] * m.m[1][3] + m.m[2][0] * m.m[0][3] * m.m[1][1];
|
||||||
|
matInv.m[3][3] = m.m[0][0] * m.m[1][1] * m.m[2][2] - m.m[0][0] * m.m[1][2] * m.m[2][1] - m.m[1][0] * m.m[0][1] * m.m[2][2] + m.m[1][0] * m.m[0][2] * m.m[2][1] + m.m[2][0] * m.m[0][1] * m.m[1][2] - m.m[2][0] * m.m[0][2] * m.m[1][1];
|
||||||
|
|
||||||
|
det = m.m[0][0] * matInv.m[0][0] + m.m[0][1] * matInv.m[1][0] + m.m[0][2] * matInv.m[2][0] + m.m[0][3] * matInv.m[3][0];
|
||||||
|
// if (det == 0) return false;
|
||||||
|
|
||||||
|
det = 1.0 / det;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
matInv.m[i][j] *= (float)det;
|
||||||
|
|
||||||
|
return matInv;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Add(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2)
|
||||||
|
{
|
||||||
|
return { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Sub(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2)
|
||||||
|
{
|
||||||
|
return { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Mul(olc::GFX3D::vec3d &v1, float k)
|
||||||
|
{
|
||||||
|
return { v1.x * k, v1.y * k, v1.z * k };
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Div(olc::GFX3D::vec3d &v1, float k)
|
||||||
|
{
|
||||||
|
return { v1.x / k, v1.y / k, v1.z / k };
|
||||||
|
}
|
||||||
|
|
||||||
|
float olc::GFX3D::Math::Vec_DotProduct(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2)
|
||||||
|
{
|
||||||
|
return v1.x*v2.x + v1.y*v2.y + v1.z * v2.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float olc::GFX3D::Math::Vec_Length(olc::GFX3D::vec3d &v)
|
||||||
|
{
|
||||||
|
return sqrtf(Vec_DotProduct(v, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Normalise(olc::GFX3D::vec3d &v)
|
||||||
|
{
|
||||||
|
float l = Vec_Length(v);
|
||||||
|
return { v.x / l, v.y / l, v.z / l };
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Vec_CrossProduct(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2)
|
||||||
|
{
|
||||||
|
vec3d v;
|
||||||
|
v.x = v1.y * v2.z - v1.z * v2.y;
|
||||||
|
v.y = v1.z * v2.x - v1.x * v2.z;
|
||||||
|
v.z = v1.x * v2.y - v1.y * v2.x;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
olc::GFX3D::vec3d olc::GFX3D::Math::Vec_IntersectPlane(olc::GFX3D::vec3d &plane_p, olc::GFX3D::vec3d &plane_n, olc::GFX3D::vec3d &lineStart, olc::GFX3D::vec3d &lineEnd, float &t)
|
||||||
|
{
|
||||||
|
plane_n = Vec_Normalise(plane_n);
|
||||||
|
float plane_d = -Vec_DotProduct(plane_n, plane_p);
|
||||||
|
float ad = Vec_DotProduct(lineStart, plane_n);
|
||||||
|
float bd = Vec_DotProduct(lineEnd, plane_n);
|
||||||
|
t = (-plane_d - ad) / (bd - ad);
|
||||||
|
olc::GFX3D::vec3d lineStartToEnd = Vec_Sub(lineEnd, lineStart);
|
||||||
|
olc::GFX3D::vec3d lineToIntersect = Vec_Mul(lineStartToEnd, t);
|
||||||
|
return Vec_Add(lineStart, lineToIntersect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int olc::GFX3D::Math::Triangle_ClipAgainstPlane(vec3d plane_p, vec3d plane_n, triangle &in_tri, triangle &out_tri1, triangle &out_tri2)
|
||||||
|
{
|
||||||
|
// Make sure plane normal is indeed normal
|
||||||
|
plane_n = Math::Vec_Normalise(plane_n);
|
||||||
|
|
||||||
|
out_tri1.t[0] = in_tri.t[0];
|
||||||
|
out_tri2.t[0] = in_tri.t[0];
|
||||||
|
out_tri1.t[1] = in_tri.t[1];
|
||||||
|
out_tri2.t[1] = in_tri.t[1];
|
||||||
|
out_tri1.t[2] = in_tri.t[2];
|
||||||
|
out_tri2.t[2] = in_tri.t[2];
|
||||||
|
|
||||||
|
// Return signed shortest distance from point to plane, plane normal must be normalised
|
||||||
|
auto dist = [&](vec3d &p)
|
||||||
|
{
|
||||||
|
vec3d n = Math::Vec_Normalise(p);
|
||||||
|
return (plane_n.x * p.x + plane_n.y * p.y + plane_n.z * p.z - Math::Vec_DotProduct(plane_n, plane_p));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create two temporary storage arrays to classify points either side of plane
|
||||||
|
// If distance sign is positive, point lies on "inside" of plane
|
||||||
|
vec3d* inside_points[3]; int nInsidePointCount = 0;
|
||||||
|
vec3d* outside_points[3]; int nOutsidePointCount = 0;
|
||||||
|
vec2d* inside_tex[3]; int nInsideTexCount = 0;
|
||||||
|
vec2d* outside_tex[3]; int nOutsideTexCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Get signed distance of each point in triangle to plane
|
||||||
|
float d0 = dist(in_tri.p[0]);
|
||||||
|
float d1 = dist(in_tri.p[1]);
|
||||||
|
float d2 = dist(in_tri.p[2]);
|
||||||
|
|
||||||
|
if (d0 >= 0) { inside_points[nInsidePointCount++] = &in_tri.p[0]; inside_tex[nInsideTexCount++] = &in_tri.t[0]; }
|
||||||
|
else {
|
||||||
|
outside_points[nOutsidePointCount++] = &in_tri.p[0]; outside_tex[nOutsideTexCount++] = &in_tri.t[0];
|
||||||
|
}
|
||||||
|
if (d1 >= 0) {
|
||||||
|
inside_points[nInsidePointCount++] = &in_tri.p[1]; inside_tex[nInsideTexCount++] = &in_tri.t[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outside_points[nOutsidePointCount++] = &in_tri.p[1]; outside_tex[nOutsideTexCount++] = &in_tri.t[1];
|
||||||
|
}
|
||||||
|
if (d2 >= 0) {
|
||||||
|
inside_points[nInsidePointCount++] = &in_tri.p[2]; inside_tex[nInsideTexCount++] = &in_tri.t[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outside_points[nOutsidePointCount++] = &in_tri.p[2]; outside_tex[nOutsideTexCount++] = &in_tri.t[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now classify triangle points, and break the input triangle into
|
||||||
|
// smaller output triangles if required. There are four possible
|
||||||
|
// outcomes...
|
||||||
|
|
||||||
|
if (nInsidePointCount == 0)
|
||||||
|
{
|
||||||
|
// All points lie on the outside of plane, so clip whole triangle
|
||||||
|
// It ceases to exist
|
||||||
|
|
||||||
|
return 0; // No returned triangles are valid
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nInsidePointCount == 3)
|
||||||
|
{
|
||||||
|
// All points lie on the inside of plane, so do nothing
|
||||||
|
// and allow the triangle to simply pass through
|
||||||
|
out_tri1 = in_tri;
|
||||||
|
|
||||||
|
return 1; // Just the one returned original triangle is valid
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nInsidePointCount == 1 && nOutsidePointCount == 2)
|
||||||
|
{
|
||||||
|
// Triangle should be clipped. As two points lie outside
|
||||||
|
// the plane, the triangle simply becomes a smaller triangle
|
||||||
|
|
||||||
|
// Copy appearance info to new triangle
|
||||||
|
out_tri1.col = olc::MAGENTA;// in_tri.col;
|
||||||
|
|
||||||
|
// The inside point is valid, so keep that...
|
||||||
|
out_tri1.p[0] = *inside_points[0];
|
||||||
|
out_tri1.t[0] = *inside_tex[0];
|
||||||
|
|
||||||
|
// but the two new points are at the locations where the
|
||||||
|
// original sides of the triangle (lines) intersect with the plane
|
||||||
|
float t;
|
||||||
|
out_tri1.p[1] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[0], *outside_points[0], t);
|
||||||
|
out_tri1.t[1].x = t * (outside_tex[0]->x - inside_tex[0]->x) + inside_tex[0]->x;
|
||||||
|
out_tri1.t[1].y = t * (outside_tex[0]->y - inside_tex[0]->y) + inside_tex[0]->y;
|
||||||
|
out_tri1.t[1].z = t * (outside_tex[0]->z - inside_tex[0]->z) + inside_tex[0]->z;
|
||||||
|
|
||||||
|
out_tri1.p[2] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[0], *outside_points[1], t);
|
||||||
|
out_tri1.t[2].x = t * (outside_tex[1]->x - inside_tex[0]->x) + inside_tex[0]->x;
|
||||||
|
out_tri1.t[2].y = t * (outside_tex[1]->y - inside_tex[0]->y) + inside_tex[0]->y;
|
||||||
|
out_tri1.t[2].z = t * (outside_tex[1]->z - inside_tex[0]->z) + inside_tex[0]->z;
|
||||||
|
|
||||||
|
return 1; // Return the newly formed single triangle
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nInsidePointCount == 2 && nOutsidePointCount == 1)
|
||||||
|
{
|
||||||
|
// Triangle should be clipped. As two points lie inside the plane,
|
||||||
|
// the clipped triangle becomes a "quad". Fortunately, we can
|
||||||
|
// represent a quad with two new triangles
|
||||||
|
|
||||||
|
// Copy appearance info to new triangles
|
||||||
|
out_tri1.col = olc::GREEN;// in_tri.col;
|
||||||
|
out_tri2.col = olc::RED;// in_tri.col;
|
||||||
|
|
||||||
|
// The first triangle consists of the two inside points and a new
|
||||||
|
// point determined by the location where one side of the triangle
|
||||||
|
// intersects with the plane
|
||||||
|
out_tri1.p[0] = *inside_points[0];
|
||||||
|
out_tri1.t[0] = *inside_tex[0];
|
||||||
|
|
||||||
|
out_tri1.p[1] = *inside_points[1];
|
||||||
|
out_tri1.t[1] = *inside_tex[1];
|
||||||
|
|
||||||
|
float t;
|
||||||
|
out_tri1.p[2] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[0], *outside_points[0], t);
|
||||||
|
out_tri1.t[2].x = t * (outside_tex[0]->x - inside_tex[0]->x) + inside_tex[0]->x;
|
||||||
|
out_tri1.t[2].y = t * (outside_tex[0]->y - inside_tex[0]->y) + inside_tex[0]->y;
|
||||||
|
out_tri1.t[2].z = t * (outside_tex[0]->z - inside_tex[0]->z) + inside_tex[0]->z;
|
||||||
|
|
||||||
|
// The second triangle is composed of one of he inside points, a
|
||||||
|
// new point determined by the intersection of the other side of the
|
||||||
|
// triangle and the plane, and the newly created point above
|
||||||
|
out_tri2.p[1] = *inside_points[1];
|
||||||
|
out_tri2.t[1] = *inside_tex[1];
|
||||||
|
out_tri2.p[0] = out_tri1.p[2];
|
||||||
|
out_tri2.t[0] = out_tri1.t[2];
|
||||||
|
out_tri2.p[2] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[1], *outside_points[0], t);
|
||||||
|
out_tri2.t[2].x = t * (outside_tex[0]->x - inside_tex[1]->x) + inside_tex[1]->x;
|
||||||
|
out_tri2.t[2].y = t * (outside_tex[0]->y - inside_tex[1]->y) + inside_tex[1]->y;
|
||||||
|
out_tri2.t[2].z = t * (outside_tex[0]->z - inside_tex[1]->z) + inside_tex[1]->z;
|
||||||
|
return 2; // Return two newly formed triangles which form a quad
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::DrawTriangleFlat(olc::GFX3D::triangle &tri)
|
||||||
|
{
|
||||||
|
pge->FillTriangle(tri.p[0].x, tri.p[0].y, tri.p[1].x, tri.p[1].y, tri.p[2].x, tri.p[2].y, tri.col);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::DrawTriangleWire(olc::GFX3D::triangle &tri, olc::Pixel col)
|
||||||
|
{
|
||||||
|
pge->DrawTriangle(tri.p[0].x, tri.p[0].y, tri.p[1].x, tri.p[1].y, tri.p[2].x, tri.p[2].y, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::TexturedTriangle(int x1, int y1, float u1, float v1, float w1,
|
||||||
|
int x2, int y2, float u2, float v2, float w2,
|
||||||
|
int x3, int y3, float u3, float v3, float w3, olc::Sprite* spr)
|
||||||
|
{
|
||||||
|
pge->FillTexturedTriangle({{float(x1),float(y1)},{float(x2),float(y2)},{float(x3),float(y3)}},{{u1,v1},{u2,v2},{u3,v3}},{WHITE,WHITE,WHITE},spr);
|
||||||
|
}
|
||||||
|
|
||||||
|
float* GFX3D::m_DepthBuffer = nullptr;
|
||||||
|
|
||||||
|
void GFX3D::ConfigureDisplay()
|
||||||
|
{
|
||||||
|
m_DepthBuffer = new float[pge->ScreenWidth() * pge->ScreenHeight()]{ 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GFX3D::ClearDepth()
|
||||||
|
{
|
||||||
|
memset(m_DepthBuffer, 0, pge->ScreenWidth() * pge->ScreenHeight() * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GFX3D::PipeLine::PipeLine()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::PipeLine::SetProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar, float fLeft, float fTop, float fWidth, float fHeight)
|
||||||
|
{
|
||||||
|
matProj = GFX3D::Math::Mat_MakeProjection(fFovDegrees, fAspectRatio, fNear, fFar);
|
||||||
|
fViewX = fLeft;
|
||||||
|
fViewY = fTop;
|
||||||
|
fViewW = fWidth;
|
||||||
|
fViewH = fHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::PipeLine::SetCamera(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &lookat, olc::GFX3D::vec3d &up)
|
||||||
|
{
|
||||||
|
matView = GFX3D::Math::Mat_PointAt(pos, lookat, up);
|
||||||
|
matView = GFX3D::Math::Mat_QuickInverse(matView);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::PipeLine::SetTransform(olc::GFX3D::mat4x4 &transform)
|
||||||
|
{
|
||||||
|
matWorld = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::PipeLine::SetTexture(olc::Sprite *texture)
|
||||||
|
{
|
||||||
|
sprTexture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFX3D::PipeLine::SetLightSource(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &dir, olc::Pixel &col)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GFX3D::PipeLine::Render(std::vector<olc::GFX3D::triangle> &triangles, uint32_t flags)
|
||||||
|
{
|
||||||
|
// Calculate Transformation Matrix
|
||||||
|
mat4x4 matWorldView = Math::Mat_MultiplyMatrix(matWorld, matView);
|
||||||
|
//matWorldViewProj = Math::Mat_MultiplyMatrix(matWorldView, matProj);
|
||||||
|
|
||||||
|
// Store triangles for rastering later
|
||||||
|
std::vector<GFX3D::triangle> vecTrianglesToRaster;
|
||||||
|
|
||||||
|
int nTriangleDrawnCount = 0;
|
||||||
|
|
||||||
|
// Process Triangles
|
||||||
|
for (auto &tri : triangles)
|
||||||
|
{
|
||||||
|
GFX3D::triangle triTransformed;
|
||||||
|
|
||||||
|
// Just copy through texture coordinates
|
||||||
|
triTransformed.t[0] = { tri.t[0].x, tri.t[0].y, tri.t[0].z };
|
||||||
|
triTransformed.t[1] = { tri.t[1].x, tri.t[1].y, tri.t[1].z };
|
||||||
|
triTransformed.t[2] = { tri.t[2].x, tri.t[2].y, tri.t[2].z }; // Think!
|
||||||
|
|
||||||
|
// Transform Triangle from object into projected space
|
||||||
|
triTransformed.p[0] = GFX3D::Math::Mat_MultiplyVector(matWorldView, tri.p[0]);
|
||||||
|
triTransformed.p[1] = GFX3D::Math::Mat_MultiplyVector(matWorldView, tri.p[1]);
|
||||||
|
triTransformed.p[2] = GFX3D::Math::Mat_MultiplyVector(matWorldView, tri.p[2]);
|
||||||
|
|
||||||
|
// Calculate Triangle Normal in WorldView Space
|
||||||
|
GFX3D::vec3d normal, line1, line2;
|
||||||
|
line1 = GFX3D::Math::Vec_Sub(triTransformed.p[1], triTransformed.p[0]);
|
||||||
|
line2 = GFX3D::Math::Vec_Sub(triTransformed.p[2], triTransformed.p[0]);
|
||||||
|
normal = GFX3D::Math::Vec_CrossProduct(line1, line2);
|
||||||
|
normal = GFX3D::Math::Vec_Normalise(normal);
|
||||||
|
|
||||||
|
// Cull triangles that face away from viewer
|
||||||
|
if (flags & RENDER_CULL_CW && GFX3D::Math::Vec_DotProduct(normal, triTransformed.p[0]) > 0.0f) continue;
|
||||||
|
if (flags & RENDER_CULL_CCW && GFX3D::Math::Vec_DotProduct(normal, triTransformed.p[0]) < 0.0f) continue;
|
||||||
|
|
||||||
|
// If Lighting, calculate shading
|
||||||
|
triTransformed.col = olc::WHITE;
|
||||||
|
|
||||||
|
// Clip triangle against near plane
|
||||||
|
int nClippedTriangles = 0;
|
||||||
|
triangle clipped[2];
|
||||||
|
nClippedTriangles = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, 0.0f, 0.1f }, { 0.0f, 0.0f, 1.0f }, triTransformed, clipped[0], clipped[1]);
|
||||||
|
|
||||||
|
// This may yield two new triangles
|
||||||
|
for (int n = 0; n < nClippedTriangles; n++)
|
||||||
|
{
|
||||||
|
triangle triProjected = clipped[n];
|
||||||
|
|
||||||
|
// Project new triangle
|
||||||
|
triProjected.p[0] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[0]);
|
||||||
|
triProjected.p[1] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[1]);
|
||||||
|
triProjected.p[2] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[2]);
|
||||||
|
|
||||||
|
// Apply Projection to Verts
|
||||||
|
triProjected.p[0].x = triProjected.p[0].x / triProjected.p[0].w;
|
||||||
|
triProjected.p[1].x = triProjected.p[1].x / triProjected.p[1].w;
|
||||||
|
triProjected.p[2].x = triProjected.p[2].x / triProjected.p[2].w;
|
||||||
|
|
||||||
|
triProjected.p[0].y = triProjected.p[0].y / triProjected.p[0].w;
|
||||||
|
triProjected.p[1].y = triProjected.p[1].y / triProjected.p[1].w;
|
||||||
|
triProjected.p[2].y = triProjected.p[2].y / triProjected.p[2].w;
|
||||||
|
|
||||||
|
triProjected.p[0].z = triProjected.p[0].z / triProjected.p[0].w;
|
||||||
|
triProjected.p[1].z = triProjected.p[1].z / triProjected.p[1].w;
|
||||||
|
triProjected.p[2].z = triProjected.p[2].z / triProjected.p[2].w;
|
||||||
|
|
||||||
|
// Apply Projection to Tex coords
|
||||||
|
triProjected.t[0].x = triProjected.t[0].x / triProjected.p[0].w;
|
||||||
|
triProjected.t[1].x = triProjected.t[1].x / triProjected.p[1].w;
|
||||||
|
triProjected.t[2].x = triProjected.t[2].x / triProjected.p[2].w;
|
||||||
|
|
||||||
|
triProjected.t[0].y = triProjected.t[0].y / triProjected.p[0].w;
|
||||||
|
triProjected.t[1].y = triProjected.t[1].y / triProjected.p[1].w;
|
||||||
|
triProjected.t[2].y = triProjected.t[2].y / triProjected.p[2].w;
|
||||||
|
|
||||||
|
triProjected.t[0].z = 1.0f / triProjected.p[0].w;
|
||||||
|
triProjected.t[1].z = 1.0f / triProjected.p[1].w;
|
||||||
|
triProjected.t[2].z = 1.0f / triProjected.p[2].w;
|
||||||
|
|
||||||
|
// Clip against viewport in screen space
|
||||||
|
// Clip triangles against all four screen edges, this could yield
|
||||||
|
// a bunch of triangles, so create a queue that we traverse to
|
||||||
|
// ensure we only test new triangles generated against planes
|
||||||
|
triangle sclipped[2];
|
||||||
|
std::list<triangle> listTriangles;
|
||||||
|
|
||||||
|
|
||||||
|
// Add initial triangle
|
||||||
|
listTriangles.push_back(triProjected);
|
||||||
|
int nNewTriangles = 1;
|
||||||
|
|
||||||
|
for (int p = 0; p < 4; p++)
|
||||||
|
{
|
||||||
|
int nTrisToAdd = 0;
|
||||||
|
while (nNewTriangles > 0)
|
||||||
|
{
|
||||||
|
// Take triangle from front of queue
|
||||||
|
triangle test = listTriangles.front();
|
||||||
|
listTriangles.pop_front();
|
||||||
|
nNewTriangles--;
|
||||||
|
|
||||||
|
// Clip it against a plane. We only need to test each
|
||||||
|
// subsequent plane, against subsequent new triangles
|
||||||
|
// as all triangles after a plane clip are guaranteed
|
||||||
|
// to lie on the inside of the plane. I like how this
|
||||||
|
// comment is almost completely and utterly justified
|
||||||
|
switch (p)
|
||||||
|
{
|
||||||
|
case 0: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, -1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
|
||||||
|
case 1: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, +1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
|
||||||
|
case 2: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
|
||||||
|
case 3: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ +1.0f, 0.0f, 0.0f }, { -1.0f, 0.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clipping may yield a variable number of triangles, so
|
||||||
|
// add these new ones to the back of the queue for subsequent
|
||||||
|
// clipping against next planes
|
||||||
|
for (int w = 0; w < nTrisToAdd; w++)
|
||||||
|
listTriangles.push_back(sclipped[w]);
|
||||||
|
}
|
||||||
|
nNewTriangles = listTriangles.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &triRaster : listTriangles)
|
||||||
|
{
|
||||||
|
// Scale to viewport
|
||||||
|
/*triRaster.p[0].x *= -1.0f;
|
||||||
|
triRaster.p[1].x *= -1.0f;
|
||||||
|
triRaster.p[2].x *= -1.0f;
|
||||||
|
triRaster.p[0].y *= -1.0f;
|
||||||
|
triRaster.p[1].y *= -1.0f;
|
||||||
|
triRaster.p[2].y *= -1.0f;*/
|
||||||
|
vec3d vOffsetView = { 1,1,0 };
|
||||||
|
triRaster.p[0] = Math::Vec_Add(triRaster.p[0], vOffsetView);
|
||||||
|
triRaster.p[1] = Math::Vec_Add(triRaster.p[1], vOffsetView);
|
||||||
|
triRaster.p[2] = Math::Vec_Add(triRaster.p[2], vOffsetView);
|
||||||
|
triRaster.p[0].x *= 0.5f * fViewW;
|
||||||
|
triRaster.p[0].y *= 0.5f * fViewH;
|
||||||
|
triRaster.p[1].x *= 0.5f * fViewW;
|
||||||
|
triRaster.p[1].y *= 0.5f * fViewH;
|
||||||
|
triRaster.p[2].x *= 0.5f * fViewW;
|
||||||
|
triRaster.p[2].y *= 0.5f * fViewH;
|
||||||
|
vOffsetView = { fViewX,fViewY,0 };
|
||||||
|
triRaster.p[0] = Math::Vec_Add(triRaster.p[0], vOffsetView);
|
||||||
|
triRaster.p[1] = Math::Vec_Add(triRaster.p[1], vOffsetView);
|
||||||
|
triRaster.p[2] = Math::Vec_Add(triRaster.p[2], vOffsetView);
|
||||||
|
|
||||||
|
// For now, just draw triangle
|
||||||
|
|
||||||
|
if (flags & RENDER_TEXTURED)
|
||||||
|
{
|
||||||
|
TexturedTriangle(
|
||||||
|
triRaster.p[0].x, triRaster.p[0].y, triRaster.t[0].x, triRaster.t[0].y, triRaster.t[0].z,
|
||||||
|
triRaster.p[1].x, triRaster.p[1].y, triRaster.t[1].x, triRaster.t[1].y, triRaster.t[1].z,
|
||||||
|
triRaster.p[2].x, triRaster.p[2].y, triRaster.t[2].x, triRaster.t[2].y, triRaster.t[2].z,
|
||||||
|
sprTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & RENDER_WIRE)
|
||||||
|
{
|
||||||
|
DrawTriangleWire(triRaster, olc::RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & RENDER_FLAT)
|
||||||
|
{
|
||||||
|
DrawTriangleFlat(triRaster);
|
||||||
|
}
|
||||||
|
|
||||||
|
nTriangleDrawnCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nTriangleDrawnCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -315,11 +315,9 @@
|
|||||||
+FillTexturedTriangle() - Software rasterizes a textured, coloured, triangle
|
+FillTexturedTriangle() - Software rasterizes a textured, coloured, triangle
|
||||||
+FillTexturedPolygon() - Hijacks DecalStructure for configuration
|
+FillTexturedPolygon() - Hijacks DecalStructure for configuration
|
||||||
+olc::vf2d arguments for Sprite::Sample() functions
|
+olc::vf2d arguments for Sprite::Sample() functions
|
||||||
|
2.22: = Fix typo on dragged file buffers for unicode builds
|
||||||
SIG Updates:
|
2.23: Fixed Emscripten host sizing errors - Thanks Moros
|
||||||
The following additions are included in Sig's version of the PGE header (this is a sig version)
|
Fixed v2d_generic.clamp() function
|
||||||
+GetAnyKey() - Returns when a key is activated
|
|
||||||
+GetAnyKeyPress() - Returns when a key is pressed down (and if a keyboard key, which key it was)
|
|
||||||
|
|
||||||
!! Apple Platforms will not see these updates immediately - Sorry, I dont have a mac to test... !!
|
!! 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 !!
|
!! Volunteers willing to help appreciated, though PRs are manually integrated with credit !!
|
||||||
@ -976,8 +974,6 @@ namespace olc
|
|||||||
virtual bool OnUserUpdate(float fElapsedTime);
|
virtual bool OnUserUpdate(float fElapsedTime);
|
||||||
// Called once on application termination, so you can be one clean coder
|
// Called once on application termination, so you can be one clean coder
|
||||||
virtual bool OnUserDestroy();
|
virtual bool OnUserDestroy();
|
||||||
virtual void GetAnyKey();
|
|
||||||
virtual void GetAnyKeyPress(olc::Key pressedKey);
|
|
||||||
|
|
||||||
// Called when a text entry is confirmed with "enter" key
|
// Called when a text entry is confirmed with "enter" key
|
||||||
virtual void OnTextEntryComplete(const std::string& sText);
|
virtual void OnTextEntryComplete(const std::string& sText);
|
||||||
@ -3682,9 +3678,6 @@ namespace olc
|
|||||||
bool PixelGameEngine::OnUserDestroy()
|
bool PixelGameEngine::OnUserDestroy()
|
||||||
{ return true; }
|
{ return true; }
|
||||||
|
|
||||||
void PixelGameEngine::GetAnyKey(){};
|
|
||||||
void PixelGameEngine::GetAnyKeyPress(olc::Key pressedKey){};
|
|
||||||
|
|
||||||
void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); }
|
void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); }
|
||||||
bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; }
|
bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; }
|
||||||
|
|
||||||
@ -3842,10 +3835,8 @@ namespace olc
|
|||||||
platform->HandleSystemEvent();
|
platform->HandleSystemEvent();
|
||||||
|
|
||||||
// Compare hardware input states from previous frame
|
// 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++)
|
for (uint32_t i = 0; i < nKeyCount; i++)
|
||||||
{
|
{
|
||||||
pKeys[i].bPressed = false;
|
pKeys[i].bPressed = false;
|
||||||
@ -3854,8 +3845,6 @@ namespace olc
|
|||||||
{
|
{
|
||||||
if (pStateNew[i])
|
if (pStateNew[i])
|
||||||
{
|
{
|
||||||
pressed=true;
|
|
||||||
key=i;
|
|
||||||
pKeys[i].bPressed = !pKeys[i].bHeld;
|
pKeys[i].bPressed = !pKeys[i].bHeld;
|
||||||
pKeys[i].bHeld = true;
|
pKeys[i].bHeld = true;
|
||||||
}
|
}
|
||||||
@ -3864,18 +3853,13 @@ namespace olc
|
|||||||
pKeys[i].bReleased = true;
|
pKeys[i].bReleased = true;
|
||||||
pKeys[i].bHeld = false;
|
pKeys[i].bHeld = false;
|
||||||
}
|
}
|
||||||
GetAnyKey();
|
|
||||||
}
|
}
|
||||||
pStateOld[i] = pStateNew[i];
|
pStateOld[i] = pStateNew[i];
|
||||||
}
|
}
|
||||||
if (pressed) {
|
|
||||||
if (keyboard) {GetAnyKeyPress((olc::Key)key);}
|
|
||||||
else {GetAnyKeyPress(olc::Key::NONE);}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ScanHardware(pKeyboardState, pKeyOldState, pKeyNewState, 256);
|
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
|
// Cache mouse coordinates so they remain consistent during frame
|
||||||
vMousePos = vMousePosCache;
|
vMousePos = vMousePosCache;
|
||||||
@ -6709,3 +6693,4 @@ namespace olc
|
|||||||
// O------------------------------------------------------------------------------O
|
// O------------------------------------------------------------------------------O
|
||||||
// | END OF OLC_PGE_APPLICATION |
|
// | END OF OLC_PGE_APPLICATION |
|
||||||
// O------------------------------------------------------------------------------O
|
// O------------------------------------------------------------------------------O
|
||||||
|
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user