-
-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy path3dcube.c
136 lines (109 loc) · 3.24 KB
/
3dcube.c
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
#include <stdio.h>
#include <stdlib.h>
#include <uvm/syscalls.h>
#include <uvm/window.h>
#include <uvm/math.h>
#include <uvm/3dmath.h>
#include <uvm/graphics.h>
#define FRAME_WIDTH 800
#define FRAME_HEIGHT 600
#define remap(v, a0, a1, b0, b1) (b0 + (b1 - b0) * ((v) - a0) / (a1 - a0))
// RGBA pixels
u32 frame_buffer[FRAME_HEIGHT][FRAME_WIDTH];
// Cube vertices in [-1, 1]
float verts[8][3] = {
{-1.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f },
{ 1.0f,-1.0f, 1.0f },
{-1.0f,-1.0f, 1.0f },
{-1.0f, 1.0f,-1.0f },
{ 1.0f, 1.0f,-1.0f },
{ 1.0f,-1.0f,-1.0f },
{-1.0f,-1.0f,-1.0f },
};
vec3 cube_pos = { 0.0f, 0.0f, -6.0f };
// Cube rotation angle
float angle = 0.0f;
// Perspective projection matrix
mat44 persp;
// Translation matrix for the cube
mat44 trans;
// Draw a line between two 3D points
void draw_line3d(vec3 v0, vec3 v1, u32 color)
{
// Note that +Y in the image frame goes downwards,
// so we have to flip the Y coordinates
vec3 v_tmp;
mat44_transform(persp, v0, v_tmp);
int x0 = (int)remap(v_tmp[0], -1.0f, 1.0f, (float)FRAME_WIDTH, 0.0f);
int y0 = (int)remap(v_tmp[1], -1.0f, 1.0f, (float)FRAME_HEIGHT, 0.0f);
mat44_transform(persp, v1, v_tmp);
int x1 = (int)remap(v_tmp[0], -1.0f, 1.0f, (float)FRAME_WIDTH, 0.0f);
int y1 = (int)remap(v_tmp[1], -1.0f, 1.0f, (float)FRAME_HEIGHT, 0.0f);
draw_line_clipped(
(u32*)frame_buffer,
FRAME_WIDTH,
FRAME_HEIGHT,
(u32)x0,
(u32)y0,
(u32)x1,
(u32)y1,
color
);
}
// Transform and draw a 3D line
void trans_line3d(mat44 trans, vec3 _v0, vec3 _v1)
{
vec3 v0;
vec3 v1;
mat44_transform(trans, _v0, v0);
mat44_transform(trans, _v1, v1);
draw_line3d(v0, v1, COLOR_PURPLE);
}
void update()
{
u64 start_time = time_current_ms();
// Clear the frame buffer, set all pixels to black
memset32(frame_buffer, 0, 800 * 600);
angle = angle + 0.01f;
// Rotation matrices for the cube
mat44 rotx;
mat44 roty;
mat44_rotx(angle, rotx);
mat44_roty(angle, roty);
mat44 rot;
mat44 m_cube;
mat44_mul(roty, rotx, rot);
mat44_mul(rot, trans, m_cube);
trans_line3d(m_cube, verts[0], verts[1]);
trans_line3d(m_cube, verts[1], verts[2]);
trans_line3d(m_cube, verts[2], verts[3]);
trans_line3d(m_cube, verts[3], verts[0]);
trans_line3d(m_cube, verts[4], verts[5]);
trans_line3d(m_cube, verts[5], verts[6]);
trans_line3d(m_cube, verts[6], verts[7]);
trans_line3d(m_cube, verts[7], verts[4]);
trans_line3d(m_cube, verts[0], verts[4]);
trans_line3d(m_cube, verts[1], verts[5]);
trans_line3d(m_cube, verts[2], verts[6]);
trans_line3d(m_cube, verts[3], verts[7]);
window_draw_frame(0, frame_buffer);
u64 end_time = time_current_ms();
printf("render time: %dms\n", end_time - start_time);
}
int main()
{
window_create(FRAME_WIDTH, FRAME_HEIGHT, "Rotating 3D Cube Example", 0);
// Setup the perspective projection matrix
perspective(
DEG2RAD(40.0f),
(float)FRAME_WIDTH / (float)FRAME_HEIGHT,
0.1f, // near,
100.0f, // far,
persp
);
// Translation matrix for the cube
mat44_translate(cube_pos, trans);
anim_event_loop(60, update);
return 0;
}