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