-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
executable file
·244 lines (177 loc) · 5.84 KB
/
main.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
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#include <sys/types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#define MAXOBJS 6
#define OTSIZE (4096)
typedef struct {
DRAWENV draw; /* drawing environment */
DISPENV disp; /* display environment */
u_long ot[OTSIZE]; /* Ordering Table */
POLY_F4 polys[MAXOBJS]; /* polys */
} DB;
/* double buffer */
DB db[2];
/* current double buffer */
DB *cdb;
/*************************************************************/
// Hardcoded vertices + normals for a cube
/*************************************************************/
#define SCR_Z (512) /* screen depth */
#define CUBESIZE 50
// Vertices
static SVECTOR P0 = {-CUBESIZE/2,-CUBESIZE/2,-CUBESIZE/2,0};
static SVECTOR P1 = { CUBESIZE/2,-CUBESIZE/2,-CUBESIZE/2,0};
static SVECTOR P2 = { CUBESIZE/2, CUBESIZE/2,-CUBESIZE/2,0};
static SVECTOR P3 = {-CUBESIZE/2, CUBESIZE/2,-CUBESIZE/2,0};
static SVECTOR P4 = {-CUBESIZE/2,-CUBESIZE/2, CUBESIZE/2,0};
static SVECTOR P5 = { CUBESIZE/2,-CUBESIZE/2, CUBESIZE/2,0};
static SVECTOR P6 = { CUBESIZE/2, CUBESIZE/2, CUBESIZE/2,0};
static SVECTOR P7 = {-CUBESIZE/2, CUBESIZE/2, CUBESIZE/2,0};
static SVECTOR *vertices[6*4] = {
&P0,&P1,&P2,&P3,
&P1,&P5,&P6,&P2,
&P5,&P4,&P7,&P6,
&P4,&P0,&P3,&P7,
&P4,&P5,&P1,&P0,
&P6,&P7,&P3,&P2,
};
// Normals
static SVECTOR N0 = { ONE, 0, 0, 0,};
static SVECTOR N1 = {-ONE, 0, 0, 0,};
static SVECTOR N2 = {0, ONE, 0, 0,};
static SVECTOR N3 = {0, -ONE, 0, 0,};
static SVECTOR N4 = {0, 0, ONE, 0,};
static SVECTOR N5 = {0, 0, -ONE, 0,};
static SVECTOR *normals[6] = { &N5, &N0, &N4, &N1, &N3, &N2};
/*************************************************************/
// Light stuff
/*************************************************************/
static SVECTOR lightDirVec = {0,0,-4096}; // Directly into screen
/* Local Light Matrix */
static MATRIX llm;
/* Local Color Matrix */
static MATRIX lcm = {4096,0,0, 4096,0,0, 4096,0,0, 0,0,0};
/*************************************************************/
// Prototypes
/*************************************************************/
void initPrimitives(DB *buffer);
void addCube(u_long *ot, POLY_F4 *s,VECTOR *posVec,SVECTOR *rotVecs);
/*************************************************************/
int main()
{
SVECTOR rotAngVec = { 0, 0, 0};
VECTOR posVec = {0, 0, 2*SCR_Z};
ResetGraph(0);
ResetCallback();
SetGraphDebug(0);
InitGeom();
SetGeomOffset(160, 120);
SetGeomScreen(SCR_Z);
SetVideoMode(MODE_PAL);
SetDispMask(1);
/* Render upper part of framebuffer, while drawing to bottom, and vice versa */
SetDefDrawEnv(&db[0].draw, 0, 0, 320, 240);
SetDefDrawEnv(&db[1].draw, 0, 240, 320, 240);
SetDefDispEnv(&db[0].disp, 0, 240, 320, 240);
SetDefDispEnv(&db[1].disp, 0, 0, 320, 240);
SetBackColor(100,100,100);
SetColorMatrix(&lcm);
initPrimitives(&db[0]);
initPrimitives(&db[1]);
while (1)
{
cdb = (cdb==db)? db+1: db; // Switch double buffer
ClearOTagR(cdb->ot, OTSIZE);
rotAngVec.vz -= 5;
rotAngVec.vy += 15;
rotAngVec.vx += 8;
// transpose + light + perspective + add to OT
addCube(cdb->ot, cdb->polys, &posVec,&rotAngVec);
DrawSync(0);
VSync(0);
/* swap double buffer */
PutDispEnv(&cdb->disp);
PutDrawEnv(&cdb->draw);
/* draw OT */
//DrawOTag(cdb->ot);
DrawOTag(cdb->ot+OTSIZE-1);
}
}
// ***************************************************
// initPrimitives
//
// Initializes all the POLY_F4 primitive structs
// ***************************************************
void initPrimitives(DB *buffer)
{
int i = 0;
POLY_F4 *poly;
// Set the background color for this buffer
buffer->draw.isbg = 1;
setRGB0(&buffer->draw, 60, 120, 120);
// Initialize all primitive structs
for(poly = buffer->polys;i<MAXOBJS;i++,poly++)
{
SetPolyF4(poly);
}
}
// ***************************************************
//
// addCube
//
// takes a POLY_F4 primitive and does:
// - coordinate and perspective transform
// - light calculation
// - add to OT
//
// ***************************************************
void addCube(u_long *ot, POLY_F4 *s,VECTOR *posVec,SVECTOR *rotVecs)
{
int i;
long p, otz, opz, flg;
int isomote;
SVECTOR **vp, **np;
CVECTOR colorIn;
CVECTOR colorOut;
SVECTOR normal;
MATRIX rottrans;
MATRIX inverseLightMatrix;
// Create a rotation matrix for the cube
RotMatrix_gte(rotVecs, &rottrans);
TransMatrix(&rottrans,posVec);
// Set it as active in the GTE
SetRotMatrix(&rottrans);
SetTransMatrix(&rottrans);
// Transpose the rotation matrix, so the light does not appear to be following the cubes rotation.
// Make a matrix the is the reverse of the rotation we are going to apply to cube, so the
// light apperas to be in a fixed position.
TransposeMatrix(&rottrans, &inverseLightMatrix);
ApplyMatrixSV(&inverseLightMatrix,(SVECTOR*)&lightDirVec,(SVECTOR*)&llm);
SetLightMatrix(&llm);
vp = vertices; // vp: vertex pointer
np = normals; // np: normal pointer
// Loop through all 6 surfaces and render them
for (i = 0; i < 6; i++, s++, vp += 4, np++) {
SetRotMatrix(&rottrans);
isomote = RotAverageNclip4(vp[0], vp[1], vp[2], vp[3],
(long *)&s->x0, (long *)&s->x1,
(long *)&s->x3, (long *)&s->x2, &p, &otz, &flg);
if (isomote <= 0) continue;
/* Put into OT:
* The length of the OT is assumed to 4096. */
if (otz > 0 && otz < 4096) {
// just use a hardcoded unlit color for the surface
colorIn.r = 200;
colorIn.g = 200;
colorIn.b = 0;
// Get local light value..
NormalColorCol(*np, &colorIn, &colorOut);
// and apply it to surface
s->r0 = colorOut.r;
s->g0 = colorOut.g;
s->b0 = colorOut.b;
AddPrim(ot+otz, s);
}
}
}