]>
Commit | Line | Data |
---|---|---|
81345200 A |
1 | try { |
2 | ||
3 | // 3D Cube Rotation | |
4 | // http://www.speich.net/computer/moztesting/3d.htm | |
5 | // Created by Simon Speich | |
6 | ||
ed1e77d3 A |
7 | enableExceptionFuzz(); |
8 | ||
9 | ||
81345200 A |
10 | var Q = new Array(); |
11 | var MTrans = new Array(); // transformation matrix | |
12 | var MQube = new Array(); // position information of qube | |
13 | var I = new Array(); // entity matrix | |
14 | var Origin = new Object(); | |
15 | var Testing = new Object(); | |
16 | var LoopTimer; | |
17 | ||
18 | var validation = { | |
19 | 20: 2889.0000000000045, | |
20 | 40: 2889.0000000000055, | |
21 | 80: 2889.000000000005, | |
22 | 160: 2889.0000000000055 | |
23 | }; | |
24 | ||
25 | var DisplArea = new Object(); | |
26 | DisplArea.Width = 300; | |
27 | DisplArea.Height = 300; | |
28 | ||
29 | function DrawLine(From, To) { | |
30 | var x1 = From.V[0]; | |
31 | var x2 = To.V[0]; | |
32 | var y1 = From.V[1]; | |
33 | var y2 = To.V[1]; | |
34 | var dx = Math.abs(x2 - x1); | |
35 | var dy = Math.abs(y2 - y1); | |
36 | var x = x1; | |
37 | var y = y1; | |
38 | var IncX1, IncY1; | |
39 | var IncX2, IncY2; | |
40 | var Den; | |
41 | var Num; | |
42 | var NumAdd; | |
43 | var NumPix; | |
44 | ||
45 | if (x2 >= x1) { IncX1 = 1; IncX2 = 1; } | |
46 | else { IncX1 = -1; IncX2 = -1; } | |
47 | if (y2 >= y1) { IncY1 = 1; IncY2 = 1; } | |
48 | else { IncY1 = -1; IncY2 = -1; } | |
49 | if (dx >= dy) { | |
50 | IncX1 = 0; | |
51 | IncY2 = 0; | |
52 | Den = dx; | |
53 | Num = dx / 2; | |
54 | NumAdd = dy; | |
55 | NumPix = dx; | |
56 | } | |
57 | else { | |
58 | IncX2 = 0; | |
59 | IncY1 = 0; | |
60 | Den = dy; | |
61 | Num = dy / 2; | |
62 | NumAdd = dx; | |
63 | NumPix = dy; | |
64 | } | |
65 | ||
66 | NumPix = Math.round(Q.LastPx + NumPix); | |
67 | ||
68 | var i = Q.LastPx; | |
69 | for (; i < NumPix; i++) { | |
70 | Num += NumAdd; | |
71 | if (Num >= Den) { | |
72 | Num -= Den; | |
73 | x += IncX1; | |
74 | y += IncY1; | |
75 | } | |
76 | x += IncX2; | |
77 | y += IncY2; | |
78 | } | |
79 | Q.LastPx = NumPix; | |
80 | } | |
81 | ||
82 | function CalcCross(V0, V1) { | |
83 | var Cross = new Array(); | |
84 | Cross[0] = V0[1]*V1[2] - V0[2]*V1[1]; | |
85 | Cross[1] = V0[2]*V1[0] - V0[0]*V1[2]; | |
86 | Cross[2] = V0[0]*V1[1] - V0[1]*V1[0]; | |
87 | return Cross; | |
88 | } | |
89 | ||
90 | function CalcNormal(V0, V1, V2) { | |
91 | var A = new Array(); var B = new Array(); | |
92 | for (var i = 0; i < 3; i++) { | |
93 | A[i] = V0[i] - V1[i]; | |
94 | B[i] = V2[i] - V1[i]; | |
95 | } | |
96 | A = CalcCross(A, B); | |
97 | var Length = Math.sqrt(A[0]*A[0] + A[1]*A[1] + A[2]*A[2]); | |
98 | for (var i = 0; i < 3; i++) A[i] = A[i] / Length; | |
99 | A[3] = 1; | |
100 | return A; | |
101 | } | |
102 | ||
103 | function CreateP(X,Y,Z) { | |
104 | this.V = [X,Y,Z,1]; | |
105 | } | |
106 | ||
107 | // multiplies two matrices | |
108 | function MMulti(M1, M2) { | |
109 | var M = [[],[],[],[]]; | |
110 | var i = 0; | |
111 | var j = 0; | |
112 | for (; i < 4; i++) { | |
113 | j = 0; | |
114 | for (; j < 4; j++) M[i][j] = M1[i][0] * M2[0][j] + M1[i][1] * M2[1][j] + M1[i][2] * M2[2][j] + M1[i][3] * M2[3][j]; | |
115 | } | |
116 | return M; | |
117 | } | |
118 | ||
119 | //multiplies matrix with vector | |
120 | function VMulti(M, V) { | |
121 | var Vect = new Array(); | |
122 | var i = 0; | |
123 | for (;i < 4; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2] + M[i][3] * V[3]; | |
124 | return Vect; | |
125 | } | |
126 | ||
127 | function VMulti2(M, V) { | |
128 | var Vect = new Array(); | |
129 | var i = 0; | |
130 | for (;i < 3; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2]; | |
131 | return Vect; | |
132 | } | |
133 | ||
134 | // add to matrices | |
135 | function MAdd(M1, M2) { | |
136 | var M = [[],[],[],[]]; | |
137 | var i = 0; | |
138 | var j = 0; | |
139 | for (; i < 4; i++) { | |
140 | j = 0; | |
141 | for (; j < 4; j++) M[i][j] = M1[i][j] + M2[i][j]; | |
142 | } | |
143 | return M; | |
144 | } | |
145 | ||
146 | function Translate(M, Dx, Dy, Dz) { | |
147 | var T = [ | |
148 | [1,0,0,Dx], | |
149 | [0,1,0,Dy], | |
150 | [0,0,1,Dz], | |
151 | [0,0,0,1] | |
152 | ]; | |
153 | return MMulti(T, M); | |
154 | } | |
155 | ||
156 | function RotateX(M, Phi) { | |
157 | var a = Phi; | |
158 | a *= Math.PI / 180; | |
159 | var Cos = Math.cos(a); | |
160 | var Sin = Math.sin(a); | |
161 | var R = [ | |
162 | [1,0,0,0], | |
163 | [0,Cos,-Sin,0], | |
164 | [0,Sin,Cos,0], | |
165 | [0,0,0,1] | |
166 | ]; | |
167 | return MMulti(R, M); | |
168 | } | |
169 | ||
170 | function RotateY(M, Phi) { | |
171 | var a = Phi; | |
172 | a *= Math.PI / 180; | |
173 | var Cos = Math.cos(a); | |
174 | var Sin = Math.sin(a); | |
175 | var R = [ | |
176 | [Cos,0,Sin,0], | |
177 | [0,1,0,0], | |
178 | [-Sin,0,Cos,0], | |
179 | [0,0,0,1] | |
180 | ]; | |
181 | return MMulti(R, M); | |
182 | } | |
183 | ||
184 | function RotateZ(M, Phi) { | |
185 | var a = Phi; | |
186 | a *= Math.PI / 180; | |
187 | var Cos = Math.cos(a); | |
188 | var Sin = Math.sin(a); | |
189 | var R = [ | |
190 | [Cos,-Sin,0,0], | |
191 | [Sin,Cos,0,0], | |
192 | [0,0,1,0], | |
193 | [0,0,0,1] | |
194 | ]; | |
195 | return MMulti(R, M); | |
196 | } | |
197 | ||
198 | function DrawQube() { | |
199 | // calc current normals | |
200 | var CurN = new Array(); | |
201 | var i = 5; | |
202 | Q.LastPx = 0; | |
203 | for (; i > -1; i--) CurN[i] = VMulti2(MQube, Q.Normal[i]); | |
204 | if (CurN[0][2] < 0) { | |
205 | if (!Q.Line[0]) { DrawLine(Q[0], Q[1]); Q.Line[0] = true; }; | |
206 | if (!Q.Line[1]) { DrawLine(Q[1], Q[2]); Q.Line[1] = true; }; | |
207 | if (!Q.Line[2]) { DrawLine(Q[2], Q[3]); Q.Line[2] = true; }; | |
208 | if (!Q.Line[3]) { DrawLine(Q[3], Q[0]); Q.Line[3] = true; }; | |
209 | } | |
210 | if (CurN[1][2] < 0) { | |
211 | if (!Q.Line[2]) { DrawLine(Q[3], Q[2]); Q.Line[2] = true; }; | |
212 | if (!Q.Line[9]) { DrawLine(Q[2], Q[6]); Q.Line[9] = true; }; | |
213 | if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; }; | |
214 | if (!Q.Line[10]) { DrawLine(Q[7], Q[3]); Q.Line[10] = true; }; | |
215 | } | |
216 | if (CurN[2][2] < 0) { | |
217 | if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; }; | |
218 | if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; }; | |
219 | if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; }; | |
220 | if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; }; | |
221 | } | |
222 | if (CurN[3][2] < 0) { | |
223 | if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; }; | |
224 | if (!Q.Line[8]) { DrawLine(Q[5], Q[1]); Q.Line[8] = true; }; | |
225 | if (!Q.Line[0]) { DrawLine(Q[1], Q[0]); Q.Line[0] = true; }; | |
226 | if (!Q.Line[11]) { DrawLine(Q[0], Q[4]); Q.Line[11] = true; }; | |
227 | } | |
228 | if (CurN[4][2] < 0) { | |
229 | if (!Q.Line[11]) { DrawLine(Q[4], Q[0]); Q.Line[11] = true; }; | |
230 | if (!Q.Line[3]) { DrawLine(Q[0], Q[3]); Q.Line[3] = true; }; | |
231 | if (!Q.Line[10]) { DrawLine(Q[3], Q[7]); Q.Line[10] = true; }; | |
232 | if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; }; | |
233 | } | |
234 | if (CurN[5][2] < 0) { | |
235 | if (!Q.Line[8]) { DrawLine(Q[1], Q[5]); Q.Line[8] = true; }; | |
236 | if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; }; | |
237 | if (!Q.Line[9]) { DrawLine(Q[6], Q[2]); Q.Line[9] = true; }; | |
238 | if (!Q.Line[1]) { DrawLine(Q[2], Q[1]); Q.Line[1] = true; }; | |
239 | } | |
240 | Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false]; | |
241 | Q.LastPx = 0; | |
242 | } | |
243 | ||
244 | function Loop() { | |
245 | if (Testing.LoopCount > Testing.LoopMax) return; | |
246 | var TestingStr = String(Testing.LoopCount); | |
247 | while (TestingStr.length < 3) TestingStr = "0" + TestingStr; | |
248 | MTrans = Translate(I, -Q[8].V[0], -Q[8].V[1], -Q[8].V[2]); | |
249 | MTrans = RotateX(MTrans, 1); | |
250 | MTrans = RotateY(MTrans, 3); | |
251 | MTrans = RotateZ(MTrans, 5); | |
252 | MTrans = Translate(MTrans, Q[8].V[0], Q[8].V[1], Q[8].V[2]); | |
253 | MQube = MMulti(MTrans, MQube); | |
254 | var i = 8; | |
255 | for (; i > -1; i--) { | |
256 | Q[i].V = VMulti(MTrans, Q[i].V); | |
257 | } | |
258 | DrawQube(); | |
259 | Testing.LoopCount++; | |
260 | Loop(); | |
261 | } | |
262 | ||
263 | function Init(CubeSize) { | |
264 | // init/reset vars | |
265 | Origin.V = [150,150,20,1]; | |
266 | Testing.LoopCount = 0; | |
267 | Testing.LoopMax = 50; | |
268 | Testing.TimeMax = 0; | |
269 | Testing.TimeAvg = 0; | |
270 | Testing.TimeMin = 0; | |
271 | Testing.TimeTemp = 0; | |
272 | Testing.TimeTotal = 0; | |
273 | Testing.Init = false; | |
274 | ||
275 | // transformation matrix | |
276 | MTrans = [ | |
277 | [1,0,0,0], | |
278 | [0,1,0,0], | |
279 | [0,0,1,0], | |
280 | [0,0,0,1] | |
281 | ]; | |
282 | ||
283 | // position information of qube | |
284 | MQube = [ | |
285 | [1,0,0,0], | |
286 | [0,1,0,0], | |
287 | [0,0,1,0], | |
288 | [0,0,0,1] | |
289 | ]; | |
290 | ||
291 | // entity matrix | |
292 | I = [ | |
293 | [1,0,0,0], | |
294 | [0,1,0,0], | |
295 | [0,0,1,0], | |
296 | [0,0,0,1] | |
297 | ]; | |
298 | ||
299 | // create qube | |
300 | Q[0] = new CreateP(-CubeSize,-CubeSize, CubeSize); | |
301 | Q[1] = new CreateP(-CubeSize, CubeSize, CubeSize); | |
302 | Q[2] = new CreateP( CubeSize, CubeSize, CubeSize); | |
303 | Q[3] = new CreateP( CubeSize,-CubeSize, CubeSize); | |
304 | Q[4] = new CreateP(-CubeSize,-CubeSize,-CubeSize); | |
305 | Q[5] = new CreateP(-CubeSize, CubeSize,-CubeSize); | |
306 | Q[6] = new CreateP( CubeSize, CubeSize,-CubeSize); | |
307 | Q[7] = new CreateP( CubeSize,-CubeSize,-CubeSize); | |
308 | ||
309 | // center of gravity | |
310 | Q[8] = new CreateP(0, 0, 0); | |
311 | ||
312 | // anti-clockwise edge check | |
313 | Q.Edge = [[0,1,2],[3,2,6],[7,6,5],[4,5,1],[4,0,3],[1,5,6]]; | |
314 | ||
315 | // calculate squad normals | |
316 | Q.Normal = new Array(); | |
317 | for (var i = 0; i < Q.Edge.length; i++) Q.Normal[i] = CalcNormal(Q[Q.Edge[i][0]].V, Q[Q.Edge[i][1]].V, Q[Q.Edge[i][2]].V); | |
318 | ||
319 | // line drawn ? | |
320 | Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false]; | |
321 | ||
322 | // create line pixels | |
323 | Q.NumPx = 9 * 2 * CubeSize; | |
324 | for (var i = 0; i < Q.NumPx; i++) CreateP(0,0,0); | |
325 | ||
326 | MTrans = Translate(MTrans, Origin.V[0], Origin.V[1], Origin.V[2]); | |
327 | MQube = MMulti(MTrans, MQube); | |
328 | ||
329 | var i = 0; | |
330 | for (; i < 9; i++) { | |
331 | Q[i].V = VMulti(MTrans, Q[i].V); | |
332 | } | |
333 | DrawQube(); | |
334 | Testing.Init = true; | |
335 | Loop(); | |
336 | ||
337 | // Perform a simple sum-based verification. | |
338 | var sum = 0; | |
339 | for (var i = 0; i < Q.length; ++i) { | |
340 | var vector = Q[i].V; | |
341 | for (var j = 0; j < vector.length; ++j) | |
342 | sum += vector[j]; | |
343 | } | |
344 | if (sum != validation[CubeSize]) | |
345 | throw "Error: bad vector sum for CubeSize = " + CubeSize + "; expected " + validation[CubeSize] + " but got " + sum; | |
346 | } | |
347 | ||
348 | for ( var i = 20; i <= 160; i *= 2 ) { | |
349 | Init(i); | |
350 | } | |
351 | ||
352 | Q = null; | |
353 | MTrans = null; | |
354 | MQube = null; | |
355 | I = null; | |
356 | Origin = null; | |
357 | Testing = null; | |
358 | LoopTime = null; | |
359 | DisplArea = null; | |
360 | ||
361 | } catch (e) { | |
362 | print("JSC EXCEPTION FUZZ: Caught exception: " + e); | |
363 | } |