1
0
Fork 0

Clean up main engine loop

This commit is contained in:
Austin Morlan 2018-09-18 19:18:58 -07:00
parent d26e4cb5dc
commit 0f73e2cd91
Signed by: austin
GPG Key ID: FD6B27654AF5E348
8 changed files with 200 additions and 170 deletions

View File

@ -1,5 +1,6 @@
#ifndef CAMERA_H #ifndef CAMERA_H
#include "engine.h"
#include "point.h" #include "point.h"
#include "util.h" #include "util.h"
#include <cmath> #include <cmath>
@ -14,27 +15,28 @@ struct Camera
position.y = 0.0f; position.y = 0.0f;
position.z = 0.0f; position.z = 0.0f;
rotation[0] = 0.0f; rotation.x = 0.0f;
rotation[1] = 0.0f; rotation.y = 0.0f;
rotation[2] = 0.0f; rotation.z = 0.0f;
nearClip = 5.0f; zClipBias0 =
farClip = 600.0f; (CAMERA_FAR_CLIP + CAMERA_NEAR_CLIP)
/ (CAMERA_FAR_CLIP - CAMERA_NEAR_CLIP);
zClipBias1 =
(-2.0f * CAMERA_FAR_CLIP * CAMERA_NEAR_CLIP)
/ (CAMERA_FAR_CLIP - CAMERA_NEAR_CLIP);
xZoom = 1.0f / tanf(DEG_TO_RAD(CAMERA_FOV/2.0f));
yZoom = (xZoom * WINDOW_WIDTH) / WINDOW_HEIGHT;
xScale = (0.5f * WINDOW_WIDTH) - 0.5f;
yScale = (0.5f * WINDOW_HEIGHT) - 0.5f;
} }
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; Point position;
float rotation[3]; Point rotation;
float nearClip, farClip; float zClipBias0, zClipBias1;
float xZoom, yZoom; float xZoom, yZoom;
float xScale, yScale; float xScale, yScale;
}; };

View File

@ -3,11 +3,22 @@
#include <cstdint> #include <cstdint>
// CONSTANTS // WINDOW CONFIGURATION
#define WINDOW_WIDTH (1920) #define WINDOW_WIDTH (1920)
#define WINDOW_HEIGHT (1080) #define WINDOW_HEIGHT (1080)
#define WINDOW_FPS (30) #define WINDOW_FPS (30)
// CAMERA CONFIGURATION
#define CAMERA_FOV (90.0f)
#define CAMERA_NEAR_CLIP (5.0f)
#define CAMERA_FAR_CLIP (600.0f)
// GEOMETRY CONFIGURATION
#define FACE_LIMIT (30000)
#define MATERIAL_LIMIT (10)
#define TEXTURE_SIZE_LIMIT (1024)
#define VERTEX_LIMIT (20000)
// ENUMS // ENUMS
enum Engine_Input enum Engine_Input
@ -40,7 +51,7 @@ struct Engine_Buffer
// FUNCTIONS // FUNCTIONS
int Engine_Init(Engine_Buffer &buffer, char *objFilename, char *mtlFilename); int Engine_Init(char *objFilename, char *mtlFilename);
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

@ -6,13 +6,6 @@
#include <cstdint> #include <cstdint>
// CONSTANTS
#define VERTEX_LIMIT (20000)
#define FACE_LIMIT (30000)
#define MATERIAL_LIMIT (10)
#define TEXTURE_SIZE_LIMIT (1024)
// STRUCTURES // STRUCTURES
struct Texture struct Texture
{ {
@ -82,21 +75,8 @@ struct FaceList
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; Point position;
float rotation[3]; Point rotation;
float scale; float scale;
}; };

View File

@ -1,15 +1,15 @@
#ifndef TRANSFORM_H #ifndef TRANSFORM_H
#include "camera.h"
#include "matrix.h" #include "matrix.h"
Matrix Transform_Translate(float x, float y, float z); Matrix Transform_Translate(Point &translation);
Matrix Transform_Rotate(float x, float y, float z); Matrix Transform_Rotate(Point &rotation);
Matrix Transform_Scale(float s); Matrix Transform_Scale(float scale);
Matrix Transform_View(Point &position, float rotation[]); Matrix Transform_View(Camera &camera);
Matrix Transform_Perspective(float zoomX, float zoomY, float nearClip, float farClip); Matrix Transform_Perspective(Camera &camera);
Matrix Transform_Screen(float xScale, float yScale); Matrix Transform_Screen(Camera &camera);
#define TRANSFORM_H #define TRANSFORM_H

View File

@ -23,117 +23,94 @@ static FaceList transFaces;
static UVList uvs; static UVList uvs;
static MaterialList materials; static MaterialList materials;
static TextureList textures; static TextureList textures;
static Matrix tPersp;
static Matrix tScreen;
// PRIVATE PROTOTYPES // PRIVATE PROTOTYPES
static void CheckInputs(uint32_t input); static void CheckInputs(uint32_t input);
static void ComputeNormals(VertexList &verts, FaceList &faces); static void ComputeNormals(void);
static void ClearDepthBuffer(Engine_Buffer &buffer);
static void TransformToClipSpace(void);
static void TransformToScreenSpace(void);
static void ComputeLighting(void);
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
int Engine_Init(Engine_Buffer &buffer, char *objFilename, char *mtlFilename) int Engine_Init(char *objFilename, char *mtlFilename)
{ {
int result = ParseOBJ(objFilename, localVerts, localFaces, uvs); int result;
result = ParseOBJ(objFilename, localVerts, localFaces, uvs);
if (result < 0) if (result < 0)
{ {
return result; return -1;
} }
result = ParseMTL(mtlFilename, materials, textures); result = ParseMTL(mtlFilename, materials, textures);
if (result < 0) if (result < 0)
{ {
return -1; return -1;
} }
printf("Verts: %lu\n", localVerts.size); printf("Verts: %lu\n", localVerts.size);
printf("Faces: %lu\n", localFaces.size); printf("Faces: %lu\n", localFaces.size);
printf("Materials: %lu\n", materials.size); printf("Materials: %lu\n", materials.size);
transVerts.size = localVerts.size; transVerts.size = localVerts.size;
ComputeNormals(localVerts, localFaces);
// Compute vertex and face normals for lighting calculation
ComputeNormals();
// Mesh configuration
mesh.position.z = 50; mesh.position.z = 50;
mesh.position.y = -50; mesh.position.y = -50;
mesh.scale = 1.0f;
camera.SetFOV(90.0f, buffer.width, buffer.height);
// Light configuration
lights.ambient.intensity = 1.0f; lights.ambient.intensity = 1.0f;
lights.diffuse.intensity = 1.0f; lights.diffuse.intensity = 1.0f;
lights.diffuse.direction = Vector(1.0f, 1.0f, 1.0f); lights.diffuse.direction = Vector(1.0f, 1.0f, 1.0f);
// Transformation matrices that do not change
tPersp = Transform_Perspective(camera);
tScreen = Transform_Screen(camera);
return 0; return 0;
} }
void Engine_Render(Engine_Buffer &buffer, uint32_t input) void Engine_Render(Engine_Buffer &buffer, uint32_t input)
{ {
// Check for user input
CheckInputs(input); CheckInputs(input);
// Clear the z-buffer // Clear the z-buffer
memset(buffer.zbuffer, 0, sizeof(float) * (size_t)(buffer.width * buffer.height)); ClearDepthBuffer(buffer);
// Local space to world space // Transform vertices to clip space
Matrix tTranslate = Transform_Translate( TransformToClipSpace();
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);
// World space to camera (view) space
Matrix tView = Transform_View(camera.position, camera.rotation);
// Camera space to perspective
Matrix tPersp = Transform_Perspective(
camera.xZoom, camera.yZoom, camera.nearClip, camera.farClip);
for (size_t v = 0; v < localVerts.size; ++v)
{
transVerts.data[v].point = localVerts.data[v].point * tScale * tRotate * tTranslate * tView * tPersp;
transVerts.data[v].normal = localVerts.data[v].normal * tScale * tRotate * tTranslate;
}
// Clip near and far Z, and cull backfaces // Clip near/far Z and cull backfaces
ClipAndCull(transVerts, localFaces, transFaces, camera.position); ClipAndCull(transVerts, localFaces, transFaces, camera.position);
// Lighting // Light vertices and/or faces
for (size_t f = 0; f < transFaces.size; ++f) ComputeLighting();
{
Face &face = transFaces.data[f];
Material &material = materials.data[face.materialIndex];
// TODO: Fix weird lighting
material.ambient = {1.0,1.0,1.0,1.0};
material.diffuse = {0.5,0.5,0.5,0.5};
// Gouraud shading
for (int i = 0; i < 3; ++i)
{
Vertex &vert = transVerts.data[face.vertIndex[i]];
vert.color =
lights.ambient.ComputeColor(material.ambient)
+ lights.diffuse.ComputeColor(material.diffuse, vert.normal);
}
}
// Perspective to screen // Transform vertices to screen space
Matrix tScreen = Transform_Screen(camera.xScale, camera.yScale); TransformToScreenSpace();
for (size_t v = 0; v < transVerts.size; ++v)
{
transVerts.data[v].point *= tScreen;
transVerts.data[v].point.x /= transVerts.data[v].point.w;
transVerts.data[v].point.y /= transVerts.data[v].point.w;
transVerts.data[v].point.z /= transVerts.data[v].point.w;
}
// Render // Render
@ -177,29 +154,29 @@ static void CheckInputs(uint32_t input)
if (CHECK_BIT(input, ROTATE_X_POS)) if (CHECK_BIT(input, ROTATE_X_POS))
{ {
mesh.rotation[0] += .10; mesh.rotation.x += .10;
} }
else if (CHECK_BIT(input, ROTATE_X_NEG)) else if (CHECK_BIT(input, ROTATE_X_NEG))
{ {
mesh.rotation[0] -= .10; mesh.rotation.x -= .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)) if (CHECK_BIT(input, ROTATE_Y_POS))
{ {
mesh.rotation[2] += .10; mesh.rotation.y += .10;
} }
else if (CHECK_BIT(input, ROTATE_Y_NEG)) else if (CHECK_BIT(input, ROTATE_Y_NEG))
{ {
mesh.rotation[2] -= .10; mesh.rotation.y -= .10;
}
if (CHECK_BIT(input, ROTATE_Z_POS))
{
mesh.rotation.z += .10;
}
else if (CHECK_BIT(input, ROTATE_Z_NEG))
{
mesh.rotation.z -= .10;
} }
if (CHECK_BIT(input, SCALE_UP)) if (CHECK_BIT(input, SCALE_UP))
@ -213,19 +190,19 @@ static void CheckInputs(uint32_t input)
} }
static void ComputeNormals(VertexList &verts, FaceList &faces) static void ComputeNormals(void)
{ {
int vertexNormalCount[VERTEX_LIMIT]; int vertexNormalCount[VERTEX_LIMIT] = {};
for (size_t f = 0; f < faces.size; ++f) for (size_t f = 0; f < localFaces.size; ++f)
{ {
size_t v0 = (size_t)faces.data[f].vertIndex[0]; size_t v0 = (size_t)localFaces.data[f].vertIndex[0];
size_t v1 = (size_t)faces.data[f].vertIndex[1]; size_t v1 = (size_t)localFaces.data[f].vertIndex[1];
size_t v2 = (size_t)faces.data[f].vertIndex[2]; size_t v2 = (size_t)localFaces.data[f].vertIndex[2];
Point &p0 = verts.data[v0].point; Point &p0 = localVerts.data[v0].point;
Point &p1 = verts.data[v1].point; Point &p1 = localVerts.data[v1].point;
Point &p2 = verts.data[v2].point; Point &p2 = localVerts.data[v2].point;
Vector v01 = p1 - p0; Vector v01 = p1 - p0;
Vector v02 = p2 - p0; Vector v02 = p2 - p0;
@ -233,9 +210,9 @@ static void ComputeNormals(VertexList &verts, FaceList &faces)
Vector normal = Vector::Cross(v01, v02); Vector normal = Vector::Cross(v01, v02);
// Add each vertex's normal to the sum for future averaging // Add each vertex's normal to the sum for future averaging
verts.data[v0].normal += normal; localVerts.data[v0].normal += normal;
verts.data[v1].normal += normal; localVerts.data[v1].normal += normal;
verts.data[v2].normal += normal; localVerts.data[v2].normal += normal;
++vertexNormalCount[v0]; ++vertexNormalCount[v0];
++vertexNormalCount[v1]; ++vertexNormalCount[v1];
@ -247,8 +224,66 @@ static void ComputeNormals(VertexList &verts, FaceList &faces)
if (vertexNormalCount[v] > 0) if (vertexNormalCount[v] > 0)
{ {
// Compute the average normal for this vertex // Compute the average normal for this vertex
verts.data[v].normal /= vertexNormalCount[v]; localVerts.data[v].normal /= vertexNormalCount[v];
verts.data[v].normal.Normalize(); localVerts.data[v].normal.Normalize();
}
}
}
static void ClearDepthBuffer(Engine_Buffer &buffer)
{
memset(buffer.zbuffer, 0, sizeof(float) * (size_t)(buffer.width * buffer.height));
}
static void TransformToClipSpace(void)
{
Matrix tTranslate = Transform_Translate(mesh.position);
Matrix tRotate = Transform_Rotate(mesh.rotation);
Matrix tScale = Transform_Scale(mesh.scale);
Matrix tView = Transform_View(camera);
for (size_t v = 0; v < localVerts.size; ++v)
{
transVerts.data[v].point =
localVerts.data[v].point * tScale * tRotate * tTranslate * tView * tPersp;
transVerts.data[v].normal =
localVerts.data[v].normal * tScale * tRotate * tTranslate;
}
}
static void TransformToScreenSpace(void)
{
for (size_t v = 0; v < transVerts.size; ++v)
{
transVerts.data[v].point *= tScreen;
transVerts.data[v].point.x /= transVerts.data[v].point.w;
transVerts.data[v].point.y /= transVerts.data[v].point.w;
transVerts.data[v].point.z /= transVerts.data[v].point.w;
}
}
static void ComputeLighting(void)
{
for (size_t f = 0; f < transFaces.size; ++f)
{
Face &face = transFaces.data[f];
Material &material = materials.data[face.materialIndex];
// TODO: Fix weird lighting
material.ambient = {1.0,1.0,1.0,1.0};
material.diffuse = {0.5,0.5,0.5,0.5};
// Gouraud shading
for (int i = 0; i < 3; ++i)
{
Vertex &vert = transVerts.data[face.vertIndex[i]];
vert.color =
lights.ambient.ComputeColor(material.ambient)
+ lights.diffuse.ComputeColor(material.diffuse, vert.normal);
} }
} }
} }

View File

@ -28,7 +28,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(buffer, objFilename, mtlFilename); result = Engine_Init(objFilename, mtlFilename);
if (result < 0) if (result < 0)
{ {

View File

@ -154,19 +154,19 @@ static void HandleEvent(
} break; } break;
case SDLK_j: case SDLK_j:
{ {
SET_BIT(platform.input, ROTATE_Z_POS); SET_BIT(platform.input, ROTATE_Y_POS);
} break; } break;
case SDLK_l: case SDLK_l:
{ {
SET_BIT(platform.input, ROTATE_Z_NEG); SET_BIT(platform.input, ROTATE_Y_NEG);
} break; } break;
case SDLK_u: case SDLK_u:
{ {
SET_BIT(platform.input, ROTATE_Y_POS); SET_BIT(platform.input, ROTATE_Z_POS);
} break; } break;
case SDLK_o: case SDLK_o:
{ {
SET_BIT(platform.input, ROTATE_Y_NEG); SET_BIT(platform.input, ROTATE_Z_NEG);
} break; } break;
case SDLK_UP: case SDLK_UP:
{ {
@ -216,19 +216,19 @@ static void HandleEvent(
} break; } break;
case SDLK_j: case SDLK_j:
{ {
CLEAR_BIT(platform.input, ROTATE_Z_POS); CLEAR_BIT(platform.input, ROTATE_Y_POS);
} break; } break;
case SDLK_l: case SDLK_l:
{ {
CLEAR_BIT(platform.input, ROTATE_Z_NEG); CLEAR_BIT(platform.input, ROTATE_Y_NEG);
} break; } break;
case SDLK_u: case SDLK_u:
{ {
CLEAR_BIT(platform.input, ROTATE_Y_POS); CLEAR_BIT(platform.input, ROTATE_Z_POS);
} break; } break;
case SDLK_o: case SDLK_o:
{ {
CLEAR_BIT(platform.input, ROTATE_Y_NEG); CLEAR_BIT(platform.input, ROTATE_Z_NEG);
} break; } break;
case SDLK_UP: case SDLK_UP:
{ {

View File

@ -4,22 +4,22 @@
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
Matrix Transform_Translate(float x, float y, float z) Matrix Transform_Translate(Point &translation)
{ {
Matrix result; Matrix result;
result.e41 = x; result.e41 = translation.x;
result.e42 = y; result.e42 = translation.y;
result.e43 = z; result.e43 = translation.z;
return result; return result;
} }
Matrix Transform_Rotate(float x, float y, float z) Matrix Transform_Rotate(Point &rotation)
{ {
// YXZ Euler rotation // YXZ Euler rotation
float cosThetaY = cosf(y); float cosThetaY = cosf(rotation.y);
float sinThetaY = sinf(y); float sinThetaY = sinf(rotation.y);
Matrix tRotateY; Matrix tRotateY;
@ -29,8 +29,8 @@ Matrix Transform_Rotate(float x, float y, float z)
tRotateY.e33 = cosThetaY; tRotateY.e33 = cosThetaY;
float cosThetaX = cosf(x); float cosThetaX = cosf(rotation.x);
float sinThetaX = sinf(x); float sinThetaX = sinf(rotation.x);
Matrix tRotateX; Matrix tRotateX;
@ -40,8 +40,8 @@ Matrix Transform_Rotate(float x, float y, float z)
tRotateX.e33 = cosThetaX; tRotateX.e33 = cosThetaX;
float cosThetaZ = cosf(z); float cosThetaZ = cosf(rotation.z);
float sinThetaZ = sinf(z); float sinThetaZ = sinf(rotation.z);
Matrix tRotateZ; Matrix tRotateZ;
@ -56,49 +56,51 @@ Matrix Transform_Rotate(float x, float y, float z)
return result; return result;
} }
Matrix Transform_Scale(float s) Matrix Transform_Scale(float scale)
{ {
Matrix result; Matrix result;
result.e11 = s; result.e11 = scale;
result.e22 = s; result.e22 = scale;
result.e33 = s; result.e33 = scale;
return result; return result;
} }
Matrix Transform_View(Point &position, float rotation[]) Matrix Transform_View(Camera &camera)
{ {
Matrix tInvTranslate = Transform_Translate(-position.x, -position.y, -position.z); Point invPosition = -camera.position;
Matrix tInvTranslate = Transform_Translate(invPosition);
Matrix tInvRotate = Transform_Rotate(-rotation[0], -rotation[1], -rotation[2]); Point invRotation = -camera.rotation;
Matrix tInvRotate = Transform_Rotate(invRotation);
Matrix result = tInvTranslate * tInvRotate; Matrix result = tInvTranslate * tInvRotate;
return result; return result;
} }
Matrix Transform_Perspective(float zoomX, float zoomY, float nearClip, float farClip) Matrix Transform_Perspective(Camera &camera)
{ {
Matrix result; Matrix result;
result.e11 = zoomX; result.e11 = camera.xZoom;
result.e22 = zoomY; result.e22 = camera.yZoom;
result.e33 = (farClip + nearClip) / (farClip - nearClip); result.e33 = camera.zClipBias0;
result.e34 = 1; result.e34 = 1;
result.e43 = (-2.0f * farClip * nearClip) / (farClip - nearClip); result.e43 = camera.zClipBias1;
return result; return result;
} }
Matrix Transform_Screen(float xScale, float yScale) Matrix Transform_Screen(Camera &camera)
{ {
Matrix result; Matrix result;
result.e11 = xScale; result.e11 = camera.xScale;
result.e41 = xScale; result.e41 = camera.xScale;
result.e22 = -yScale; result.e22 = -camera.yScale;
result.e42 = yScale; result.e42 = camera.yScale;
return result; return result;
} }