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