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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
#include "model_instance.hpp"
#include "scene.hpp"
#include <tuple>
/**
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;
}
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(©V);
// Grayscale color of the triangle from light intensity
clr = createColor(intensity >> FIX_SHIFT, intensity >> FIX_SHIFT,
intensity >> FIX_SHIFT);
if (dotProduct(&n, ©V) < 0) {
// The triangle is viewable by the camera
drawFilledTriangle(
&(projected[addr->v0]),
&(projected[addr->v1]),
&(projected[addr->v2]),
&clr,
renderer
);
}
}
transformed = NULL;
free(transformed);
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);
}
}
*/
VECTOR rotate(VECTOR v, VECTOR rot) {
FIXED sin_theta_x, sin_theta_y, sin_theta_z;
FIXED cos_theta_x, cos_theta_y, cos_theta_z;
VECTOR res = {v.x, v.y, v.z};
if (rot.x != 0) {
sin_theta_x = lu_sin(rot.x) >> 4;
cos_theta_x = lu_cos(rot.x) >> 4;
res.y = fxmul(res.y, cos_theta_x) - fxmul(res.z, sin_theta_x);
res.z = fxmul(res.z, cos_theta_x) + fxmul(res.y, sin_theta_x);
}
if (rot.y != 0) {
sin_theta_y = lu_sin(rot.y) >> 4;
cos_theta_y = lu_cos(rot.y) >> 4;
res.x = fxmul(res.x, cos_theta_y) + fxmul(res.z, sin_theta_y);
res.z = fxmul(res.z, cos_theta_y) - fxmul(res.x, sin_theta_y);
}
if (rot.z != 0) {
sin_theta_z = lu_sin(rot.z) >> 4;
cos_theta_z = lu_cos(rot.z) >> 4;
res.x = fxmul(res.x, cos_theta_z) - fxmul(res.y, sin_theta_z);
res.y = fxmul(res.z, cos_theta_z) + fxmul(res.x, sin_theta_z);
}
return res;
};
void ModelInstance::render(std::shared_ptr<Scene> scene_context) {
usu::vector<VECTOR> transformed(m_mesh->vertices.size());
usu::vector<POINT> projected(transformed.size());
for (std::uint32_t i = 0; i < transformed.size(); i++) {
transformed[i] = rotate(m_mesh->vertices[i], m_rotation);
projected[i] = scene_context->project_2d(m_mesh->vertices[i]);
}
for (const TRIANGLE triangle : m_mesh->triangles) {
VECTOR v0 = transformed[std::get<0>(triangle.vertex_indices)];
VECTOR v1 = transformed[std::get<1>(triangle.vertex_indices)];
VECTOR v2 = transformed[std::get<2>(triangle.vertex_indices)];
}
}
|