Implement model-to-screen space transformations
This commit is contained in:
parent
c82f690943
commit
33cb124d77
4
Makefile
4
Makefile
|
@ -36,10 +36,10 @@ WARNINGS_OFF=-Wno-missing-braces -Wno-gnu-anonymous-struct -Wno-old-style-cast\
|
||||||
CFLAGS=$(D) $(O) -std=c++11 $(WARNINGS_ON) $(WARNINGS_OFF) -I$(INCLUDE_DIR)
|
CFLAGS=$(D) $(O) -std=c++11 $(WARNINGS_ON) $(WARNINGS_OFF) -I$(INCLUDE_DIR)
|
||||||
LIBS=-lSDL2
|
LIBS=-lSDL2
|
||||||
|
|
||||||
_HEADERS = engine.h loader.h geometry.h platform.h point.h util.h
|
_HEADERS = engine.h geometry.h loader.h platform.h point.h transform.h util.h
|
||||||
HEADERS = $(patsubst %,$(INCLUDE_DIR)/%,$(_HEADERS))
|
HEADERS = $(patsubst %,$(INCLUDE_DIR)/%,$(_HEADERS))
|
||||||
|
|
||||||
_OBJS = engine.o loader.o main.o platform.o
|
_OBJS = engine.o loader.o main.o platform.o transform.o
|
||||||
OBJS = $(patsubst %,$(BUILD_DIR)/%,$(_OBJS))
|
OBJS = $(patsubst %,$(BUILD_DIR)/%,$(_OBJS))
|
||||||
|
|
||||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS)
|
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS)
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef CAMERA_H
|
||||||
|
|
||||||
|
#include "point.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
// STRUCTURE
|
||||||
|
struct Camera
|
||||||
|
{
|
||||||
|
inline Camera(void)
|
||||||
|
{
|
||||||
|
position.x = 0.0f;
|
||||||
|
position.y = 0.0f;
|
||||||
|
position.z = 0.0f;
|
||||||
|
|
||||||
|
rotation[0] = 0.0f;
|
||||||
|
rotation[1] = 0.0f;
|
||||||
|
rotation[2] = 0.0f;
|
||||||
|
|
||||||
|
nearClip = 1.0f;
|
||||||
|
farClip = 1000.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetFOV(float fov, int winWidth, int winHeight)
|
||||||
|
{
|
||||||
|
xZoom = 1.0f / tanf(DEG_TO_RAD(fov/2.0f));
|
||||||
|
yZoom = (xZoom * winWidth) / winHeight;
|
||||||
|
|
||||||
|
xScale = (0.5f * winWidth) - 0.5f;
|
||||||
|
yScale = (0.5f * winHeight) - 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Point position;
|
||||||
|
float rotation[3];
|
||||||
|
float nearClip, farClip;
|
||||||
|
float xZoom, yZoom;
|
||||||
|
float xScale, yScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define CAMERA_H
|
||||||
|
#endif
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct Engine_Buffer
|
||||||
|
|
||||||
|
|
||||||
// FUNCTIONS
|
// FUNCTIONS
|
||||||
int Engine_Init(char *filename);
|
int Engine_Init(Engine_Buffer &buffer, char *filename);
|
||||||
void Engine_Render(Engine_Buffer &buffer, uint32_t input);
|
void Engine_Render(Engine_Buffer &buffer, uint32_t input);
|
||||||
void Engine_Shutdown(void);
|
void Engine_Shutdown(void);
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,24 @@ struct Face
|
||||||
|
|
||||||
struct Mesh
|
struct Mesh
|
||||||
{
|
{
|
||||||
|
inline Mesh(void)
|
||||||
|
{
|
||||||
|
position.x = 0.0f;
|
||||||
|
position.y = 0.0f;
|
||||||
|
position.z = 0.0f;
|
||||||
|
|
||||||
|
rotation[0] = 0.0f;
|
||||||
|
rotation[1] = 0.0f;
|
||||||
|
rotation[2] = 0.0f;
|
||||||
|
|
||||||
|
scale = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point position;
|
||||||
|
float rotation[3];
|
||||||
|
float scale;
|
||||||
std::vector<Point> verts;
|
std::vector<Point> verts;
|
||||||
|
std::vector<Point> vertsTransformed;
|
||||||
std::vector<Face> faces;
|
std::vector<Face> faces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
#ifndef MATRIX_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "point.h"
|
||||||
|
|
||||||
|
|
||||||
|
// STRUCTURE
|
||||||
|
struct Matrix
|
||||||
|
{
|
||||||
|
inline Matrix(void)
|
||||||
|
{
|
||||||
|
e11 = 1.0; e12 = 0.0; e13 = 0.0; e14 = 0.0;
|
||||||
|
e21 = 0.0; e22 = 1.0; e23 = 0.0; e24 = 0.0;
|
||||||
|
e31 = 0.0; e32 = 0.0; e33 = 1.0; e34 = 0.0;
|
||||||
|
e41 = 0.0; e42 = 0.0; e43 = 0.0; e44 = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
float e[4][4];
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float e11, e12, e13, e14;
|
||||||
|
float e21, e22, e23, e24;
|
||||||
|
float e31, e32, e33, e34;
|
||||||
|
float e41, e42, e43, e44;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// OPERATORS
|
||||||
|
// m1 * m2
|
||||||
|
inline Matrix operator*(Matrix m1, Matrix m2)
|
||||||
|
{
|
||||||
|
Matrix result;
|
||||||
|
|
||||||
|
for (int row = 0; row < 4; ++row)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < 4; ++col)
|
||||||
|
{
|
||||||
|
float sum = 0.0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
sum += m1.e[row][i] * m2.e[i][col];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.e[row][col] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// v * m
|
||||||
|
inline Point operator*(Point v, Matrix m)
|
||||||
|
{
|
||||||
|
Point result;
|
||||||
|
|
||||||
|
for (int col = 0; col < 4; ++col)
|
||||||
|
{
|
||||||
|
float sum = 0.0;
|
||||||
|
|
||||||
|
for (int row = 0; row < 4; ++row)
|
||||||
|
{
|
||||||
|
sum += v.e[row] * m.e[row][col];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.e[col] = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MATRIX_H
|
||||||
|
#endif
|
||||||
|
|
|
@ -19,6 +19,22 @@ struct Point
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// OPERATORS
|
||||||
|
// v / f
|
||||||
|
inline Point operator/(Point v, float f)
|
||||||
|
{
|
||||||
|
Point result;
|
||||||
|
|
||||||
|
float inverse = 1.0f / f;
|
||||||
|
|
||||||
|
result.x = v.x * inverse;
|
||||||
|
result.y = v.y * inverse;
|
||||||
|
result.z = v.z * inverse;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define POINT_H
|
#define POINT_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef TRANSFORM_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
|
||||||
|
Matrix Transform_Translate(float x, float y, float z);
|
||||||
|
Matrix Transform_Rotate(float x, float y, float z);
|
||||||
|
Matrix Transform_Scale(float s);
|
||||||
|
Matrix Transform_View(Point &position, float rotation[]);
|
||||||
|
Matrix Transform_Perspective(float zoomX, float zoomY, float nearClip, float farClip);
|
||||||
|
Matrix Transform_Screen(float xScale, float yScale);
|
||||||
|
|
||||||
|
|
||||||
|
#define TRANSFORM_H
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
// CONSTANTS
|
||||||
|
const float EPSILON_E3 = 1E-3f;
|
||||||
|
|
||||||
|
|
||||||
// MACROS
|
// MACROS
|
||||||
#define SET_BIT(x, bit) (x |= (1UL << bit))
|
#define SET_BIT(x, bit) (x |= (1UL << bit))
|
||||||
#define CLEAR_BIT(x, bit) (x &= ~(1UL << bit))
|
#define CLEAR_BIT(x, bit) (x &= ~(1UL << bit))
|
||||||
#define CHECK_BIT(x, bit) (x & (1UL << bit))
|
#define CHECK_BIT(x, bit) (x & (1UL << bit))
|
||||||
|
#define DEG_TO_RAD(deg) ((deg * (float)M_PI) / 180.0f)
|
||||||
|
#define SWAP(a, b, temp) {temp = a; a = b; b = temp;}
|
||||||
|
#define FLOAT_EQUAL(a, b) ((fabsf(a - b) < EPSILON_E3) ? 1 : 0)
|
||||||
|
|
||||||
|
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
123
src/engine.cpp
123
src/engine.cpp
|
@ -1,12 +1,23 @@
|
||||||
|
#include "camera.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
|
#include "matrix.h"
|
||||||
|
#include "transform.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
||||||
// GLOBALS
|
// GLOBALS
|
||||||
static Mesh mesh;
|
static Mesh mesh;
|
||||||
|
static Camera camera;
|
||||||
|
|
||||||
|
|
||||||
int Engine_Init(char *filename)
|
// PRIVATE PROTOTYPES
|
||||||
|
static void CheckInputs(uint32_t input);
|
||||||
|
|
||||||
|
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
int Engine_Init(Engine_Buffer &buffer, char *filename)
|
||||||
{
|
{
|
||||||
int result = LoadMesh(filename, mesh);
|
int result = LoadMesh(filename, mesh);
|
||||||
|
|
||||||
|
@ -15,14 +26,124 @@ int Engine_Init(char *filename)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mesh.position.z = 250;
|
||||||
|
|
||||||
|
camera.SetFOV(90.0f, buffer.width, buffer.height);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
||||||
{
|
{
|
||||||
|
CheckInputs(input);
|
||||||
|
|
||||||
|
Matrix tTranslate = Transform_Translate(
|
||||||
|
mesh.position.x, mesh.position.y, mesh.position.z);
|
||||||
|
|
||||||
|
Matrix tRotate = Transform_Rotate(
|
||||||
|
mesh.rotation[0], mesh.rotation[1], mesh.rotation[2]);
|
||||||
|
|
||||||
|
Matrix tScale = Transform_Scale(
|
||||||
|
mesh.scale);
|
||||||
|
|
||||||
|
Matrix tView = Transform_View(
|
||||||
|
camera.position, camera.rotation);
|
||||||
|
|
||||||
|
Matrix tPersp = Transform_Perspective(
|
||||||
|
camera.xZoom, camera.yZoom, camera.nearClip, camera.farClip);
|
||||||
|
|
||||||
|
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
||||||
|
{
|
||||||
|
mesh.vertsTransformed[v] =
|
||||||
|
mesh.verts[v] * tScale * tRotate * tTranslate * tView * tPersp;
|
||||||
|
|
||||||
|
mesh.vertsTransformed[v] =
|
||||||
|
mesh.vertsTransformed[v] / mesh.vertsTransformed[v].w;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix tScreen = Transform_Screen(camera.xScale, camera.yScale);
|
||||||
|
|
||||||
|
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
||||||
|
{
|
||||||
|
mesh.vertsTransformed[v] = mesh.vertsTransformed[v] * tScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t f = 0; f < mesh.faces.size(); ++f)
|
||||||
|
{
|
||||||
|
unsigned int v0 = mesh.faces[f].vertIndex[0];
|
||||||
|
unsigned int v1 = mesh.faces[f].vertIndex[1];
|
||||||
|
unsigned int v2 = mesh.faces[f].vertIndex[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine_Shutdown(void)
|
void Engine_Shutdown(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PRIVATE FUNCTIONS
|
||||||
|
static void CheckInputs(uint32_t input)
|
||||||
|
{
|
||||||
|
if (CHECK_BIT(input, TRANSLATE_X_POS))
|
||||||
|
{
|
||||||
|
mesh.position.x += 10;
|
||||||
|
}
|
||||||
|
else if (CHECK_BIT(input, TRANSLATE_X_NEG))
|
||||||
|
{
|
||||||
|
mesh.position.x -= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_BIT(input, TRANSLATE_Z_POS))
|
||||||
|
{
|
||||||
|
mesh.position.z += 10;
|
||||||
|
}
|
||||||
|
else if (CHECK_BIT(input, TRANSLATE_Z_NEG))
|
||||||
|
{
|
||||||
|
mesh.position.z -= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_BIT(input, TRANSLATE_Y_POS))
|
||||||
|
{
|
||||||
|
mesh.position.y += 10;
|
||||||
|
}
|
||||||
|
else if (CHECK_BIT(input, TRANSLATE_Y_NEG))
|
||||||
|
{
|
||||||
|
mesh.position.y -= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_BIT(input, ROTATE_X_POS))
|
||||||
|
{
|
||||||
|
mesh.rotation[0] += .10;
|
||||||
|
}
|
||||||
|
else if (CHECK_BIT(input, ROTATE_X_NEG))
|
||||||
|
{
|
||||||
|
mesh.rotation[0] -= .10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_BIT(input, ROTATE_Z_POS))
|
||||||
|
{
|
||||||
|
mesh.rotation[1] += .10;
|
||||||
|
}
|
||||||
|
else if (CHECK_BIT(input, ROTATE_Z_NEG))
|
||||||
|
{
|
||||||
|
mesh.rotation[1] -= .10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_BIT(input, ROTATE_Y_POS))
|
||||||
|
{
|
||||||
|
mesh.rotation[2] += .10;
|
||||||
|
}
|
||||||
|
else if (CHECK_BIT(input, ROTATE_Y_NEG))
|
||||||
|
{
|
||||||
|
mesh.rotation[2] -= .10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_BIT(input, SCALE_UP))
|
||||||
|
{
|
||||||
|
mesh.scale += 0.1f;
|
||||||
|
}
|
||||||
|
else if (CHECK_BIT(input, SCALE_DOWN))
|
||||||
|
{
|
||||||
|
mesh.scale -= 0.1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -67,6 +67,8 @@ int LoadMesh(char *filename, Mesh &mesh)
|
||||||
printf("Verts: %lu\n", mesh.verts.size());
|
printf("Verts: %lu\n", mesh.verts.size());
|
||||||
printf("Faces: %lu\n", mesh.faces.size());
|
printf("Faces: %lu\n", mesh.faces.size());
|
||||||
|
|
||||||
|
mesh.vertsTransformed.resize(mesh.verts.size());
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
|
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
const unsigned int WINDOW_WIDTH = 800;
|
const unsigned int WINDOW_WIDTH = 1920;
|
||||||
const unsigned int WINDOW_HEIGHT = 600;
|
const unsigned int WINDOW_HEIGHT = 1080;
|
||||||
const unsigned int WINDOW_FPS = 30;
|
const unsigned int WINDOW_FPS = 30;
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ int main(int argc, char *argv[])
|
||||||
buffer.width = platform.surface->w;
|
buffer.width = platform.surface->w;
|
||||||
buffer.height = platform.surface->h;
|
buffer.height = platform.surface->h;
|
||||||
|
|
||||||
result = Engine_Init(filename);
|
result = Engine_Init(buffer, filename);
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
#include "matrix.h"
|
||||||
|
#include "transform.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
Matrix Transform_Translate(float x, float y, float z)
|
||||||
|
{
|
||||||
|
Matrix result;
|
||||||
|
|
||||||
|
result.e41 = x;
|
||||||
|
result.e42 = y;
|
||||||
|
result.e43 = z;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix Transform_Rotate(float x, float y, float z)
|
||||||
|
{
|
||||||
|
// YXZ Euler rotation
|
||||||
|
float cosThetaY = cosf(y);
|
||||||
|
float sinThetaY = sinf(y);
|
||||||
|
|
||||||
|
Matrix tRotateY;
|
||||||
|
|
||||||
|
tRotateY.e11 = cosThetaY;
|
||||||
|
tRotateY.e13 = -sinThetaY;
|
||||||
|
tRotateY.e31 = sinThetaY;
|
||||||
|
tRotateY.e33 = cosThetaY;
|
||||||
|
|
||||||
|
|
||||||
|
float cosThetaX = cosf(x);
|
||||||
|
float sinThetaX = sinf(x);
|
||||||
|
|
||||||
|
Matrix tRotateX;
|
||||||
|
|
||||||
|
tRotateX.e22 = cosThetaX;
|
||||||
|
tRotateX.e23 = sinThetaX;
|
||||||
|
tRotateX.e32 = -sinThetaX;
|
||||||
|
tRotateX.e33 = cosThetaX;
|
||||||
|
|
||||||
|
|
||||||
|
float cosThetaZ = cosf(z);
|
||||||
|
float sinThetaZ = sinf(z);
|
||||||
|
|
||||||
|
Matrix tRotateZ;
|
||||||
|
|
||||||
|
tRotateZ.e11 = cosThetaZ;
|
||||||
|
tRotateZ.e12 = sinThetaZ;
|
||||||
|
tRotateZ.e21 = -sinThetaZ;
|
||||||
|
tRotateZ.e22 = cosThetaZ;
|
||||||
|
|
||||||
|
|
||||||
|
Matrix result = tRotateY * tRotateX * tRotateZ;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix Transform_Scale(float s)
|
||||||
|
{
|
||||||
|
Matrix result;
|
||||||
|
|
||||||
|
result.e11 = s;
|
||||||
|
result.e22 = s;
|
||||||
|
result.e33 = s;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix Transform_View(Point &position, float rotation[])
|
||||||
|
{
|
||||||
|
Matrix tInvTranslate = Transform_Translate(-position.x, -position.y, -position.z);
|
||||||
|
|
||||||
|
Matrix tInvRotate = Transform_Rotate(-rotation[0], -rotation[1], -rotation[2]);
|
||||||
|
|
||||||
|
Matrix result = tInvTranslate * tInvRotate;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix Transform_Perspective(float zoomX, float zoomY, float nearClip, float farClip)
|
||||||
|
{
|
||||||
|
Matrix result;
|
||||||
|
|
||||||
|
result.e11 = zoomX;
|
||||||
|
result.e22 = zoomY;
|
||||||
|
result.e33 = (farClip + nearClip) / (farClip - nearClip);
|
||||||
|
result.e34 = 1;
|
||||||
|
result.e43 = (-2.0f * farClip * nearClip) / (farClip - nearClip);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix Transform_Screen(float xScale, float yScale)
|
||||||
|
{
|
||||||
|
Matrix result;
|
||||||
|
|
||||||
|
result.e11 = xScale;
|
||||||
|
result.e41 = xScale;
|
||||||
|
result.e22 = -yScale;
|
||||||
|
result.e42 = yScale;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue