summaryrefslogtreecommitdiff
path: root/src/vertex.h
blob: 7880495fe1782a58bd8a9e473567a33733cfdd81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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