Added files

This commit is contained in:
Simponic 2020-08-04 23:36:21 -06:00
parent b323ae0ca0
commit ebd81999b7
13 changed files with 757 additions and 0 deletions

41
src/Makefile Normal file
View File

@ -0,0 +1,41 @@
# A simple Makefile for compiling small SDL projects
# set the compiler
CC := gcc
# set the compiler flags
CFLAGS := `sdl2-config --libs --cflags` -ggdb3 -O0 --std=c99 -Wall -lSDL2_image -lm -g
# add header files here
HDRS := color.h defs.h fixed.h model.h triangle.h vertex.h model.h instance.h
# add source files here
SRCS := main.c model.c instance.c
# generate names of object files
OBJS := $(SRCS:.c=.o)
# name of executable
EXEC := a.out
# default recipe
all: $(EXEC)
showfont: showfont.c Makefile
$(CC) -o $@ $@.c $(CFLAGS) $(LIBS)
glfont: glfont.c Makefile
$(CC) -o $@ $@.c $(CFLAGS) $(LIBS)
# recipe for building the final executable
$(EXEC): $(OBJS) $(HDRS) Makefile
$(CC) -o $@ $(OBJS) $(CFLAGS)
# recipe for building object files
#$(OBJS): $(@:.o=.c) $(HDRS) Makefile
# $(CC) -o $@ $(@:.o=.c) -c $(CFLAGS)
# recipe to clean the workspace
clean:
rm -f $(EXEC) $(OBJS)
.PHONY: all clean

19
src/color.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef COLOR_H
#define COLOR_H
typedef struct COLOR {
unsigned char red;
unsigned char green;
unsigned char blue;
} COLOR;
static inline COLOR createColor(unsigned char red, unsigned char green, unsigned char blue) {
// Create a color given values
COLOR temp;
temp.red = red;
temp.green = green;
temp.blue = blue;
return temp;
}
#endif // COLOR_H

39
src/defs.h Normal file
View File

@ -0,0 +1,39 @@
#include "color.h"
#include <SDL2/SDL.h>
#ifndef DEFS_H
#define DEFS_H
#define WINDOW_WIDTH 960
#define WINDOW_HEIGHT 640
#define ZPlane 1
#define viewport_width 3
#define viewport_height 2
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
static inline void drawPixel(int x, int y, COLOR clr, SDL_Renderer *renderer) {
// Draw pixel to screen
SDL_SetRenderDrawColor(renderer, clr.red, clr.green, clr.blue, 255);
SDL_RenderDrawPoint(renderer, WINDOW_WIDTH / 2 + x, WINDOW_HEIGHT / 2 - y - 1);
}
static inline void updateDisplay(SDL_Renderer *renderer) {
// Update a SDL renderer
SDL_RenderPresent(renderer);
}
static inline void fillDisplay(SDL_Renderer *renderer, COLOR clr) {
// Fill a renderer with color
SDL_SetRenderDrawColor(renderer, clr.red, clr.blue, clr.green, 255);
SDL_RenderClear(renderer);
}
#endif // DEFS_H

74
src/fixed.h Normal file
View File

@ -0,0 +1,74 @@
#include "defs.h"
#ifndef FIXED_H
#define FIXED_H
#define FIX_SHIFT 8
#define HALF_FIX_SHIFT 4
#define FIX_SCALE ( 1 << FIX_SHIFT )
#define FIX_SCALE_FLOAT ((float)(FIX_SCALE))
typedef s32 FIXED;
static inline FIXED fixed_OverMultiply(FIXED a, FIXED b) {
// This should multiply two fixed-point numbers sacrificing a little
// accuracy in exchange for less chance of an overflow
return ((a >> HALF_FIX_SHIFT) * (b >> HALF_FIX_SHIFT));
}
static inline FIXED fixed_multiply (FIXED a, FIXED b) {
// Multiply two fixed numbers. Possibility of overflow.
return (a * b) >> FIX_SHIFT;
}
static inline FIXED fixed_divide(FIXED a, FIXED b) {
if (b != 0){
return (a * FIX_SCALE) / b;
}
else {
return 100000 << FIX_SHIFT;
}
}
static inline FIXED float_to_fixed(float a) {
// Convert a float to fixed point
return ((FIXED)(a * FIX_SCALE_FLOAT));
}
static inline float fixed_to_float(FIXED a) {
// Convert fixed point to float
return (a / FIX_SCALE_FLOAT);
}
static inline void swapFixed(FIXED *a, FIXED *b) {
// Swap two fixed point integer pointers
FIXED temp;
temp = *a;
*a = *b;
*b = temp;
}
static inline FIXED fixed_sqrt(FIXED a, int iterations) {
// Calculate square root of a fixed-point number using Binary-Search
FIXED low = 0;
FIXED high = a;
FIXED mid;
FIXED midSquared;
for (int i = 0; i < iterations; i++) {
mid = fixed_divide((low + high), 2 << FIX_SHIFT);
midSquared = fixed_OverMultiply(mid, mid);
if (midSquared == a) {
return mid;
}
else if (midSquared > a) {
high = mid;
}
else {
low = mid;
}
}
return mid;
}
#endif // FIXED_H

63
src/instance.c Normal file
View File

@ -0,0 +1,63 @@
#include "instance.h"
void renderInstance(INSTANCE *instance, SDL_Renderer *renderer) {
// Render an instance
// Array for projected points
POINT projected[instance->model->vertices_length];
// Pointers for transformed vertices
VERTEX *transformed = malloc(sizeof(VERTEX) * instance->model->vertices_length);
for (int i = 0; i < instance->model->vertices_length; i++) {
// Apply translation and rotation
*(transformed + i) = *(instance->model->vertices + i);
applyXRotation((transformed + i), *instance->xRotation);
applyYRotation((transformed + i), *instance->yRotation);
applyZRotation((transformed + i), *instance->zRotation);
*(transformed + i) = addVertices((transformed + i), instance->position);
// Project vertices
projected[i] = projectVertex(transformed + i);
}
VERTEX n, copyV;
// A directional light source
VERTEX playerLight = createVertex(0, 0, -1 << FIX_SHIFT);
normalizeVertex(&playerLight);
TRIANGLE *addr;
FIXED intensity;
COLOR clr;
for (int i = 0; i < instance->model->triangles_length; i++) {
// Render the triangle
addr = (instance->model->triangles + i);
n = computeNormal(transformed, addr);
normalizeVertex(&n);
// Intensity of light on the triangle
intensity = fixed_multiply(dotProduct(&n, &playerLight) + (1 << FIX_SHIFT), 127 << FIX_SHIFT);
copyV = *(transformed + addr->v2);
normalizeVertex(&copyV);
// Grayscale color of the triangle from light intensity
clr = createColor(intensity >> FIX_SHIFT, intensity >> FIX_SHIFT, intensity >> FIX_SHIFT);
if (dotProduct(&n, &copyV) < 0) {
// The triangle is viewable by the camera
drawFilledTriangle(
&(projected[addr->v0]),
&(projected[addr->v1]),
&(projected[addr->v2]),
&clr,
renderer
);
}
}
transformed = NULL;
free(transformed);
}
void destroyInstance(INSTANCE *instance) {
// Free memory from instance
instance->model = NULL;
instance->position = NULL;
instance->zRotation = NULL;
instance->xRotation = NULL;
instance->yRotation = NULL;
}

24
src/instance.h Normal file
View File

@ -0,0 +1,24 @@
#include "defs.h"
#include "pt.h"
#include "vertex.h"
#include "triangle.h"
#include "model.h"
#include <math.h>
#include <stdlib.h>
#ifndef INSTANCE_H
#define INSTANCE_H
typedef struct INSTANCE {
MODEL *model;
VERTEX *position;
FIXED scale;
FIXED *xRotation;
FIXED *yRotation;
FIXED *zRotation;
} INSTANCE;
void renderInstance();
void destroyInstance();
#endif // INSTANCE_H

111
src/main.c Normal file
View File

@ -0,0 +1,111 @@
#include "defs.h"
#include "color.h"
#include "model.h"
#include "instance.h"
#include "fixed.h"
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <unistd.h>
int runningGame = 1;
int main() {
// Create sdl window
SDL_Event event;
SDL_Renderer *renderer;
SDL_Window *window;
// Array of keys being pressed
const unsigned char *keys = SDL_GetKeyboardState(NULL);
// Initialize sdl window
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer);
fillDisplay(renderer, createColor(0, 0, 0));
// Positions and rotations of each cube
VERTEX positions[2] = {createVertex(2 << FIX_SHIFT, 0 << FIX_SHIFT, 7 << FIX_SHIFT),
createVertex(-2 << FIX_SHIFT, 0, 7 << FIX_SHIFT)
};
FIXED xRots[2] = {0 << FIX_SHIFT, 0 << FIX_SHIFT};
FIXED yRots[2] = {30 << FIX_SHIFT, 30 << FIX_SHIFT};
FIXED zRots[2] = {0 << FIX_SHIFT, 0 << FIX_SHIFT};
// Create cube and instances of cube
MODEL cube;
INSTANCE instances[2];
for (int i = 0; i < 2; i++) {
// Set properties of each cube
instances[i].scale = 1;
instances[i].xRotation = &xRots[i];
instances[i].yRotation = &yRots[i];
instances[i].zRotation = &zRots[i];
instances[i].model = &cube;
instances[i].position = &positions[i];
}
// Initialize the base cube model
initializeCube(&cube);
while(runningGame) {
// Draw the cubes and interact with them
fillDisplay(renderer, createColor(0,0,0));
for (int i = 0; i < 2; i++) {
renderInstance(&instances[i], renderer);
}
updateDisplay(renderer);
while (SDL_PollEvent(&event)) {
for (int i = 0; i < 2; i++) {
// Check events and update each cube accordingly
if (event.type == SDL_QUIT) {
runningGame = 0;
}
if (keys[SDL_SCANCODE_RIGHT]) {
positions[i].x += float_to_fixed(0.2);
}
if (keys[SDL_SCANCODE_LEFT]) {
positions[i].x -= float_to_fixed(0.2);
}
if (keys[SDL_SCANCODE_DOWN]) {
positions[i].y -= float_to_fixed(0.1);
}
if (keys[SDL_SCANCODE_UP]) {
positions[i].y += float_to_fixed(0.1);
}
if (keys[SDL_SCANCODE_W]) {
positions[i].z += float_to_fixed(0.1);
}
if (keys[SDL_SCANCODE_S]) {
positions[i].z -= float_to_fixed(0.1);
}
if (keys[SDL_SCANCODE_Q]) {
xRots[i] += float_to_fixed(1);
}
if (keys[SDL_SCANCODE_E]) {
xRots[i] += float_to_fixed(-1);
}
if (keys[SDL_SCANCODE_Z]) {
zRots[i] += float_to_fixed(1);
}
if (keys[SDL_SCANCODE_C]) {
zRots[i] += float_to_fixed(-1);
}
if (keys[SDL_SCANCODE_A]) {
yRots[i] += float_to_fixed(1);
}
if (keys[SDL_SCANCODE_D]) {
yRots[i] += float_to_fixed(-1);
}
}
}
sleep(.1);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
destroyModel(&cube);
for (int i = 0; i < 2; i++) {
destroyInstance(&instances[i]);
}
return EXIT_SUCCESS;
}

57
src/model.c Normal file
View File

@ -0,0 +1,57 @@
#include "model.h"
#include <stdlib.h>
void initializeCube(MODEL *cube) {
// Initialize a cube model
cube->bounds_center = createVertex(0, 0, 0);
COLOR red = createColor(255,0,0);
COLOR green = createColor(0,255,0);
COLOR blue = createColor(0,0,255);
COLOR yellow = createColor(255,255,0);
COLOR pink = createColor(255, 0, 100);
COLOR weird = createColor(100, 255, 70);
cube->vertices = malloc(sizeof(VERTEX) * 8);
cube->triangles = malloc(sizeof(TRIANGLE) * 12);
cube->vertices_length = 8;
cube->triangles_length = 12;
VERTEX vertices[8] = {
createVertex( -1 << FIX_SHIFT, -1 << FIX_SHIFT, -1 << FIX_SHIFT), // (0,0,0) 0
createVertex( -1 << FIX_SHIFT, 1 << FIX_SHIFT, -1 << FIX_SHIFT), // (0,1,0) 1
createVertex( 1 << FIX_SHIFT, 1 << FIX_SHIFT, -1 << FIX_SHIFT), // (1,1,0) 2
createVertex( 1 << FIX_SHIFT, -1 << FIX_SHIFT, -1 << FIX_SHIFT), // (1,0,0) 3
createVertex( 1 << FIX_SHIFT, 1 << FIX_SHIFT, 1 << FIX_SHIFT), // (1,1,1) 4
createVertex( 1 << FIX_SHIFT, -1 << FIX_SHIFT, 1 << FIX_SHIFT), // (1,0,1) 5
createVertex( -1 << FIX_SHIFT, 1 << FIX_SHIFT, 1 << FIX_SHIFT), // (0,1,1) 6
createVertex( -1 << FIX_SHIFT, -1 << FIX_SHIFT, 1 << FIX_SHIFT), // (0,0,1) 7
};
TRIANGLE triangles[12] = {
createTriangle( 0, 1, 2, red),
createTriangle( 0, 2, 3, red),
createTriangle( 3, 2, 4, green),
createTriangle( 3, 4, 5, green),
createTriangle( 5, 4, 6, blue),
createTriangle( 5, 6, 7, blue),
createTriangle( 7, 6, 1, yellow),
createTriangle( 7, 1, 0, yellow),
createTriangle( 1, 6, 4, pink),
createTriangle( 1, 4, 2, pink),
createTriangle( 5, 7, 0, weird),
createTriangle( 5, 0, 3, weird),
};
for (int i = 0; i < 8; i++) {
// Copy vertices data to cube
*(cube->vertices + i) = vertices[i];
}
for (int i = 0; i < 12; i++) {
// Copy triangles to cube
*(cube->triangles + i) = triangles[i];
}
}
void destroyModel(MODEL *model) {
// Free memory of a model
model->vertices = NULL;
model->triangles = NULL;
free(model->vertices);
free(model->triangles);
}

21
src/model.h Normal file
View File

@ -0,0 +1,21 @@
#include "defs.h"
#include "fixed.h"
#include "vertex.h"
#include "triangle.h"
#include "pt.h"
#ifndef MODEL_H
#define MODEL_H
typedef struct MODEL {
VERTEX *vertices;
int vertices_length;
TRIANGLE *triangles;
int triangles_length;
VERTEX bounds_center;
} MODEL;
void initializeCube();
void destroyModel();
#endif // MODEL_H

21
src/plane.h Normal file
View File

@ -0,0 +1,21 @@
#include "defs.h"
#include "vertex.h"
#include "fixed.h"
#ifndef PLANE_H
#define PLANE_H
typedef struct PLANE {
VERTEX normal;
FIXED distance;
} PLANE;
static inline PLANE createPlane(VERTEX *normal, FIXED distance) {
// Create a plane from data
PLANE temp;
temp.normal = *normal;
temp.distance = distance;
return temp;
}
#endif // PLANE_H

36
src/pt.h Normal file
View File

@ -0,0 +1,36 @@
#include "defs.h"
#include "fixed.h"
#ifndef PT_H
#define PT_H
typedef struct POINT {
FIXED x;
FIXED y;
} POINT;
static inline void convertPointToScreen(POINT *point) {
// Convert point where (SCREEN_WIDTH / 2 * x,
// SCREEN_HEIGHT / 2 - y - 1)
// is the origin (0,0)
point->x += (WINDOW_WIDTH / 2) << FIX_SHIFT;
point->y = (WINDOW_HEIGHT / 2 - (point->y >> FIX_SHIFT) - 1) << FIX_SHIFT;
}
static inline POINT createPoint(FIXED x, FIXED y) {
// Create a point from data
POINT temp;
temp.x = x;
temp.y = y;
return temp;
}
static inline void swapPoint(POINT *p1, POINT *p2) {
POINT temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
#endif // PT_H

139
src/triangle.h Normal file
View File

@ -0,0 +1,139 @@
#include "fixed.h"
#include "defs.h"
#include "vertex.h"
#include "plane.h"
#include "color.h"
#include <math.h>
#ifndef TRIANGLE_H
#define TRIANGLE_H
typedef struct TRIANGLE {
int v0;
int v1;
int v2;
COLOR color;
} TRIANGLE;
static inline TRIANGLE createTriangle(int v0, int v1, int v2, COLOR color) {
// Create a triangle from data
TRIANGLE temp;
temp.v0 = v0;
temp.v1 = v1;
temp.v2 = v2;
temp.color = color;
return temp;
}
static inline VERTEX computeNormal(VERTEX *vertices, TRIANGLE *triangle) {
// Use cross product to compute a normal vector to a triangle
VERTEX normal, v1, v2;
// Compute vectors for cross product
v1.x = (vertices + triangle->v1)->x - (vertices + triangle->v0)->x;
v1.y = (vertices + triangle->v1)->y - (vertices + triangle->v0)->y;
v1.z = (vertices + triangle->v1)->z - (vertices + triangle->v0)->z;
v2.x = (vertices + triangle->v2)->x - (vertices + triangle->v0)->x;
v2.y = (vertices + triangle->v2)->y - (vertices + triangle->v0)->y;
v2.z = (vertices + triangle->v2)->z - (vertices + triangle->v0)->z;
// Compute cross product
normal.x = fixed_multiply(v1.y, v2.z) - fixed_multiply(v1.z, v2.y);
normal.y = fixed_multiply(v1.z, v2.x) - fixed_multiply(v1.x, v2.z);
normal.z = fixed_multiply(v1.x, v2.y) - fixed_multiply(v1.y, v2.x);
return normal;
}
static inline void drawTriangle(POINT *v1, POINT *v2, POINT *v3, COLOR *clr, SDL_Renderer *renderer) {
// Draw a triangle to screen from data
int x1, x2, x3, y1, y2, y3;
SDL_SetRenderDrawColor(renderer, clr->red, clr->green, clr->blue, 255);
x1 = (v1->x >> FIX_SHIFT) + WINDOW_WIDTH / 2;
x2 = (v2->x >> FIX_SHIFT) + WINDOW_WIDTH / 2;
x3 = (v3->x >> FIX_SHIFT) + WINDOW_WIDTH / 2;
y1 = WINDOW_HEIGHT / 2 - (v1->y >> FIX_SHIFT) - 1;
y2 = WINDOW_HEIGHT / 2 - (v2->y >> FIX_SHIFT) - 1;
y3 = WINDOW_HEIGHT / 2 - (v3->y >> FIX_SHIFT) - 1;
SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
SDL_RenderDrawLine(renderer, x1, y1, x3, y3);
SDL_RenderDrawLine(renderer, x2, y2, x3, y3);
}
static inline void fillBottomFlatTriangle(POINT *v1, POINT *v2, POINT *v3, COLOR *clr, SDL_Renderer *renderer) {
// Ported from sunshine2k.de
SDL_SetRenderDrawColor(renderer, clr->red, clr->green, clr->blue, 255);
FIXED iSlope1 = fixed_divide(v2->x - v1->x, v2->y - v1->y);
FIXED iSlope2 = fixed_divide(v3->x - v1->x, v3->y - v1->y);
FIXED curx1 = v1->x;
FIXED curx2 = curx1;
int scanline;
for (int scanlineY = ((v1->y + (1 << FIX_SHIFT)) >> FIX_SHIFT); scanlineY <= (v2->y >> FIX_SHIFT); scanlineY++) {
scanline = WINDOW_HEIGHT / 2 - scanlineY - 1;
SDL_RenderDrawLine(renderer, ((curx1 >> FIX_SHIFT) + WINDOW_WIDTH / 2),
scanline, ((curx2 >> FIX_SHIFT) + WINDOW_WIDTH / 2), scanline
);
curx1 += iSlope1;
curx2 += iSlope2;
}
}
static inline void fillTopFlatTriangle(POINT *v1, POINT *v2, POINT *v3, COLOR *clr, SDL_Renderer *renderer) {
// Ported from sunshine2k.de
SDL_SetRenderDrawColor(renderer, clr->red, clr->green, clr->blue, 255);
FIXED iSlope1 = fixed_divide(v3->x - v1->x, v3->y - v1->y);
FIXED iSlope2 = fixed_divide(v3->x - v2->x, v3->y - v2->y);
FIXED curx1 = v3->x;
FIXED curx2 = curx1;
int scanline;
for (int scanlineY = ((v3->y - (1 << FIX_SHIFT)) >> FIX_SHIFT); scanlineY > (v1->y >> FIX_SHIFT); scanlineY--) {
scanline = WINDOW_HEIGHT / 2 - scanlineY - 1;
SDL_RenderDrawLine(renderer, ((curx1 >> FIX_SHIFT) + WINDOW_WIDTH / 2),
scanline, ((curx2 >> FIX_SHIFT) + WINDOW_WIDTH / 2), scanline
);
curx1 -= iSlope1;
curx2 -= iSlope2;
}
}
static inline void drawFilledTriangle(POINT *v1, POINT *v2, POINT *v3, COLOR *clr, SDL_Renderer *renderer) {
// Draw a filled triangle at points
// Sort the vertex points
POINT p1, p2, p3;
p1 = *v1;
p2 = *v2;
p3 = *v3;
if (p1.y > p2.y) {
swapPoint(&p1, &p2);
}
if (p1.y > p3.y) {
swapPoint(&p1, &p3);
}
if (p2.y > p3.y) {
swapPoint(&p2, &p3);
}
// Check if bottom of triangle is flat
if (p2.y == p3.y) {
fillBottomFlatTriangle(&p1, &p2, &p3, clr, renderer);
}
// Check if top of triangle is flat
else if (p1.y == p2.y) {
fillTopFlatTriangle(&p1, &p2, &p3, clr, renderer);
}
else {
// General case where neither top or bottom is flat
POINT p4 = createPoint(
p1.x + fixed_multiply(fixed_divide(p2.y - p1.y, p3.y - p1.y), (p3.x - p1.x))
,p2.y
);
fillBottomFlatTriangle(&p1, &p2, &p4, clr, renderer);
fillTopFlatTriangle(&p2, &p4, &p3, clr, renderer);
}
}
#endif // TRIANGLE_H

112
src/vertex.h Normal file
View File

@ -0,0 +1,112 @@
#include "defs.h"
#include "fixed.h"
#include "pt.h"
#include <math.h>
#ifndef VERTEX_H
#define VERTEX_H
typedef struct VERTEX {
FIXED x;
FIXED y;
FIXED z;
} VERTEX;
static inline POINT viewportToScreen (POINT *point) {
// Convert a viewport coordinate to screen x, y
return createPoint(fixed_multiply(point->x, fixed_divide(WINDOW_WIDTH << FIX_SHIFT, viewport_width << FIX_SHIFT)),
fixed_multiply(point->y, fixed_divide(WINDOW_HEIGHT << FIX_SHIFT, viewport_height << FIX_SHIFT))
);
}
static inline POINT projectVertex(VERTEX *vertex) {
// Project a vertex to a point
POINT temp;
if (vertex->z != 0) {
// Make sure we don't divide by zero
temp = createPoint(fixed_multiply(vertex->x, fixed_divide(ZPlane << FIX_SHIFT, vertex->z)),
fixed_multiply(vertex->y, fixed_divide(ZPlane << FIX_SHIFT, vertex->z))
);
}
else {
temp = createPoint(0, 0);
}
temp = viewportToScreen(&temp);
return temp;
}
static inline VERTEX createVertex(FIXED x, FIXED y, FIXED z) {
// Create a vertex from data
VERTEX temp;
temp.x = x;
temp.y = y;
temp.z = z;
return temp;
}
static inline VERTEX addVertices(VERTEX *a, VERTEX *b) {
// Add two vertices together
VERTEX temp = createVertex(a->x + b->x, a->y + b->y, a->z + b->z);
return temp;
}
static inline void applyXRotation(VERTEX *vertex, FIXED xRotation) {
// Apply rotation to vertex on x-axis
FIXED sinTheta = float_to_fixed(sin(fixed_to_float(xRotation) * (3.14159 / 180)));
FIXED cosTheta = float_to_fixed(cos(fixed_to_float(xRotation) * (3.14159 / 180)));
FIXED y = vertex->y;
FIXED z = vertex->z;
vertex->y = fixed_multiply(y, cosTheta) - fixed_multiply(z, sinTheta);
vertex->z = fixed_multiply(z, cosTheta) + fixed_multiply(y, sinTheta);
}
static inline void applyYRotation(VERTEX *vertex, FIXED yRotation) {
// Apply rotation to vertex on y-axis
FIXED sinTheta = float_to_fixed(sin(fixed_to_float(yRotation) * (3.14159 / 180)));
FIXED cosTheta = float_to_fixed(cos(fixed_to_float(yRotation) * (3.14159 / 180)));
FIXED x = vertex->x;
FIXED z = vertex->z;
vertex->x = fixed_multiply(x, cosTheta) + fixed_multiply(z, sinTheta);
vertex->z = fixed_multiply(z, cosTheta) - fixed_multiply(x, sinTheta);
}
static inline void applyZRotation(VERTEX *vertex, FIXED zRotation) {
// Apply rotation to vertex on z-axis
FIXED sinTheta = float_to_fixed(sin(fixed_to_float(zRotation) * (3.14159 / 180)));
FIXED cosTheta = float_to_fixed(cos(fixed_to_float(zRotation) * (3.14159 / 180)));
FIXED x = vertex->x;
FIXED y = vertex->y;
vertex->x = fixed_multiply(x, cosTheta) - fixed_multiply(y, sinTheta);
vertex->y = fixed_multiply(y, cosTheta) + fixed_multiply(x, sinTheta);
}
static inline VERTEX crossProduct(VERTEX *a, VERTEX *b) {
// Calculate the cross product of two vertices
return createVertex(
fixed_multiply(a->y, b->z) - fixed_multiply(a->z, b->y),
fixed_multiply(a->z, b->x) - fixed_multiply(a->x, b->z),
fixed_multiply(a->x, b->y) - fixed_multiply(a->y, b->x)
);
}
static inline FIXED dotProduct(VERTEX *a, VERTEX *b) {
// Dot two vertices
FIXED product = fixed_multiply(a->x, b->x) +
fixed_multiply(a->y, b->y) +
fixed_multiply(a->z, b->z);
return product;
}
static inline void normalizeVertex(VERTEX *vertex) {
// Normalize (magnitude = 1) a vertex
float x = fixed_to_float(vertex->x);
float y = fixed_to_float(vertex->y);
float z = fixed_to_float(vertex->z);
float d = sqrtf(x*x + y*y + z*z);
vertex->x = float_to_fixed(fixed_to_float(vertex->x) / d);
vertex->y = float_to_fixed(fixed_to_float(vertex->y) / d);
vertex->z = float_to_fixed(fixed_to_float(vertex->z) / d);
}
#endif // VERTEX_H