{"__browser":{"country":"US","device":"unknown_device","mobile":false,"name":"unknown browser","platform":"unknown_platform","version":"0"},"__constants":{},"__CPDATA":{"domain_iframe":"https://cdpn.io","environment":"production","host":"codepen.io","iframe_allow":"accelerometer *; ambient-light-sensor *; camera *; display-capture *; encrypted-media *; geolocation *; gyroscope *; microphone *; midi *; payment *; vr *; web-share *; serial *; xr-spatial-tracking *","iframe_sandbox":"allow-downloads allow-forms allow-modals allow-pointer-lock allow-popups-to-escape-sandbox allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation"},"__graphql":{"data":{"data":{"sessionUser":{"id":"VoDkNZ","name":"Captain Anonymous","title":"Captain Anonymous","avatar":"https://assets.codepen.io/t-1/user-default-avatar.jpg?format=auto&version=0","currentContext":{"id":"VoDkNZ","title":"Captain Anonymous","name":"Captain Anonymous","avatar":"https://assets.codepen.io/t-1/user-default-avatar.jpg?format=auto&version=0","username":"anon","__typename":"User"},"currentTeamId":null,"username":"anon","admin":false,"anon":true,"pro":false,"verified":false,"featureFlags":[],"teams":[],"__typename":"User"}}},"url":"https://codepen.io/graphql","api":"cprails"},"__user":{"anon":true,"base_url":"/anon/","cohorts":[],"current_team_hashid":null,"current_team_id":0,"hashid":"VoDkNZ","id":1,"itemType":"user","name":"Captain Anonymous","paid":false,"tier":0,"username":"anon","created_at":null,"email_verified":null,"collections_count":0,"collections_private_count":0,"followers_count":0,"followings_count":0,"pens_count":0,"pens_private_count":0,"projects_count":0,"projects_private_count":0},"__firebase":{"config":{"apiKey":"AIzaSyBgLAe7N_MdFpuVofMkcQLGwwhUu5tuxls","authDomain":"codepen-store-production.firebaseapp.com","databaseURL":"https://codepen-store-production.firebaseio.com","disabled":false,"projectId":"codepen-store-production"},"token":"eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL2lkZW50aXR5dG9vbGtpdC5nb29nbGVhcGlzLmNvbS9nb29nbGUuaWRlbnRpdHkuaWRlbnRpdHl0b29sa2l0LnYxLklkZW50aXR5VG9vbGtpdCIsImNsYWltcyI6eyJvd25lcklkIjoiVm9Ea05aIiwiYWRtaW4iOmZhbHNlfSwiZXhwIjoxNzI2NTk0ODU5LCJpYXQiOjE3MjY1OTEyNTksImlzcyI6ImZpcmViYXNlLWFkbWluc2RrLThva3lsQGNvZGVwZW4tc3RvcmUtcHJvZHVjdGlvbi5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInN1YiI6ImZpcmViYXNlLWFkbWluc2RrLThva3lsQGNvZGVwZW4tc3RvcmUtcHJvZHVjdGlvbi5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInVpZCI6IlZvRGtOWiJ9.SoJsB-_RIYZM5gqy4MTy0QwDFeLl9MEecberR1MghEEqtoS_ydUrY5j-gXTeqHXBY1i2Bltn-kwSHhx3t9THPqwbVxSDgHUqtscn9Mp5aPrFHhh-QZx1Ixu224yCabCay6_TfREJbZa2HcdEAA3EcgXn8YXpCTnTiD8gXfHR-F8eNVTvXVQni1JL_nThfwakVLRwufAG-OfeEqMcLorXQws2ayf2TCq2X00dc_t5MBfDsJs_dZrqhXphYbwxgALBW3_tNPob7e8ignRGtmmMIg8m7D5XdUua1BTtYV6OHBMwnJU1lZerBrktk0dffrpTAqPcJlA7sWV266F-0ZGLaw"},"__pay_stripe_public_key":"pk_live_2GndomDfiklqpSNQn8FrGuwZSMIMzha7DkLJqlYe7IR0ihKAlKdiHg68JJc5eVPt68rzAjzAAVXcUwjySHRCsgjQQ00gtRBUFNH","__pay_braintree_env":"production","__item":"{\"id\":28675948,\"user_id\":409445,\"html\":\"\\n<!------- TRANSITION PAGES ------->\\n\\n<div id=\\\"landing_page_div\\\" class=\\\"display_page\\\">\\n <div id=\\\"landing_logo_div\\\">\\n <img id=\\\"logo_landing\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_derby_logo.svg\\\">\\n <img id=\\\"button_play\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_play.svg\\\">\\n <\\/div>\\n<\\/div>\\n\\n<!-- animated loader page -->\\n<div id=\\\"loading_animation_page\\\" class=\\\"display_page\\\">\\n <div id=\\\"loading_animation_div\\\">\\n <svg id=\\\"loading_animation_svg\\\" viewBox=\\\"0 0 100 100\\\">\\n <line class=\\\"loading_animation_lines\\\" id=\\\"loading_animation_line_1\\\" x1=5% y1=45% x2=95% y2=45% \\/>\\n <line class=\\\"loading_animation_lines\\\" id=\\\"loading_animation_line_2\\\" x1=5% y1=50% x2=95% y2=50% \\/>\\n <line class=\\\"loading_animation_lines\\\" id=\\\"loading_animation_line_3\\\" x1=19% y1=55% x2=81% y2=55% \\/>\\n <\\/svg>\\n <img id=\\\"loading_animation_insignia\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_insignia.svg\\\">\\n <\\/div>\\n<\\/div>\\n\\n<!-- round win announcement page -->\\n<div id=\\\"round_win_page_div\\\" class=\\\"display_page announcement_page\\\">\\n <div id=\\\"round_win_card_div\\\" class=\\\"card_div\\\"> \\n <img id=\\\"round_win_card\\\" class=\\\"card\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_round_win_card_gretchen.svg\\\">\\n <img id=\\\"round_score_green\\\" class=\\\"round_score green_score\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_1of3_green.svg\\\">\\n <img id=\\\"round_score_red\\\" class=\\\"round_score red_score\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_0of3_red.svg\\\">\\n <img id=\\\"button_play_next_round\\\" class=\\\"card_button\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_play_next_round.svg\\\">\\n <\\/div>\\n<\\/div>\\n\\n<!-- round draw announcement page -->\\n<div id=\\\"round_draw_page_div\\\" class=\\\"display_page announcement_page\\\">\\n <div id=\\\"round_draw_card_div\\\" class=\\\"card_div\\\"> \\n <img id=\\\"round_draw_card\\\" class=\\\"card\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_round_draw_card.svg\\\">\\n <img id=\\\"button_replay_round\\\" class=\\\"card_button\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_replay_round.svg\\\">\\n <\\/div>\\n<\\/div>\\n\\n<!-- game win announcement pages -->\\n<div id=\\\"game_win_gretchen_page_div\\\" class=\\\"display_page announcement_page\\\">\\n <div id=\\\"game_win_gretchen_card_div\\\" class=\\\"card_div\\\"> \\n <img id=\\\"game_win_gretchen_card\\\" class=\\\"card\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_game_win_card_gretchen.svg\\\">\\n <img class=\\\"card_button button_new_game\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_new_game.svg\\\">\\n <\\/div>\\n<\\/div>\\n\\n<div id=\\\"game_win_bertha_page_div\\\" class=\\\"display_page announcement_page\\\">\\n <div id=\\\"game_win_bertha_card_div\\\" class=\\\"card_div\\\"> \\n <img id=\\\"game_win_bertha_card\\\" class=\\\"card\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_game_win_card_bertha.svg\\\">\\n <img class=\\\"card_button button_new_game\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_new_game.svg\\\">\\n <\\/div>\\n<\\/div>\\n\\n\\n\\n\\n<!------- UI ------->\\n\\n<!-- logo -->\\n<div id=\\\"logo_div\\\">\\n <img id=\\\"logo\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_derby_logo.svg\\\">\\n <a href=\\\"https:\\/\\/matthewma.in\\\" target=\\\"_blank\\\"><img id=\\\"copyright\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_copyright.svg\\\"><\\/a>\\n<\\/div>\\n\\n\\n<!-- scoreboard -->\\n<div id=\\\"scoreboard_div\\\">\\n <img id=\\\"scoreboard_img\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_scoreboard.svg\\\">\\n <img id=\\\"board_score_green\\\" class=\\\"board_score green_score\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_0of3_green.svg\\\">\\n <img id=\\\"board_score_red\\\" class=\\\"board_score red_score\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_0of3_red.svg\\\">\\n<\\/div>\\n\\n<!-- buttons -->\\n<div id=\\\"buttons_div\\\">\\n <img id=\\\"button_restart\\\" class=\\\"buttons_items button_restart\\\" title=\\\"restart the game\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_restart.svg\\\">\\n <img class=\\\"buttons_items button_divider\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_divider.svg\\\">\\n <img id=\\\"button_draw\\\" class=\\\"buttons_items button_draw\\\" title=\\\"declare match a draw\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_button_draw.svg\\\">\\n<\\/div>\\n\\n<!-- nav -->\\n<img class=\\\"nav left_nav\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_nav_left.svg\\\">\\n<img class=\\\"nav right_nav\\\" src=\\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_nav_right.svg\\\">\\n\\n\\n\\n<!------- LIBRARIES ------->\\n\\n<!-- jQuery source -->\\n<script src=\\\"https:\\/\\/ajax.googleapis.com\\/ajax\\/libs\\/jquery\\/3.3.1\\/jquery.min.js\\\"><\\/script>\\n<!-- three.js source -->\\n<script src='https:\\/\\/assets.codepen.io\\/409445\\/three.min.js'><\\/script>\\n<!-- GLTFLoader.js source -->\\n<script src=\\\"https:\\/\\/assets.codepen.io\\/409445\\/GLTFLoader.js\\\"><\\/script>\\n<!-- physi.js source -->\\n<script src=\\\"https:\\/\\/assets.codepen.io\\/409445\\/physi.js\\\"><\\/script>\\n<!-- full physijs_worker.js contents in a script (necessary so that worker can be used in codepen) -->\\n<script id=\\\"physijs_worker\\\" type=\\\"javascript\\/worker\\\">\\n \\n \\nvar\\ttransferableMessage = self.webkitPostMessage || self.postMessage,\\n\\t\\n\\t\\/\\/ enum\\n\\tMESSAGE_TYPES = {\\n\\t\\tWORLDREPORT: 0,\\n\\t\\tCOLLISIONREPORT: 1,\\n\\t\\tVEHICLEREPORT: 2,\\n\\t\\tCONSTRAINTREPORT: 3\\n\\t},\\n\\t\\n\\t\\/\\/ temp variables\\n\\t_object,\\n\\t_vector,\\n\\t_transform,\\n\\t\\n\\t\\/\\/ functions\\n\\tpublic_functions = {},\\n\\tgetShapeFromCache,\\n\\tsetShapeCache,\\n\\tcreateShape,\\n\\treportWorld,\\n\\treportVehicles,\\n\\treportCollisions,\\n\\treportConstraints,\\n\\t\\n\\t\\/\\/ world variables\\n\\tfixedTimeStep, \\/\\/ used when calling stepSimulation\\n\\trateLimit, \\/\\/ sets whether or not to sync the simulation rate with fixedTimeStep\\n\\tlast_simulation_time,\\n\\tlast_simulation_duration = 0,\\n\\tworld,\\n\\ttransform,\\n\\t_vec3_1,\\n\\t_vec3_2,\\n\\t_vec3_3,\\n\\t_quat,\\n\\t\\/\\/ private cache\\n\\t_objects = {},\\n\\t_vehicles = {},\\n\\t_constraints = {},\\n\\t_materials = {},\\n\\t_objects_ammo = {},\\n\\t_num_objects = 0,\\n\\t_num_wheels = 0,\\n\\t_num_constraints = 0,\\n\\t_object_shapes = {},\\n\\n\\t\\/\\/ The following objects are to track objects that ammo.js doesn't clean\\n\\t\\/\\/ up. All are cleaned up when they're corresponding body is destroyed.\\n\\t\\/\\/ Unfortunately, it's very difficult to get at these objects from the\\n\\t\\/\\/ body, so we have to track them ourselves.\\n\\t_motion_states = {}, \\n\\t\\/\\/ Don't need to worry about it for cached shapes.\\n _noncached_shapes = {},\\n\\t\\/\\/ A body with a compound shape always has a regular shape as well, so we\\n\\t\\/\\/ have track them separately.\\n _compound_shapes = {}, \\n\\t\\n\\t\\/\\/ object reporting\\n\\tREPORT_CHUNKSIZE, \\/\\/ report array is increased in increments of this chunk size\\n\\t\\n\\tWORLDREPORT_ITEMSIZE = 14, \\/\\/ how many float values each reported item needs\\n\\tworldreport,\\n\\n\\tCOLLISIONREPORT_ITEMSIZE = 5, \\/\\/ one float for each object id, and a Vec3 contact normal\\n\\tcollisionreport,\\n\\n\\tVEHICLEREPORT_ITEMSIZE = 9, \\/\\/ vehicle id, wheel index, 3 for position, 4 for rotation\\n\\tvehiclereport,\\n\\n\\tCONSTRAINTREPORT_ITEMSIZE = 6, \\/\\/ constraint id, offset object, offset, applied impulse\\n\\tconstraintreport;\\n\\nvar ab = new ArrayBuffer( 1 );\\n\\ntransferableMessage( ab, [ab] );\\nvar SUPPORT_TRANSFERABLE = ( ab.byteLength === 0 );\\n\\ngetShapeFromCache = function ( cache_key ) {\\n\\tif ( _object_shapes[ cache_key ] !== undefined ) {\\n\\t\\treturn _object_shapes[ cache_key ];\\n\\t}\\n\\treturn null;\\n};\\n\\nsetShapeCache = function ( cache_key, shape ) {\\n\\t_object_shapes[ cache_key ] = shape;\\n}\\n\\ncreateShape = function( description ) {\\n\\tvar cache_key, shape;\\n\\t\\n\\t_transform.setIdentity();\\n\\tswitch ( description.type ) {\\n\\t\\tcase 'plane':\\n\\t\\t\\tcache_key = 'plane_' + description.normal.x + '_' + description.normal.y + '_' + description.normal.z;\\n\\t\\t\\tif ( ( shape = getShapeFromCache( cache_key ) ) === null ) {\\n\\t\\t\\t\\t_vec3_1.setX(description.normal.x);\\n\\t\\t\\t\\t_vec3_1.setY(description.normal.y);\\n\\t\\t\\t\\t_vec3_1.setZ(description.normal.z);\\n\\t\\t\\t\\tshape = new Ammo.btStaticPlaneShape(_vec3_1, 0 );\\n\\t\\t\\t\\tsetShapeCache( cache_key, shape );\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'box':\\n\\t\\t\\tcache_key = 'box_' + description.width + '_' + description.height + '_' + description.depth;\\n\\t\\t\\tif ( ( shape = getShapeFromCache( cache_key ) ) === null ) {\\n\\t\\t\\t\\t_vec3_1.setX(description.width \\/ 2);\\n\\t\\t\\t\\t_vec3_1.setY(description.height \\/ 2);\\n\\t\\t\\t\\t_vec3_1.setZ(description.depth \\/ 2);\\n\\t\\t\\t\\tshape = new Ammo.btBoxShape(_vec3_1);\\n\\t\\t\\t\\tsetShapeCache( cache_key, shape );\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'sphere':\\n\\t\\t\\tcache_key = 'sphere_' + description.radius;\\n\\t\\t\\tif ( ( shape = getShapeFromCache( cache_key ) ) === null ) {\\n\\t\\t\\t\\tshape = new Ammo.btSphereShape( description.radius );\\n\\t\\t\\t\\tsetShapeCache( cache_key, shape );\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'cylinder':\\n\\t\\t\\tcache_key = 'cylinder_' + description.width + '_' + description.height + '_' + description.depth;\\n\\t\\t\\tif ( ( shape = getShapeFromCache( cache_key ) ) === null ) {\\n\\t\\t\\t\\t_vec3_1.setX(description.width \\/ 2);\\n\\t\\t\\t\\t_vec3_1.setY(description.height \\/ 2);\\n\\t\\t\\t\\t_vec3_1.setZ(description.depth \\/ 2);\\n\\t\\t\\t\\tshape = new Ammo.btCylinderShape(_vec3_1);\\n\\t\\t\\t\\tsetShapeCache( cache_key, shape );\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'capsule':\\n\\t\\t\\tcache_key = 'capsule_' + description.radius + '_' + description.height;\\n\\t\\t\\tif ( ( shape = getShapeFromCache( cache_key ) ) === null ) {\\n\\t\\t\\t\\t\\/\\/ In Bullet, capsule height excludes the end spheres\\n\\t\\t\\t\\tshape = new Ammo.btCapsuleShape( description.radius, description.height - 2 * description.radius );\\n\\t\\t\\t\\tsetShapeCache( cache_key, shape );\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'cone':\\n\\t\\t\\tcache_key = 'cone_' + description.radius + '_' + description.height;\\n\\t\\t\\tif ( ( shape = getShapeFromCache( cache_key ) ) === null ) {\\n\\t\\t\\t\\tshape = new Ammo.btConeShape( description.radius, description.height );\\n\\t\\t\\t\\tsetShapeCache( cache_key, shape );\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'concave':\\n\\t\\t\\tvar i, triangle, triangle_mesh = new Ammo.btTriangleMesh;\\n\\t\\t\\tif (!description.triangles.length) return false\\n\\n\\t\\t\\tfor ( i = 0; i < description.triangles.length; i++ ) {\\n\\t\\t\\t\\ttriangle = description.triangles[i];\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_1.setX(triangle[0].x);\\n\\t\\t\\t\\t_vec3_1.setY(triangle[0].y);\\n\\t\\t\\t\\t_vec3_1.setZ(triangle[0].z);\\n\\n\\t\\t\\t\\t_vec3_2.setX(triangle[1].x);\\n\\t\\t\\t\\t_vec3_2.setY(triangle[1].y);\\n\\t\\t\\t\\t_vec3_2.setZ(triangle[1].z);\\n\\n\\t\\t\\t\\t_vec3_3.setX(triangle[2].x);\\n\\t\\t\\t\\t_vec3_3.setY(triangle[2].y);\\n\\t\\t\\t\\t_vec3_3.setZ(triangle[2].z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\ttriangle_mesh.addTriangle(\\n\\t\\t\\t\\t\\t_vec3_1,\\n\\t\\t\\t\\t\\t_vec3_2,\\n\\t\\t\\t\\t\\t_vec3_3,\\n\\t\\t\\t\\t\\ttrue\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\n\\t\\t\\tshape = new Ammo.btBvhTriangleMeshShape(\\n\\t\\t\\t\\ttriangle_mesh,\\n\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\ttrue\\n\\t\\t\\t);\\n\\t\\t\\t_noncached_shapes[description.id] = shape;\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'convex':\\n\\t\\t\\tvar i, point, shape = new Ammo.btConvexHullShape;\\n\\t\\t\\tfor ( i = 0; i < description.points.length; i++ ) {\\n\\t\\t\\t\\tpoint = description.points[i];\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_1.setX(point.x);\\n\\t\\t\\t\\t_vec3_1.setY(point.y);\\n\\t\\t\\t\\t_vec3_1.setZ(point.z);\\n\\n\\t\\t\\t\\tshape.addPoint(_vec3_1);\\n\\t\\t\\t\\t\\n\\t\\t\\t}\\n\\t\\t\\t_noncached_shapes[description.id] = shape;\\n\\t\\t\\tbreak;\\n\\n\\t\\tcase 'heightfield':\\n\\n\\t\\t\\tvar ptr = Ammo.allocate(4 * description.xpts * description.ypts, \\\"float\\\", Ammo.ALLOC_NORMAL);\\n\\n\\t\\t\\tfor (var f = 0; f < description.points.length; f++) {\\n\\t\\t\\t\\tAmmo.setValue(ptr + f, description.points[f] , 'float');\\n\\t\\t\\t}\\n\\n\\t\\t\\tshape = new Ammo.btHeightfieldTerrainShape(\\n\\t\\t\\t\\t\\tdescription.xpts,\\n\\t\\t\\t\\t\\tdescription.ypts,\\n\\t\\t\\t\\t\\tptr,\\n\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t-description.absMaxHeight,\\n\\t\\t\\t\\t\\tdescription.absMaxHeight,\\n\\t\\t\\t\\t\\t2,\\n\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\tfalse\\n\\t\\t\\t\\t);\\n\\n\\t\\t\\t_vec3_1.setX(description.xsize\\/(description.xpts - 1));\\n\\t\\t\\t_vec3_1.setY(description.ysize\\/(description.ypts - 1));\\n\\t\\t\\t_vec3_1.setZ(1);\\n\\t\\t\\t\\n\\t\\t\\tshape.setLocalScaling(_vec3_1);\\n\\t\\t\\t_noncached_shapes[description.id] = shape;\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tdefault:\\n\\t\\t\\t\\/\\/ Not recognized\\n\\t\\t\\treturn;\\n\\t\\t\\tbreak;\\n\\t}\\n\\t\\n\\treturn shape;\\n};\\n\\npublic_functions.init = function( params ) {\\n\\timportScripts( params.ammo );\\n\\t\\n\\t_transform = new Ammo.btTransform;\\n\\t_vec3_1 = new Ammo.btVector3(0,0,0);\\n\\t_vec3_2 = new Ammo.btVector3(0,0,0);\\n\\t_vec3_3 = new Ammo.btVector3(0,0,0);\\n\\t_quat = new Ammo.btQuaternion(0,0,0,0);\\n\\t\\n\\tREPORT_CHUNKSIZE = params.reportsize || 50;\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\t\\/\\/ Transferable messages are supported, take advantage of them with TypedArrays\\n\\t\\tworldreport = new Float32Array(2 + REPORT_CHUNKSIZE * WORLDREPORT_ITEMSIZE); \\/\\/ message id + # of objects to report + chunk size * # of values per object\\n\\t\\tcollisionreport = new Float32Array(2 + REPORT_CHUNKSIZE * COLLISIONREPORT_ITEMSIZE); \\/\\/ message id + # of collisions to report + chunk size * # of values per object\\n\\t\\tvehiclereport = new Float32Array(2 + REPORT_CHUNKSIZE * VEHICLEREPORT_ITEMSIZE); \\/\\/ message id + # of vehicles to report + chunk size * # of values per object\\n\\t\\tconstraintreport = new Float32Array(2 + REPORT_CHUNKSIZE * CONSTRAINTREPORT_ITEMSIZE); \\/\\/ message id + # of constraints to report + chunk size * # of values per object\\n\\t} else {\\n\\t\\t\\/\\/ Transferable messages are not supported, send data as normal arrays\\n\\t\\tworldreport = [];\\n\\t\\tcollisionreport = [];\\n\\t\\tvehiclereport = [];\\n\\t\\tconstraintreport = [];\\n\\t}\\n\\tworldreport[0] = MESSAGE_TYPES.WORLDREPORT;\\n\\tcollisionreport[0] = MESSAGE_TYPES.COLLISIONREPORT;\\n\\tvehiclereport[0] = MESSAGE_TYPES.VEHICLEREPORT;\\n\\tconstraintreport[0] = MESSAGE_TYPES.CONSTRAINTREPORT;\\n\\t\\n\\tvar collisionConfiguration = new Ammo.btDefaultCollisionConfiguration,\\n\\t\\tdispatcher = new Ammo.btCollisionDispatcher( collisionConfiguration ),\\n\\t\\tsolver = new Ammo.btSequentialImpulseConstraintSolver,\\n\\t\\tbroadphase;\\n\\t\\n\\tif ( !params.broadphase ) params.broadphase = { type: 'dynamic' };\\n\\tswitch ( params.broadphase.type ) {\\n\\t\\tcase 'sweepprune':\\n\\t\\t\\t\\n\\t\\t\\t_vec3_1.setX(params.broadphase.aabbmin.x);\\n\\t\\t\\t_vec3_1.setY(params.broadphase.aabbmin.y);\\n\\t\\t\\t_vec3_1.setZ(params.broadphase.aabbmin.z);\\n\\t\\t\\t\\n\\t\\t\\t_vec3_2.setX(params.broadphase.aabbmax.x);\\n\\t\\t\\t_vec3_2.setY(params.broadphase.aabbmax.y);\\n\\t\\t\\t_vec3_2.setZ(params.broadphase.aabbmax.z);\\n\\t\\t\\t\\n\\t\\t\\tbroadphase = new Ammo.btAxisSweep3(\\n\\t\\t\\t\\t_vec3_1,\\n\\t\\t\\t\\t_vec3_2\\n\\t\\t\\t);\\n\\t\\t\\t\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'dynamic':\\n\\t\\tdefault:\\n\\t\\t\\tbroadphase = new Ammo.btDbvtBroadphase;\\n\\t\\t\\tbreak;\\n\\t}\\n\\t\\n\\tworld = new Ammo.btDiscreteDynamicsWorld( dispatcher, broadphase, solver, collisionConfiguration );\\n\\t\\n\\tfixedTimeStep = params.fixedTimeStep;\\n\\trateLimit = params.rateLimit;\\n\\n\\ttransferableMessage({ cmd: 'worldReady' });\\n};\\n\\npublic_functions.registerMaterial = function( description ) {\\n\\t_materials[ description.id ] = description;\\n};\\n\\npublic_functions.unRegisterMaterial = function( description ) {\\n\\tdelete _materials[ description.id ];\\n};\\n\\npublic_functions.setFixedTimeStep = function( description ) {\\n\\tfixedTimeStep = description;\\n};\\n\\npublic_functions.setGravity = function( description ) {\\n\\t_vec3_1.setX(description.x);\\n\\t_vec3_1.setY(description.y);\\n\\t_vec3_1.setZ(description.z);\\n\\tworld.setGravity(_vec3_1);\\n};\\n\\npublic_functions.addObject = function( description ) {\\n\\t\\n\\tvar i,\\n\\tlocalInertia, shape, motionState, rbInfo, body;\\n\\nshape = createShape( description );\\nif (!shape) return\\n\\/\\/ If there are children then this is a compound shape\\nif ( description.children ) {\\n\\tvar compound_shape = new Ammo.btCompoundShape, _child;\\n\\tcompound_shape.addChildShape( _transform, shape );\\n\\t\\n\\tfor ( i = 0; i < description.children.length; i++ ) {\\n\\t\\t_child = description.children[i];\\n\\t\\t\\n\\t\\tvar trans = new Ammo.btTransform;\\n\\t\\ttrans.setIdentity();\\n\\t\\t\\n\\t\\t_vec3_1.setX(_child.position_offset.x);\\n\\t\\t_vec3_1.setY(_child.position_offset.y);\\n\\t\\t_vec3_1.setZ(_child.position_offset.z);\\n\\t\\ttrans.setOrigin(_vec3_1); \\n\\t\\t\\n\\t\\t_quat.setX(_child.rotation.x);\\n\\t\\t_quat.setY(_child.rotation.y);\\n\\t\\t_quat.setZ(_child.rotation.z);\\n\\t\\t_quat.setW(_child.rotation.w);\\n\\t\\ttrans.setRotation(_quat); \\n\\t\\t\\n\\t\\tshape = createShape( description.children[i] );\\n\\t\\tcompound_shape.addChildShape( trans, shape );\\n\\t\\tAmmo.destroy(trans);\\n\\t}\\n\\t\\n\\tshape = compound_shape;\\n _compound_shapes[ description.id ] = shape;\\n\\t}\\n\\t_vec3_1.setX(0);\\n\\t_vec3_1.setY(0);\\n\\t_vec3_1.setZ(0);\\n\\tshape.calculateLocalInertia( description.mass, _vec3_1 );\\n\\t\\n\\t_transform.setIdentity();\\n\\t\\n\\t_vec3_2.setX(description.position.x);\\n\\t_vec3_2.setY(description.position.y);\\n\\t_vec3_2.setZ(description.position.z);\\n\\t_transform.setOrigin(_vec3_2);\\n\\t\\n\\t_quat.setX(description.rotation.x);\\n\\t_quat.setY(description.rotation.y);\\n\\t_quat.setZ(description.rotation.z);\\n\\t_quat.setW(description.rotation.w);\\n\\t_transform.setRotation(_quat);\\n\\t\\n\\tmotionState = new Ammo.btDefaultMotionState( _transform ); \\/\\/ #TODO: btDefaultMotionState supports center of mass offset as second argument - implement\\n\\trbInfo = new Ammo.btRigidBodyConstructionInfo( description.mass, motionState, shape, _vec3_1 );\\n\\t\\n\\tif ( description.materialId !== undefined ) {\\n\\t\\trbInfo.set_m_friction( _materials[ description.materialId ].friction );\\n\\t\\trbInfo.set_m_restitution( _materials[ description.materialId ].restitution );\\n\\t}\\n\\t\\n\\tbody = new Ammo.btRigidBody( rbInfo );\\n\\tAmmo.destroy(rbInfo);\\n\\t\\n\\tif ( typeof description.collision_flags !== 'undefined' ) {\\n\\t\\tbody.setCollisionFlags( description.collision_flags );\\n\\t}\\n\\t\\n\\tworld.addRigidBody( body );\\n\\t\\n\\tbody.id = description.id;\\n\\t_objects[ body.id ] = body;\\n\\t_motion_states[ body.id ] = motionState;\\n\\t\\n\\tvar ptr = body.a != undefined ? body.a : body.ptr;\\n\\t_objects_ammo[ptr] = body.id;\\n\\t_num_objects++;\\n\\t\\n\\ttransferableMessage({ cmd: 'objectReady', params: body.id });\\n};\\n\\npublic_functions.addVehicle = function( description ) {\\n\\tvar vehicle_tuning = new Ammo.btVehicleTuning(),\\n\\t\\tvehicle;\\n\\n\\tvehicle_tuning.set_m_suspensionStiffness( description.suspension_stiffness );\\n\\tvehicle_tuning.set_m_suspensionCompression( description.suspension_compression );\\n\\tvehicle_tuning.set_m_suspensionDamping( description.suspension_damping );\\n\\tvehicle_tuning.set_m_maxSuspensionTravelCm( description.max_suspension_travel );\\n\\tvehicle_tuning.set_m_maxSuspensionForce( description.max_suspension_force );\\n\\n\\tvehicle = new Ammo.btRaycastVehicle( vehicle_tuning, _objects[ description.rigidBody ], new Ammo.btDefaultVehicleRaycaster( world ) );\\n\\tvehicle.tuning = vehicle_tuning;\\n\\n\\t_objects[ description.rigidBody ].setActivationState( 4 );\\n\\tvehicle.setCoordinateSystem( 0, 1, 2 );\\n\\n\\tworld.addVehicle( vehicle );\\n\\t_vehicles[ description.id ] = vehicle;\\n};\\npublic_functions.removeVehicle = function( description ) {\\n\\tdelete _vehicles[ description.id ];\\n};\\n\\npublic_functions.addWheel = function( description ) {\\n\\tif ( _vehicles[description.id] !== undefined ) {\\n\\t\\tvar tuning = _vehicles[description.id].tuning;\\n\\t\\tif ( description.tuning !== undefined ) {\\n\\t\\t\\ttuning = new Ammo.btVehicleTuning();\\n\\t\\t\\ttuning.set_m_suspensionStiffness( description.tuning.suspension_stiffness );\\n\\t\\t\\ttuning.set_m_suspensionCompression( description.tuning.suspension_compression );\\n\\t\\t\\ttuning.set_m_suspensionDamping( description.tuning.suspension_damping );\\n\\t\\t\\ttuning.set_m_maxSuspensionTravelCm( description.tuning.max_suspension_travel );\\n\\t\\t\\ttuning.set_m_maxSuspensionForce( description.tuning.max_suspension_force );\\n\\t\\t}\\n\\t\\t\\n\\t\\t_vec3_1.setX(description.connection_point.x);\\n\\t\\t_vec3_1.setY(description.connection_point.y);\\n\\t\\t_vec3_1.setZ(description.connection_point.z);\\n\\t\\t\\n\\t\\t_vec3_2.setX(description.wheel_direction.x);\\n\\t\\t_vec3_2.setY(description.wheel_direction.y);\\n\\t\\t_vec3_2.setZ(description.wheel_direction.z);\\n\\t\\t\\n\\t\\t_vec3_3.setX(description.wheel_axle.x);\\n\\t\\t_vec3_3.setY(description.wheel_axle.y);\\n\\t\\t_vec3_3.setZ(description.wheel_axle.z);\\n\\t\\t\\n\\t\\t_vehicles[description.id].addWheel(\\n\\t\\t\\t_vec3_1,\\n\\t\\t\\t_vec3_2,\\n\\t\\t\\t_vec3_3,\\n\\t\\t\\tdescription.suspension_rest_length,\\n\\t\\t\\tdescription.wheel_radius,\\n\\t\\t\\ttuning,\\n\\t\\t\\tdescription.is_front_wheel\\n\\t\\t);\\n\\t}\\n\\n\\t_num_wheels++;\\n\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\tvehiclereport = new Float32Array(1 + _num_wheels * VEHICLEREPORT_ITEMSIZE); \\/\\/ message id & ( # of objects to report * # of values per object )\\n\\t\\tvehiclereport[0] = MESSAGE_TYPES.VEHICLEREPORT;\\n\\t} else {\\n\\t\\tvehiclereport = [ MESSAGE_TYPES.VEHICLEREPORT ];\\n\\t}\\n};\\n\\npublic_functions.setSteering = function( details ) {\\n\\tif ( _vehicles[details.id] !== undefined ) {\\n\\t\\t_vehicles[details.id].setSteeringValue( details.steering, details.wheel );\\n\\t}\\n};\\npublic_functions.setBrake = function( details ) {\\n\\tif ( _vehicles[details.id] !== undefined ) {\\n\\t\\t_vehicles[details.id].setBrake( details.brake, details.wheel );\\n\\t}\\n};\\npublic_functions.applyEngineForce = function( details ) {\\n\\tif ( _vehicles[details.id] !== undefined ) {\\n\\t\\t_vehicles[details.id].applyEngineForce( details.force, details.wheel );\\n\\t}\\n};\\n\\npublic_functions.removeObject = function( details ) {\\n\\tworld.removeRigidBody( _objects[details.id] );\\n\\tAmmo.destroy(_objects[details.id]);\\n\\tAmmo.destroy(_motion_states[details.id]);\\n if (_compound_shapes[details.id]) Ammo.destroy(_compound_shapes[details.id]);\\n\\tif (_noncached_shapes[details.id]) Ammo.destroy(_noncached_shapes[details.id]);\\n\\tvar ptr = _objects[details.id].a != undefined ? _objects[details.id].a : _objects[details.id].ptr;\\n\\tdelete _objects_ammo[ptr];\\n\\tdelete _objects[details.id];\\n\\tdelete _motion_states[details.id];\\n if (_compound_shapes[details.id]) delete _compound_shapes[details.id];\\n\\tif (_noncached_shapes[details.id]) delete _noncached_shapes[details.id];\\n\\t_num_objects--;\\n};\\n\\npublic_functions.updateTransform = function( details ) {\\n\\t_object = _objects[details.id];\\n\\t_object.getMotionState().getWorldTransform( _transform );\\n\\t\\n\\tif ( details.pos ) {\\n\\t\\t_vec3_1.setX(details.pos.x);\\n\\t\\t_vec3_1.setY(details.pos.y);\\n\\t\\t_vec3_1.setZ(details.pos.z);\\n\\t\\t_transform.setOrigin(_vec3_1);\\n\\t}\\n\\t\\n\\tif ( details.quat ) {\\n\\t\\t_quat.setX(details.quat.x);\\n\\t\\t_quat.setY(details.quat.y);\\n\\t\\t_quat.setZ(details.quat.z);\\n\\t\\t_quat.setW(details.quat.w);\\n\\t\\t_transform.setRotation(_quat);\\n\\t}\\n\\t\\n\\t_object.setWorldTransform( _transform );\\n\\t_object.activate();\\n};\\n\\npublic_functions.updateMass = function( details ) {\\n\\t\\/\\/ #TODO: changing a static object into dynamic is buggy\\n\\t_object = _objects[details.id];\\n\\t\\n\\t\\/\\/ Per http:\\/\\/www.bulletphysics.org\\/Bullet\\/phpBB3\\/viewtopic.php?p=&f=9&t=3663#p13816\\n\\tworld.removeRigidBody( _object );\\n\\t\\n\\t_vec3_1.setX(0);\\n\\t_vec3_1.setY(0);\\n\\t_vec3_1.setZ(0);\\n\\t\\n\\t_object.setMassProps( details.mass, _vec3_1 );\\n\\tworld.addRigidBody( _object );\\n\\t_object.activate();\\n};\\n\\npublic_functions.applyCentralImpulse = function ( details ) {\\n\\t\\n\\t_vec3_1.setX(details.x);\\n\\t_vec3_1.setY(details.y);\\n\\t_vec3_1.setZ(details.z);\\n\\t\\n\\t_objects[details.id].applyCentralImpulse(_vec3_1);\\n\\t_objects[details.id].activate();\\n};\\n\\npublic_functions.applyImpulse = function ( details ) {\\n\\n\\t_vec3_1.setX(details.impulse_x);\\n\\t_vec3_1.setY(details.impulse_y);\\n\\t_vec3_1.setZ(details.impulse_z);\\n\\t\\n\\t_vec3_2.setX(details.x);\\n\\t_vec3_2.setY(details.y);\\n\\t_vec3_2.setZ(details.z);\\n\\n\\t_objects[details.id].applyImpulse(\\n\\t\\t_vec3_1,\\n\\t\\t_vec3_2\\n\\t);\\n\\t_objects[details.id].activate();\\n};\\n\\npublic_functions.applyCentralForce = function ( details ) {\\n\\t\\n\\t_vec3_1.setX(details.x);\\n\\t_vec3_1.setY(details.y);\\n\\t_vec3_1.setZ(details.z);\\n\\t\\n\\t_objects[details.id].applyCentralForce(_vec3_1);\\n\\t_objects[details.id].activate();\\n};\\n\\npublic_functions.applyForce = function ( details ) {\\n\\t\\n\\t_vec3_1.setX(details.impulse_x);\\n\\t_vec3_1.setY(details.impulse_y);\\n\\t_vec3_1.setZ(details.impulse_z);\\n\\t\\n\\t_vec3_2.setX(details.x);\\n\\t_vec3_2.setY(details.y);\\n\\t_vec3_2.setZ(details.z);\\n\\t\\n\\t_objects[details.id].applyForce(\\n\\t\\t_vec3_1,\\n\\t\\t_vec3_2\\n\\t);\\t\\n\\t_objects[details.id].activate();\\n};\\n\\npublic_functions.setAngularVelocity = function ( details ) {\\n\\n\\t_vec3_1.setX(details.x);\\n\\t_vec3_1.setY(details.y);\\n\\t_vec3_1.setZ(details.z);\\n\\t\\n\\t_objects[details.id].setAngularVelocity(\\n\\t\\t_vec3_1\\n\\t);\\n\\t_objects[details.id].activate();\\n};\\n\\npublic_functions.setLinearVelocity = function ( details ) {\\n\\n\\t_vec3_1.setX(details.x);\\n\\t_vec3_1.setY(details.y);\\n\\t_vec3_1.setZ(details.z);\\n\\t\\n\\t_objects[details.id].setLinearVelocity(\\n\\t\\t_vec3_1\\n\\t);\\n\\t_objects[details.id].activate();\\n};\\n\\npublic_functions.setAngularFactor = function ( details ) {\\n\\n\\t_vec3_1.setX(details.x);\\n\\t_vec3_1.setY(details.y);\\n\\t_vec3_1.setZ(details.z);\\n\\t\\n\\t_objects[details.id].setAngularFactor(\\n\\t\\t\\t_vec3_1\\n\\t);\\n};\\n\\npublic_functions.setLinearFactor = function ( details ) {\\n\\n\\t_vec3_1.setX(details.x);\\n\\t_vec3_1.setY(details.y);\\n\\t_vec3_1.setZ(details.z);\\n\\t\\n\\t_objects[details.id].setLinearFactor(\\n\\t\\t_vec3_1\\n\\t);\\n};\\n\\npublic_functions.setDamping = function ( details ) {\\n\\t_objects[details.id].setDamping( details.linear, details.angular );\\n};\\n\\npublic_functions.setCcdMotionThreshold = function ( details ) {\\n\\t_objects[details.id].setCcdMotionThreshold( details.threshold );\\n};\\n\\npublic_functions.setCcdSweptSphereRadius = function ( details ) {\\n\\t_objects[details.id].setCcdSweptSphereRadius( details.radius );\\n};\\n\\npublic_functions.addConstraint = function ( details ) {\\n\\tvar constraint;\\n\\n\\tswitch ( details.type ) {\\n\\t\\t\\n\\t\\tcase 'point':\\n\\t\\t\\tif ( details.objectb === undefined ) {\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_1.setX(details.positiona.x);\\n\\t\\t\\t\\t_vec3_1.setY(details.positiona.y);\\n\\t\\t\\t\\t_vec3_1.setZ(details.positiona.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tconstraint = new Ammo.btPoint2PointConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\t_vec3_1\\n\\t\\t\\t\\t);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_1.setX(details.positiona.x);\\n\\t\\t\\t\\t_vec3_1.setY(details.positiona.y);\\n\\t\\t\\t\\t_vec3_1.setZ(details.positiona.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_2.setX(details.positionb.x);\\n\\t\\t\\t\\t_vec3_2.setY(details.positionb.y);\\n\\t\\t\\t\\t_vec3_2.setZ(details.positionb.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tconstraint = new Ammo.btPoint2PointConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\t_objects[ details.objectb ],\\n\\t\\t\\t\\t\\t_vec3_1,\\n\\t\\t\\t\\t\\t_vec3_2\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'hinge':\\n\\t\\t\\tif ( details.objectb === undefined ) {\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_1.setX(details.positiona.x);\\n\\t\\t\\t\\t_vec3_1.setY(details.positiona.y);\\n\\t\\t\\t\\t_vec3_1.setZ(details.positiona.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_2.setX(details.axis.x);\\n\\t\\t\\t\\t_vec3_2.setY(details.axis.y);\\n\\t\\t\\t\\t_vec3_2.setZ(details.axis.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tconstraint = new Ammo.btHingeConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\t_vec3_1,\\n\\t\\t\\t\\t\\t_vec3_2\\n\\t\\t\\t\\t);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_1.setX(details.positiona.x);\\n\\t\\t\\t\\t_vec3_1.setY(details.positiona.y);\\n\\t\\t\\t\\t_vec3_1.setZ(details.positiona.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_2.setX(details.positionb.x);\\n\\t\\t\\t\\t_vec3_2.setY(details.positionb.y);\\n\\t\\t\\t\\t_vec3_2.setZ(details.positionb.z);\\n\\n\\t\\t\\t\\t_vec3_3.setX(details.axis.x);\\n\\t\\t\\t\\t_vec3_3.setY(details.axis.y);\\n\\t\\t\\t\\t_vec3_3.setZ(details.axis.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tconstraint = new Ammo.btHingeConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\t_objects[ details.objectb ],\\n\\t\\t\\t\\t\\t_vec3_1,\\n\\t\\t\\t\\t\\t_vec3_2,\\n\\t\\t\\t\\t\\t_vec3_3,\\n\\t\\t\\t\\t\\t_vec3_3\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'slider':\\n\\t\\t\\tvar transforma, transformb, rotation;\\n\\t\\t\\n\\t\\t\\ttransforma = new Ammo.btTransform();\\n\\t\\t\\t\\n\\t\\t\\t_vec3_1.setX(details.positiona.x);\\n\\t\\t\\t_vec3_1.setY(details.positiona.y);\\n\\t\\t\\t_vec3_1.setZ(details.positiona.z);\\n\\t\\t\\t\\n\\t\\t\\ttransforma.setOrigin(_vec3_1);\\n\\t\\t\\t\\n\\t\\t\\tvar rotation = transforma.getRotation();\\n\\t\\t\\trotation.setEuler( details.axis.x, details.axis.y, details.axis.z );\\n\\t\\t\\ttransforma.setRotation( rotation );\\n\\t\\t\\t\\n\\t\\t\\tif ( details.objectb ) {\\n\\t\\t\\t\\ttransformb = new Ammo.btTransform();\\n\\n\\t\\t\\t\\t_vec3_2.setX(details.positionb.x);\\n\\t\\t\\t\\t_vec3_2.setY(details.positionb.y);\\n\\t\\t\\t\\t_vec3_2.setZ(details.positionb.z);\\n\\n\\t\\t\\t\\ttransformb.setOrigin(_vec3_2);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\trotation = transformb.getRotation();\\n\\t\\t\\t\\trotation.setEuler( details.axis.x, details.axis.y, details.axis.z );\\n\\t\\t\\t\\ttransformb.setRotation( rotation );\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tconstraint = new Ammo.btSliderConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\t_objects[ details.objectb ],\\n\\t\\t\\t\\t\\ttransforma,\\n\\t\\t\\t\\t\\ttransformb,\\n\\t\\t\\t\\t\\ttrue\\n\\t\\t\\t\\t);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconstraint = new Ammo.btSliderConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\ttransforma,\\n\\t\\t\\t\\t\\ttrue\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t\\t\\n\\t\\t\\tAmmo.destroy(transforma);\\n\\t\\t\\tif (transformb != undefined) {\\n\\t\\t\\t\\tAmmo.destroy(transformb);\\t\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'conetwist':\\n\\t\\t\\tvar transforma, transformb;\\n\\t\\t\\t\\n\\t\\t\\ttransforma = new Ammo.btTransform();\\n\\t\\t\\ttransforma.setIdentity();\\n\\t\\t\\t\\n\\t\\t\\ttransformb = new Ammo.btTransform();\\n\\t\\t\\ttransformb.setIdentity();\\n\\t\\t\\t\\n\\t\\t\\t_vec3_1.setX(details.positiona.x);\\n\\t\\t\\t_vec3_1.setY(details.positiona.y);\\n\\t\\t\\t_vec3_1.setZ(details.positiona.z);\\n\\t\\t\\t\\n\\t\\t\\t_vec3_2.setX(details.positionb.x);\\n\\t\\t\\t_vec3_2.setY(details.positionb.y);\\n\\t\\t\\t_vec3_2.setZ(details.positionb.z);\\n\\t\\t\\t\\n\\t\\t\\ttransforma.setOrigin(_vec3_1);\\n\\t\\t\\ttransformb.setOrigin(_vec3_2);\\n\\t\\t\\t\\n\\t\\t\\tvar rotation = transforma.getRotation();\\n\\t\\t\\trotation.setEulerZYX( -details.axisa.z, -details.axisa.y, -details.axisa.x );\\n\\t\\t\\ttransforma.setRotation( rotation );\\n\\t\\t\\t\\n\\t\\t\\trotation = transformb.getRotation();\\n\\t\\t\\trotation.setEulerZYX( -details.axisb.z, -details.axisb.y, -details.axisb.x );\\n\\t\\t\\ttransformb.setRotation( rotation );\\n\\t\\t\\t\\n\\t\\t\\tconstraint = new Ammo.btConeTwistConstraint(\\n\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t_objects[ details.objectb ],\\n\\t\\t\\t\\ttransforma,\\n\\t\\t\\t\\ttransformb\\n\\t\\t\\t);\\n\\t\\t\\t\\n\\t\\t\\tconstraint.setLimit( Math.PI, 0, Math.PI );\\n\\t\\t\\t\\n\\t\\t\\tAmmo.destroy(transforma);\\n\\t\\t\\tAmmo.destroy(transformb);\\t\\n\\t\\t\\t\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tcase 'dof':\\n\\t\\t\\tvar transforma, transformb, rotation;\\n\\t\\t\\n\\t\\t\\ttransforma = new Ammo.btTransform();\\n\\t\\t\\ttransforma.setIdentity();\\n\\t\\t\\t\\n\\t\\t\\t_vec3_1.setX(details.positiona.x);\\n\\t\\t\\t_vec3_1.setY(details.positiona.y);\\n\\t\\t\\t_vec3_1.setZ(details.positiona.z);\\n\\t\\t\\t\\n\\t\\t\\ttransforma.setOrigin(_vec3_1 );\\n\\t\\t\\t\\n\\t\\t\\trotation = transforma.getRotation();\\n\\t\\t\\trotation.setEulerZYX( -details.axisa.z, -details.axisa.y, -details.axisa.x );\\n\\t\\t\\ttransforma.setRotation( rotation );\\n\\t\\t\\t\\n\\t\\t\\tif ( details.objectb ) {\\n\\t\\t\\t\\ttransformb = new Ammo.btTransform();\\n\\t\\t\\t\\ttransformb.setIdentity();\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t_vec3_2.setX(details.positionb.x);\\n\\t\\t\\t\\t_vec3_2.setY(details.positionb.y);\\n\\t\\t\\t\\t_vec3_2.setZ(details.positionb.z);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\ttransformb.setOrigin(_vec3_2);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\trotation = transformb.getRotation();\\n\\t\\t\\t\\trotation.setEulerZYX( -details.axisb.z, -details.axisb.y, -details.axisb.x );\\n\\t\\t\\t\\ttransformb.setRotation( rotation );\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tconstraint = new Ammo.btGeneric6DofConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\t_objects[ details.objectb ],\\n\\t\\t\\t\\t\\ttransforma,\\n\\t\\t\\t\\t\\ttransformb\\n\\t\\t\\t\\t);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconstraint = new Ammo.btGeneric6DofConstraint(\\n\\t\\t\\t\\t\\t_objects[ details.objecta ],\\n\\t\\t\\t\\t\\ttransforma\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t\\tAmmo.destroy(transforma);\\n\\t\\t\\tif (transformb != undefined) {\\n\\t\\t\\t\\tAmmo.destroy(transformb);\\t\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t\\t\\n\\t\\tdefault:\\n\\t\\t\\treturn;\\n\\t\\t\\n\\t};\\n\\t\\n\\tworld.addConstraint( constraint );\\n\\n\\tconstraint.enableFeedback();\\n\\t_constraints[ details.id ] = constraint;\\n\\t_num_constraints++;\\n\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\tconstraintreport = new Float32Array(1 + _num_constraints * CONSTRAINTREPORT_ITEMSIZE); \\/\\/ message id & ( # of objects to report * # of values per object )\\n\\t\\tconstraintreport[0] = MESSAGE_TYPES.CONSTRAINTREPORT;\\n\\t} else {\\n\\t\\tconstraintreport = [ MESSAGE_TYPES.CONSTRAINTREPORT ];\\n\\t}\\n};\\n\\npublic_functions.removeConstraint = function( details ) {\\n\\tvar constraint = _constraints[ details.id ];\\n\\tif ( constraint !== undefined ) {\\n\\t\\tworld.removeConstraint( constraint );\\n\\t\\tdelete _constraints[ details.id ];\\n\\t\\t_num_constraints--;\\n\\t}\\n};\\n\\npublic_functions.constraint_setBreakingImpulseThreshold = function( details ) {\\n\\tvar constraint = _constraints[ details.id ];\\n\\tif ( constraint !== undefind ) {\\n\\t\\tconstraint.setBreakingImpulseThreshold( details.threshold );\\n\\t}\\n};\\n\\npublic_functions.simulate = function simulate( params ) {\\n\\tif ( world ) {\\n\\t\\tparams = params || {};\\n\\t\\t\\n\\t\\tif ( !params.timeStep ) {\\n\\t\\t\\tif ( last_simulation_time ) {\\n\\t\\t\\t\\tparams.timeStep = 0;\\n\\t\\t\\t\\twhile ( params.timeStep + last_simulation_duration <= fixedTimeStep ) {\\n\\t\\t\\t\\t\\tparams.timeStep = ( Date.now() - last_simulation_time ) \\/ 1000; \\/\\/ time since last simulation\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tparams.timeStep = fixedTimeStep; \\/\\/ handle first frame\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif ( params.timeStep < fixedTimeStep ) {\\n\\t\\t\\t\\tparams.timeStep = fixedTimeStep;\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\tparams.maxSubSteps = params.maxSubSteps || Math.ceil( params.timeStep \\/ fixedTimeStep ); \\/\\/ If maxSubSteps is not defined, keep the simulation fully up to date\\n\\n\\t\\tlast_simulation_duration = Date.now();\\n\\t\\tworld.stepSimulation( params.timeStep, params.maxSubSteps, fixedTimeStep );\\n\\t\\t\\n\\t\\treportVehicles();\\n\\t\\treportCollisions();\\n\\t\\treportConstraints();\\n\\t\\treportWorld();\\n\\t\\t\\n\\t\\tlast_simulation_duration = ( Date.now() - last_simulation_duration ) \\/ 1000;\\n\\t\\tlast_simulation_time = Date.now();\\n\\t}\\n};\\n\\n\\n\\/\\/ Constraint functions\\npublic_functions.hinge_setLimits = function( params ) {\\n\\t_constraints[ params.constraint ].setLimit( params.low, params.high, 0, params.bias_factor, params.relaxation_factor );\\n};\\npublic_functions.hinge_enableAngularMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.enableAngularMotor( true, params.velocity, params.acceleration );\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.hinge_disableMotor = function( params ) {\\n\\t_constraints[ params.constraint ].enableMotor( false );\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\n\\npublic_functions.slider_setLimits = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.setLowerLinLimit( params.lin_lower || 0 );\\n\\tconstraint.setUpperLinLimit( params.lin_upper || 0 );\\n\\t\\n\\tconstraint.setLowerAngLimit( params.ang_lower || 0 );\\n\\tconstraint.setUpperAngLimit( params.ang_upper || 0 );\\n};\\npublic_functions.slider_setRestitution = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.setSoftnessLimLin( params.linear || 0 );\\n\\tconstraint.setSoftnessLimAng( params.angular || 0 );\\n};\\npublic_functions.slider_enableLinearMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.setTargetLinMotorVelocity( params.velocity );\\n\\tconstraint.setMaxLinMotorForce( params.acceleration );\\n\\tconstraint.setPoweredLinMotor( true );\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.slider_disableLinearMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.setPoweredLinMotor( false );\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.slider_enableAngularMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.setTargetAngMotorVelocity( params.velocity );\\n\\tconstraint.setMaxAngMotorForce( params.acceleration );\\n\\tconstraint.setPoweredAngMotor( true );\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.slider_disableAngularMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.setPoweredAngMotor( false );\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\n\\npublic_functions.conetwist_setLimit = function( params ) {\\n\\t_constraints[ params.constraint ].setLimit( params.z, params.y, params.x ); \\/\\/ ZYX order\\n};\\npublic_functions.conetwist_enableMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.enableMotor( true );\\n\\tconstraint.getRigidBodyA().activate();\\n\\tconstraint.getRigidBodyB().activate();\\n};\\npublic_functions.conetwist_setMaxMotorImpulse = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.setMaxMotorImpulse( params.max_impulse );\\n\\tconstraint.getRigidBodyA().activate();\\n\\tconstraint.getRigidBodyB().activate();\\n};\\npublic_functions.conetwist_setMotorTarget = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\t_quat.setX(params.x);\\n\\t_quat.setY(params.y);\\n\\t_quat.setZ(params.z);\\n\\t_quat.setW(params.w);\\n\\t\\n\\tconstraint.setMotorTarget(_quat);\\n\\t\\n\\tconstraint.getRigidBodyA().activate();\\n\\tconstraint.getRigidBodyB().activate();\\n};\\npublic_functions.conetwist_disableMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\tconstraint.enableMotor( false );\\n\\tconstraint.getRigidBodyA().activate();\\n\\tconstraint.getRigidBodyB().activate();\\n};\\n\\npublic_functions.dof_setLinearLowerLimit = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\t_vec3_1.setX(params.x);\\n\\t_vec3_1.setY(params.y);\\n\\t_vec3_1.setZ(params.z);\\n\\t\\n\\tconstraint.setLinearLowerLimit(_vec3_1);\\n\\t\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.dof_setLinearUpperLimit = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\t_vec3_1.setX(params.x);\\n\\t_vec3_1.setY(params.y);\\n\\t_vec3_1.setZ(params.z);\\n\\t\\n\\tconstraint.setLinearUpperLimit(_vec3_1);\\n\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.dof_setAngularLowerLimit = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\t_vec3_1.setX(params.x);\\n\\t_vec3_1.setY(params.y);\\n\\t_vec3_1.setZ(params.z);\\n\\t\\n\\tconstraint.setAngularLowerLimit(_vec3_1);\\n\\t\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.dof_setAngularUpperLimit = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\t_vec3_1.setX(params.x);\\n\\t_vec3_1.setY(params.y);\\n\\t_vec3_1.setZ(params.z);\\n\\t\\n\\tconstraint.setAngularUpperLimit(_vec3_1);\\n\\t\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.dof_enableAngularMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\tvar motor = constraint.getRotationalLimitMotor( params.which );\\n\\tmotor.set_m_enableMotor( true );\\n\\t\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.dof_configureAngularMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\tvar motor = constraint.getRotationalLimitMotor( params.which );\\n\\t\\n\\tmotor.set_m_loLimit( params.low_angle );\\n\\tmotor.set_m_hiLimit( params.high_angle );\\n\\tmotor.set_m_targetVelocity( params.velocity );\\n\\tmotor.set_m_maxMotorForce( params.max_force );\\n\\t\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\npublic_functions.dof_disableAngularMotor = function( params ) {\\n\\tvar constraint = _constraints[ params.constraint ];\\n\\t\\n\\tvar motor = constraint.getRotationalLimitMotor( params.which );\\n\\tmotor.set_m_enableMotor( false );\\n\\t\\n\\tconstraint.getRigidBodyA().activate();\\n\\tif ( constraint.getRigidBodyB() ) {\\n\\t\\tconstraint.getRigidBodyB().activate();\\n\\t}\\n};\\n\\nreportWorld = function() {\\n\\tvar index, object,\\n\\t\\ttransform, origin, rotation, \\n\\t\\toffset = 0,\\n\\t\\ti = 0;\\n\\t\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\tif ( worldreport.length < 2 + _num_objects * WORLDREPORT_ITEMSIZE ) {\\n\\t\\t\\tworldreport = new Float32Array(\\n\\t\\t\\t\\t2 + \\/\\/ message id & # objects in report\\n\\t\\t\\t\\t( Math.ceil( _num_objects \\/ REPORT_CHUNKSIZE ) * REPORT_CHUNKSIZE ) * WORLDREPORT_ITEMSIZE \\/\\/ # of values needed * item size\\n\\t\\t\\t);\\n\\t\\t\\tworldreport[0] = MESSAGE_TYPES.WORLDREPORT;\\n\\t\\t}\\n\\t}\\n\\t\\n\\tworldreport[1] = _num_objects; \\/\\/ record how many objects we're reporting on\\n\\n\\t\\/\\/for ( i = 0; i < worldreport[1]; i++ ) {\\n\\tfor ( index in _objects ) {\\n\\t\\tif ( _objects.hasOwnProperty( index ) ) {\\n\\t\\t\\tobject = _objects[index];\\n\\t\\t\\t\\n\\t\\t\\t\\/\\/ #TODO: we can't use center of mass transform when center of mass can change,\\n\\t\\t\\t\\/\\/ but getMotionState().getWorldTransform() screws up on objects that have been moved\\n\\t\\t\\t\\/\\/object.getMotionState().getWorldTransform( transform );\\n\\t\\t\\ttransform = object.getCenterOfMassTransform(); \\n\\t\\t\\t\\n\\t\\t\\torigin = transform.getOrigin(); \\n\\t\\t\\trotation = transform.getRotation();\\n\\t\\t\\t\\n\\t\\t\\t\\/\\/ add values to report\\n\\t\\t\\toffset = 2 + (i++) * WORLDREPORT_ITEMSIZE;\\n\\t\\t\\t\\n\\t\\t\\tworldreport[ offset ] = object.id;\\n\\t\\t\\t\\n\\t\\t\\tworldreport[ offset + 1 ] = origin.x();\\n\\t\\t\\tworldreport[ offset + 2 ] = origin.y();\\n\\t\\t\\tworldreport[ offset + 3 ] = origin.z();\\n\\t\\t\\t\\n\\t\\t\\tworldreport[ offset + 4 ] = rotation.x();\\n\\t\\t\\tworldreport[ offset + 5 ] = rotation.y();\\n\\t\\t\\tworldreport[ offset + 6 ] = rotation.z();\\n\\t\\t\\tworldreport[ offset + 7 ] = rotation.w();\\n\\t\\t\\t\\n\\t\\t\\t_vector = object.getLinearVelocity();\\n\\t\\t\\tworldreport[ offset + 8 ] = _vector.x();\\n\\t\\t\\tworldreport[ offset + 9 ] = _vector.y();\\n\\t\\t\\tworldreport[ offset + 10 ] = _vector.z();\\n\\t\\t\\t\\n\\t\\t\\t_vector = object.getAngularVelocity();\\n\\t\\t\\tworldreport[ offset + 11 ] = _vector.x();\\n\\t\\t\\tworldreport[ offset + 12 ] = _vector.y();\\n\\t\\t\\tworldreport[ offset + 13 ] = _vector.z();\\n\\t\\t}\\n\\t}\\n\\t\\n\\t\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\ttransferableMessage( worldreport.buffer, [worldreport.buffer] );\\n\\t} else {\\n\\t\\ttransferableMessage( worldreport );\\n\\t}\\n\\t\\n};\\n\\nreportCollisions = function() {\\n\\tvar i, offset,\\n\\t\\tdp = world.getDispatcher(),\\n\\t\\tnum = dp.getNumManifolds(),\\n\\t\\tmanifold, num_contacts, j, pt,\\n\\t\\t_collided = false;\\n\\t\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\tif ( collisionreport.length < 2 + num * COLLISIONREPORT_ITEMSIZE ) {\\n\\t\\t\\tcollisionreport = new Float32Array(\\n\\t\\t\\t\\t2 + \\/\\/ message id & # objects in report\\n\\t\\t\\t\\t( Math.ceil( _num_objects \\/ REPORT_CHUNKSIZE ) * REPORT_CHUNKSIZE ) * COLLISIONREPORT_ITEMSIZE \\/\\/ # of values needed * item size\\n\\t\\t\\t);\\n\\t\\t\\tcollisionreport[0] = MESSAGE_TYPES.COLLISIONREPORT;\\n\\t\\t}\\n\\t}\\n\\t\\n\\tcollisionreport[1] = 0; \\/\\/ how many collisions we're reporting on\\n\\t\\n\\tfor ( i = 0; i < num; i++ ) {\\n\\t\\tmanifold = dp.getManifoldByIndexInternal( i );\\n\\t\\t\\n\\t\\tnum_contacts = manifold.getNumContacts();\\n\\t\\tif ( num_contacts === 0 ) {\\n\\t\\t\\tcontinue;\\n\\t\\t}\\n\\t\\t\\n\\t\\tfor ( j = 0; j < num_contacts; j++ ) {\\n\\t\\t\\tpt = manifold.getContactPoint( j );\\n\\t\\t\\t\\/\\/if ( pt.getDistance() < 0 ) {\\n\\t\\t\\t\\toffset = 2 + (collisionreport[1]++) * COLLISIONREPORT_ITEMSIZE;\\n\\t\\t\\t\\tcollisionreport[ offset ] = _objects_ammo[ manifold.getBody0() ];\\n\\t\\t\\t\\tcollisionreport[ offset + 1 ] = _objects_ammo[ manifold.getBody1() ];\\n\\n\\t\\t\\t\\t_vector = pt.get_m_normalWorldOnB();\\n\\t\\t\\t\\tcollisionreport[ offset + 2 ] = _vector.x();\\n\\t\\t\\t\\tcollisionreport[ offset + 3 ] = _vector.y();\\n\\t\\t\\t\\tcollisionreport[ offset + 4 ] = _vector.z();\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\/\\/}\\n\\t\\t\\t\\t\\n\\t\\t\\t\\ttransferableMessage( _objects_ammo );\\t\\n\\t\\t\\n\\t\\t}\\t\\n\\t}\\n\\t\\n\\t\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\ttransferableMessage( collisionreport.buffer, [collisionreport.buffer] );\\n\\t} else {\\n\\t\\ttransferableMessage( collisionreport );\\n\\t}\\n};\\n\\nreportVehicles = function() {\\n\\tvar index, vehicle,\\n\\t\\ttransform, origin, rotation, \\n\\t\\toffset = 0,\\n\\t\\ti = 0, j = 0;\\n\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\tif ( vehiclereport.length < 2 + _num_wheels * VEHICLEREPORT_ITEMSIZE ) {\\n\\t\\t\\tvehiclereport = new Float32Array(\\n\\t\\t\\t\\t2 + \\/\\/ message id & # objects in report\\n\\t\\t\\t\\t( Math.ceil( _num_wheels \\/ REPORT_CHUNKSIZE ) * REPORT_CHUNKSIZE ) * VEHICLEREPORT_ITEMSIZE \\/\\/ # of values needed * item size\\n\\t\\t\\t);\\n\\t\\t\\tvehiclereport[0] = MESSAGE_TYPES.VEHICLEREPORT;\\n\\t\\t}\\n\\t}\\n\\n\\tfor ( index in _vehicles ) {\\n\\t\\tif ( _vehicles.hasOwnProperty( index ) ) {\\n\\t\\t\\tvehicle = _vehicles[index];\\n\\n\\t\\t\\tfor ( j = 0; j < vehicle.getNumWheels(); j++ ) {\\n\\n\\t\\t\\t\\t\\/\\/vehicle.updateWheelTransform( j, true );\\n\\n\\t\\t\\t\\t\\/\\/transform = vehicle.getWheelTransformWS( j );\\n\\t\\t\\t\\ttransform = vehicle.getWheelInfo( j ).get_m_worldTransform(); \\n\\n\\t\\t\\t\\torigin = transform.getOrigin(); \\n\\t\\t\\t\\trotation = transform.getRotation(); \\n\\n\\t\\t\\t\\t\\/\\/ add values to report\\n\\t\\t\\t\\toffset = 1 + (i++) * VEHICLEREPORT_ITEMSIZE;\\n\\n\\t\\t\\t\\tvehiclereport[ offset ] = index;\\n\\t\\t\\t\\tvehiclereport[ offset + 1 ] = j;\\n\\n\\t\\t\\t\\tvehiclereport[ offset + 2 ] = origin.x();\\n\\t\\t\\t\\tvehiclereport[ offset + 3 ] = origin.y();\\n\\t\\t\\t\\tvehiclereport[ offset + 4 ] = origin.z();\\n\\n\\t\\t\\t\\tvehiclereport[ offset + 5 ] = rotation.x();\\n\\t\\t\\t\\tvehiclereport[ offset + 6 ] = rotation.y();\\n\\t\\t\\t\\tvehiclereport[ offset + 7 ] = rotation.z();\\n\\t\\t\\t\\tvehiclereport[ offset + 8 ] = rotation.w();\\n\\n\\t\\t\\t}\\n\\n\\t\\t}\\n\\t}\\n\\t\\n\\tif ( j !== 0 ) {\\n\\t\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\t\\ttransferableMessage( vehiclereport.buffer, [vehiclereport.buffer] );\\n\\t\\t} else {\\n\\t\\t\\ttransferableMessage( vehiclereport );\\n\\t\\t}\\n\\t}\\n};\\n\\nreportConstraints = function() {\\n\\tvar index, constraint,\\n\\t\\toffset_body,\\n\\t\\ttransform, origin, \\n\\t\\toffset = 0,\\n\\t\\ti = 0;\\n\\n\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\tif ( constraintreport.length < 2 + _num_constraints * CONSTRAINTREPORT_ITEMSIZE ) {\\n\\t\\t\\tconstraintreport = new Float32Array(\\n\\t\\t\\t\\t2 + \\/\\/ message id & # objects in report\\n\\t\\t\\t\\t( Math.ceil( _num_constraints \\/ REPORT_CHUNKSIZE ) * REPORT_CHUNKSIZE ) * CONSTRAINTREPORT_ITEMSIZE \\/\\/ # of values needed * item size\\n\\t\\t\\t);\\n\\t\\t\\tconstraintreport[0] = MESSAGE_TYPES.CONSTRAINTREPORT;\\n\\t\\t}\\n\\t}\\n\\n\\tfor ( index in _constraints ) {\\n\\t\\tif ( _constraints.hasOwnProperty( index ) ) {\\n\\t\\t\\tconstraint = _constraints[index];\\n\\t\\t\\toffset_body = constraint.getRigidBodyA();\\n\\t\\t\\ttransform = constraint.getFrameOffsetA(); \\n\\t\\t\\torigin = transform.getOrigin();\\n\\n\\t\\t\\t\\/\\/ add values to report\\n\\t\\t\\toffset = 1 + (i++) * CONSTRAINTREPORT_ITEMSIZE;\\n\\n\\t\\t\\tconstraintreport[ offset ] = index;\\n\\t\\t\\tconstraintreport[ offset + 1 ] = offset_body.id;\\n\\t\\t\\tconstraintreport[ offset + 2 ] = origin.getX();\\n\\t\\t\\tconstraintreport[ offset + 3 ] = origin.getY();\\n\\t\\t\\tconstraintreport[ offset + 4 ] = origin.getZ();\\n\\t\\t\\tconstraintreport[ offset + 5 ] = constraint.getAppliedImpulse();\\n\\t\\t}\\n\\t}\\n\\n\\t\\n\\tif ( i !== 0 ) {\\n\\t\\tif ( SUPPORT_TRANSFERABLE ) {\\n\\t\\t\\ttransferableMessage( constraintreport.buffer, [constraintreport.buffer] );\\n\\t\\t} else {\\n\\t\\t\\ttransferableMessage( constraintreport );\\n\\t\\t}\\n\\t}\\n\\t\\n};\\n\\nself.onmessage = function( event ) {\\n\\t\\n\\tif ( event.data instanceof Float32Array ) {\\n\\t\\t\\/\\/ transferable object\\n\\t\\t\\n\\t\\tswitch ( event.data[0] ) {\\n\\t\\t\\tcase MESSAGE_TYPES.WORLDREPORT:\\n\\t\\t\\t\\tworldreport = new Float32Array( event.data );\\n\\t\\t\\t\\tbreak;\\n\\n\\t\\t\\tcase MESSAGE_TYPES.COLLISIONREPORT:\\n\\t\\t\\t\\tcollisionreport = new Float32Array( event.data );\\n\\t\\t\\t\\tbreak;\\n\\n\\t\\t\\tcase MESSAGE_TYPES.VEHICLEREPORT:\\n\\t\\t\\t\\tvehiclereport = new Float32Array( event.data );\\n\\t\\t\\t\\tbreak;\\n\\n\\t\\t\\tcase MESSAGE_TYPES.CONSTRAINTREPORT:\\n\\t\\t\\t\\tconstraintreport = new Float32Array( event.data );\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\t\\n\\t\\treturn;\\n\\t}\\n\\t\\n\\tif ( event.data.cmd && public_functions[event.data.cmd] ) {\\n\\t\\t\\/\\/if ( event.data.params.id !== undefined && _objects[event.data.params.id] === undefined && event.data.cmd !== 'addObject' && event.data.cmd !== 'registerMaterial' ) return;\\n\\t\\tpublic_functions[event.data.cmd]( event.data.params );\\n\\t}\\n\\t\\n};\\n \\n<\\/script>\",\"css\":\"body { \\n margin: 0; \\n width: 100%;\\n height: 100%;\\n overflow: hidden;\\n}\\n\\ncanvas { \\n width: 100%; \\n height: 100%;\\n}\\n\\n.display_page {\\n position: fixed;\\n width: 100%;\\n height: 100%;\\n background: #F6EDD0;\\n box-shadow: 0 0 120px 5px #514014 inset;\\n z-index: 1;\\n}\\n\\n\\n\\/* Loading Animation *\\/\\n\\n#loading_animation_page {\\n visibility: hidden;\\n z-index: 2;\\n}\\n\\n#loading_animation_div {\\n width: 25%;\\n height: 25%;\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n}\\n\\n#loading_animation_svg {\\n width: 100%;\\n height: 100%;\\n}\\n\\n.loading_animation_lines { \\n stroke: #272727;\\n stroke-width: 1%;\\n stroke-linecap: round;\\n animation-name: fade_out_in;\\n animation-iteration-count: infinite;\\n animation-duration: 900ms;\\n animation-timing-function: linear;\\n}\\n#loading_animation_line_1 { animation-delay: 0ms; }\\n#loading_animation_line_2 { animation-delay: 175ms; }\\n#loading_animation_line_3 { animation-delay: 350ms; }\\n\\n@keyframes fade_out_in {\\n 0% { opacity: 1 }\\n 20% { opacity: 0 }\\n 100% { opacity: 1 }\\n}\\n\\n#loading_animation_insignia {\\n position: absolute;\\n width: 22%;\\n height: 22%;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n}\\n\\n\\n\\n\\/* Landing Page *\\/\\n\\n#landing_page_div {\\n background: #F9F9F9;\\n}\\n\\n#landing_logo_div {\\n position: absolute;\\n width: 50%;\\n top: 37%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n}\\n\\n#logo_landing {\\n width: 100%;\\n}\\n\\n#button_play {\\n position: absolute;\\n width: 20%;\\n top: 140%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n opacity: .9;\\n}\\n#button_play:hover { \\n opacity: 1;\\n cursor: pointer;\\n}\\n\\n\\n\\n\\/* Announcement Pages *\\/\\n\\n.announcement_page { \\n visibility: hidden;\\n}\\n\\n.card_div {\\n position: absolute;\\n width: 60%;\\n top: 48%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n}\\n\\n.card {\\n width: 100%;\\n}\\n\\n.card_button {\\n position: absolute;\\n width: 30%;\\n top: 95.5%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n opacity: .9;\\n cursor: pointer;\\n}\\n.card_button:hover { opacity: 1 }\\n\\n.round_score {\\n position: absolute;\\n height: 8%;\\n top: 66%;\\n transform: translate(-50%, -50%);\\n}\\n#round_score_green { left: 38%; }\\n#round_score_red { left: 80%; }\\n\\n\\n\\n\\/* UI *\\/\\n\\n#logo_div {\\n position: fixed;\\n width: 23%;\\n min-width: 115px;\\n max-width: 220px;\\n top: 6%;\\n left: 4%;\\n opacity: .8;\\n}\\n#logo {\\n width: 100%;\\n}\\n#copyright {\\n position: absolute;\\n bottom: -5%;\\n left: 50%;\\n transform: translate(-50%);\\n width: 22%;\\n}\\n\\n#scoreboard_div {\\n position: fixed;\\n width: 16%;\\n max-width: 160px;\\n min-width: 90px;\\n top: 6%;\\n right: 4%;\\n opacity: .8;\\n}\\n#scoreboard_img {\\n height: 100%;\\n width: 100%;\\n}\\n.board_score {\\n position: absolute;\\n height: 35%;\\n left: 76%;\\n}\\n#board_score_green { top: -1.5%; }\\n#board_score_red { top: 60%; }\\n\\n#buttons_div {\\n position: fixed;\\n width: 35px;\\n height: 80px;\\n top: 47%;\\n transform: translate(0, -50%);\\n right: 4%;\\n}\\n.buttons_items {\\n position: absolute;\\n width: 100%;\\n opacity: .7;\\n}\\n.button_restart {\\n height: 33.333%;\\n top: 0;\\n}\\n.button_divider {\\n height: 33.333%;\\n width: 70%;\\n left: 50%;\\n top: 50%;\\n transform: translate(-50%, -50%);\\n opacity: .5;\\n}\\n.button_draw {\\n height: 33.333%;\\n bottom: 0;\\n}\\n.button_restart:hover { opacity: 1; }\\n.button_draw:hover { opacity: 1; }\\n\\n.nav {\\n position: fixed;\\n width: 12%;\\n max-width: 125px;\\n min-width: 75px;\\n bottom: 5%;\\n opacity: .85;\\n}\\n.left_nav { left: 4%; }\\n.right_nav { right: 4%; }\\n\",\"js\":\"\\n\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\n\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/ BUS DERBY \\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\n\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\n\\n\\n\\n\\/\\/\\/\\/\\/---Sources---\\/\\/\\/\\/\\/\\n\\nPhysijs.scripts.ammo = \\\"https:\\/\\/assets.codepen.io\\/409445\\/ammo.js\\\";\\n\\n\\/\\/physijs_worker.js called from HTML script (needed so worker can be used in codepen)\\n\\/\\/ Physijs.scripts.worker = \\\"https:\\/\\/chandlerprall.github.io\\/Physijs\\/physijs_worker.js\\\";\\nvar blob = new Blob( [document.querySelector('#physijs_worker').textContent] );\\nPhysijs.scripts.worker = window.URL.createObjectURL(blob);\\n\\n\\n\\n\\/\\/\\/\\/\\/---Settings---\\/\\/\\/\\/\\/\\n\\nvar bwf = 3.5; \\/\\/bus wheel friction \\nvar bwr = 0; \\/\\/bus wheel restitution\\nvar pf = 4.2; \\/\\/platform friction\\nvar pr = 0; \\/\\/platform restitution\\nvar gravity = -50;\\n\\n\\n\\n\\/\\/\\/\\/\\/---Initiation---\\/\\/\\/\\/\\/\\n \\nvar scene, environment, camera;\\nvar backgroundColor = 0xCDD3D6;\\nvar busArray = [];\\nvar Player1 = { name: \\\"gretchen\\\", score: 0 };\\nvar Player2 = { name: \\\"bertha\\\", score: 0 };\\nvar gameHasBegun = false;\\nvar roundActive = false;\\nvar gameHasEnded = false;\\nvar loadingAnimation = document.getElementById(\\\"loading_animation_page\\\");\\nvar loadingAnimationVisible = false;\\n\\n\\/\\/\\/Renderer\\nvar renderer = new THREE.WebGLRenderer( { antialias: true } );\\nrenderer.setSize( window.innerWidth, window.innerHeight );\\ndocument.body.appendChild( renderer.domElement );\\n\\n\\n\\n\\/\\/\\/\\/\\/---Objects---\\/\\/\\/\\/\\/\\n\\n\\n\\/\\/\\/--Environment---\\/\\/\\/\\nfunction Environment() {\\n \\n \\/\\/\\/physi.js scene\\n scene = new Physijs.Scene;\\n scene.setGravity(new THREE.Vector3(0, gravity, 0));\\n\\n \\/\\/\\/background\\n renderer.setClearColor (backgroundColor, 1);\\n\\n \\/\\/\\/camera\\n camera = new THREE.PerspectiveCamera(35, window.innerWidth\\/window.innerHeight, 1, 10000 );\\n camera.position.set( 0, 300, 600 );\\n camera.zoom = 3;\\n scene.add( camera );\\n\\n \\/\\/\\/lighting & shadows\\n var lightA1 = new THREE.AmbientLight(0xFFFFFF, 0.85);\\n scene.add(lightA1);\\n var lightD1 = new THREE.DirectionalLight( 0xFFFFFF, 0.3 );\\n lightD1.position.set( -20, 100, 20 );\\n lightD1.castShadow = true;\\n lightD1.shadow.camera.left = -100;\\n lightD1.shadow.camera.top = -100;\\n lightD1.shadow.camera.right = 100;\\n lightD1.shadow.camera.bottom = 100;\\n lightD1.shadow.camera.near = 1;\\n lightD1.shadow.camera.far = 130;\\n lightD1.shadow.mapSize.height = lightD1.shadow.mapSize.width = 1000;\\n scene.add( lightD1 );\\n renderer.shadowMap.enabled = true;\\n renderer.shadowMap.type = THREE.PCFSoftShadowMap;\\n\\n \\/\\/\\/fog\\n scene.fog = new THREE.Fog( \\n backgroundColor, \\n camera.position.z + 35, \\n camera.position.z + 250 \\n );\\n\\n \\/\\/\\/platform\\n var platform;\\n var platformDiameter = 170;\\n var platformRadiusTop = platformDiameter * 0.5; \\n var platformRadiusBottom = platformDiameter * 0.5 + 0.2;\\n var platformHeight = 1;\\n var platformSegments = 85;\\n \\n var platformGeometry = new THREE.CylinderGeometry( \\n platformRadiusTop, \\n platformRadiusBottom, \\n platformHeight, \\n platformSegments \\n );\\n \\n \\/\\/physi.js platform (invisible; provides structure) (separating three.js & physi.js improves peformance)\\n var physiPlatformMaterial = Physijs.createMaterial(\\n new THREE.MeshLambertMaterial(), pf, pr \\n );\\n var physiPlatform = new Physijs.CylinderMesh(platformGeometry, physiPlatformMaterial, 0 );\\n physiPlatform.name = \\\"physicalPlatform\\\";\\n physiPlatform.position.set(0, -0.5, 0);\\n physiPlatform.visible = false;\\n scene.add( physiPlatform );\\n\\n \\/\\/three.js platform (visible; provides image) (separating three.js & physi.js improves peformance)\\n var platformMaterialsArray = [];\\n var platformMaterialColor = new THREE.MeshLambertMaterial( { color: 0x606060 } );\\n platformMaterialsArray.push( platformMaterialColor ); \\/\\/(materialindex = 0)\\n var platformImage = \\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/asphalt_texture_2.jpg\\\";\\n var platformTextureLoader = new THREE.TextureLoader();\\n ptr = 4.5; \\/\\/platform texture repeat\\n platformTextureLoader.load(platformImage, function (texture) {\\n \\/\\/shrinks & repeats the image for the designate number of times\\n texture.wrapS = texture.wrapT = THREE.RepeatWrapping;\\n texture.repeat.set( ptr, ptr );\\n \\/\\/sets textue\\n var platformMaterialImage = new THREE.MeshLambertMaterial( { map: texture } );\\n platformMaterialsArray.push( platformMaterialImage ); \\/\\/(materials index = 1)\\n });\\n var faceCount = platformGeometry.faces.length;\\n for ( i=0; i<faceCount; i++ ) {\\n if ( i < platformSegments*2 ) { \\/\\/(cylinder side)\\n platformGeometry.faces[i].materialIndex = 0;\\n } else if ( i < platformSegments*3 ) { \\/\\/(cylinder top)\\n platformGeometry.faces[i].materialIndex = 1;\\n } else { \\/\\/(cylinder bottom)\\n platformGeometry.faces[i].materialIndex = 0;\\n }\\n }\\n var visiblePlatform = new THREE.Mesh( platformGeometry, platformMaterialsArray );\\n visiblePlatform.name = \\\"visiblePlatform\\\"\\n visiblePlatform.position.set(0, -.5, 0);\\n visiblePlatform.rotation.y = .4;\\n visiblePlatform.receiveShadow = true;\\n scene.add( visiblePlatform );\\n\\n}\\n\\n\\n\\/\\/\\/---Buses---\\/\\/\\/\\nfunction Bus(platformSide) { \\/\\/platformSide should be \\\"platformLeft\\\" or \\\"platformRight\\\"\\n \\n var bus = this;\\n bus.platformSide = platformSide;\\n bus.score = 0;\\n\\n \\/\\/\\/frame\\n var bfp = ( bus.platformSide == \\\"platformLeft\\\" ? { x:-40, y:3, z:0 } : { x:40, y:3, z:0 } ); \\/\\/bus frame position\\n var busFrameGeometry = new THREE.BoxGeometry( 33, 4, 5 );\\n var busFrameMesh = new THREE.MeshStandardMaterial({ color: 0x333333 });\\n var busFrameMaterial = Physijs.createMaterial( busFrameMesh, 0.9, 0.9 );\\n bus.frame = new Physijs.BoxMesh(busFrameGeometry, busFrameMaterial, 100 );\\n bus.frame.name = \\\"frame\\\";\\n bus.frame.componentOf = \\\"bus\\\";\\n bus.frame.position.set( bfp.x, bfp.y, bfp.z );\\n bus.frame.castShadow = true;\\n\\n \\/\\/\\/interior (provides mass to body for collisions)\\n var busInteriorGeometry = new THREE.BoxGeometry( 33, 7, 11 );\\n var busInteriorMesh = new THREE.MeshStandardMaterial({ color: 0x777777 });\\n var busInteriorMaterial = Physijs.createMaterial( busInteriorMesh, 50, 50 );\\n bus.interior = new Physijs.BoxMesh(busInteriorGeometry, busInteriorMaterial, 5000 );\\n bus.interior.name = \\\"interior\\\";\\n bus.interior.visible = false; \\/\\/(if visible, edges stick out from rounded frame)\\n bus.interior.componentOf = \\\"bus\\\"; \\n bus.interior.position.set( 0, 5.5, 0 );\\n bus.frame.add(bus.interior);\\n\\n \\/\\/\\/body\\n var color = ( bus.platformSide == \\\"platformLeft\\\" ? \\\"green\\\" : \\\"red\\\" );\\n var loader = new THREE.GLTFLoader();\\n loader.load(\\n `https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_body_${color}.glb`,\\n function ( gltf ) {\\n var scale = 5.6; \\n bus.body = gltf.scene.children[0]; \\n bus.body.name = \\\"body\\\";\\n bus.body.componentOf = \\\"bus\\\"; \\n bus.body.rotation.set ( 0, -1.5708, 0 );\\n bus.body.scale.set (scale,scale,scale);\\n bus.body.position.set ( 0, 3.6, 0 );\\n bus.body.castShadow = true;\\n bus.frame.add(bus.body);\\n },\\n );\\n \\n \\/\\/rotates platformLeft bus 180 degress so facing right bus\\n if ( bus.platformSide === \\\"platformLeft\\\" ) { bus.frame.rotation.y = Math.PI }\\n \\n \\/\\/adds all static bus parts to the scene as a single physical object\\n scene.add( bus.frame );\\n \\n \\/\\/\\/wheels\\n var fr = 2; \\/\\/wheel front radius\\n var br = 2; \\/\\/wheel back radius\\n var wi = 1; \\/\\/wheel width\\n var segments = 50; \\/\\/wheel cylinder segments (pie slices)\\n var busWheelMaterialsArray = [];\\n var busWheelImage = \\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_wheel_front_uv_fill.png\\\";\\n var busWheelGeometry = new THREE.CylinderGeometry( fr, br, wi, segments );\\n\\n \\/\\/wheel side & back material (color only, no image)\\n var busWheelColorBaseMaterial = new THREE.MeshLambertMaterial({ color: 0x000000 });\\n var busWheelColorMaterial = Physijs.createMaterial( busWheelColorBaseMaterial, bwf, bwr );\\n busWheelMaterialsArray.push( busWheelColorMaterial ); \\/\\/(.materialindex = 0)\\n\\n \\/\\/wheel front material (wheel image)\\n var busWheelImageLoader = new THREE.TextureLoader();\\n busWheelImageLoader.load( busWheelImage, function ( texture ) { \\n var busWheelImageMaterial = Physijs.createMaterial( \\n new THREE.MeshBasicMaterial({ map: texture }), bwf, bwr \\n ); \\n busWheelMaterialsArray.push( busWheelImageMaterial ); \\/\\/(.materialindex = 1)\\n }); \\n\\n \\/\\/assigns each of the wheel's faces to a .materialindex\\n var busWheelFaceCount = busWheelGeometry.faces.length;\\n for ( i=0; i<busWheelFaceCount; i++ ) {\\n \\/\\/first set of faces makes up the wheel's tread\\n if ( i < segments*2 ) {\\n busWheelGeometry.faces[i].materialIndex = 0; \\/\\/assigns color material index\\n \\/\\/second set of faces makes up the wheel's outside\\n } else if ( i < segments*3 ) {\\n busWheelGeometry.faces[i].materialIndex = 1; \\/\\/assigns image material index\\n \\/\\/third set of faces makes up the wheel's inside\\n } else {\\n busWheelGeometry.faces[i].materialIndex = 0; \\/\\/assigns color material index\\n }\\n }\\n\\n \\/\\/wheel creation & configuration as four physi.js objects\\n bus.wheel_fl = new Physijs.CylinderMesh( busWheelGeometry, busWheelMaterialsArray, 300 );\\n bus.wheel_fr = new Physijs.CylinderMesh( busWheelGeometry, busWheelMaterialsArray, 300 );\\n bus.wheel_bl = new Physijs.CylinderMesh( busWheelGeometry, busWheelMaterialsArray, 300 );\\n bus.wheel_br = new Physijs.CylinderMesh( busWheelGeometry, busWheelMaterialsArray, 300 );\\n\\n if ( bus.platformSide === \\\"platformRight\\\" ) {\\n var frontX = bfp.x - 9.5; var backX = bfp.x + 9.5 \\n } else { \\n var frontX = bfp.x + 9.5; var backX = bfp.x - 9.5 \\n }\\n configureWheel( bus.wheel_fl, { x: frontX, y: 2, z: bfp.z + 5 }, \\\"port\\\" );\\n configureWheel( bus.wheel_fr, { x: frontX, y: 2, z: bfp.z - 5 }, \\\"starboard\\\" );\\n configureWheel( bus.wheel_bl, { x: backX, y: 2, z: bfp.z + 5 }, \\\"port\\\" );\\n configureWheel( bus.wheel_br, { x: backX, y: 2, z: bfp.z - 5 }, \\\"starboard\\\" ); \\n \\n \\/\\/\\/wheel constraints\\n var wheel_fl_constraint = new Physijs.DOFConstraint( bus.wheel_fl, bus.frame, bus.wheel_fl.position );\\n var wheel_fr_constraint = new Physijs.DOFConstraint( bus.wheel_fr, bus.frame, bus.wheel_fr.position );\\n var wheel_bl_constraint = new Physijs.DOFConstraint( bus.wheel_bl, bus.frame, bus.wheel_bl.position );\\n var wheel_br_constraint = new Physijs.DOFConstraint( bus.wheel_br, bus.frame, bus.wheel_br.position );\\n\\n bus.wheel_fl_constraint = configureWheelConstraints( wheel_fl_constraint );\\n bus.wheel_fr_constraint = configureWheelConstraints( wheel_fr_constraint );\\n bus.wheel_bl_constraint = configureWheelConstraints( wheel_bl_constraint );\\n bus.wheel_br_constraint = configureWheelConstraints( wheel_br_constraint );\\n\\n}\\n\\n\\n \\n\\/\\/\\/\\/\\/---Functions---\\/\\/\\/\\/\\/\\n\\nfunction playLoadingAnimationIfDocumentNotReady() {\\n loadingAnimation.style.visibility = \\\"visible\\\";\\n document.onreadystatechange = () => {\\n if (document.readyState === \\\"complete\\\") { \\n loadingAnimation.style.visibility = \\\"hidden\\\"; \\n }\\n }\\n}\\n\\nfunction onWindowResize() {\\n\\tsceneHeight = window.innerHeight;\\n\\tsceneWidth = window.innerWidth;\\n\\trenderer.setSize(sceneWidth, sceneHeight);\\n\\tcamera.aspect = sceneWidth\\/sceneHeight;\\n\\tcamera.updateProjectionMatrix();\\n}\\n\\nfunction configureWheel( wheel, position, BusSide ) {\\n wheel.name = \\\"wheel\\\";\\n wheel.componentOf = \\\"bus\\\";\\n BusSide === \\\"port\\\" ? wheel.rotation.x = Math.PI \\/ 2 : wheel.rotation.x = -Math.PI \\/ 2;\\n wheel.position.set( position.x, position.y, position.z );\\n wheel.setDamping( 0.5, 0.5 );\\n wheel.castShadow = true;\\n scene.add( wheel );\\n}\\n\\nfunction configureWheelConstraints( constraint ) {\\n scene.addConstraint( constraint );\\n constraint.setAngularLowerLimit({ x: 0, y: 0, z: 1 });\\n constraint.setAngularUpperLimit({ x: 0, y: 0, z: 0 });\\n return constraint;\\n}\\n\\nfunction restartGame() {\\n window.location.reload();\\n}\\n\\nfunction initializeMatch() {\\n environment = new Environment();\\n busArray = [];\\n busArray.push( new Bus(\\\"platformLeft\\\") );\\n busArray.push( new Bus(\\\"platformRight\\\") );\\n roundActive = true;\\n}\\n\\nfunction displayLoadingAnimation(milliseconds) {\\n loadingAnimation.style.visibility = \\\"visible\\\";\\n loadingAnimationVisible = true;\\n setTimeout(function(){ \\n loadingAnimation.style.visibility = \\\"hidden\\\"; \\n loadingAnimationVisible = false;\\n }, milliseconds); \\n}\\n\\nfunction pause(milliseconds) {\\n var then = Date.now(); \\n var now;\\n do { now = Date.now() } while ( now - then < milliseconds );\\n}\\n\\nfunction freezeBuses() {\\n for ( i=0; i<busArray.count; i++ ) {\\n busArray[i].frame.mass = 0;\\n busArray[i].interior.mass = 0;\\n busArray[i].wheel_fl.mass = busArray[i].wheel_fr.mass = 0;\\n busArray[i].wheel_bl.mass = busArray[i].wheel_br.mass = 0;\\n } \\n}\\n\\nfunction restartGame() {\\n Player1.score = 0;\\n Player2.score = 0;\\n var greenScoreEls = document.getElementsByClassName(\\\"green_score\\\"); \\n var redScoreEls = document.getElementsByClassName(\\\"red_score\\\");\\n for ( i=0; i<2; i++) {\\n greenScoreEls[i].src = \\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_0of3_green.svg\\\";\\n redScoreEls[i].src = \\\"https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_0of3_red.svg\\\";\\n };\\n $(\\\"#game_win_gretchen_page_div\\\").css(\\\"visibility\\\", \\\"hidden\\\");\\n $(\\\"#game_win_bertha_page_div\\\").css(\\\"visibility\\\", \\\"hidden\\\");\\n gameHasEnded = false;\\n initializeMatch();\\n}\\n\\nfunction aBusHasFallen() {\\n return ( busArray[0].frame.position.y < -50 || busArray[1].frame.position.y < -50 )\\n}\\n\\nfunction bothBusesHaveFallen() {\\n return ( busArray[0].frame.position.y < 0 && busArray[1].frame.position.y < 0 )\\n}\\n\\nfunction declareMatchDraw() {\\n roundActive = false;\\n $(\\\"#round_draw_page_div\\\").css(\\\"visibility\\\", \\\"visible\\\");\\n}\\n\\nfunction declareRoundWin(winner) {\\n loadingAnimation.style.visibility = \\\"visible\\\";\\n var cardEl = document.getElementById(\\\"round_win_card\\\"); \\n cardEl.src = `https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_round_win_card_${winner.name}.svg`;\\n var greenScoreEls = document.getElementsByClassName(\\\"green_score\\\"); \\n var redScoreEls = document.getElementsByClassName(\\\"red_score\\\");\\n for ( i=0; i<2; i++) {\\n greenScoreEls[i].src = `https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_${Player1.score}of3_green.svg`;\\n redScoreEls[i].src = `https:\\/\\/s3-us-west-2.amazonaws.com\\/s.cdpn.io\\/409445\\/bus_${Player2.score}of3_red.svg`;\\n };\\n $(\\\"#round_win_page_div\\\").css(\\\"visibility\\\", \\\"visible\\\");\\n displayLoadingAnimation(1500);\\n}\\n\\nfunction declareGameWin(winner) {\\n gameHasEnded = true;\\n loadingAnimation.style.visibility = \\\"visible\\\";\\n if (winner.name === \\\"gretchen\\\") {\\n $(\\\"#game_win_gretchen_page_div\\\").css(\\\"visibility\\\", \\\"visible\\\");\\n } else {\\n $(\\\"#game_win_bertha_page_div\\\").css(\\\"visibility\\\", \\\"visible\\\");\\n }\\n displayLoadingAnimation(1500);\\n}\\n\\nfunction checkForMatchCompletion() {\\n if ( aBusHasFallen() ) {\\n freezeBuses(); \\n pause(1000);\\n roundActive = false;\\n if ( bothBusesHaveFallen() ) { \\n declareMatchDraw();\\n } else {\\n var winner = busArray[0].frame.position.y > 0 ? Player1 : Player2;\\n winner.score += 1;\\n if (winner.score < 3) {\\n declareRoundWin(winner);\\n } else {\\n declareGameWin(winner);\\n }\\n }\\n }\\n}\\n\\nfunction handleKeyDown ( keyEvent ) {\\n \\/\\/ sets wheel motors; configureAngularMotor params are:\\n \\/\\/ 1) which_motor (as numbers matched to axes: 0 = x, 1 = y, 2 = z)\\n \\/\\/ 2) low_limit (lower limit of the motor)\\n \\/\\/ 3) high_limit (upper limit of the motor)\\n \\/\\/ 4) velocity (target velocity)\\n \\/\\/ 5) max_force (maximum force the motor can apply)\\n switch ( keyEvent.keyCode ) {\\n \\/\\/ BUS 1\\n \\/\\/ pivots wheels for steering\\n case 65: case 37: \\/\\/ \\\"a\\\" key or left arrow key (turn left)\\n busArray[0].wheel_fr_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, 10, 200 );\\n busArray[0].wheel_fr_constraint.enableAngularMotor( 1 );\\n busArray[0].wheel_fl_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, 10, 200 );\\n busArray[0].wheel_fl_constraint.enableAngularMotor( 1 );\\n break;\\n case 68: case 39: \\/\\/ \\\"d\\\" key or right arrow key (turn right)\\n busArray[0].wheel_fr_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, -10, 200 );\\n busArray[0].wheel_fr_constraint.enableAngularMotor( 1 );\\n busArray[0].wheel_fl_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, -10, 200 );\\n busArray[0].wheel_fl_constraint.enableAngularMotor( 1 );\\n break;\\n \\/\\/ rotates wheels for propulsion\\n case 87: case 38: \\/\\/ \\\"w\\\" key or up arrow key (forward)\\n busArray[0].wheel_bl_constraint.configureAngularMotor( 2, 1, 0, -30, 50000 );\\n busArray[0].wheel_bl_constraint.enableAngularMotor( 2 );\\n busArray[0].wheel_br_constraint.configureAngularMotor( 2, 1, 0, -30, 50000 );\\n busArray[0].wheel_br_constraint.enableAngularMotor( 2 );\\n break;\\n case 83: case 40: \\/\\/ \\\"s\\\" key or down arrow key (backward)\\n busArray[0].wheel_bl_constraint.configureAngularMotor( 2, 1, 0, 20, 3500 );\\n busArray[0].wheel_bl_constraint.enableAngularMotor( 2 );\\n busArray[0].wheel_br_constraint.configureAngularMotor( 2, 1, 0, 20, 3500 );\\n busArray[0].wheel_br_constraint.enableAngularMotor( 2 );\\n break;\\n \\/\\/ BUS 2\\n \\/\\/ pivots wheels for steering\\n case 76: \\/\\/ \\\"l\\\" key (turn left)\\n busArray[1].wheel_fr_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, 10, 200 );\\n busArray[1].wheel_fr_constraint.enableAngularMotor( 1 );\\n busArray[1].wheel_fl_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, 10, 200 );\\n busArray[1].wheel_fl_constraint.enableAngularMotor( 1 );\\n break;\\n case 222: \\/\\/ \\\"'\\\" key (turn right)\\n busArray[1].wheel_fr_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, -10, 200 );\\n busArray[1].wheel_fr_constraint.enableAngularMotor( 1 );\\n busArray[1].wheel_fl_constraint.configureAngularMotor( 1, -Math.PI \\/ 4, Math.PI \\/ 4, -10, 200 );\\n busArray[1].wheel_fl_constraint.enableAngularMotor( 1 );\\n break;\\n \\/\\/ rotates wheels for propulsion\\n case 80: \\/\\/ \\\"p\\\" key (forward)\\n busArray[1].wheel_bl_constraint.configureAngularMotor( 2, 1, 0, 30, 50000 );\\n busArray[1].wheel_bl_constraint.enableAngularMotor( 2 );\\n busArray[1].wheel_br_constraint.configureAngularMotor( 2, 1, 0, 30, 50000 );\\n busArray[1].wheel_br_constraint.enableAngularMotor( 2 );\\n break;\\n case 186: \\/\\/ \\\";\\\" key (backward)\\n busArray[1].wheel_bl_constraint.configureAngularMotor( 2, 1, 0, -20, 3500 );\\n busArray[1].wheel_bl_constraint.enableAngularMotor( 2 );\\n busArray[1].wheel_br_constraint.configureAngularMotor( 2, 1, 0, -20, 3500 );\\n busArray[1].wheel_br_constraint.enableAngularMotor( 2 );\\n break;\\n }\\n}\\n\\nfunction handleKeyUp(keyEvent){\\n switch( keyEvent.keyCode ) {\\n \\/\\/ BUS 1\\n \\/\\/sets front wheels straight again\\n case 65: case 68: case 37: case 39:\\n busArray[0].wheel_fr_constraint.configureAngularMotor( 1, 0, 0, 10, 200 );\\n busArray[0].wheel_fr_constraint.enableAngularMotor( 1 );\\n busArray[0].wheel_fl_constraint.configureAngularMotor( 1, 0, 0, 10, 200 );\\n busArray[0].wheel_fl_constraint.enableAngularMotor( 1 );\\n\\t\\tbreak;\\n \\/\\/stops back wheel rotation\\n case 87: case 83: case 38: case 40: \\n busArray[0].wheel_bl_constraint.configureAngularMotor( 2, 0, 0, 0, 2000 );\\n busArray[0].wheel_bl_constraint.enableAngularMotor( 2 );\\n busArray[0].wheel_br_constraint.configureAngularMotor( 2, 0, 0, 0, 2000 );\\n busArray[0].wheel_br_constraint.enableAngularMotor( 2 );\\n\\t\\tbreak;\\n \\/\\/ BUS 2\\n \\/\\/sets front wheels straight again\\n case 76: case 222:\\n busArray[1].wheel_fr_constraint.configureAngularMotor( 1, 0, 0, 10, 200 );\\n busArray[1].wheel_fr_constraint.enableAngularMotor( 1 );\\n busArray[1].wheel_fl_constraint.configureAngularMotor( 1, 0, 0, 10, 200 );\\n busArray[1].wheel_fl_constraint.enableAngularMotor( 1 );\\n\\t\\tbreak;\\n \\/\\/stops back wheel rotation\\n case 80: case 186:\\n busArray[1].wheel_bl_constraint.configureAngularMotor( 2, 0, 0, 0, 2000 );\\n busArray[1].wheel_bl_constraint.enableAngularMotor( 2 );\\n busArray[1].wheel_br_constraint.configureAngularMotor( 2, 0, 0, 0, 2000 );\\n busArray[1].wheel_br_constraint.enableAngularMotor( 2 );\\n\\t\\tbreak;\\n\\t}\\n}\\n\\n\\n\\n\\/\\/\\/\\/\\/---Interaction---\\/\\/\\/\\/\\/\\n\\nwindow.addEventListener(\\\"resize\\\", onWindowResize, false);\\n\\ndocument.onkeydown = handleKeyDown;\\ndocument.onkeyup = handleKeyUp;\\n\\n\\n$(\\\"#button_play\\\").click(function(){ \\n gameHasBegun = true;\\n displayLoadingAnimation(1500); \\n $(\\\"#landing_page_div\\\").hide(); \\n initializeMatch(); \\n});\\n\\n$(\\\"#button_restart\\\").click(function(){ \\n displayLoadingAnimation(1500); \\n restartGame() \\n});\\n\\n$(\\\"#button_draw\\\").click(function(){ \\n declareMatchDraw(); \\n});\\n\\n$(\\\"#button_play_next_round\\\").click(function(){ \\n displayLoadingAnimation(1500); \\n $(\\\"#round_win_page_div\\\").css(\\\"visibility\\\", \\\"hidden\\\"); \\n initializeMatch(); \\n});\\n\\n$(\\\"#button_replay_round\\\").click(function(){ \\n displayLoadingAnimation(1500); \\n $(\\\"#round_draw_page_div\\\").css(\\\"visibility\\\", \\\"hidden\\\"); \\n initializeMatch(); \\n});\\n\\n$(\\\".button_new_game\\\").click(function(){ \\n displayLoadingAnimation(1500); \\n restartGame(); \\n});\\n\\n$(document).on(\\\"keypress\\\",function(e) {\\n if ( e.key === \\\"Enter\\\" && !loadingAnimationVisible ) {\\n if ( !gameHasBegun ) {\\n $(\\\"#button_play\\\").click();\\n } else if ( gameHasEnded ) {\\n $(\\\".button_new_game\\\").click();\\n } else if ( !roundActive ) {\\n $(\\\"#button_play_next_round\\\").click();\\n $(\\\"#button_replay_round\\\").click();\\n }\\n e.stopPropagation();\\n }\\n});\\n\\n\\n\\n\\/\\/\\/\\/\\/---Display---\\/\\/\\/\\/\\/\\n\\ninitializeMatch();\\n\\/\\/playLoadingAnimationIfDocumentNotReady();\\n\\nfunction render() {\\n if ( roundActive === true ) { checkForMatchCompletion(); }\\n scene.simulate();\\n camera.lookAt( 0, 1, 0 );\\n \\/\\/camera.lookAt( busArray[1].frame.position );\\n camera.updateProjectionMatrix();\\n renderer.render( scene, camera);\\n requestAnimationFrame( render ); \\n};\\n\\nrender();\",\"html_pre_processor\":\"none\",\"css_pre_processor\":\"none\",\"js_pre_processor\":\"none\",\"html_classes\":\"\",\"css_starter\":\"neither\",\"js_library\":null,\"created_at\":\"2018-10-03T16:45:00.000Z\",\"updated_at\":\"2022-02-24T13:36:28.239Z\",\"title\":\"Bus Derby\",\"description\":\"![](https:\\/\\/dzwonsemrish7.cloudfront.net\\/items\\/2m0U072g25250e0I3m19\\/ezgif.com-video-to-gif.gif)\\n\\nA 3D vehicle derby video game rendered in three.js and run on a physi.js physics engine. UV maps designed in Adobe Illustrator; meshes created in Blender and imported as glTF. \\n\\nAlso wrote a [tutorial](https:\\/\\/codepen.io\\/matthewmain\\/post\\/how-to-import-a-3d-blender-object-into-a-three-js-project-as-a-gltf-file) on implementing complex 3D shapes like these, check it out. :)\",\"slug_hash\":\"YJwoVy\",\"head\":\"\",\"private\":false,\"slug_hash_private\":\"c44db81a38a797cdfbc6d96272e8103e\",\"has_animation\":true,\"team_id\":0,\"css_prefix\":\"neither\",\"template\":false,\"parent_id\":0,\"comments_count\":0,\"custom_screenshot_filename\":null,\"loves_count\":0,\"pick\":false,\"popularity_score\":0,\"views_count\":0,\"pick_visible_at\":null,\"cpid\":\"01663ad1-7ee0-7b0b-83d9-5f5746f18849\",\"is_new_editor_pen\":false,\"protected\":false,\"access\":\"Public\",\"pen_hash\":null,\"hashid\":\"YJwoVy\"}"}