1 /**
  2  * @fileOverview
  3  * physics.gl.enchant.js
  4  * @version 0.3.6
  5  * @require enchant.js v0.4.5+
  6  * @require gl.enchant.js v0.3.6+
  7  * @require primitive.gl.enchant.js v0.3.5+
  8  * @require gl-matrix.js 1.3.7+
  9  * @author UEI Corporation
 10  *
 11  * @description
 12  * @detail
 13  * ammo.js:
 14  * https://github.com/kripken/ammo.js
 15  */
 16 if (typeof Ammo === 'undefined') {
 17     throw new Error('physics.gl.enchant.js must be loaded after ammo.js');
 18 }
 19 if (enchant.gl !== undefined && enchant.gl.primitive !== undefined) {
 20     (function() {
 21         /**
 22          * namespace object
 23          * @type {Object}
 24          */
 25         enchant.gl.physics = {};
 26         /**
 27          * @scope enchant.gl.physics.World.prototype
 28          */
 29         enchant.gl.physics.World = enchant.Class.create({
 30             /**
 31              */
 32             initialize: function() {
 33                 var g = new Ammo.btVector3(0, -10, 0);
 34                 var collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
 35                 var dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
 36                 var pairCache = new Ammo.btDbvtBroadphase();
 37                 var constraintSolver = new Ammo.btSequentialImpulseConstraintSolver();
 38 
 39                 this._dynamicsWorld = new Ammo.btDiscreteDynamicsWorld(
 40                     dispatcher, pairCache, constraintSolver, collisionConfiguration);
 41 
 42                 this._dynamicsWorld.setGravity(g);
 43 
 44                 Ammo.destroy(g);
 45             },
 46             /**
 47              */
 48             setGravity: function(gx, gy, gz) {
 49                 var g = new Ammo.btVector3(gx, gy, gz);
 50                 this._dynamicsWorld.setGravity(g);
 51                 Ammo.destroy(g);
 52             },
 53             /**
 54              */
 55             stepSimulation: function(timeStep, maxSubSteps, fixedTimeStep) {
 56                 return this._dynamicsWorld.stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
 57             },
 58             /**
 59              */
 60             addRigid: function(rigid) {
 61                 this._dynamicsWorld.addRigidBody(rigid.rigidBody);
 62                 rigid.world = this;
 63             },
 64             /**
 65              */
 66             removeRigid: function(rigid) {
 67                 this._dynamicsWorld.removeRigidBody(rigid.rigidBody);
 68                 rigid.world = null;
 69             },
 70             /**
 71              */
 72             contactPairTest: function(rigid1, rigid2) {
 73                 var callback = new Ammo.ConcreteContactResultCallback();
 74                 var result = false;
 75                 Ammo.customizeVTable(callback, [
 76                     {
 77                         original: Ammo.ConcreteContactResultCallback.prototype.addSingleResult,
 78                         replacement: function(tp, cp, colObj0, partid0, index0, colObj1, partid1, index1) {
 79                             result = true;
 80                         }
 81                     }
 82                 ]);
 83                 this._dynamicsWorld.contactPairTest(rigid1.rigidBody, rigid2.rigidBody, callback);
 84                 Ammo.destroy(callback);
 85                 return result;
 86             }
 87         });
 88 
 89         /**
 90          * @scope enchant.gl.physics.Rigid.prototype
 91          */
 92         enchant.gl.physics.Rigid = enchant.Class.create({
 93             /**
 94              */
 95             initialize: function(shape, mass, lDamp, aDamp) {
 96                 if (typeof shape === 'undefined') {
 97                     shape = new Ammo.btBoxShape(1);
 98                 }
 99                 if (typeof mass === 'undefined') {
100                     mass = 1;
101                 }
102 
103                 var localInertia = new Ammo.btVector3(0, 0, 0);
104                 shape.calculateLocalInertia(mass, localInertia);
105 
106                 var transform = new Ammo.btTransform();
107                 transform.setIdentity();
108 
109                 var motionState = new Ammo.btDefaultMotionState(transform);
110                 var rigidBodyInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
111                 rigidBodyInfo.set_m_restitution(0.1);
112                 rigidBodyInfo.set_m_friction(3.0);
113 
114                 if (typeof lDamp !== 'undefined') {
115                     rigidBodyInfo.set_m_linearDamping(lDamp);
116                 }
117                 if (typeof aDamp !== 'undefined') {
118                     rigidBodyInfo.set_m_angularDamping(aDamp);
119                 }
120 
121                 this.shape = shape;
122                 /**
123                  */
124                 this.world = null;
125 
126                 /**
127                  */
128                 this.rigidBody = new Ammo.btRigidBody(rigidBodyInfo);
129                 var p = Ammo.getPointer(this.rigidBody);
130                 enchant.gl.physics.Rigid._refs[p] = this;
131 
132                 Ammo.destroy(transform);
133                 Ammo.destroy(localInertia);
134                 Ammo.destroy(rigidBodyInfo);
135 
136                 this._x = 0;
137                 this._y = 0;
138                 this._z = 0;
139                 this._scaleX = 1;
140                 this._scaleY = 1;
141                 this._scaleZ = 1;
142                 this._mass = mass;
143                 this._restitution = 0.3;
144                 this._friction = 0.3;
145             },
146             /**
147              */
148             scale: function(x, y, z) {
149                 this.activate();
150                 this._scaleX *= x;
151                 this._scaleY *= y;
152                 this._scaleZ *= z;
153                 var sv = new Ammo.btVector3(this._scaleX, this._scaleY, this._scaleZ);
154                 this.shape.setLocalScaling(sv);
155                 Ammo.destroy(sv);
156             },
157             _scaleAxis: function(axis, scale) {
158                 axis.toUpperCase();
159                 this['_scale' + axis] = scale;
160                 var sv = new Ammo.btVector3(this._scaleX, this._scaleY, this._scaleZ);
161                 this.shape.setLocalScaling(sv);
162                 Ammo.destroy(sv);
163             },
164             /**
165              */
166             translate: function(x, y, z) {
167                 this.activate();
168                 var vec = new Ammo.btVector3(x, y, z);
169                 this.rigidBody.translate(vec);
170                 Ammo.destroy(vec);
171                 this._x += x;
172                 this._y += y;
173                 this._z += z;
174             },
175             _translateAxis: function(axis, n) {
176                 this.activate();
177                 var x = 0;
178                 var y = 0;
179                 var z = 0;
180                 if (axis === 'x') {
181                     x = n - this._x;
182                     this._x = n;
183                 } else if (axis === 'y') {
184                     y = n - this._y;
185                     this._y = n;
186                 } else if (axis === 'z') {
187                     z = n - this._z;
188                     this._z = n;
189                 }
190                 var vec = new Ammo.btVector3(x, y, z);
191                 this.rigidBody.translate(vec);
192                 Ammo.destroy(vec);
193             },
194             /**
195              */
196             rotationSet: function(quat) {
197                 var qq = quat._quat;
198                 var q = new Ammo.btQuaternion(qq[0], qq[1], qq[2], qq[3]);
199                 var t = this._getTransform();
200                 t.setRotation(q);
201                 this.rigidBody.setWorldTransform(t);
202                 Ammo.destroy(q);
203                 Ammo.destroy(t);
204             },
205             /**
206              */
207             rotationApply: function(quat) {
208                 var quat1 = quat._quat;
209                 var t = this._getTransform();
210                 var qq = t.getRotation();
211                 var quat2 = quat4.create([qq.x(), qq.y(), qq.z(), qq.w()]);
212                 quat4.multiply(quat2, quat1, quat2);
213                 var q = new Ammo.btQuaternion(quat2[0], quat2[1], quat2[2], quat2[3]);
214                 t.setRotation(q);
215                 this.rigidBody.setWorldTransform(t);
216                 Ammo.destroy(q);
217                 Ammo.destroy(t);
218             },
219             /**
220              */
221             clearForces: function() {
222                 var vec0 = new Ammo.btVector3(0, 0, 0);
223                 this.rigidBody.setLinearVelocity(vec0);
224                 this.rigidBody.setAngularVelocity(vec0);
225                 this.rigidBody.clearForces();
226                 Ammo.destroy(vec0);
227             },
228             /**
229              */
230             contactTest: function(rigid) {
231                 if (this.world && rigid.world &&
232                     this.world === rigid.world) {
233                     return this.world.contactPairTest(this, rigid);
234                 } else {
235                     return false;
236                 }
237             },
238             /**
239              */
240             activate: function(force) {
241                 this.rigidBody.activate(force);
242             },
243             /**
244              */
245             applyCentralImpulse: function(powx, powy, powz) {
246                 var powv = new Ammo.btVector3(powx, powy, powz);
247                 this.activate();
248                 this.rigidBody.applyCentralImpulse(powv);
249                 Ammo.destroy(powv);
250             },
251             /**
252              */
253             applyImpulse: function(powx, powy, powz, posx, posy, posz) {
254                 var powv = new Ammo.btVector3(powx, powy, powz);
255                 var posv = new Ammo.btVector3(posx, posy, posz);
256                 this.activate();
257                 this.rigidBody.applyImpulse(powv, posv);
258                 Ammo.destroy(powv);
259                 Ammo.destroy(posv);
260             },
261             _getTransform: function() {
262                 return this.rigidBody.getWorldTransform();
263             },
264             /**
265              */
266             kinematize: function() {
267                 var flag = this.rigidBody.getCollisionFlags();
268                 this.rigidBody.setCollisionFlags(flag | 2);
269                 this.rigidBody.setActivationState(4);
270             },
271             /**
272              */
273             restitution: {
274                 get: function() {
275                     return this._restitution;
276                 },
277                 set: function(n) {
278                     this._restitution = n;
279                     this.rigidBody.setRestitution(n);
280                 }
281             },
282             /**
283              */
284             friction: {
285                 get: function() {
286                     return this._friction;
287                 },
288                 set: function(n) {
289                     this._friction = n;
290                     this.rigidBody.setFriction(n);
291                 }
292             }
293         });
294         enchant.gl.physics.Rigid._refs = {};
295 
296         /**
297          * @scope enchant.gl.physics.RigidBox.prototype
298          */
299         enchant.gl.physics.RigidBox = enchant.Class.create(enchant.gl.physics.Rigid, {
300             /**
301              */
302             initialize: function(sx, sy, sz, mass) {
303                 var scale = new Ammo.btVector3(sx, sy, sz);
304                 var shape = new Ammo.btBoxShape(scale);
305                 enchant.gl.physics.Rigid.call(this, shape, mass);
306                 Ammo.destroy(scale);
307             }
308         });
309         /**
310          * @scope enchant.gl.physics.RigidCube.prototype
311          */
312         enchant.gl.physics.RigidCube = enchant.Class.create(enchant.gl.physics.RigidBox, {
313             /**
314              */
315             initialize: function(scale, mass) {
316                 enchant.gl.physics.RigidBox.call(this, scale, scale, scale, mass);
317             }
318         });
319 
320         /**
321          * @scope enchant.gl.physics.RigidSphere.prototype
322          */
323         enchant.gl.physics.RigidSphere = enchant.Class.create(enchant.gl.physics.Rigid, {
324             /**
325              */
326             initialize: function(s, mass, lDamp, aDamp) {
327                 var shape = new Ammo.btSphereShape(s);
328                 enchant.gl.physics.Rigid.call(this, shape, mass, lDamp, aDamp);
329             }
330         });
331 
332         /**
333          * @scope enchant.gl.physics.RigidCylinder.prototype
334          */
335         enchant.gl.physics.RigidCylinder = enchant.Class.create(enchant.gl.physics.Rigid, {
336             /**
337              */
338             initialize: function(r, h, mass) {
339                 var scale = new Ammo.btVector3(r, h, r);
340                 var shape = new Ammo.btCylinderShape(scale);
341                 enchant.gl.physics.Rigid.call(this, shape, mass);
342                 Ammo.destroy(scale);
343             }
344         });
345 
346         /**
347          * @scope enchant.gl.physics.RigidCapsule.prototype
348          */
349         enchant.gl.physics.RigidCapsule = enchant.Class.create(enchant.gl.physics.Rigid, {
350             /**
351              */
352             initialize: function(r, h, mass) {
353                 var shape = new Ammo.btCapsuleShape(r, h);
354                 enchant.gl.physics.Rigid.call(this, shape, mass);
355             }
356         });
357 
358         /**
359          * @scope enchant.gl.physics.RigidPlane.prototype
360          */
361         enchant.gl.physics.RigidPlane = enchant.Class.create(enchant.gl.physics.Rigid, {
362             /**
363              */
364             initialize: function(nx, ny, nz, distance) {
365                 var normal = new Ammo.btVector3(nx, ny, nz);
366                 var shape = new Ammo.btStaticPlaneShape(normal, distance);
367                 enchant.gl.physics.Rigid.call(this, shape, 0);
368                 Ammo.destroy(normal);
369             }
370         });
371 
372         /**
373          * @scope enchant.gl.physics.RigidContainer.prototype
374          */
375         enchant.gl.physics.RigidContainer = enchant.Class.create(enchant.gl.physics.Rigid, {
376             /**
377              */
378             initialize: function(s, mass) {
379                 var shape = new Ammo.btCompoundShape(s);
380                 var addWall = function(sx, sy, sz, px, py, pz) {
381                     var sc = new Ammo.btVector3(sx, sy, sz);
382                     var tr = new Ammo.btTransform();
383                     tr.setIdentity();
384                     var or = new Ammo.btVector3(px, py, pz);
385                     tr.setOrigin(or);
386                     var shp = new Ammo.btBoxShape(sc);
387                     shape.addChildShape(tr, shp);
388                     Ammo.destroy(sc);
389                     Ammo.destroy(or);
390                     Ammo.destroy(tr);
391                 };
392                 addWall(s, s / 8, s, 0, s / 8 - s, 0);
393                 addWall(s - s / 8, s - s / 8 - s / 8, s / 8, s / 8, 0, s / 8 - s);
394                 addWall(s - s / 8, s - s / 8 - s / 8, s / 8, -s / 8, 0, s - s / 8);
395                 addWall(s / 8, s - s / 8 - s / 8, s - s / 8, s / 8 - s, 0, -s / 8);
396                 addWall(s / 8, s - s / 8 - s / 8, s - s / 8, s - s / 8, 0, s / 8);
397                 enchant.gl.physics.Rigid.call(this, shape, mass);
398             }
399         });
400 
401         /**
402          * @scope enchant.gl.physics.PhyScene3D.prototype
403          */
404         enchant.gl.physics.PhyScene3D = enchant.Class.create(enchant.gl.Scene3D, {
405             /**
406              */
407             initialize: function() {
408                 enchant.gl.Scene3D.call(this);
409                 var core = enchant.Core.instance;
410                 this.world = new enchant.gl.physics.World();
411                 this.isPlaying = false;
412                 this.timeStep = 1 / core.fps;
413                 this.maxSubSteps = 1;
414                 this.fixedTimeStep = 1 / 60;
415                 var that = this;
416                 this._stepping = function() {
417                     that.stepSimulation(that.timeStep, that.maxSubSteps, that.fixedTimeStep);
418                 };
419             },
420             /**
421              */
422             addChild: function(sprite) {
423                 enchant.gl.Scene3D.prototype.addChild.call(this, sprite);
424                 if (sprite instanceof enchant.gl.physics.PhySprite3D) {
425                     this.world.addRigid(sprite.rigid);
426                 }
427             },
428             /**
429              */
430             removeChild: function(sprite) {
431                 enchant.gl.Scene3D.prototype.removeChild.call(this, sprite);
432                 if (sprite instanceof enchant.gl.physics.PhySprite3D) {
433                     this.world.removeRigid(sprite.rigid);
434                 }
435             },
436             /**
437              */
438             setGravity: function(x, y, z) {
439                 this.world.setGravity(x, y, z);
440             },
441             /**
442              */
443             stepSimulation: function(timeStep, maxSubSteps, fixedTimeStep) {
444                 var subStep = this.world.stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
445                 var e = new enchant.Event('timestep');
446                 e.timeStep = timeStep;
447                 e.subStep = subStep;
448                 this.dispatchEvent(e);
449                 for (var i = 0, l = this.childNodes.length; i < l; i++) {
450                     if (this.childNodes[i] instanceof enchant.gl.physics.PhySprite3D) {
451                         this.childNodes[i].dispatchEvent(e);
452                     }
453                 }
454             },
455             /**
456              */
457             play: function() {
458                 var core = enchant.Core.instance;
459                 if (!this.isPlaying) {
460                     this.isPlaying = true;
461                     core.addEventListener('enterframe', this._stepping);
462                 }
463             },
464             /**
465              */
466             stop: function() {
467                 var core = enchant.Core.instance;
468                 this.isPlaying = false;
469                 core.removeEventListener('enterframe', this._stepping);
470             }
471         });
472 
473         /**
474          * @scope enchant.gl.physics.PhySprite3D.prototype
475          */
476         enchant.gl.physics.PhySprite3D = enchant.Class.create(enchant.gl.Sprite3D, {
477             /**
478              */
479             initialize: function(rigid) {
480                 enchant.gl.Sprite3D.call(this);
481                 this.rigid = rigid;
482 
483                 this.addEventListener('timestep', function() {
484                     var t = this.rigid._getTransform();
485                     var o = t.getOrigin();
486                     var q = t.getRotation();
487                     this._x = this.rigid._x = o.x();
488                     this._y = this.rigid._y = o.y();
489                     this._z = this.rigid._z = o.z();
490                     this._changedTranslation = true;
491                     var a = [ q.x(), q.y(), q.z(), q.w() ];
492                     var quat = quat4.create(a);
493                     quat4.toMat4(quat, this.rotation);
494                     Ammo.destroy(t);
495                 });
496             },
497             /**
498              */
499             scale: function(x, y, z) {
500                 enchant.gl.Sprite3D.prototype.scale.call(this, x, y, z);
501                 this.rigid.scale(x, y, z);
502             },
503             /**
504              */
505             translate: function(x, y, z) {
506                 enchant.gl.Sprite3D.prototype.translate.call(this, x, y, z);
507                 this.rigid.translate(x, y, z);
508             },
509             /**
510              */
511             rotationSet: function(quat) {
512                 enchant.gl.Sprite3D.prototype.rotationSet.call(this, quat);
513                 this.rigid.rotationSet(quat);
514             },
515             /**
516              */
517             rotationApply: function(quat) {
518                 enchant.gl.Sprite3D.prototype.rotationApply.call(this, quat);
519                 this.rigid.rotationApply(quat);
520             },
521             /**
522              */
523             clearForces: function() {
524                 this.rigid.clearForces();
525             },
526             /**
527              */
528             contactTest: function(sprite) {
529                 return this.rigid.contactTest(sprite.rigid);
530             },
531             /**
532              */
533             applyCentralImpulse: function(powx, powy, powz) {
534                 this.rigid.applyCentralImpulse(powx, powy, powz);
535             },
536             /**
537              */
538             applyImpulse: function(powx, powy, powz, posx, posy, posz) {
539                 this.rigid.applyImpulse(powx, powy, powz, posx, posy, posz);
540             },
541             /**
542              */
543             kinematize: function() {
544                 this.rigid.kinematize();
545             },
546             /**
547              */
548             restitution: {
549                 get: function() {
550                     return this.rigid._restitution;
551                 },
552                 set: function(n) {
553                     this.rigid._restitution = n;
554                     this.rigid.rigidBody.setRestitution(n);
555                 }
556             },
557             /**
558              */
559             friction: {
560                 get: function() {
561                     return this.rigid._friction;
562                 },
563                 set: function(n) {
564                     this.rigid._friction = n;
565                     this.rigid.rigidBody.setFriction(n);
566                 }
567             }
568         });
569         'x y z'.split(' ').forEach(function(prop) {
570             Object.defineProperty(enchant.gl.physics.PhySprite3D.prototype, prop, {
571                 get: function() {
572                     return this['_' + prop];
573                 },
574                 set: function(n) {
575                     this['_' + prop] = n;
576                     this._changedTranslation = true;
577                     this.rigid._translateAxis(prop, n);
578                 }
579             });
580         });
581         'scaleX scaleY scaleZ'.split(' ').forEach(function(prop) {
582             Object.defineProperty(enchant.gl.physics.PhySprite3D.prototype, prop, {
583                 get: function() {
584                     return this['_' + prop];
585                 },
586                 set: function(scale) {
587                     this['_' + prop] = scale;
588                     this._changedScale = true;
589                     this.rigid._scaleAxis(prop, scale);
590                 }
591             });
592         });
593 
594         /**
595          * @scope enchant.gl.physics.PhyBox.prototype
596          */
597         enchant.gl.physics.PhyBox = enchant.Class.create(enchant.gl.physics.PhySprite3D, {
598             /**
599              */
600             initialize: function(sx, sy, sz, mass) {
601                 var rigid = new enchant.gl.physics.RigidBox(sx, sy, sz, mass);
602                 enchant.gl.physics.PhySprite3D.call(this, rigid);
603                 this.mesh = enchant.gl.Mesh.createBox(sx, sy, sz);
604             }
605         });
606 
607         /**
608          * @scope enchant.gl.physics.PhyCube.prototype
609          */
610         enchant.gl.physics.PhyCube = enchant.Class.create(enchant.gl.physics.PhyBox, {
611             /**
612              */
613             initialize: function(s, mass) {
614                 var rigid = new enchant.gl.physics.RigidBox(s, s, s, mass);
615                 enchant.gl.physics.PhySprite3D.call(this, rigid);
616                 this.mesh = enchant.gl.Mesh.createBox(s, s, s);
617             }
618         });
619 
620         /**
621          * @scope enchant.gl.physics.PhySphere.prototype
622          */
623         enchant.gl.physics.PhySphere = enchant.Class.create(enchant.gl.physics.PhySprite3D, {
624             /**
625              */
626             initialize: function(r, mass, lDamp, aDamp) {
627                 if (typeof lDamp === 'undefined') {
628                     lDamp = 0.05;
629                 }
630                 if (typeof aDamp === 'undefined') {
631                     aDamp = 0.05;
632                 }
633                 var rigid = new enchant.gl.physics.RigidSphere(r, mass, lDamp, aDamp);
634                 enchant.gl.physics.PhySprite3D.call(this, rigid);
635                 this.mesh = enchant.gl.Mesh.createSphere(r);
636                 this.addEventListener('timestep', function(e) {
637                     this.rigid.rigidBody.applyDamping(e.timeStep);
638                 });
639             }
640         });
641 
642         /**
643          * @scope enchant.gl.physics.PhyCylinder.prototype
644          */
645         enchant.gl.physics.PhyCylinder = enchant.Class.create(enchant.gl.physics.PhySprite3D, {
646             /**
647              */
648             initialize: function(r, h, mass) {
649                 var rigid = new enchant.gl.physics.RigidCylinder(r, h, mass);
650                 enchant.gl.physics.PhySprite3D.call(this, rigid);
651                 this.mesh = enchant.gl.Mesh.createCylinder(r, h);
652             }
653         });
654 
655         /**
656          * @scope enchant.gl.physics.PhyCapsule.prototype
657          */
658         enchant.gl.physics.PhyCapsule = enchant.Class.create(enchant.gl.physics.PhySprite3D, {
659             /**
660              */
661             initialize: function(r, h, mass) {
662                 var rigid = new enchant.gl.physics.RigidCapsule(r, h, mass);
663                 enchant.gl.physics.PhySprite3D.call(this, rigid);
664                 this.mesh = enchant.gl.Mesh.createCylinder(r, h);
665                 this.mesh._join(enchant.gl.Mesh.createSphere(r), 0, h, 0);
666                 this.mesh._join(enchant.gl.Mesh.createSphere(r), 0, -h, 0);
667             }
668         });
669 
670         /**
671          * @scope enchant.gl.physics.PhyPlane.prototype
672          */
673         enchant.gl.physics.PhyPlane = enchant.Class.create(enchant.gl.physics.PhySprite3D, {
674             /**
675              */
676             initialize: function(nx, ny, nz, dist, scale) {
677                 if (!scale) {
678                     scale = 50;
679                 }
680 
681                 var rigid = new enchant.gl.physics.RigidPlane(nx, ny, nz, dist);
682                 enchant.gl.physics.PhySprite3D.call(this, rigid);
683                 this.mesh = enchant.gl.Mesh.createPlaneXZ(scale);
684                 var up = vec3.create([0, 1, 0]);
685                 var norm = vec3.create([nx, ny, nz]);
686                 var axis = vec3.create();
687                 vec3.cross(up, norm, axis);
688                 var rad = Math.acos(vec3.dot(up, norm) / (vec3.length(up) * vec3.length(norm)));
689                 var q = new enchant.gl.Quat(axis[0], axis[1], axis[2], rad);
690                 var vertices = [];
691                 for (var i = 0, l = this.mesh.vertices.length; i < l; i += 3) {
692                     var x = this.mesh.vertices[i];
693                     var y = this.mesh.vertices[i + 1];
694                     var z = this.mesh.vertices[i + 2];
695                     var arr = q.multiplyVec3([x, y, z]);
696                     vertices.push(arr[0] + nx * dist);
697                     vertices.push(arr[1] + ny * dist);
698                     vertices.push(arr[2] + nz * dist);
699                 }
700                 this.mesh.vertices = vertices;
701             }
702         });
703 
704         /**
705          * @scope enchant.gl.physics.PhyContainer.prototype
706          */
707         enchant.gl.physics.PhyContainer = enchant.Class.create(enchant.gl.physics.PhySprite3D, {
708             /**
709              */
710             initialize: function(scale, mass) {
711                 var s = scale;
712                 var rigid = new enchant.gl.physics.RigidContainer(s, mass);
713                 enchant.gl.physics.PhySprite3D.call(this, rigid);
714                 var that = this;
715                 this.mesh = new enchant.gl.Mesh();
716                 var addWall = function(sx, sy, sz, px, py, pz) {
717                     that.mesh._join(enchant.gl.Mesh.createBox(sx, sy, sz), px, py, pz);
718                 };
719                 addWall(s, s / 8, s, 0, s / 8 - s, 0);
720                 addWall(s - s / 8, s - s / 8 - s / 8, s / 8, s / 8, 0, s / 8 - s);
721                 addWall(s - s / 8, s - s / 8 - s / 8, s / 8, -s / 8, 0, s - s / 8);
722                 addWall(s / 8, s - s / 8 - s / 8, s - s / 8, s / 8 - s, 0, -s / 8);
723                 addWall(s / 8, s - s / 8 - s / 8, s - s / 8, s - s / 8, 0, s / 8);
724             }
725 
726         });
727     }());
728 }
729