@c-frame/aframe-physics-system
Version:
Physics system for A-Frame VR, built on Cannon.js & Ammo.js
170 lines (142 loc) • 6.09 kB
JavaScript
/**
* CANNON.shape2mesh
*
* Source: https://schteppe.github.io/cannon.js/build/cannon.demo.js
* Author: @schteppe
*/
var CANNON = require('cannon-es');
CANNON.shape2mesh = function(body){
var obj = new THREE.Object3D();
function createBufferGeometry(positions, faces) {
var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
geometry.setIndex(faces);
geometry.computeBoundingSphere();
return geometry;
}
for (var l = 0; l < body.shapes.length; l++) {
var shape = body.shapes[l];
var mesh;
switch(shape.type){
case CANNON.Shape.types.SPHERE:
var sphere_geometry = new THREE.SphereGeometry( shape.radius, 8, 8);
mesh = new THREE.Mesh( sphere_geometry, this.currentMaterial );
break;
case CANNON.Shape.types.PARTICLE:
mesh = new THREE.Mesh( this.particleGeo, this.particleMaterial );
var s = this.settings;
mesh.scale.set(s.particleSize,s.particleSize,s.particleSize);
break;
case CANNON.Shape.types.PLANE:
var geometry = new THREE.PlaneGeometry(10, 10, 4, 4);
mesh = new THREE.Object3D();
var submesh = new THREE.Object3D();
var ground = new THREE.Mesh( geometry, this.currentMaterial );
ground.scale.set(100, 100, 100);
submesh.add(ground);
ground.castShadow = true;
ground.receiveShadow = true;
mesh.add(submesh);
break;
case CANNON.Shape.types.BOX:
var box_geometry = new THREE.BoxGeometry( shape.halfExtents.x*2,
shape.halfExtents.y*2,
shape.halfExtents.z*2 );
mesh = new THREE.Mesh( box_geometry, this.currentMaterial );
break;
case CANNON.Shape.types.CONVEXPOLYHEDRON:
// Add vertices
var positions = []
for (var i = 0; i < shape.vertices.length; i++) {
var v = shape.vertices[i];
positions.push(v.x, v.y, v.z);
}
var faces = []
for(var i=0; i < shape.faces.length; i++){
var face = shape.faces[i];
// add triangles
var a = face[0];
for (var j = 1; j < face.length - 1; j++) {
var b = face[j];
var c = face[j + 1];
faces.push(a, b, c);
}
}
var geo = createBufferGeometry(positions, faces);
mesh = new THREE.Mesh( geo, this.currentMaterial );
break;
case CANNON.Shape.types.HEIGHTFIELD:
var v0 = new CANNON.Vec3();
var v1 = new CANNON.Vec3();
var v2 = new CANNON.Vec3();
var positions = [];
var faces = [];
for (var xi = 0; xi < shape.data.length - 1; xi++) {
for (var yi = 0; yi < shape.data[xi].length - 1; yi++) {
for (var k = 0; k < 2; k++) {
shape.getConvexTrianglePillar(xi, yi, k===0);
v0.copy(shape.pillarConvex.vertices[0]);
v1.copy(shape.pillarConvex.vertices[1]);
v2.copy(shape.pillarConvex.vertices[2]);
v0.vadd(shape.pillarOffset, v0);
v1.vadd(shape.pillarOffset, v1);
v2.vadd(shape.pillarOffset, v2);
positions.push(
v0.x, v0.y, v0.z,
v1.x, v1.y, v1.z,
v2.x, v2.y, v2.z
);
var i = positions.length / 3 - 3;
faces.push(i, i+1, i+2);
}
}
}
var geometry = createBufferGeometry(positions, faces);
mesh = new THREE.Mesh(geometry, this.currentMaterial);
break;
case CANNON.Shape.types.TRIMESH:
var geometry = new THREE.BufferGeometry();
var v0 = new CANNON.Vec3();
var v1 = new CANNON.Vec3();
var v2 = new CANNON.Vec3();
var positions = [];
var faces = [];
for (var i = 0; i < shape.indices.length / 3; i++) {
shape.getTriangleVertices(i, v0, v1, v2);
positions.push(
v0.x, v0.y, v0.z,
v1.x, v1.y, v1.z,
v2.x, v2.y, v2.z
);
var j = positions.length / 3 - 3;
faces.push(j, j+1, j+2);
}
var geometry = createBufferGeometry(positions, faces);
mesh = new THREE.Mesh(geometry, this.currentMaterial);
break;
default:
throw "Visual type not recognized: "+shape.type;
}
mesh.receiveShadow = true;
mesh.castShadow = true;
if(mesh.children){
for(var i=0; i<mesh.children.length; i++){
mesh.children[i].castShadow = true;
mesh.children[i].receiveShadow = true;
if(mesh.children[i]){
for(var j=0; j<mesh.children[i].length; j++){
mesh.children[i].children[j].castShadow = true;
mesh.children[i].children[j].receiveShadow = true;
}
}
}
}
var o = body.shapeOffsets[l];
var q = body.shapeOrientations[l];
mesh.position.set(o.x, o.y, o.z);
mesh.quaternion.set(q.x, q.y, q.z, q.w);
obj.add(mesh);
}
return obj;
};
module.exports = CANNON.shape2mesh;