1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1999-2000 Revolution Software Ltd.
9  * This code is based on source code created by Revolution Software,
10  * used with permission.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25  *
26  */
27 
28 #ifndef ICB_PX_CAPRI_MATHS_PC_H
29 #define ICB_PX_CAPRI_MATHS_PC_H
30 
31 #include "common/util.h"
32 
33 namespace ICB {
34 
35 #if (_PSX_ON_PC == 0) && !defined ICB_PX_CAPRI_MATHS_PC_H
36 
37 // make our own equivalents
38 typedef struct MATRIXPC {
39 	int32 m[3][3]; /* 3x3 rotation matrix */
40 	int32 pad;
41 	int32 t[3]; /* transfer vector */
MATRIXPCMATRIXPC42 	MATRIXPC() { pad = 0; }
43 } MATRIXPC;
44 
45 /* int32 word type 3D vector */
46 typedef struct VECTOR {
47 	int32 vx, vy;
48 	int32 vz, pad;
VECTORVECTOR49 	VECTOR() { pad = 0; }
50 } VECTOR;
51 
52 /* short word type 3D vector */
53 typedef struct SVECTORPC {
54 	int32 vx, vy;
55 	int32 vz, pad;
SVECTORPCSVECTORPC56 	SVECTORPC() { pad = 0; }
57 	bool operator==(const SVECTORPC &v) { return ((v.vx == vx) && (v.vy == vy) && (v.vz == vz)); }
58 } SVECTORPC;
59 
60 /* short word type 3D vector */
61 typedef struct CVECTOR {
62 	uint8 r, g;
63 	int16 b, pad;
CVECTORCVECTOR64 	CVECTOR() { pad = 0; }
65 	bool operator==(const CVECTOR &v) { return ((v.r == r) && (v.g == g) && (v.b == b)); }
66 } CVECTOR;
67 
68 #endif // #if (_PSX_ON_PC==0)
69 
70 //-=- Definitions -=-//
71 const int32 ONE_PC_SCALE = 12;
72 const int32 ONE_PC = 1 << ONE_PC_SCALE;
73 const float myPI_PC = 3.141592654f;
74 const int32 ZSCALE = 1;
75 
myNINT_PC(float f)76 inline int32 myNINT_PC(float f) {
77 	if (f >= 0.0f)
78 		return int(f + 0.5f);
79 	else
80 		return int(f - 0.5f);
81 }
82 
83 //------------------------------------------------------------------------
84 
85 #define VectorNormal_pc myVectorNormal_pc
86 #define ApplyMatrixLV_pc myApplyMatrixLV_pc
87 #define ApplyMatrixSV_pc myApplyMatrixSV_pc
88 #define RotMatrix_gte_pc myRotMatrix_gte_pc
89 #define gte_MulMatrix0_pc mygte_MulMatrix0_pc
90 #define gte_RotTrans_pc mygte_RotTrans_pc
91 #define gte_RotTransPers_pc mygte_RotTransPers_pc
92 #define gte_RotTransPers3_pc mygte_RotTransPers3_pc
93 #define gte_SetRotMatrix_pc mygte_SetRotMatrix_pc
94 #define gte_SetTransMatrix_pc mygte_SetTransMatrix_pc
95 #define gte_ApplyRotMatrix_pc mygte_ApplyRotMatrix_pc
96 #define gte_SetGeomScreen_pc mygte_SetGeomScreen_pc
97 #define gte_SetBackColor_pc mygte_SetBackColor_pc
98 #define gte_SetColorMatrix_pc mygte_SetColorMatrix_pc
99 #define gte_SetLightMatrix_pc mygte_SetLightMatrix_pc
100 #define gte_NormalColorCol_pc mygte_NormalColorCol_pc
101 #define gte_NormalColorCol3_pc mygte_NormalColorCol3_pc
102 #define gte_NormalClip_pc mygte_NormalClip_pc
103 #define gte_AverageZ3_pc mygte_AverageZ3_pc
104 #define gte_SetScreenScaleShift_pc mygte_SetScreenScaleShift_pc
105 
106 //------------------------------------------------------------------------
107 
108 extern MATRIXPC *gterot_pc;
109 extern MATRIXPC *gtetrans_pc;
110 extern MATRIXPC *gtecolour_pc;
111 extern MATRIXPC *gtelight_pc;
112 extern int32 gteback_pc[3];
113 extern int32 gtegeomscrn_pc;
114 extern int32 gtescreenscaleshift_pc;
115 
116 //------------------------------------------------------------------------
117 
118 inline void myApplyMatrixLV_pc(MATRIXPC *m, VECTOR *invec, VECTOR *outvec);
119 
120 inline void myApplyMatrixSV_pc(MATRIXPC *m, SVECTORPC *invec, SVECTORPC *outvec);
121 inline void myApplyMatrixSV_pc(MATRIXPC *m, SVECTOR *invec, SVECTORPC *outvec);
122 
123 inline int32 myVectorNormal_pc(VECTOR *in0, VECTOR *out0);
124 
125 inline void mygte_MulMatrix0_pc(MATRIXPC *m1, MATRIXPC *m2, MATRIXPC *out);
126 
127 inline void mygte_RotTrans_pc(SVECTORPC *in0, VECTOR *out0, int32 *flag);
128 inline void mygte_RotTrans_pc(SVECTOR *in0, VECTOR *out0, int32 *flag);
129 
130 inline void mygte_RotTransPers_pc(SVECTORPC *in0, SVECTORPC *sxy0, int32 *p, int32 *flag, int32 *z);
131 inline void mygte_RotTransPers_pc(SVECTOR *in0, SVECTORPC *sxy0, int32 *p, int32 *flag, int32 *z);
132 
133 inline void mygte_RotTransPers3_pc(SVECTORPC *in0, SVECTORPC *in1, SVECTORPC *in2, SVECTORPC *sxy0, SVECTORPC *sxy1, SVECTORPC *sxy2, int32 *p, int32 *flag, int32 *z);
134 
135 inline void mygte_SetRotMatrix_pc(MATRIXPC *m);
136 
137 inline void mygte_SetTransMatrix_pc(MATRIXPC *m);
138 
139 inline void mygte_ApplyRotMatrix_pc(SVECTORPC *invec, VECTOR *outvec);
140 
141 inline void myRotMatrix_gte_pc(SVECTOR *rot, MATRIXPC *m);
142 
143 inline void mygte_SetColorMatrix_pc(MATRIXPC *m);
144 
145 inline void mygte_SetLightMatrix_pc(MATRIXPC *m);
146 
147 inline void mygte_SetGeomScreen_pc(int32 h);
148 
149 inline void mygte_SetBackColor_pc(int32 r, int32 g, int32 b);
150 
151 inline void mygte_SetScreenScaleShift_pc(int32 shift);
152 
153 inline void mygte_NormalColorCol_pc(SVECTOR *v0, CVECTOR *in0, CVECTOR *out0);
154 
155 inline void mygte_NormalColorCol3_pc(SVECTOR *v0, SVECTOR *v1, SVECTOR *v2, CVECTOR *in0, CVECTOR *out0, CVECTOR *out1, CVECTOR *out2);
156 
157 inline void mygte_NormalClip_pc(SVECTORPC *sxy0, SVECTORPC *sxy1, SVECTORPC *sxy2, int32 *flag);
158 inline void mygte_NormalClip_pc(SVECTOR *sxy0, SVECTOR *sxy1, SVECTOR *sxy2, int32 *flag);
159 
160 inline void mygte_AverageZ3_pc(int32 z0, int32 z1, int32 z2, int32 *sz);
161 
162 //------------------------------------------------------------------------
163 
myApplyMatrixLV_pc(MATRIXPC * m,VECTOR * invec,VECTOR * outvec)164 inline void myApplyMatrixLV_pc(MATRIXPC *m, VECTOR *invec, VECTOR *outvec) {
165 	outvec->vx = (m->m[0][0] * invec->vx + m->m[0][1] * invec->vy + m->m[0][2] * invec->vz) / ONE_PC;
166 	outvec->vy = (m->m[1][0] * invec->vx + m->m[1][1] * invec->vy + m->m[1][2] * invec->vz) / ONE_PC;
167 	outvec->vz = (m->m[2][0] * invec->vx + m->m[2][1] * invec->vy + m->m[2][2] * invec->vz) / ONE_PC;
168 }
169 
170 //------------------------------------------------------------------------
171 
myApplyMatrixSV_pc(MATRIXPC * m,SVECTORPC * invec,SVECTORPC * outvec)172 inline void myApplyMatrixSV_pc(MATRIXPC *m, SVECTORPC *invec, SVECTORPC *outvec) {
173 	outvec->vx = (int)((m->m[0][0] * invec->vx + m->m[0][1] * invec->vy + m->m[0][2] * invec->vz) / ONE_PC);
174 	outvec->vy = (int)((m->m[1][0] * invec->vx + m->m[1][1] * invec->vy + m->m[1][2] * invec->vz) / ONE_PC);
175 	outvec->vz = (int)((m->m[2][0] * invec->vx + m->m[2][1] * invec->vy + m->m[2][2] * invec->vz) / ONE_PC);
176 }
177 
178 //------------------------------------------------------------------------
179 
myApplyMatrixSV_pc(MATRIXPC * m,SVECTOR * invec,SVECTORPC * outvec)180 inline void myApplyMatrixSV_pc(MATRIXPC *m, SVECTOR *invec, SVECTORPC *outvec) {
181 	outvec->vx = (int)((m->m[0][0] * (int)invec->vx + m->m[0][1] * (int)invec->vy + m->m[0][2] * (int)invec->vz) / ONE_PC);
182 	outvec->vy = (int)((m->m[1][0] * (int)invec->vx + m->m[1][1] * (int)invec->vy + m->m[1][2] * (int)invec->vz) / ONE_PC);
183 	outvec->vz = (int)((m->m[2][0] * (int)invec->vx + m->m[2][1] * (int)invec->vy + m->m[2][2] * (int)invec->vz) / ONE_PC);
184 }
185 
186 //------------------------------------------------------------------------
187 
mygte_MulMatrix0_pc(MATRIXPC * m1,MATRIXPC * m2,MATRIXPC * out)188 inline void mygte_MulMatrix0_pc(MATRIXPC *m1, MATRIXPC *m2, MATRIXPC *out) {
189 	MATRIXPC local;
190 	MATRIXPC *work;
191 	if ((out == m1) || (out == m2))
192 		work = &local;
193 	else
194 		work = out;
195 	work->m[0][0] = (int)((m1->m[0][0] * m2->m[0][0] + m1->m[0][1] * m2->m[1][0] + m1->m[0][2] * m2->m[2][0]) / ONE_PC);
196 	work->m[0][1] = (int)((m1->m[0][0] * m2->m[0][1] + m1->m[0][1] * m2->m[1][1] + m1->m[0][2] * m2->m[2][1]) / ONE_PC);
197 	work->m[0][2] = (int)((m1->m[0][0] * m2->m[0][2] + m1->m[0][1] * m2->m[1][2] + m1->m[0][2] * m2->m[2][2]) / ONE_PC);
198 	work->m[1][0] = (int)((m1->m[1][0] * m2->m[0][0] + m1->m[1][1] * m2->m[1][0] + m1->m[1][2] * m2->m[2][0]) / ONE_PC);
199 	work->m[1][1] = (int)((m1->m[1][0] * m2->m[0][1] + m1->m[1][1] * m2->m[1][1] + m1->m[1][2] * m2->m[2][1]) / ONE_PC);
200 	work->m[1][2] = (int)((m1->m[1][0] * m2->m[0][2] + m1->m[1][1] * m2->m[1][2] + m1->m[1][2] * m2->m[2][2]) / ONE_PC);
201 	work->m[2][0] = (int)((m1->m[2][0] * m2->m[0][0] + m1->m[2][1] * m2->m[1][0] + m1->m[2][2] * m2->m[2][0]) / ONE_PC);
202 	work->m[2][1] = (int)((m1->m[2][0] * m2->m[0][1] + m1->m[2][1] * m2->m[1][1] + m1->m[2][2] * m2->m[2][1]) / ONE_PC);
203 	work->m[2][2] = (int)((m1->m[2][0] * m2->m[0][2] + m1->m[2][1] * m2->m[1][2] + m1->m[2][2] * m2->m[2][2]) / ONE_PC);
204 
205 	if (work != out) {
206 		out->m[0][0] = work->m[0][0];
207 		out->m[0][1] = work->m[0][1];
208 		out->m[0][2] = work->m[0][2];
209 
210 		out->m[1][0] = work->m[1][0];
211 		out->m[1][1] = work->m[1][1];
212 		out->m[1][2] = work->m[1][2];
213 
214 		out->m[2][0] = work->m[2][0];
215 		out->m[2][1] = work->m[2][1];
216 		out->m[2][2] = work->m[2][2];
217 	}
218 }
219 
220 //------------------------------------------------------------------------
221 
mygte_SetRotMatrix_pc(MATRIXPC * m)222 inline void mygte_SetRotMatrix_pc(MATRIXPC *m) { *gterot_pc = *m; }
223 
224 //------------------------------------------------------------------------
225 
mygte_SetTransMatrix_pc(MATRIXPC * m)226 inline void mygte_SetTransMatrix_pc(MATRIXPC *m) { *gtetrans_pc = *m; }
227 
228 //------------------------------------------------------------------------
229 
mygte_ApplyRotMatrix_pc(SVECTORPC * invec,VECTOR * outvec)230 inline void mygte_ApplyRotMatrix_pc(SVECTORPC *invec, VECTOR *outvec) {
231 	outvec->vx = ((gterot_pc->m[0][0] * invec->vx + gterot_pc->m[0][1] * invec->vy + gterot_pc->m[0][2] * invec->vz) / ONE_PC);
232 	outvec->vy = ((gterot_pc->m[1][0] * invec->vx + gterot_pc->m[1][1] * invec->vy + gterot_pc->m[1][2] * invec->vz) / ONE_PC);
233 	outvec->vz = ((gterot_pc->m[2][0] * invec->vx + gterot_pc->m[2][1] * invec->vy + gterot_pc->m[2][2] * invec->vz) / ONE_PC);
234 }
235 
236 //------------------------------------------------------------------------
237 
mygte_RotTrans_pc(SVECTORPC * in0,VECTOR * out0,int32 * flag)238 inline void mygte_RotTrans_pc(SVECTORPC *in0, VECTOR *out0, int32 *flag) {
239 	mygte_ApplyRotMatrix_pc(in0, out0);
240 	out0->vx += gtetrans_pc->t[0];
241 	out0->vy += gtetrans_pc->t[1];
242 	out0->vz += gtetrans_pc->t[2];
243 
244 	// What GTE flags should we set ?
245 	*flag = 0;
246 }
247 
248 //------------------------------------------------------------------------
249 
mygte_RotTrans_pc(SVECTOR * in0,VECTOR * out0,int32 * flag)250 inline void mygte_RotTrans_pc(SVECTOR *in0, VECTOR *out0, int32 *flag) {
251 	SVECTORPC sv_pc;
252 	sv_pc.vx = in0->vx;
253 	sv_pc.vy = in0->vy;
254 	sv_pc.vz = in0->vz;
255 
256 	mygte_ApplyRotMatrix_pc(&sv_pc, out0);
257 
258 	out0->vx += gtetrans_pc->t[0];
259 	out0->vy += gtetrans_pc->t[1];
260 	out0->vz += gtetrans_pc->t[2];
261 
262 	// What GTE flags should we set ?
263 	*flag = 0;
264 }
265 
266 //------------------------------------------------------------------------
267 
mygte_RotTransPers_pc(SVECTORPC * in0,SVECTORPC * sxy0,int32 *,int32 * flag,int32 * z)268 inline void mygte_RotTransPers_pc(SVECTORPC *in0, SVECTORPC *sxy0, int32 * /* p */, int32 *flag, int32 *z) {
269 	VECTOR cam;
270 	cam.vx = ((gterot_pc->m[0][0] * in0->vx + gterot_pc->m[0][1] * in0->vy + gterot_pc->m[0][2] * in0->vz) / ONE_PC);
271 	cam.vy = ((gterot_pc->m[1][0] * in0->vx + gterot_pc->m[1][1] * in0->vy + gterot_pc->m[1][2] * in0->vz) / ONE_PC);
272 	cam.vz = ((gterot_pc->m[2][0] * in0->vx + gterot_pc->m[2][1] * in0->vy + gterot_pc->m[2][2] * in0->vz) / ONE_PC);
273 	cam.vx += (gtetrans_pc->t[0] << gtescreenscaleshift_pc);
274 	cam.vy += (gtetrans_pc->t[1] << gtescreenscaleshift_pc);
275 	cam.vz += (gtetrans_pc->t[2] << gtescreenscaleshift_pc);
276 
277 	*flag = 0;
278 
279 	if (cam.vz != 0) {
280 		sxy0->vx = (int)((cam.vx * gtegeomscrn_pc) / cam.vz);
281 		sxy0->vy = (int)((cam.vy * gtegeomscrn_pc) / cam.vz);
282 	} else {
283 		// To force an error and hence an illegal polygon
284 		sxy0->vx = 2048;
285 		sxy0->vy = 2048;
286 	}
287 
288 	cam.vz >>= gtescreenscaleshift_pc;
289 	*z = cam.vz / 4;
290 
291 	if (abs(sxy0->vx) > 1024)
292 		*flag |= 0x80000000;
293 	if (abs(sxy0->vy) > 1024)
294 		*flag |= 0x80000000;
295 
296 	// set the value of flag : closer than h/2
297 	if (cam.vz < 0)
298 		*flag |= 0x80000000;
299 }
300 
301 //------------------------------------------------------------------------
302 
mygte_RotTransPers_pc(SVECTOR * in0,SVECTORPC * sxy0,int32 *,int32 * flag,int32 * z)303 inline void mygte_RotTransPers_pc(SVECTOR *in0, SVECTORPC *sxy0, int32 * /* p */, int32 *flag, int32 *z) {
304 	VECTOR cam;
305 	cam.vx = ((gterot_pc->m[0][0] * (int)in0->vx + gterot_pc->m[0][1] * (int)in0->vy + gterot_pc->m[0][2] * (int)in0->vz) / ONE_PC);
306 	cam.vy = ((gterot_pc->m[1][0] * (int)in0->vx + gterot_pc->m[1][1] * (int)in0->vy + gterot_pc->m[1][2] * (int)in0->vz) / ONE_PC);
307 	cam.vz = ((gterot_pc->m[2][0] * (int)in0->vx + gterot_pc->m[2][1] * (int)in0->vy + gterot_pc->m[2][2] * (int)in0->vz) / ONE_PC);
308 	cam.vx += (gtetrans_pc->t[0] << gtescreenscaleshift_pc);
309 	cam.vy += (gtetrans_pc->t[1] << gtescreenscaleshift_pc);
310 	cam.vz += (gtetrans_pc->t[2] << gtescreenscaleshift_pc);
311 
312 	*flag = 0;
313 
314 	if (cam.vz != 0) {
315 		sxy0->vx = (int)((cam.vx * gtegeomscrn_pc) / cam.vz);
316 		sxy0->vy = (int)((cam.vy * gtegeomscrn_pc) / cam.vz);
317 	} else {
318 		// To force an error and hence an illegal polygon
319 		sxy0->vx = 2048;
320 		sxy0->vy = 2048;
321 	}
322 
323 	cam.vz >>= gtescreenscaleshift_pc;
324 	*z = cam.vz / 4;
325 
326 	if (abs(sxy0->vx) > 1024)
327 		*flag |= 0x80000000;
328 	if (abs(sxy0->vy) > 1024)
329 		*flag |= 0x80000000;
330 
331 	// set the value of flag : closer than h/2
332 	if (cam.vz < 0)
333 		*flag |= 0x80000000;
334 }
335 
336 //------------------------------------------------------------------------
337 
mygte_RotTransPers3_pc(SVECTORPC * in0,SVECTORPC * in1,SVECTORPC * in2,SVECTORPC * sxy0,SVECTORPC * sxy1,SVECTORPC * sxy2,int32 * p,int32 * flag,int32 * z)338 inline void mygte_RotTransPers3_pc(SVECTORPC *in0, SVECTORPC *in1, SVECTORPC *in2, SVECTORPC *sxy0, SVECTORPC *sxy1, SVECTORPC *sxy2, int32 *p, int32 *flag, int32 *z) {
339 	int32 z0, z1, z2;
340 	int32 p0, p1, p2;
341 	int32 flag0, flag1, flag2;
342 
343 	mygte_RotTransPers_pc(in0, sxy0, &p0, &flag0, &z0);
344 	mygte_RotTransPers_pc(in1, sxy1, &p1, &flag1, &z1);
345 	mygte_RotTransPers_pc(in2, sxy2, &p2, &flag2, &z2);
346 
347 	// What GTE flags should we set ?
348 	*flag = flag0 | flag1 | flag2;
349 	*p = p2;
350 	*z = z2;
351 }
352 
353 //------------------------------------------------------------------------
354 
myRotMatrix_gte_pc(SVECTOR * rot,MATRIXPC * m)355 inline void myRotMatrix_gte_pc(SVECTOR *rot, MATRIXPC *m) {
356 	float ang0 = (float)rot->vx * 2.0f * myPI_PC / 4096;
357 	MATRIXPC m0;
358 	int32 c0 = myNINT_PC(ONE_PC * (float)cos(ang0));
359 	int32 s0 = myNINT_PC(ONE_PC * (float)sin(ang0));
360 	m0.m[0][0] = ONE_PC;
361 	m0.m[0][1] = 0;
362 	m0.m[0][2] = 0;
363 
364 	m0.m[1][0] = 0;
365 	m0.m[1][1] = c0;
366 	m0.m[1][2] = -s0;
367 
368 	m0.m[2][0] = 0;
369 	m0.m[2][1] = s0;
370 	m0.m[2][2] = c0;
371 
372 	float ang1 = (float)rot->vy * 2.0f * myPI_PC / 4096;
373 	int32 c1 = myNINT_PC(ONE_PC * (float)cos(ang1));
374 	int32 s1 = myNINT_PC(ONE_PC * (float)sin(ang1));
375 	MATRIXPC m1;
376 	m1.m[0][0] = c1;
377 	m1.m[0][1] = 0;
378 	m1.m[0][2] = s1;
379 
380 	m1.m[1][0] = 0;
381 	m1.m[1][1] = ONE_PC;
382 	m1.m[1][2] = 0;
383 
384 	m1.m[2][0] = -s1;
385 	m1.m[2][1] = 0;
386 	m1.m[2][2] = c1;
387 
388 	float ang2 = (float)rot->vz * 2.0f * myPI_PC / 4096;
389 	int32 c2 = myNINT_PC(ONE_PC * (float)cos(ang2));
390 	int32 s2 = myNINT_PC(ONE_PC * (float)sin(ang2));
391 	MATRIXPC m2;
392 
393 	m2.m[0][0] = c2;
394 	m2.m[0][1] = -s2;
395 	m2.m[0][2] = 0;
396 
397 	m2.m[1][0] = s2;
398 	m2.m[1][1] = c2;
399 	m2.m[1][2] = 0;
400 
401 	m2.m[2][0] = 0;
402 	m2.m[2][1] = 0;
403 	m2.m[2][2] = ONE_PC;
404 
405 	mygte_MulMatrix0_pc(&m0, &m1, m);
406 	mygte_MulMatrix0_pc(m, &m2, m);
407 }
408 
409 //------------------------------------------------------------------------
410 
mygte_SetBackColor_pc(int32 r,int32 g,int32 b)411 inline void mygte_SetBackColor_pc(int32 r, int32 g, int32 b) {
412 	gteback_pc[0] = r;
413 	gteback_pc[1] = g;
414 	gteback_pc[2] = b;
415 }
416 
417 //------------------------------------------------------------------------
418 
mygte_SetColorMatrix_pc(MATRIXPC * m)419 inline void mygte_SetColorMatrix_pc(MATRIXPC *m) { *gtecolour_pc = *m; }
420 
421 //------------------------------------------------------------------------
422 
mygte_SetLightMatrix_pc(MATRIXPC * m)423 inline void mygte_SetLightMatrix_pc(MATRIXPC *m) { *gtelight_pc = *m; }
424 
425 //------------------------------------------------------------------------
426 
mygte_SetGeomScreen_pc(int32 h)427 inline void mygte_SetGeomScreen_pc(int32 h) { gtegeomscrn_pc = h; }
428 
429 //------------------------------------------------------------------------
430 
mygte_NormalColorCol_pc(SVECTOR * v0,CVECTOR * in0,CVECTOR * out0)431 inline void mygte_NormalColorCol_pc(SVECTOR *v0, CVECTOR *in0, CVECTOR *out0) {
432 	SVECTORPC lightEffect;
433 	// Normal line vector(local) -> light source effect
434 	ApplyMatrixSV_pc(gtelight_pc, v0, &lightEffect);
435 	if (lightEffect.vx < 0)
436 		lightEffect.vx = 0;
437 	if (lightEffect.vy < 0)
438 		lightEffect.vy = 0;
439 	if (lightEffect.vz < 0)
440 		lightEffect.vz = 0;
441 
442 	// Light source effect -> Colour effect(local colour matrix+back colour)
443 	SVECTORPC colourEffect;
444 	ApplyMatrixSV_pc(gtecolour_pc, &lightEffect, &colourEffect);
445 	if (colourEffect.vx < 0)
446 		colourEffect.vx = 0;
447 	if (colourEffect.vy < 0)
448 		colourEffect.vy = 0;
449 	if (colourEffect.vz < 0)
450 		colourEffect.vz = 0;
451 
452 	// colourEffect is 0-ONE_PC (2^ONE_PC_SCALE)
453 	// gteback is 0-255 (2^8)
454 	colourEffect.vx = ((colourEffect.vx >> (ONE_PC_SCALE - 8)) + gteback_pc[0]);
455 	colourEffect.vy = ((colourEffect.vy >> (ONE_PC_SCALE - 8)) + gteback_pc[1]);
456 	colourEffect.vz = ((colourEffect.vz >> (ONE_PC_SCALE - 8)) + gteback_pc[2]);
457 
458 	// 256 = 1.0 in colourEffect
459 	// 128 = 1.0 in in0
460 	int32 red = ((in0->r * colourEffect.vx) >> 8);
461 	int32 green = ((in0->g * colourEffect.vy) >> 8);
462 	int32 blue = ((in0->b * colourEffect.vz) >> 8);
463 
464 	if (red > 255)
465 		red = 255;
466 	if (green > 255)
467 		green = 255;
468 	if (blue > 255)
469 		blue = 255;
470 
471 	out0->r = (uint8)(red);
472 	out0->g = (uint8)(green);
473 	out0->b = (uint8)(blue);
474 }
475 
476 //------------------------------------------------------------------------
477 
mygte_NormalColorCol3_pc(SVECTOR * v0,SVECTOR * v1,SVECTOR * v2,CVECTOR * in0,CVECTOR * out0,CVECTOR * out1,CVECTOR * out2)478 inline void mygte_NormalColorCol3_pc(SVECTOR *v0, SVECTOR *v1, SVECTOR *v2, CVECTOR *in0, CVECTOR *out0, CVECTOR *out1, CVECTOR *out2) {
479 	gte_NormalColorCol_pc(v0, in0, out0);
480 	gte_NormalColorCol_pc(v1, in0, out1);
481 	gte_NormalColorCol_pc(v2, in0, out2);
482 }
483 
484 //------------------------------------------------------------------------
485 
myVectorNormal_pc(VECTOR * in0,VECTOR * out0)486 inline int32 myVectorNormal_pc(VECTOR *in0, VECTOR *out0) {
487 	int32 r2 = (in0->vx * in0->vx + in0->vy * in0->vy + in0->vz * in0->vz);
488 	float r = (float)sqrt((float)r2) / (float)ONE_PC;
489 
490 	if (fabs(r) < 1.0e-6)
491 		return 0;
492 
493 	out0->vx = (int32)((float)in0->vx / r);
494 	out0->vy = (int32)((float)in0->vy / r);
495 	out0->vz = (int32)((float)in0->vz / r);
496 	return r2;
497 }
498 
499 //////////////////////////////////////////////////////////////////////
500 
mygte_NormalClip_pc(SVECTORPC * sxy0,SVECTORPC * sxy1,SVECTORPC * sxy2,int32 * flag)501 inline void mygte_NormalClip_pc(SVECTORPC *sxy0, SVECTORPC *sxy1, SVECTORPC *sxy2, int32 *flag) {
502 	// compute the cross-product of (v1-v0) x (v2-v0)
503 	int32 l0x = sxy1->vx - sxy0->vx;
504 	int32 l0y = sxy1->vy - sxy0->vy;
505 	int32 l1x = sxy2->vx - sxy0->vx;
506 	int32 l1y = sxy2->vy - sxy0->vy;
507 
508 	*flag = ((l0x * l1y) - (l0y * l1x));
509 }
510 
511 //------------------------------------------------------------------------
512 
mygte_NormalClip_pc(SVECTOR * sxy0,SVECTOR * sxy1,SVECTOR * sxy2,int32 * flag)513 inline void mygte_NormalClip_pc(SVECTOR *sxy0, SVECTOR *sxy1, SVECTOR *sxy2, int32 *flag) {
514 	// compute the cross-product of (v1-v0) x (v2-v0)
515 	int32 l0x = sxy1->vx - sxy0->vx;
516 	int32 l0y = sxy1->vy - sxy0->vy;
517 	int32 l1x = sxy2->vx - sxy0->vx;
518 	int32 l1y = sxy2->vy - sxy0->vy;
519 
520 	*flag = ((l0x * l1y) - (l0y * l1x));
521 }
522 
523 //------------------------------------------------------------------------
524 
mygte_AverageZ3_pc(int32 z0,int32 z1,int32 z2,int32 * sz)525 inline void mygte_AverageZ3_pc(int32 z0, int32 z1, int32 z2, int32 *sz) {
526 	*sz = (z0 + z1 + z2) / 3;
527 	*sz /= 4;
528 }
529 
530 //------------------------------------------------------------------------
531 
mygte_SetScreenScaleShift_pc(int32 shift)532 inline void mygte_SetScreenScaleShift_pc(int32 shift) { gtescreenscaleshift_pc = shift; }
533 
534 //------------------------------------------------------------------------
535 
536 } // End of namespace ICB
537 
538 #endif // #ifndef __PC_CAPRI_MATHS_PC_H
539