1
0
Fork 0
2018-soft-3d-renderer/src/engine.cpp

218 lines
5.2 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);
// Clear the z-buffer
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.renderData.vertsTransformed[v].point = mesh.verts[v].point * tScale * tRotate * tTranslate;
mesh.renderData.vertsTransformed[v].normal = mesh.verts[v].normal * tScale * tRotate * tTranslate;
}
// Cull backfaces before computing colors
mesh.CullBackfaces(camera.position);
// Color the vertices for Gouraud shading
if (mesh.renderData.smooth)
{
for (size_t f = 0; f < mesh.renderData.culledFaces.size(); ++f)
{
for (int i = 0; i < 3; ++i)
{
unsigned int v = mesh.renderData.culledFaces[f].vertIndex[i];
ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient);
for (int c = 0; c < lights.diffuseCount; ++c)
{
totalColor += lights.diffuse[c].ComputeColor(
mesh.material.kDiffuse, mesh.renderData.vertsTransformed[v].normal);
}
mesh.renderData.vertsTransformed[v].color = totalColor;
}
}
}
// Color the face for flat shading
else
{
for (size_t f = 0; f < mesh.renderData.culledFaces.size(); ++f)
{
ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient);
for (int c = 0; c < lights.diffuseCount; ++c)
{
totalColor += lights.diffuse[c].ComputeColor(
mesh.material.kDiffuse, mesh.renderData.culledFaces[f].normal);
}
mesh.renderData.culledFaces[f].color = 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.renderData.vertsTransformed[v].point *= tView * tPersp * tScreen;
mesh.renderData.vertsTransformed[v].point /= mesh.renderData.vertsTransformed[v].point.w;
}
RenderMesh(buffer, mesh.renderData);
}
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;
}
if (CHECK_BIT(input, SHADING_TOGGLE))
{
mesh.renderData.smooth = true;
}
else
{
mesh.renderData.smooth = false;
}
}