1
0
Fork 0

Implement model-to-screen space transformations

This commit is contained in:
Austin Morlan 2018-09-05 18:48:27 -07:00
parent c82f690943
commit 33cb124d77
Signed by: austin
GPG Key ID: FD6B27654AF5E348
12 changed files with 418 additions and 7 deletions

View File

@ -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)

45
include/camera.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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;
}; };

80
include/matrix.h Normal file
View File

@ -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

View File

@ -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

17
include/transform.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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)
{ {

104
src/transform.cpp Normal file
View File

@ -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;
}