204 lines
5.1 KiB
C++
204 lines
5.1 KiB
C++
#include "camera.h"
|
|
#include "color.h"
|
|
#include "engine.h"
|
|
#include "geometry.h"
|
|
#include "light.h"
|
|
#include "loader.h"
|
|
#include "matrix.h"
|
|
#include "transform.h"
|
|
#include "util.h"
|
|
#include "vec.h"
|
|
#include <cstring>
|
|
|
|
|
|
// GLOBALS
|
|
static Mesh mesh;
|
|
static Camera camera;
|
|
static LightList lights;
|
|
|
|
|
|
// PRIVATE PROTOTYPES
|
|
static void CheckInputs(uint32_t input);
|
|
|
|
|
|
// PUBLIC FUNCTIONS
|
|
int Engine_Init(Engine_Buffer &buffer, char *filename)
|
|
{
|
|
int result = LoadMesh(filename, mesh);
|
|
|
|
if (result < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
mesh.position.z = 250;
|
|
mesh.material.kDiffuse = {1.0,1.0,1.0,1.0};
|
|
mesh.material.kAmbient = {1.0,1.0,1.0,1.0};
|
|
|
|
camera.SetFOV(90.0f, buffer.width, buffer.height);
|
|
|
|
lights.diffuse = (LightDiffuse*)malloc(sizeof(LightDiffuse));
|
|
lights.diffuseCount = 1;
|
|
lights.ambient.intensity = 1.0;
|
|
lights.diffuse[0].intensity = 0.5;
|
|
lights.diffuse[0].direction = Vector(1,1,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
|
{
|
|
CheckInputs(input);
|
|
|
|
unsigned long bufferSize = (unsigned long)(buffer.width * buffer.height);
|
|
memset(buffer.zbuffer, 0, bufferSize * sizeof(float));
|
|
|
|
// Local space to world space
|
|
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);
|
|
|
|
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
|
{
|
|
mesh.vertsTransformed[v] = mesh.verts[v] * tScale * tRotate * tTranslate;
|
|
}
|
|
|
|
|
|
// Cull backfaces before computing colors
|
|
mesh.CullBackfaces(camera.position);
|
|
|
|
|
|
// Color the faces (flat shading)
|
|
for (size_t f = 0; f < mesh.culledFaces.size(); ++f)
|
|
{
|
|
unsigned int v0 = mesh.culledFaces[f].vertIndex[0];
|
|
unsigned int v1 = mesh.culledFaces[f].vertIndex[1];
|
|
unsigned int v2 = mesh.culledFaces[f].vertIndex[2];
|
|
|
|
Vector v01 = mesh.vertsTransformed[v1] - mesh.vertsTransformed[v0];
|
|
Vector v02 = mesh.vertsTransformed[v2] - mesh.vertsTransformed[v0];
|
|
|
|
Vector normal = Vector::Cross(v01, v02);
|
|
normal.Normalize();
|
|
|
|
ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient);
|
|
|
|
for (int c = 0; c < lights.diffuseCount; ++c)
|
|
{
|
|
totalColor += lights.diffuse[c].ComputeColor(
|
|
mesh.material.kDiffuse, normal);
|
|
}
|
|
|
|
mesh.faces[f].color = ColorF32::ConvertToU32(totalColor);
|
|
}
|
|
|
|
|
|
// 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);
|
|
|
|
// Perspective to screen
|
|
Matrix tScreen = Transform_Screen(camera.xScale, camera.yScale);
|
|
|
|
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
|
{
|
|
mesh.vertsTransformed[v] *= tView * tPersp * tScreen;
|
|
mesh.vertsTransformed[v] /= mesh.vertsTransformed[v].w;
|
|
}
|
|
|
|
|
|
// Fill each face with its respective color
|
|
for(size_t f = 0; f < mesh.culledFaces.size(); ++f)
|
|
{
|
|
unsigned int v0 = mesh.culledFaces[f].vertIndex[0];
|
|
unsigned int v1 = mesh.culledFaces[f].vertIndex[1];
|
|
unsigned int v2 = mesh.culledFaces[f].vertIndex[2];
|
|
|
|
FillTriangle(
|
|
buffer.buffer, buffer.width,
|
|
buffer.zbuffer, mesh.faces[f].color.u32,
|
|
mesh.vertsTransformed[v0].x, mesh.vertsTransformed[v0].y, mesh.vertsTransformed[v0].z,
|
|
mesh.vertsTransformed[v1].x, mesh.vertsTransformed[v1].y, mesh.vertsTransformed[v1].z,
|
|
mesh.vertsTransformed[v2].x, mesh.vertsTransformed[v2].y, mesh.vertsTransformed[v2].z);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|