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 #include "engines/icb/px_common.h"
29 #include "engines/icb/px_rcutypes.h"
30 #include "engines/icb/psx_pcdefines.h"
31 #include "engines/icb/shade.h"
32
33 namespace ICB {
34
35 // Handy maths function
makePlaneEquation(FVECTOR * v0,FVECTOR * v1,FVECTOR * v2,int32 * d,FVECTOR * pn)36 void makePlaneEquation(FVECTOR *v0, FVECTOR *v1, FVECTOR *v2, int32 *d, FVECTOR *pn) {
37 FVECTOR l01, l02;
38 // Line from vertex 0 -> vertex 1
39 VEC_SUB_VECTOR(*v0, *v1, l01);
40 // Line from vertex 0 -> vertex 2
41 VEC_SUB_VECTOR(*v0, *v2, l02);
42
43 // the cross-product to get the normal : l01 x l02
44 CROSS_PRODUCT_VECTOR(l01, l02, *pn);
45 NORMALISE_VECTOR(*pn);
46
47 // the planar distance
48 *d = (int32)DOT_PRODUCT_VECTOR(*pn, *v0);
49 }
50
51 /*
52 // A triangle
53 typedef struct ShadeTriangle
54 {
55 SVECTOR l01; // line vertex 0 -> vertex 1
56 SVECTOR l12; // line vertex 1 -> vertex 2
57 SVECTOR l20; // line vertex 2 -> vertex 0
58 SVECTOR n01; // normal to plane & line 01
59 SVECTOR n12; // normal to plane & line 12
60 SVECTOR n20; // normal to plane & line 20
61 SVECTOR pn; // plane normal
62 uint32 d; // plane distance
63 } ShadeTriangle;
64 */
65
preprocessShadeData(FVECTOR v[3],ShadeTriangle * s)66 void preprocessShadeData(FVECTOR v[3], ShadeTriangle *s) {
67 // find the normal for the shade triangle / polygon !
68 double l01x = v[1].vx - v[0].vx;
69 double l01y = v[1].vy - v[0].vy;
70 double l01z = v[1].vz - v[0].vz;
71
72 double l20x = v[0].vx - v[2].vx;
73 double l20y = v[0].vy - v[2].vy;
74 double l20z = v[0].vz - v[2].vz;
75
76 double l12x = v[2].vx - v[1].vx;
77 double l12y = v[2].vy - v[1].vy;
78 double l12z = v[2].vz - v[1].vz;
79
80 // the cross-product to get the normal : l01 x l02
81 double nx, ny, nz;
82 CROSS_PRODUCT(l01x, l01y, l01z, -l20x, -l20y, -l20z, nx, ny, nz);
83 NORMALISE(nx, ny, nz);
84
85 // the planar distance
86 double d = DOT_PRODUCT(nx, ny, nz, v[0].vx, v[0].vy, v[0].vz);
87
88 // n01 is normal in the plane of l01 : n01 = l01 x n
89 double n01x, n01y, n01z;
90 CROSS_PRODUCT(l01x, l01y, l01z, nx, ny, nz, n01x, n01y, n01z);
91 NORMALISE(n01x, n01y, n01z);
92 // n12 is normal in the plane of l12 : n12 = l12 x n
93 double n12x, n12y, n12z;
94 CROSS_PRODUCT(l12x, l12y, l12z, nx, ny, nz, n12x, n12y, n12z);
95 NORMALISE(n12x, n12y, n12z);
96 // n20 is normal in the plane of l20 : n20 = l20 x n
97 double n20x, n20y, n20z;
98 CROSS_PRODUCT(l20x, l20y, l20z, nx, ny, nz, n20x, n20y, n20z);
99 NORMALISE(n20x, n20y, n20z);
100
101 double n01dots0, n12dots1, n20dots2;
102 n01dots0 = DOT_PRODUCT(n01x, n01y, n01z, v[0].vx, v[0].vy, v[0].vz);
103 n12dots1 = DOT_PRODUCT(n12x, n12y, n12z, v[1].vx, v[1].vy, v[1].vz);
104 n20dots2 = DOT_PRODUCT(n20x, n20y, n20z, v[2].vx, v[2].vy, v[2].vz);
105
106 // Store the pre-processed data
107 s->l01.vx = (int16)l01x;
108 s->l01.vy = (int16)l01y;
109 s->l01.vz = (int16)l01z;
110
111 s->l12.vx = (int16)l12x;
112 s->l12.vy = (int16)l12y;
113 s->l12.vz = (int16)l12z;
114
115 s->l20.vx = (int16)l20x;
116 s->l20.vy = (int16)l20y;
117 s->l20.vz = (int16)l20z;
118
119 s->n01.vx = (int16)(4096.0f * n01x);
120 s->n01.vy = (int16)(4096.0f * n01y);
121 s->n01.vz = (int16)(4096.0f * n01z);
122
123 s->n12.vx = (int16)(4096.0f * n12x);
124 s->n12.vy = (int16)(4096.0f * n12y);
125 s->n12.vz = (int16)(4096.0f * n12z);
126
127 s->n20.vx = (int16)(4096.0f * n20x);
128 s->n20.vy = (int16)(4096.0f * n20y);
129 s->n20.vz = (int16)(4096.0f * n20z);
130
131 s->pn.vx = (int16)(4096.0f * nx);
132 s->pn.vy = (int16)(4096.0f * ny);
133 s->pn.vz = (int16)(4096.0f * nz);
134
135 s->d = (int32)(4096.0f * d);
136 s->n01dots0 = (int32)n01dots0;
137 s->n12dots1 = (int32)n12dots1;
138 s->n20dots2 = (int32)n20dots2;
139 }
140
141 /*
142 // A quad
143 typedef struct ShadeQuad
144 {
145 SVECTOR l01; // line vertex 0 -> vertex 1
146 SVECTOR l12; // line vertex 1 -> vertex 2
147 SVECTOR l23; // line vertex 2 -> vertex 3
148 SVECTOR l30; // line vertex 3 -> vertex 0
149 SVECTOR n01; // normal to plane & line 01
150 SVECTOR n12; // normal to plane & line 12
151 SVECTOR n23; // normal to plane & line 23
152 SVECTOR n30; // normal to plane & line 30
153 SVECTOR pn; // plane normal
154 uint32 d; // plane distance
155 uint32 n01dots0; // n01 . vertex 0
156 uint32 n12dots1; // n12 . vertex 1
157 uint32 n20dots2; // n23 . vertex 2
158 uint32 n20dots3; // n30 . vertex 3
159 } ShadeQuad;
160 */
161
preprocessShadeData(FVECTOR v[4],ShadeQuad * s)162 void preprocessShadeData(FVECTOR v[4], ShadeQuad *s) {
163
164 // find the normal for the shade quad !
165 double l01x = v[1].vx - v[0].vx;
166 double l01y = v[1].vy - v[0].vy;
167 double l01z = v[1].vz - v[0].vz;
168
169 double l12x = v[2].vx - v[1].vx;
170 double l12y = v[2].vy - v[1].vy;
171 double l12z = v[2].vz - v[1].vz;
172
173 double l23x = v[3].vx - v[2].vx;
174 double l23y = v[3].vy - v[2].vy;
175 double l23z = v[3].vz - v[2].vz;
176
177 double l30x = v[0].vx - v[3].vx;
178 double l30y = v[0].vy - v[3].vy;
179 double l30z = v[0].vz - v[3].vz;
180
181 // the cross-product to get the normal : l01 x l03
182 double nx, ny, nz;
183 CROSS_PRODUCT(l01x, l01y, l01z, -l30x, -l30y, -l30z, nx, ny, nz);
184 NORMALISE(nx, ny, nz);
185
186 // the planar distance
187 double d = DOT_PRODUCT(nx, ny, nz, v[0].vx, v[0].vy, v[0].vz);
188
189 // n01 is normal in the plane of l01 : n01 = l01 x n
190 double n01x, n01y, n01z;
191 CROSS_PRODUCT(l01x, l01y, l01z, nx, ny, nz, n01x, n01y, n01z);
192 NORMALISE(n01x, n01y, n01z);
193 // n12 is normal in the plane of l12 : n12 = l12 x n
194 double n12x, n12y, n12z;
195 CROSS_PRODUCT(l12x, l12y, l12z, nx, ny, nz, n12x, n12y, n12z);
196 NORMALISE(n12x, n12y, n12z);
197 // n23 is normal in the plane of l23 : n23 = l23 x n
198 double n23x, n23y, n23z;
199 CROSS_PRODUCT(l23x, l23y, l23z, nx, ny, nz, n23x, n23y, n23z);
200 NORMALISE(n23x, n23y, n23z);
201 // n30 is normal in the plane of l30 : n30 = l30 x n
202 double n30x, n30y, n30z;
203 CROSS_PRODUCT(l30x, l30y, l30z, nx, ny, nz, n30x, n30y, n30z);
204 NORMALISE(n30x, n30y, n30z);
205
206 double n01dots0, n12dots1, n23dots2, n30dots3;
207 n01dots0 = DOT_PRODUCT(n01x, n01y, n01z, v[0].vx, v[0].vy, v[0].vz);
208 n12dots1 = DOT_PRODUCT(n12x, n12y, n12z, v[1].vx, v[1].vy, v[1].vz);
209 n23dots2 = DOT_PRODUCT(n23x, n23y, n23z, v[2].vx, v[2].vy, v[2].vz);
210 n30dots3 = DOT_PRODUCT(n30x, n30y, n30z, v[3].vx, v[3].vy, v[3].vz);
211
212 // Store the pre-processed data
213 s->l01.vx = (int16)l01x;
214 s->l01.vy = (int16)l01y;
215 s->l01.vz = (int16)l01z;
216
217 s->l12.vx = (int16)l12x;
218 s->l12.vy = (int16)l12y;
219 s->l12.vz = (int16)l12z;
220
221 s->l23.vx = (int16)l23x;
222 s->l23.vy = (int16)l23y;
223 s->l23.vz = (int16)l23z;
224
225 s->l30.vx = (int16)l30x;
226 s->l30.vy = (int16)l30y;
227 s->l30.vz = (int16)l30z;
228
229 s->n01.vx = (int16)(4096.0f * n01x);
230 s->n01.vy = (int16)(4096.0f * n01y);
231 s->n01.vz = (int16)(4096.0f * n01z);
232
233 s->n12.vx = (int16)(4096.0f * n12x);
234 s->n12.vy = (int16)(4096.0f * n12y);
235 s->n12.vz = (int16)(4096.0f * n12z);
236
237 s->n23.vx = (int16)(4096.0f * n23x);
238 s->n23.vy = (int16)(4096.0f * n23y);
239 s->n23.vz = (int16)(4096.0f * n23z);
240
241 s->n30.vx = (int16)(4096.0f * n30x);
242 s->n30.vy = (int16)(4096.0f * n30y);
243 s->n30.vz = (int16)(4096.0f * n30z);
244
245 s->pn.vx = (int16)(4096.0f * nx);
246 s->pn.vy = (int16)(4096.0f * ny);
247 s->pn.vz = (int16)(4096.0f * nz);
248
249 s->d = (int32)(4096.0f * d);
250 s->n01dots0 = (int32)n01dots0;
251 s->n12dots1 = (int32)n12dots1;
252 s->n23dots2 = (int32)n23dots2;
253 s->n30dots3 = (int32)n30dots3;
254 }
255
256 } // End of namespace ICB
257