GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / native_client_sdk / src / gonacl_appengine / static / bullet / scene.js
blob9325f4d5da1c9eac500b03d0b4bb36da78fd7f14
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var container, stats;
6 var camera, controls, scene, projector, renderer;
7 var plane;
8 var lastSceneDescription;
9 var skipSceneUpdates = 0;
10 var hold = false;
11 var holdObjectIndex = -1;
13 var mouse = new THREE.Vector2();
14 var offset = new THREE.Vector3();
15 var INTERSECTED, SELECTED;
17 var sceneDescription = [];
19 var shapes = {};
20 var objects = [];
22 function clearWorld() {
23   for (var i = 0; i < objects.length; i++) {
24     scene.remove(objects[i]);
25   }
26   objects = [];
27   shapes = {};
28   // Make sure we drop the object.
29   hold = false;
30   SELECTED = undefined;
31   NaClAMBulletDropObject();
34 function loadShape(shape) {
35   if (shapes[shape.name] != undefined) {
36     return shapes[shape.name];
37   }
39   if (shape.type == "cube") {
40     shapes[shape.name] = new THREE.CubeGeometry(shape['wx'], shape['wy'], shape['wz']);
41     return shapes[shape.name];
42   }
44   if (shape.type == "convex") {
45     var vertices = [];
46     for (var i = 0; i < shape['points'].length; i++) {
47       vertices.push(new THREE.Vector3(shape['points'][i][0], shape['points'][i][1], shape['points'][i][2]));
48     }
49     shapes[shape.name] = new THREE.ConvexGeometry(vertices);
50     return shapes[shape.name];
51   }
53   if (shape.type == "cylinder") {
54     shapes[shape.name] = new THREE.CylinderGeometry(shape['radius'], shape['radius'], shape['height'])
55       return shapes[shape.name];
56   }
58   if (shape.type == "sphere") {
59     shapes[shape.name] = new THREE.SphereGeometry(shape['radius']);
60     return shapes[shape.name];
61   }
63   return undefined;
66 function loadBody(body) {
67   var shape = shapes[body.shape];
68   if (shape == undefined) {
69     return shape;
70   }
72   var object = new THREE.Mesh( shape, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
74   object.material.ambient = object.material.color;
76   object.position.x = body.position.x;
77   object.position.y = body.position.y;
78   object.position.z = body.position.z;
80   object.rotation.x = body.rotation.x;
81   object.rotation.y = body.rotation.y;
82   object.rotation.z = body.rotation.z;
84   object.updateMatrixWorld(true);
85   var T = [object.matrixWorld.elements[0],
86       object.matrixWorld.elements[1],
87       object.matrixWorld.elements[2],
88       object.matrixWorld.elements[3],
89       object.matrixWorld.elements[4],
90       object.matrixWorld.elements[5],
91       object.matrixWorld.elements[6],
92       object.matrixWorld.elements[7],
93       object.matrixWorld.elements[8],
94       object.matrixWorld.elements[9],
95       object.matrixWorld.elements[10],
96       object.matrixWorld.elements[11],
97       object.matrixWorld.elements[12],
98       object.matrixWorld.elements[13],
99       object.matrixWorld.elements[14],
100       object.matrixWorld.elements[15]];
101   body.transform = T;
103   object.castShadow = false;
104   object.receiveShadow = false;
105   object.matrixAutoUpdate = false;
106   object.objectTableIndex = objects.length;
107   scene.add(object);
108   objects.push(object);
110   return object;
113 function loadWorld(worldDescription) {
114   clearWorld();
115   var i;
116   var shapes = worldDescription['shapes'];
117   var bodies = worldDescription['bodies'];
118   for (i = 0; i < shapes.length; i++) {
119     if (loadShape(shapes[i]) == undefined) {
120       console.log('Could not load shape ' + shapes[i].name);
121     }
122   }
124   for (i = 0; i < bodies.length; i++) {
125     if (loadBody(bodies[i]) == undefined) {
126       console.log('Could not make body.');
127     }
128   }
130   var r = verifyWorldDescription(worldDescription);
131   if (r == false) {
132     alert('Invalid scene description. See console.');
133     return;
134   }
135   skipSceneUpdates = 4;
136   NaClAMBulletLoadScene(worldDescription);
137   lastSceneDescription = worldDescription;
140 function reloadScene() {
141   if (lastSceneDescription)
142     loadWorld(lastSceneDescription);
145 function $(id) {
146   return document.getElementById(id);
149 function init() {
150   var rendererContainer = $('rendererContainer');
151   var rcW = rendererContainer.clientWidth;
152   var rcH = rendererContainer.clientHeight;
154   camera = new THREE.PerspectiveCamera(
155       70,
156       rcW / rcH, 1, 10000);
157   camera.position.y = 20.0;
158   camera.position.z = 40;
160   scene = new THREE.Scene();
162   scene.add( new THREE.AmbientLight( 0x505050 ) );
164   var light = new THREE.SpotLight( 0xffffff, 1.5 );
165   light.position.set( 0, 500, 2000 );
166   light.castShadow = true;
168   light.shadowCameraNear = 200;
169   light.shadowCameraFar = camera.far;
170   light.shadowCameraFov = 50;
172   light.shadowBias = -0.00022;
173   light.shadowDarkness = 0.5;
175   light.shadowMapWidth = 2048;
176   light.shadowMapHeight = 2048;
178   scene.add( light );
180   plane = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200, 100, 100), new THREE.MeshBasicMaterial( { color: 0x000000, opacity: 0.25, transparent: true, wireframe: true } ) );
181   plane.rotation.x = Math.PI * 0.5;
182   plane.visible = true;
183   scene.add( plane );
184   projector = new THREE.Projector();
186   renderer = new THREE.WebGLRenderer( { antialias: true } );
187   renderer.sortObjects = false;
188   renderer.setSize( rcW, rcH );
189   lastRendererWidth = rcW;
190   lastRendererWidth = rcH;
192   renderer.shadowMapEnabled = true;
193   renderer.shadowMapSoft = true;
195   rendererContainer.appendChild(renderer.domElement);
197   var idFuncHash = {
198     jenga10: loadJenga10,
199     jenga20: loadJenga20,
200     randomShapes: loadRandomShapes,
201     randomCube250: load250RandomCubes,
202     randomCylinder500: load500RandomCylinders,
203     randomCube1000: load1000RandomCubes,
204     randomCube2000: load2000RandomCubes
205   };
207   for (var id in idFuncHash) {
208     var func = idFuncHash[id];
209     $(id).addEventListener('click', func, false);
210   }
212   $('reload').addEventListener('click', reloadScene, false);
214   rendererContainer.addEventListener('mousedown', onMouseDown, false);
215   rendererContainer.addEventListener('mouseup', onMouseUp, false);
216   rendererContainer.addEventListener('mouseleave', onMouseUp, false);
217   renderer.domElement.addEventListener('mousemove', onMouseMove, false);
219   // Add the OrbitControls after our own listeners -- that way we can prevent
220   // the camera rotation when dragging an object.
221   controls = new THREE.OrbitControls(camera, rendererContainer);
223   window.setInterval(pollForRendererResize, 10);
226 function pollForRendererResize() {
227   var rendererContainer = $('rendererContainer');
228   var w = rendererContainer.clientWidth;
229   var h = rendererContainer.clientHeight;
230   if (w == lastRendererWidth && h == lastRendererHeight)
231     return;
233   camera.aspect = w / h;
234   camera.updateProjectionMatrix();
235   renderer.setSize( w, h );
236   lastRendererWidth = w;
237   lastRendererHeight = h;
240 function onMouseDown(event) {
241   event.preventDefault();
243   var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
244   projector.unprojectVector( vector, camera );
245   var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
246   var intersects = ray.intersectObjects( objects );
247   if (intersects.length > 0) {
248     if (intersects[0].object != plane) {
249       hold = true;
250       SELECTED = intersects[0].object;
251       //console.log(SELECTED.objectTableIndex);
252       NaClAMBulletPickObject(SELECTED.objectTableIndex, camera.position, intersects[0].point);
253       // stopImmediatePropagation() will prevent other event listeners on the
254       // same element from firing -- in this case, the OrbitControls camera
255       // rotation.
256       event.stopImmediatePropagation();
257     }
258   }
261 function onMouseUp(event) {
262   if (hold) {
263     hold = false;
264     SELECTED = undefined;
265     NaClAMBulletDropObject();
266     event.stopImmediatePropagation();
267   }
270 function onMouseMove( event ) {
271   event.preventDefault();
273   var clientRect = $('rendererContainer').getClientRects()[0];
274   var x = event.clientX - clientRect.left;
275   var y = event.clientY - clientRect.top;
276   var w = clientRect.width;
277   var h = clientRect.height;
279   mouse.x = ( x / w ) * 2 - 1;
280   mouse.y = -( y / h ) * 2 + 1;
281   var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
282   projector.unprojectVector( vector, camera );
283   offset.x = vector.x;
284   offset.y = vector.y;
285   offset.z = vector.z;
290 function animate() {
291   window.requestAnimationFrame(animate);
292   aM.sendMessage('stepscene', {rayFrom: [camera.position.x, camera.position.y, camera.position.z], rayTo: [offset.x, offset.y, offset.z]});
293   render();
296 function render() {
297   controls.update();
298   renderer.render( scene, camera );