r3-legacy/src/game-lib-d3-physics-world.js

932 lines
29 KiB
JavaScript
Raw Normal View History

2017-06-23 16:04:42 +02:00
/**
* World SuperSet - contains the custom world instance
* @constructor
* @param physics
* @param apiWorld
*/
2017-09-05 05:22:52 +02:00
GameLib.D3.PhysicsWorld = function(
2017-06-23 16:04:42 +02:00
physics,
apiWorld
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiWorld)) {
apiWorld = {};
}
2017-09-05 05:22:52 +02:00
if (apiWorld instanceof GameLib.D3.PhysicsWorld) {
2017-06-23 16:04:42 +02:00
return apiWorld;
}
2017-09-05 05:22:52 +02:00
GameLib.D3.API.PhysicsWorld.call(
2017-06-23 16:04:42 +02:00
this,
apiWorld.id,
apiWorld.name,
apiWorld.gravity,
apiWorld.broadphase,
apiWorld.solver,
apiWorld.rigidBodies,
2017-09-05 05:22:52 +02:00
apiWorld.contactMaterials,
2017-06-23 16:04:42 +02:00
apiWorld.parentEntity
);
if (this.gravity instanceof GameLib.API.Vector3) {
this.gravity = new GameLib.Vector3(
this.physics,
this.gravity,
this
);
}
2017-06-23 16:04:42 +02:00
if (this.broadphase instanceof GameLib.D3.API.Broadphase) {
this.broadphase = new GameLib.D3.Broadphase(
2017-06-23 16:04:42 +02:00
this.physics,
this.broadphase
);
}
if (this.solver instanceof GameLib.D3.API.Solver) {
this.solver = new GameLib.D3.Solver(
2017-06-23 16:04:42 +02:00
this.physics,
2017-06-24 02:42:28 +02:00
this.solver
2017-06-23 16:04:42 +02:00
);
}
2017-09-05 05:22:52 +02:00
this.rigidBodies = this.rigidBodies.map(
function(rigidBody) {
if (rigidBody instanceof GameLib.D3.API.RigidBody) {
return new GameLib.D3.RigidBody(
this.physics,
rigidBody
);
}
return rigidBody;
}.bind(this)
);
this.contactMaterials = this.contactMaterials.map(
function(contactMaterial) {
if (contactMaterial instanceof GameLib.D3.API.FrictionContactMaterial) {
return new GameLib.D3.FrictionContactMaterial(
this.physics,
contactMaterial
);
}
return contactMaterial;
}.bind(this)
);
2017-06-23 16:04:42 +02:00
GameLib.Component.call(
this,
2017-09-05 05:22:52 +02:00
GameLib.Component.COMPONENT_PHYSICS_WORLD,
2017-06-23 16:04:42 +02:00
{
'broadphase' : GameLib.D3.Broadphase,
'solver' : GameLib.D3.Solver,
2017-09-05 05:22:52 +02:00
'rigidBodies' : [GameLib.D3.RigidBody],
'contactMaterials' : [GameLib.D3.FrictionContactMaterial]
2017-06-23 16:04:42 +02:00
}
);
};
2017-09-05 05:22:52 +02:00
GameLib.D3.PhysicsWorld.prototype = Object.create(GameLib.D3.API.PhysicsWorld.prototype);
GameLib.D3.PhysicsWorld.prototype.constructor = GameLib.D3.PhysicsWorld;
2017-06-23 16:04:42 +02:00
/**
* private
2017-09-05 05:22:52 +02:00
* @returns {GameLib.D3.PhysicsWorld|GameLib.D3.Physics.World|*}
2017-06-23 16:04:42 +02:00
*/
2017-09-05 05:22:52 +02:00
GameLib.D3.PhysicsWorld.prototype.createInstance = function() {
if (this.broadphase && this.broadphase.instance &&
this.solver && this.solver.instance) {
var instance = new CANNON.World();
instance.broadphase = this.broadphase.instance;
instance.solver = this.solver.instance;
instance.gravity = this.gravity.instance;
2017-09-05 05:22:52 +02:00
this.contactMaterials.map(
function(contactMaterial) {
if (contactMaterial && contactMaterial.instance) {
instance.addContactMaterial(contactMaterial.instance);
}
}
);
return instance;
2017-09-05 05:22:52 +02:00
}
2017-09-05 05:22:52 +02:00
return false;
2017-06-23 16:04:42 +02:00
};
/**
*
*/
2017-09-05 05:22:52 +02:00
GameLib.D3.PhysicsWorld.prototype.updateInstance = function() {
if (!this.instance) {
console.log('no world instance');
return;
}
2017-06-23 16:04:42 +02:00
this.instance.broadphase = this.broadphase.instance;
this.instance.solver = this.solver.instance;
this.instance.gravity = this.gravity.instance;
2017-09-05 05:22:52 +02:00
//TODO add contact materials
2017-06-23 16:04:42 +02:00
};
/**
2017-09-05 05:22:52 +02:00
* GameLib.D3.PhysicsWorld to GameLib.D3.API.PhysicsWorld
* @returns {GameLib.D3.API.PhysicsWorld}
2017-06-23 16:04:42 +02:00
*/
2017-09-05 05:22:52 +02:00
GameLib.D3.PhysicsWorld.prototype.toApiObject = function() {
2017-06-23 16:04:42 +02:00
2017-09-05 05:22:52 +02:00
var apiWorld = new GameLib.D3.API.PhysicsWorld(
2017-06-23 16:04:42 +02:00
this.id,
this.name,
this.gravity.toApiObject(),
GameLib.Utils.IdOrNull(this.broadphase),
GameLib.Utils.IdOrNull(this.solver),
2017-06-23 16:04:42 +02:00
this.rigidBodies.map(function(body){
return GameLib.Utils.IdOrNull(body);
}),
2017-09-05 05:22:52 +02:00
this.contactMaterials.map(function(contactMaterial){
return GameLib.Utils.IdOrNull(contactMaterial);
}),
2017-06-23 16:04:42 +02:00
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiWorld;
};
/**
2017-09-05 05:22:52 +02:00
* GameLib.D3.PhysicsWorld from Object World
2017-06-23 16:04:42 +02:00
* @param graphics
* @param objectComponent
2017-09-05 05:22:52 +02:00
* @returns {GameLib.D3.PhysicsWorld}
2017-06-23 16:04:42 +02:00
* @constructor
*/
2017-09-05 05:22:52 +02:00
GameLib.D3.PhysicsWorld.FromObject = function(graphics, objectComponent) {
var apiWorld = GameLib.D3.API.PhysicsWorld.FromObject(objectComponent);
return new GameLib.D3.PhysicsWorld(
2017-06-23 16:04:42 +02:00
graphics,
apiWorld
);
};
2017-09-05 05:22:52 +02:00
GameLib.D3.PhysicsWorld.prototype.step = function(deltaTime) {
2017-06-23 16:04:42 +02:00
if (this.isCannon) {
this.instance.step(deltaTime);
}
// if (this.isOimo) {
// //TODO: oimo
// }
};
//
2017-09-05 05:22:52 +02:00
// GameLib.D3.PhysicsWorld.prototype.step = function(
2017-06-23 16:04:42 +02:00
// fixedStep,
// dtStep
// ) {
//
// };
//
2017-09-05 05:22:52 +02:00
// GameLib.D3.PhysicsWorld.prototype.generateWireframeViewTriangleMesh = function(
2017-06-23 16:04:42 +02:00
// graphics,
// triangleMeshShape,
// normalLength,
// scale,
// opacity,
// wireframeColor
// ) {
// graphics.isNotThreeThrow();
// this.engine.isNotCannonThrow();
//
// if(typeof normalLength == 'undefined') {
// normalLength = 10;
// }
//
// if(typeof scale == 'undefined') {
// scale = new graphics.instance.Vector3(1, 1, 1);
// }
//
// if(typeof opacity == 'undefined') {
// opacity = 0.5;
// }
//
// if(typeof wireframeColor == 'undefined') {
// wireframeColor = 0xfefefe;
// }
//
// var graphicsGeometry = new graphics.instance.Geometry();
//
// var wireframeMesh = new graphics.instance.Mesh(
// graphicsGeometry,
// new graphics.instance.MeshBasicMaterial({
// color: wireframeColor,
// wireframe: true,
// opacity: opacity
// })
// );
//
// for(var v = 0, l = triangleMeshShape.instance.vertices.length / 3; v < l; ++v) {
// graphicsGeometry.vertices.push(
// new graphics.instance.Vector3(
// triangleMeshShape.instance.vertices[v * 3],
// triangleMeshShape.instance.vertices[v * 3 + 1],
// triangleMeshShape.instance.vertices[v * 3 + 2]
// )
// );
// }
//
// for(var i = 0, l = triangleMeshShape.instance.indices.length / 3; i < l; ++i) {
// var i0 = triangleMeshShape.instance.indices[i * 3];
// var i1 = triangleMeshShape.instance.indices[i * 3 + 1];
// var i2 = triangleMeshShape.instance.indices[i * 3 + 2];
//
// graphicsGeometry.faces.push(
// new graphics.instance.Face3(
// i0,
// i1,
// i2
// )
// );
//
// // Center point on the current triangle
//
// var centroid = new graphics.instance.Vector3()
// .add(graphicsGeometry.vertices[i0])
// .add(graphicsGeometry.vertices[i1])
// .add(graphicsGeometry.vertices[i2])
// .divideScalar(3);
//
// // Get the normal from the mesh shape itself
// var normal = new this.engine.instance.Vec3();
// triangleMeshShape.instance.getNormal(i , normal);
//
// var arrow = new graphics.instance.ArrowHelper(
// new graphics.instance.Vector3(
// normal.x,
// normal.y,
// normal.z
// ),
// centroid,
// normalLength,
// new graphics.instance.Color(
// normal.x,
// normal.y,
// normal.z
// )
// );
// wireframeMesh.add( arrow );
// }
//
// wireframeMesh.scale.x = scale.x;
// wireframeMesh.scale.y = scale.y;
// wireframeMesh.scale.z = scale.z;
//
// return wireframeMesh;
// };
//
// /**
// * @param convexPolyMeshShape GameLib.D3.Shape
// * @param normalLength Number
// * @param scale GameLib.API.Vector3
// * @param opacity Number
// * @param wireframeColor HexCode
// * @param graphics THREE
// * @returns {THREE.Mesh|this.meshes}
// * @constructor
// */
2017-09-05 05:22:52 +02:00
// GameLib.D3.PhysicsWorld.prototype.generateWireframeViewConvexPolyMesh = function(
2017-06-23 16:04:42 +02:00
// graphics,
// convexPolyMeshShape,
// normalLength,
// scale,
// opacity,
// wireframeColor
// ) {
// graphics.isNotThreeThrow();
// this.engine.isNotCannonThrow();
//
// if(typeof normalLength == 'undefined') {
// normalLength = 10;
// }
//
// if(typeof scale == 'undefined') {
// scale = new graphics.instance.Vector3(1, 1, 1);
// }
//
// if(typeof opacity == 'undefined') {
// opacity = 0.5;
// }
//
// if(typeof wireframeColor == 'undefined') {
// wireframeColor = 0xfefefe;
// }
//
//
// var graphicsGeometry = new graphics.instance.Geometry();
// var wireframeMesh = new graphics.instance.Mesh(
// graphicsGeometry,
// new graphics.instance.MeshBasicMaterial({
// color: wireframeColor,
// wireframe: true,
// opacity: opacity
// })
// );
//
// for(var i = 0, l = convexPolyMeshShape.instance.vertices.length; i < l; i++) {
// var vertex = convexPolyMeshShape.instance.vertices[i];
// graphicsGeometry.vertices.push(new graphics.instance.Vector3(vertex.x, vertex.y, vertex.z));
// }
//
// for(var i = 0, l = convexPolyMeshShape.instance.faces.length; i < l; i++) {
// var face = convexPolyMeshShape.instance.faces[i];
//
// var i0 = face[0];
// var i1 = face[1];
// var i2 = face[2];
//
// graphicsGeometry.faces.push(new graphics.instance.Face3(i0, i1, i2));
//
// // Center point on the current triangle
// var centroid = new graphics.instance.Vector3()
// .add(graphicsGeometry.vertices[i0])
// .add(graphicsGeometry.vertices[i1])
// .add(graphicsGeometry.vertices[i2])
// .divideScalar(3);
//
// var normalVec3 = convexPolyMeshShape.instance.faceNormals[i];
// var normal = new graphics.instance.Vector3(
// normalVec3.x,
// normalVec3.y,
// normalVec3.z
// );
//
// var arrow = new graphics.instance.ArrowHelper(
// normal,
// centroid,
// normalLength,
// new graphics.instance.Color(
// normal.x,
// normal.y,
// normal.z
// )
// );
//
// wireframeMesh.add( arrow );
// }
//
// wireframeMesh.scale.x = scale.x;
// wireframeMesh.scale.y = scale.y;
// wireframeMesh.scale.z = scale.z;
//
// return wireframeMesh;
// };
//
// /**
// * @param graphics GameLib.D3.Graphics
// * @param graphicsMesh THREE.Mesh
// * @param mass Number
// * @param friction Number
// * @param createCollisionSubMeshes Boolean
// * @param facesPerSubsection Number
// * @param subsectionsToMerge Number
// * @returns {Object}
// * @constructor
// */
2017-09-05 05:22:52 +02:00
// GameLib.D3.PhysicsWorld.prototype.generateTriangleMeshShapeDivided = function(
2017-06-23 16:04:42 +02:00
// graphics,
// graphicsMesh,
// mass,
// friction,
// createCollisionSubMeshes,
// facesPerSubsection,
// subsectionsToMerge
// ) {
// graphics.isNotThreeThrow();
// this.engine.isNotCannonThrow();
//
// if(mass == null || typeof mass == 'undefined') {
// mass = 0;
// }
//
// if(friction == null || typeof friction == 'undefined') {
// friction = 10;
// }
//
// if(createCollisionSubMeshes == null || typeof createCollisionSubMeshes == 'undefined') {
// createCollisionSubMeshes = false;
// }
//
// var processedFaces = 0;
// var facesPerSubSection = facesPerSubsection || 0;
// var subMeshesToMerge = subsectionsToMerge || 0;
// var totalAmtFaces = graphicsMesh.geometry.faces.length;
// var facesToProcess = createCollisionSubMeshes ? (subMeshesToMerge * facesPerSubSection) : totalAmtFaces;
//
// var pairs = []; // output
//
// var vertices = [];
// var indicies = [];
//
// for(var i = 0; i <= totalAmtFaces; i++) {
// if(processedFaces == facesToProcess || i == totalAmtFaces) {
//
// var body = null;
//
// var meshShape = new this.engine.instance.Trimesh(vertices, indicies);
//
// meshShape.setScale(new this.engine.instance.Vec3(
// graphicsMesh.scale.x,
// graphicsMesh.scale.y,
// graphicsMesh.scale.z
// ));
//
// meshShape.updateAABB();
// meshShape.updateNormals();
// meshShape.updateEdges();
// meshShape.updateBoundingSphereRadius();
// meshShape.updateTree();
//
// body = new this.engine.instance.Body({
// mass: mass,
// friction: friction
// });
// body.addShape(meshShape);
//
// pairs.push({
// threeObject : createCollisionSubMeshes ? null : graphicsMesh,
// physicsObject : body
// });
//
// vertices = [];
// indicies = [];
// processedFaces = 0;
//
// if(i == totalAmtFaces) {
// return pairs;
// }
// }
//
// var face = graphicsMesh.geometry.faces[i];
// indicies.push(indicies.length);
// indicies.push(indicies.length);
// indicies.push(indicies.length);
//
// var v0 = graphicsMesh.geometry.vertices[face.a];
// var v1 = graphicsMesh.geometry.vertices[face.b];
// var v2 = graphicsMesh.geometry.vertices[face.c];
//
// vertices.push(v0.x, v0.y, v0.z);
// vertices.push(v1.x, v1.y, v1.z);
// vertices.push(v2.x, v2.y, v2.z);
//
// processedFaces++;
// }
// };
//
2017-09-05 05:22:52 +02:00
// GameLib.D3.PhysicsWorld.prototype.generateConvexPolyShape = function(
2017-06-23 16:04:42 +02:00
// graphics,
// mesh
// ) {
// var processedFaces = 0;
// var facesPerSubSection = 2; // *2 -> SUBDIVISION MESH
// var subMeshesToMerge = 4; // *2 -> SUBDIVISION MESH
// var facesToProcess = subMeshesToMerge * facesPerSubSection;
//
// var vertices = [];
// var indicies = [];
//
// for(var i = 0; i <= mesh.geometry.faces.length; i++) {
// if(processedFaces == facesToProcess || i == mesh.geometry.faces.length) {
//
// // try and create convex poly...........
// var convexIndices = [];
// for(var index = 0; index < indicies.length / 3; index++) {
// convexIndices.push([ indicies[index * 3], indicies[index * 3 + 1], indicies[index * 3 + 2] ]);
// }
//
// var convexVertices = [];
// for(var vert = 0; vert < vertices.length / 3; vert++) {
// convexVertices[vert] = new CANNON.Vec3(vertices[vert * 3] * mesh.scale.x, vertices[vert * 3 + 1] * mesh.scale.y, vertices[vert * 3 + 2] * mesh.scale.z);
// }
//
// var meshShape = new GameLib.D3.Shape(this.engine, GameLib.D3.Shape.SHAPE_TYPE_CONVEX_HULL, {x:1,y:1,z:1},convexVertices, convexIndices);
//
// var body = new GameLib.D3.RigidBody(this.engine, 0, 1);
// body.addShape(meshShape);
//
// this.addRigidBody(body);
//
// vertices = [];
// indicies = [];
// processedFaces = 0;
//
// console.log("SPLIT MESH TO CONVEX POLY");
//
// if(i == mesh.geometry.faces.length) {
// break;
// }
// }
//
// var face = mesh.geometry.faces[i];
// indicies.push(indicies.length);
// indicies.push(indicies.length);
// indicies.push(indicies.length);
//
// var v0 = mesh.geometry.vertices[face.a];
// var v1 = mesh.geometry.vertices[face.b];
// var v2 = mesh.geometry.vertices[face.c];
//
// vertices.push(v0.x, v0.y, v0.z);
// vertices.push(v1.x, v1.y, v1.z);
// vertices.push(v2.x, v2.y, v2.z);
//
// processedFaces++;
// }
//
// };
//
// /**
// * @param graphics GameLib.D3.Graphics
// * @param graphicsMesh THREE.Mesh
// * @returns {GameLib.D3.Shape}
// * @constructor
// */
2017-09-05 05:22:52 +02:00
// GameLib.D3.PhysicsWorld.prototype.generateTriangleMeshShape = function(
2017-06-23 16:04:42 +02:00
// graphics,
// graphicsMesh
// ) {
//
// // - - - - - - - - - - - - - - - - - - - - - - - - -
// // Note: I did not test this yet with the API data.
// // - - - - - - - - - - - - - - - - - - - - - - - - -
//
// var scaledVertices = [];
// for(var i = 0, l = graphicsMesh.geometry.vertices.length; i < l; i++) {
//
// var vertex = graphicsMesh.geometry.vertices[i];
//
// scaledVertices.push(new this.engine.instance.Vec3(
// vertex.x * graphicsMesh.scale.x,
// vertex.y * graphicsMesh.scale.y,
// vertex.z * graphicsMesh.scale.z
// ));
// }
//
// var triangleFaces = [];
// for(var f = 0, fl = graphicsMesh.geometry.faces.length; f < fl; f++) {
// var i0 = graphicsMesh.geometry.faces[f].a;
// var i1 = graphicsMesh.geometry.faces[f].b;
// var i2 = graphicsMesh.geometry.faces[f].c;
//
// triangleFaces.push([
// i0, i1, i2
// ]);
// }
//
// // - - - - - - - - - - - - - - - - - - -
// // Create collision mesh
// // - - - - - - - - - - - - - - - - - - -
//
// var reindexedFaces = {};
// var vertices = [];
// var faces = [];
//
// var processedFaces = 0;
// var totalFacesToProcess = triangleFaces.length;
// var flLastIndex = 0;
//
// for(var f = 0; f < totalFacesToProcess; f++) {
//
// var i0 = triangleFaces[f][0];
// var i1 = triangleFaces[f][1];
// var i2 = triangleFaces[f][2];
//
// if(typeof reindexedFaces[i0] === 'undefined') {
// vertices.push(scaledVertices[i0].x, scaledVertices[i0].y, scaledVertices[i0].z);
// reindexedFaces[i0] = flLastIndex;
// flLastIndex++;
// }
//
// if(typeof reindexedFaces[i1] === 'undefined') {
// vertices.push(scaledVertices[i1].x, scaledVertices[i1].y, scaledVertices[i1].z);
// reindexedFaces[i1] = flLastIndex;
// flLastIndex++;
// }
//
// if(typeof reindexedFaces[i2] === 'undefined') {
// vertices.push(scaledVertices[i2].x, scaledVertices[i2].y, scaledVertices[i2].z);
// reindexedFaces[i2] = flLastIndex;
// flLastIndex++;
// }
//
// faces.push(reindexedFaces[i0], reindexedFaces[i1], reindexedFaces[i2]);
//
// processedFaces++;
// }
//
// return new GameLib.D3.Shape(this.engine, GameLib.D3.Shape.SHAPE_TYPE_TRIMESH, {x : 1, y : 1, z : 1}, vertices, faces);
// };
//
// /**
// * @param triangleMeshBody GameLib.D3.RigidBody
// * @param rayscale Number
// * @param maxTriangleDistance Number
// * @param createCompoundShape Boolean
// * @param graphics GameLib.D3.Graphics
// * @param triangleMeshShapes GameLib.D3.Shape[]
// * @param createDebugView Boolean
// * @returns {GameLib.D3.RigidBody}
// * @constructor
// */
2017-09-05 05:22:52 +02:00
// GameLib.D3.PhysicsWorld.prototype.fixupTriangleMeshShape = function(
2017-06-23 16:04:42 +02:00
// triangleMeshBody,
// triangleMeshShapes,
// rayscale,
// maxTriangleDistance,
// createCompoundShape,
// graphics,
// createDebugView
// ) {
// this.engine.isNotCannonThrow();
//
// graphics.isNotThreeThrow();
//
// if(rayscale == null || typeof rayscale == 'undefined' || rayscale == 0) {
// rayscale = 10;
// }
//
// if(maxTriangleDistance == null || typeof maxTriangleDistance == 'undefined') {
// maxTriangleDistance = 13;
// }
//
// var world = this.instance;
//
// var raycastResult = new this.engine.instance.RaycastResult();
//
// var brokenFaceIndicators = [];
//
// var totalFaces = 0;
// var totalBrokenFaces = 0;
// var totalFixedFaces = 0;
// var fixedTriangleMeshObjects = [];
//
// for(var i in triangleMeshShapes) {
// var trimesh = triangleMeshShapes[i].instance;
//
// var brokenFaces = [];
// totalFaces += (trimesh.indices.length / 3);
//
// for(var face = 0; face < trimesh.indices.length / 3; face++) {
//
// var i0 = trimesh.indices[face * 3];
// var i1 = trimesh.indices[face * 3 + 1];
// var i2 = trimesh.indices[face * 3 + 2];
//
// var triangleCenterPoint = new graphics.instance.Vector3()
// .add(new graphics.instance.Vector3(
// trimesh.vertices[i0 * 3],
// trimesh.vertices[i0 * 3 + 1],
// trimesh.vertices[i0 * 3 + 2])
// )
// .add(new graphics.instance.Vector3(
// trimesh.vertices[i1 * 3],
// trimesh.vertices[i1 * 3 + 1],
// trimesh.vertices[i1 * 3 + 2])
// )
// .add(new graphics.instance.Vector3(
// trimesh.vertices[i2 * 3],
// trimesh.vertices[i2 * 3 + 1],
// trimesh.vertices[i2 * 3 + 2])
// )
// .divideScalar(3);
//
// var triangleNormal = new this.engine.instance.Vec3();
// trimesh.getNormal(face , triangleNormal);
//
// var from = new this.engine.instance.Vec3(
// triangleCenterPoint.x + triangleNormal.x,
// triangleCenterPoint.y + triangleNormal.y,
// triangleCenterPoint.z + triangleNormal.z
// );
//
// var to = new this.engine.instance.Vec3(
// from.x - triangleNormal.x * rayscale,
// from.y - triangleNormal.y * rayscale,
// from.z - triangleNormal.z * rayscale
// );
//
// world.raycastClosest(from, to, {}, raycastResult);
//
// // visualize results
// if(createDebugView){
// var graphicsGeometry = new graphics.instance.Geometry();
// var wireframeMesh = new graphics.instance.Mesh(
// graphicsGeometry,
// new graphics.instance.MeshBasicMaterial({
// color: 0xff0000,
// wireframe: true,
// opacity: 1
// })
// );
//
// var arrow = new graphics.instance.ArrowHelper(
// new graphics.instance.Vector3(
// triangleNormal.x,
// triangleNormal.y,
// triangleNormal.z
// ).normalize(),
//
// new graphics.instance.Vector3(
// from.x,
// from.y,
// from.z
// ),
//
// rayscale / 2,
// raycastResult.hasHit ? new graphics.instance.Color(0, 1, 0)
// : new graphics.instance.Color(1, 0, 0)
// );
//
// wireframeMesh.add( arrow );
// brokenFaceIndicators.push(wireframeMesh);
// }
//
// if(!raycastResult.hasHit) {
// brokenFaces.push({
// faceIndex : face,
//
// vertices : [
// new this.engine.instance.Vec3(
// trimesh.vertices[i0 * 3],
// trimesh.vertices[i0 * 3 + 1],
// trimesh.vertices[i0 * 3 + 2]
// ),
//
// new this.engine.instance.Vec3(
// trimesh.vertices[i1 * 3],
// trimesh.vertices[i1 * 3 + 1],
// trimesh.vertices[i1 * 3 + 2]
// ),
//
// new this.engine.instance.Vec3(
// trimesh.vertices[i2 * 3],
// trimesh.vertices[i2 * 3 + 1],
// trimesh.vertices[i2 * 3 + 2]
// )
// ],
//
// center : triangleCenterPoint,
//
// parent : trimesh
// });
// }
// }
//
// // fix up broken faces
//
// var bFaceIndexed = {};
// for(var b = 0; b < brokenFaces.length; b++) {
// var brokenFace = brokenFaces[b];
//
// if(brokenFace.marked) {
// continue;
// }
//
// bFaceIndexed[b] = {
// indices : [],
// vertices : []
// };
//
// var indicesAmount = bFaceIndexed[b].indices.length;
//
// // add the current broken face itself to the array
// bFaceIndexed[b].indices.push(
// indicesAmount,
// indicesAmount + 1,
// indicesAmount + 2
// );
//
// bFaceIndexed[b].vertices.push(
// brokenFace.vertices[0].x,
// brokenFace.vertices[0].y,
// brokenFace.vertices[0].z
// );
//
// bFaceIndexed[b].vertices.push(
// brokenFace.vertices[1].x,
// brokenFace.vertices[1].y,
// brokenFace.vertices[1].z
// );
//
// bFaceIndexed[b].vertices.push(
// brokenFace.vertices[2].x,
// brokenFace.vertices[2].y,
// brokenFace.vertices[2].z
// );
//
// for(var bb = 0; bb < brokenFaces.length; bb++) {
//
// if(bb == b) {
// continue;
// }
//
// var otherBrokenFace = brokenFaces[bb];
//
// if(otherBrokenFace.marked) {
// continue;
// }
//
// if(brokenFace.center.distanceTo(otherBrokenFace.center) <= maxTriangleDistance) {
// var indicesAmount = bFaceIndexed[b].indices.length;
//
// bFaceIndexed[b].indices.push(
// indicesAmount,
// indicesAmount + 1,
// indicesAmount + 2
// );
//
// bFaceIndexed[b].vertices.push(
// otherBrokenFace.vertices[0].x,
// otherBrokenFace.vertices[0].y,
// otherBrokenFace.vertices[0].z
// );
//
// bFaceIndexed[b].vertices.push(
// otherBrokenFace.vertices[1].x,
// otherBrokenFace.vertices[1].y,
// otherBrokenFace.vertices[1].z
// );
//
// bFaceIndexed[b].vertices.push(
// otherBrokenFace.vertices[2].x,
// otherBrokenFace.vertices[2].y,
// otherBrokenFace.vertices[2].z
// );
//
// otherBrokenFace.marked = true;
// }
// }
// }
//
//
// // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// // Decide if we want to create new rigiwyd bodies, or create a compound mesh
// // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// for(var e in bFaceIndexed) {
// var element = bFaceIndexed[e];
//
// var shape = new GameLib.D3.Shape(this.engine, GameLib.D3.Shape.SHAPE_TYPE_TRIMESH, { x : 1, y : 1, z : 1 }, element.vertices, element.indices);
//
// if(createCompoundShape) {
// triangleMeshBody.addShape(shape);
// } else {
//
// var body = new GameLib.D3.RigidBody(this.engine, 0, 12);
//
// //TODO: this is just a hack.
// body.instance.collisionFilterGroup = 1 | 2; // puts this body in two groups.
//
// body.addShape(shape);
// this.addRigidBody(body);
// }
//
// fixedTriangleMeshObjects.push(shape);
// totalFixedFaces += element.indices.length / 3;
// }
//
// // TODO: remove duplicate indices
// /*trimesh.updateNormals();
// trimesh.updateEdges();
// trimesh.updateTree();
// trimesh.updateAABB();
// trimesh.updateBoundingSphereRadius();*/
//
// // map faceIndex to flat face index (faceIndex * 3) +0, 1, 2 -> triangle indices
// console.log("i = " + i, brokenFaces);
// totalBrokenFaces += brokenFaces.length;
// }
//
// console.log("total faces", totalFaces);
// console.log("total broken faces", totalBrokenFaces);
// console.log("broken faces in percent", (totalBrokenFaces / totalFaces) * 100);
// console.log("total fixed faces", totalFixedFaces);
// console.log("fixed triangle mesh shapes", fixedTriangleMeshObjects.length);
//
// return {
// brokenFaceIndicators : brokenFaceIndicators,
// fixedTriangleMeshShapes : fixedTriangleMeshObjects
// };
// };