|
|
|
@ -1,8 +1,15 @@ |
|
|
|
|
#define OLC_PGE_APPLICATION |
|
|
|
|
#include "pixelGameEngine.h" |
|
|
|
|
#include <strstream> |
|
|
|
|
#include <algorithm> |
|
|
|
|
|
|
|
|
|
using namespace olc; |
|
|
|
|
|
|
|
|
|
struct vec2d |
|
|
|
|
{ |
|
|
|
|
float u,v; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct vec3d |
|
|
|
|
{ |
|
|
|
@ -12,11 +19,80 @@ struct vec3d |
|
|
|
|
struct triangle |
|
|
|
|
{ |
|
|
|
|
vec3d p[3]; |
|
|
|
|
vec2d uv[3]; |
|
|
|
|
Pixel col; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct mesh |
|
|
|
|
{ |
|
|
|
|
std::vector<triangle> tris; |
|
|
|
|
|
|
|
|
|
bool LoadFromObjectFile(std::string sFilename) |
|
|
|
|
{ |
|
|
|
|
std::ifstream f(sFilename); |
|
|
|
|
if (!f.is_open()) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
// Local cache of verts
|
|
|
|
|
std::vector<vec3d> verts; |
|
|
|
|
std::vector<vec2d> uvs; |
|
|
|
|
|
|
|
|
|
while (!f.eof()) |
|
|
|
|
{ |
|
|
|
|
char line[128]; |
|
|
|
|
f.getline(line, 128); |
|
|
|
|
|
|
|
|
|
std::strstream s; |
|
|
|
|
s << line; |
|
|
|
|
|
|
|
|
|
char junk; |
|
|
|
|
|
|
|
|
|
if (line[0] == 'v') |
|
|
|
|
{ |
|
|
|
|
if (line[1]=='t') { |
|
|
|
|
vec2d v; |
|
|
|
|
s >> junk >> junk >> v.u >> v.v; |
|
|
|
|
uvs.push_back(v); |
|
|
|
|
//std::cout<<"Line: "<<line<<"\n";
|
|
|
|
|
//std::cout<<"Tex coords: "<<v.u<<","<<v.v<<"\n";
|
|
|
|
|
} else |
|
|
|
|
if (line[1] != 'n') |
|
|
|
|
{ |
|
|
|
|
vec3d v; |
|
|
|
|
s >> junk >> v.x >> v.y >> v.z; |
|
|
|
|
verts.push_back(v); |
|
|
|
|
//std::cout<<"Line: "<<line<<"\n";
|
|
|
|
|
//std::cout<<"Vertex: "<<v.x<<","<<v.y<<","<<v.z<<"\n";
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (line[0] == 'f') |
|
|
|
|
{ |
|
|
|
|
s >> junk; |
|
|
|
|
|
|
|
|
|
std::string tokens[9]; |
|
|
|
|
int nTokenCount = -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (!s.eof()) |
|
|
|
|
{ |
|
|
|
|
char c = s.get(); |
|
|
|
|
if (c == ' ' || c == '/') |
|
|
|
|
nTokenCount++; |
|
|
|
|
else |
|
|
|
|
tokens[nTokenCount].append(1, c); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tokens[nTokenCount].pop_back(); |
|
|
|
|
|
|
|
|
|
tris.push_back({ verts[stoi(tokens[0]) - 1], verts[stoi(tokens[3]) - 1], verts[stoi(tokens[6]) - 1], |
|
|
|
|
0,0,0 |
|
|
|
|
/*uvs[stoi(tokens[1]) - 1], uvs[stoi(tokens[4]) - 1], uvs[stoi(tokens[7]) - 1]*/}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct mat4x4 |
|
|
|
@ -26,7 +102,10 @@ struct mat4x4 |
|
|
|
|
|
|
|
|
|
class olcEngine3D : public PixelGameEngine |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
Decal*texture; |
|
|
|
|
olcEngine3D() |
|
|
|
|
{ |
|
|
|
|
sAppName = "3D Demo"; |
|
|
|
@ -39,6 +118,8 @@ private: |
|
|
|
|
|
|
|
|
|
vec3d vCamera={0,0,0}; |
|
|
|
|
|
|
|
|
|
float zOffset=2; |
|
|
|
|
|
|
|
|
|
float fTheta=0; |
|
|
|
|
|
|
|
|
|
void MultiplyMatrixVector(vec3d &i, vec3d &o, mat4x4 &m) |
|
|
|
@ -57,33 +138,8 @@ private: |
|
|
|
|
public: |
|
|
|
|
bool OnUserCreate() override |
|
|
|
|
{ |
|
|
|
|
meshCube.tris = { |
|
|
|
|
|
|
|
|
|
// SOUTH
|
|
|
|
|
{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f }, |
|
|
|
|
{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }, |
|
|
|
|
|
|
|
|
|
// EAST
|
|
|
|
|
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f }, |
|
|
|
|
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, |
|
|
|
|
|
|
|
|
|
// NORTH
|
|
|
|
|
{ 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }, |
|
|
|
|
{ 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }, |
|
|
|
|
|
|
|
|
|
// WEST
|
|
|
|
|
{ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f }, |
|
|
|
|
{ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }, |
|
|
|
|
|
|
|
|
|
// TOP
|
|
|
|
|
{ 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, |
|
|
|
|
{ 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, |
|
|
|
|
|
|
|
|
|
// BOTTOM
|
|
|
|
|
{ 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, |
|
|
|
|
{ 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }, |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
texture = new Decal(new Sprite("Body.png")); |
|
|
|
|
meshCube.LoadFromObjectFile("Nia.obj"); |
|
|
|
|
|
|
|
|
|
// Projection Matrix
|
|
|
|
|
float fNear = 0.1f; |
|
|
|
@ -104,9 +160,21 @@ public: |
|
|
|
|
|
|
|
|
|
bool OnUserUpdate(float fElapsedTime) override |
|
|
|
|
{ |
|
|
|
|
if (GetKey(olc::DOWN).bHeld) { |
|
|
|
|
zOffset-=1*fElapsedTime; |
|
|
|
|
} |
|
|
|
|
if (GetKey(olc::UP).bHeld) { |
|
|
|
|
zOffset+=1*fElapsedTime; |
|
|
|
|
} |
|
|
|
|
if (GetKey(olc::RIGHT).bHeld) { |
|
|
|
|
fTheta-=1*fElapsedTime; |
|
|
|
|
} |
|
|
|
|
if (GetKey(olc::LEFT).bHeld) { |
|
|
|
|
fTheta+=1*fElapsedTime; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set up rotation matrices
|
|
|
|
|
mat4x4 matRotZ, matRotX; |
|
|
|
|
fTheta += 1.0f * fElapsedTime; |
|
|
|
|
|
|
|
|
|
// Rotation Z
|
|
|
|
|
matRotZ.m[0][0] = cosf(fTheta); |
|
|
|
@ -124,6 +192,8 @@ public: |
|
|
|
|
matRotX.m[2][2] = cosf(fTheta * 0.5f); |
|
|
|
|
matRotX.m[3][3] = 1; |
|
|
|
|
|
|
|
|
|
std::vector<triangle>vecTrianglesToRaster; |
|
|
|
|
|
|
|
|
|
// Draw Triangles
|
|
|
|
|
for (auto&tri : meshCube.tris) |
|
|
|
|
{ |
|
|
|
@ -141,9 +211,9 @@ public: |
|
|
|
|
|
|
|
|
|
// Offset into the screen
|
|
|
|
|
triTranslated = triRotatedZX; |
|
|
|
|
triTranslated.p[0].z = triRotatedZX.p[0].z + 3.0f; |
|
|
|
|
triTranslated.p[1].z = triRotatedZX.p[1].z + 3.0f; |
|
|
|
|
triTranslated.p[2].z = triRotatedZX.p[2].z + 3.0f; |
|
|
|
|
triTranslated.p[0].z = triRotatedZX.p[0].z + zOffset; |
|
|
|
|
triTranslated.p[1].z = triRotatedZX.p[1].z + zOffset; |
|
|
|
|
triTranslated.p[2].z = triRotatedZX.p[2].z + zOffset; |
|
|
|
|
|
|
|
|
|
vec3d normal,line1,line2; |
|
|
|
|
line1.x=triTranslated.p[1].x-triTranslated.p[0].x; |
|
|
|
@ -188,22 +258,45 @@ public: |
|
|
|
|
triProjected.p[1].y *= 0.5f * (float)ScreenHeight(); |
|
|
|
|
triProjected.p[2].x *= 0.5f * (float)ScreenWidth(); |
|
|
|
|
triProjected.p[2].y *= 0.5f * (float)ScreenHeight(); |
|
|
|
|
triProjected.col=Pixel(255*dp*dp,255*dp*dp,255*dp*dp); |
|
|
|
|
|
|
|
|
|
vecTrianglesToRaster.push_back(triProjected); |
|
|
|
|
|
|
|
|
|
// Rasterize triangle
|
|
|
|
|
//SetDecalMode(DecalMode::WIREFRAME);
|
|
|
|
|
DrawPolygonDecal(nullptr,{ |
|
|
|
|
{triProjected.p[0].x, triProjected.p[0].y}, |
|
|
|
|
{triProjected.p[1].x, triProjected.p[1].y}, |
|
|
|
|
{triProjected.p[2].x, triProjected.p[2].y} |
|
|
|
|
},{ |
|
|
|
|
{0,0}, |
|
|
|
|
{0,0}, |
|
|
|
|
{0,0}, |
|
|
|
|
},Pixel(255*dp*dp,255*dp*dp,255*dp*dp)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::sort(vecTrianglesToRaster.begin(),vecTrianglesToRaster.end(),[](triangle&t1,triangle&t2){return (t1.p[0].z+t1.p[1].z+t1.p[2].z)/3.0f>(t2.p[0].z+t2.p[1].z+t2.p[2].z)/3.0f;}); |
|
|
|
|
|
|
|
|
|
for (auto&triProjected:vecTrianglesToRaster) { |
|
|
|
|
|
|
|
|
|
// Rasterize triangle
|
|
|
|
|
SetDecalStructure(DecalStructure::LIST); |
|
|
|
|
SetDecalMode(DecalMode::NORMAL); |
|
|
|
|
DrawPolygonDecal(nullptr,{ |
|
|
|
|
{triProjected.p[0].x, triProjected.p[0].y}, |
|
|
|
|
{triProjected.p[1].x, triProjected.p[1].y}, |
|
|
|
|
{triProjected.p[2].x, triProjected.p[2].y} |
|
|
|
|
},{ |
|
|
|
|
{triProjected.uv[0].u,triProjected.uv[0].v}, |
|
|
|
|
{triProjected.uv[1].u,triProjected.uv[1].v}, |
|
|
|
|
{triProjected.uv[2].u,triProjected.uv[2].v}, |
|
|
|
|
},triProjected.col); |
|
|
|
|
/*SetDecalMode(DecalMode::WIREFRAME);
|
|
|
|
|
DrawPolygonDecal(nullptr,{ |
|
|
|
|
{triProjected.p[0].x, triProjected.p[0].y}, |
|
|
|
|
{triProjected.p[1].x, triProjected.p[1].y}, |
|
|
|
|
{triProjected.p[2].x, triProjected.p[2].y} |
|
|
|
|
},{ |
|
|
|
|
{0,0}, |
|
|
|
|
{0,0}, |
|
|
|
|
{0,0}, |
|
|
|
|
},BLACK);*/ |
|
|
|
|
SetDecalStructure(DecalStructure::FAN); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SetDecalMode(DecalMode::NORMAL); |
|
|
|
|
DrawStringDecal({0,0},"Triangles: "+std::to_string(meshCube.tris.size())); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|