THREE js : Simplify a mesh to optimize performance - performance

I have a mesh (image 1) and a parallelepipede, I add the intersection result of this 2 objects in a scene and I move the parallelepipede along my mesh repeating the same process to "cut" my mesh and get an exploded view of my mesh (image 2).
Problem is that the process time is more than 2 mins... I have tryed to reduce the mesh with meshmixxer but it's not enough... Does someone has another idea ?
function FirstCut() {
var scene, camera, renderer, controls;
//stl loader from https://threejs.org/examples/webgl_loader_stl.html
// cf example https://stemkoski.github.io/Three.js/CSG.html
//with obj
init();
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xeeeeee);
camera = new THREE.PerspectiveCamera(75, 800 / 500, 1, 2000);
//camera.position.set(50, 500, 0);
camera.position.x = 50;
camera.position.y = 500;
camera.position.z = 0;
//var axeX = new THREE.Vector3(1, 0, 0);
//camera.rotateOnAxis(axeX, -1);
camera.lookAt(new THREE.Vector3(0, 500, 0));
controls = new THREE.OrbitControls(camera);
//les valeurs de min and max distance sont choisies pour que le filet ne disparaisse pas quand on le fait tourner
controls.minDistance = 0;
controls.maxDistance = 1000;
//scene
//var ambient = new THREE.AmbientLight(0x101030);
//scene.add(ambient);
//scene.add(new THREE.GridHelper(1000, 20));
//var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
//directionalLight.position.set(0, 1, 0);
//scene.add(directionalLight);
var widthH = parseInt(document.getElementById("wdthH").value) || 0; // H for Head
var widthT = parseInt(document.getElementById("wdthT").value) || 0; // T for tail
var height = parseInt(document.getElementById("hght").value) || 0; // flank
//création du pavé
var EmportePieceH = new THREE.BoxGeometry(300, 60, widthH);
var EmportePieceT = new THREE.BoxGeometry(300, 60, widthT);
var EmportePieceB = new THREE.BoxGeometry(height, 60, 520);
var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
// création du meshage et material
var EmportePieceMeshH = new THREE.Mesh(EmportePieceH, paveMaterial);
var EmportePieceMeshT = new THREE.Mesh(EmportePieceT, paveMaterial);
var paveMeshB = new THREE.Mesh(EmportePieceB, paveMaterial);
var zH = 247 - widthH / 2;
var zT = -247 + widthT / 2;
EmportePieceMeshH.position.set(0, 30, zH);
EmportePieceMeshT.position.set(0, 30, zT);
paveMeshB.position.set(-95 + height / 2, 30, 0);
var EmportePieceBSPH = new ThreeBSP(EmportePieceMeshH);
var EmportePieceBSPT = new ThreeBSP(EmportePieceMeshT);
var paveBSPB = new ThreeBSP(paveMeshB);
//scene.add(EmportePieceMeshH);
//scene.add(EmportePieceMeshT);
//scene.add(paveMeshB);
// texture
var manager = new THREE.LoadingManager();
manager.onProgress = function (item, loaded, total) {
console.log(item, loaded, total);
};
var texture = new THREE.Texture();
var onProgress = function (xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}
};
var onError = function (xhr) {
};
var loader = new THREE.ImageLoader(manager);
loader.load('/Scan/filet_1kg500-reposition-reduit_material_0.jpg', function (image) {
texture.image = image;
texture.needsUpdate = true;
});
var width = parseInt(document.getElementById("wdth").value) || 0;
//création du pavé
var paveGeom = new THREE.BoxGeometry(250, 250, width);
var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
// création du meshage parallélépipède avec material
var paveMesh = new THREE.Mesh(paveGeom, paveMaterial);
var z0 = -247 + widthH;
paveMesh.position.set(0, 0, z0);
var paveBSP = new ThreeBSP(paveMesh);
//scene.add(paveMesh);
//tableau des volumes
var tabVolumes = new Array();
// model
var loader = new THREE.OBJLoader(manager);
loader.load('/Scan/filet_1kg500-reposition-reduit.obj', function (object) {
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = texture;
var geo = new THREE.Geometry().fromBufferGeometry(child.geometry);
var filetMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
var filetMesh = new THREE.Mesh(geo, filetMaterial);
//scene.add(filetMesh);
var newBSPH, newBSPT, newBSPB, newBSP2, newBSP1, filletBSP
var filetBSP = new ThreeBSP(filetMesh);
newBSPH = filetBSP.intersect(EmportePieceBSPH);
newBSPT = filetBSP.intersect(EmportePieceBSPT);
newBSPB = filetBSP.intersect(paveBSPB);
newBSP2 = filetBSP.subtract(EmportePieceBSPH);
newBSP1 = newBSP2.subtract(paveBSPB);
filletBSP = newBSP1.subtract(EmportePieceBSPT);
////////////////////subtract//////////////////////////////
var newFilet = new THREE.Geometry();
newFilet = filletBSP.toGeometry();
var newFilletMesh = new THREE.Mesh(newFilet, new THREE.MeshBasicMaterial({ map: texture }));
newFilletMesh.position.set(0, 0, 0);
///////////////////////////////////création morceaux découpés///////////////////////////////////////////
var HeadFillet = new THREE.Geometry();
var TailFillet = new THREE.Geometry();
var degraissageFillet = new THREE.Geometry();
HeadFillet = newBSPH.toGeometry();
TailFillet = newBSPT.toGeometry();
degraissageFillet = newBSPB.toGeometry();
/////////////////////////////////calcul des volumes des 1ers morceaux/////////////////////////////////////////
if (widthH != 0) {
tabVolumes[0] = calculateVolume2(HeadFillet);
} else { tabVolumes[0] = 0;}
if (widthT != 0) {
//alert(tabVolumes[0]);
tabVolumes[1] = calculateVolume2(TailFillet);
} else { tabVolumes[1] = 0; }
if (height != 0) {
tabVolumes[2] = calculateVolume2(degraissageFillet);
} else { tabVolumes[2] = 0; }
var ind = 3;
var HeadFilletMesh = new THREE.Mesh(HeadFillet, new THREE.MeshBasicMaterial({ map: texture }));
var TailFilletMesh = new THREE.Mesh(TailFillet, new THREE.MeshBasicMaterial({ map: texture }));
var degraissageFilletMesh = new THREE.Mesh(degraissageFillet, new THREE.MeshBasicMaterial({ map: texture }));
HeadFilletMesh.position.set(0, 0, 20);
degraissageFilletMesh.position.set(-20, 0, 0);
TailFilletMesh.position.set(0, 0, -20);
scene.add(HeadFilletMesh);
scene.add(TailFilletMesh);
scene.add(degraissageFilletMesh);
//scene.add(newFilletMesh);
var cloneHeadFilletMesh = HeadFilletMesh.clone();
var cloneTailFilletMesh = TailFilletMesh.clone();
var clonedegraissageFilletMesh = degraissageFilletMesh.clone();
var mesh_decoupe = new THREE.Object3D;
mesh_decoupe.add(cloneHeadFilletMesh);
mesh_decoupe.add(cloneTailFilletMesh);
mesh_decoupe.add(clonedegraissageFilletMesh);
if (width != 0) {
var paveGeom = new THREE.BoxGeometry(300, 300, width);
var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
var fillet2BSP = new ThreeBSP(newFilletMesh);
var intersectionPave = new THREE.Geometry();
intersectionPave = fillet2BSP.intersect(paveBSP);
var geometryPave = new THREE.Geometry();
geometryPave = intersectionPave.toGeometry();
var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
//alert(geometryPave.faces.length);
while (geometryPave.faces.length != 0) {
var z = paveMesh.position.z + width + 5;
paveMesh.position.set(0, 0, z);
paveBSP = new ThreeBSP(paveMesh);
//scene.add(paveMesh);
fillet2BSP = new ThreeBSP(newFilletMesh);
intersectionPave = filletBSP.intersect(paveBSP);
geometryPave = intersectionPave.toGeometry();
tabVolumes[ind] = calculateVolume2(geometryPave);
ind = ind + 1;
var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
newMesh.position.set(0, 0, newMesh.position.z);
scene.add(newMesh);
var meshSave = newMesh.clone();
mesh_decoupe.add(meshSave);
}
document.body.style.cursor = '';
} else {
scene.add(newFilletMesh);
document.body.style.cursor = '';
tabVolumes[3] = 0;
tabVolumes[4] = calculateVolume2(newFilet);
}
// }
//}
//else {
// scene.add(newFilletMesh);
// tabVolumes[ind] = calculateVolume2(newFilet);
//}
//alert(calculateVolume2(newBSP.toGeometry()));
//afficher les volumes dans la textarea
var txtVolume = document.getElementById("txtVolume");
txtVolume.value = tabVolumes.join("\n");
//var exporter = new THREE.OBJExporter();
//var result = exporter.parse(mesh_decoupe);
//var blob = new Blob([result], { type: 'text/plain' });
//saveAs(blob, 'dechets.obj');
}
});
//scene.add(object);
}, onProgress, onError);
renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 500, false);
document.getElementById('canvas3D').innerHTML = "";
document.getElementById('canvas3D').appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
camin();
renderer.render(scene, camera);
}
function camin() {
camera.position.y -= .1;
}
function volumeOfT(p1, p2, p3) {
var v321 = p3.x * p2.y * p1.z;
var v231 = p2.x * p3.y * p1.z;
var v312 = p3.x * p1.y * p2.z;
var v132 = p1.x * p3.y * p2.z;
var v213 = p2.x * p1.y * p3.z;
var v123 = p1.x * p2.y * p3.z;
return (-v321 + v231 + v312 - v132 - v213 + v123) / 6.0;
}
function calculateVolume2(object) {
var volumes = 0.0;
for (var i = 0; i < object.faces.length; i++) {
var Pi = object.faces[i].a;
var Qi = object.faces[i].b;
var Ri = object.faces[i].c;
//alert (Pi);
var P = new THREE.Vector3(object.vertices[Pi].x, object.vertices[Pi].y, object.vertices[Pi].z);
//alert(object.vertices[Pi].x);
var Q = new THREE.Vector3(object.vertices[Qi].x, object.vertices[Qi].y, object.vertices[Qi].z);
var R = new THREE.Vector3(object.vertices[Ri].x, object.vertices[Ri].y, object.vertices[Ri].z);
volumes += volumeOfT(P, Q, R);
}
return Math.abs(volumes);
}
}
function FirstCut() {
var scene, camera, renderer, controls;
//stl loader from https://threejs.org/examples/webgl_loader_stl.html
// cf example https://stemkoski.github.io/Three.js/CSG.html
//with obj
init();
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xeeeeee);
camera = new THREE.PerspectiveCamera(75, 800 / 500, 1, 2000);
//camera.position.set(50, 500, 0);
camera.position.x = 50;
camera.position.y = 500;
camera.position.z = 0;
//var axeX = new THREE.Vector3(1, 0, 0);
//camera.rotateOnAxis(axeX, -1);
camera.lookAt(new THREE.Vector3(0, 500, 0));
controls = new THREE.OrbitControls(camera);
//les valeurs de min and max distance sont choisies pour que le filet ne disparaisse pas quand on le fait tourner
controls.minDistance = 0;
controls.maxDistance = 1000;
//scene
//var ambient = new THREE.AmbientLight(0x101030);
//scene.add(ambient);
//scene.add(new THREE.GridHelper(1000, 20));
//var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
//directionalLight.position.set(0, 1, 0);
//scene.add(directionalLight);
var widthH = parseInt(document.getElementById("wdthH").value) || 0; // H for Head
var widthT = parseInt(document.getElementById("wdthT").value) || 0; // T for tail
var height = parseInt(document.getElementById("hght").value) || 0; // flank
//création du pavé
var EmportePieceH = new THREE.BoxGeometry(300, 60, widthH);
var EmportePieceT = new THREE.BoxGeometry(300, 60, widthT);
var EmportePieceB = new THREE.BoxGeometry(height, 60, 520);
var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
// création du meshage et material
var EmportePieceMeshH = new THREE.Mesh(EmportePieceH, paveMaterial);
var EmportePieceMeshT = new THREE.Mesh(EmportePieceT, paveMaterial);
var paveMeshB = new THREE.Mesh(EmportePieceB, paveMaterial);
var zH = 247 - widthH / 2;
var zT = -247 + widthT / 2;
EmportePieceMeshH.position.set(0, 30, zH);
EmportePieceMeshT.position.set(0, 30, zT);
paveMeshB.position.set(-95 + height / 2, 30, 0);
var EmportePieceBSPH = new ThreeBSP(EmportePieceMeshH);
var EmportePieceBSPT = new ThreeBSP(EmportePieceMeshT);
var paveBSPB = new ThreeBSP(paveMeshB);
//scene.add(EmportePieceMeshH);
//scene.add(EmportePieceMeshT);
//scene.add(paveMeshB);
// texture
var manager = new THREE.LoadingManager();
manager.onProgress = function (item, loaded, total) {
console.log(item, loaded, total);
};
var texture = new THREE.Texture();
var onProgress = function (xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}
};
var onError = function (xhr) {
};
var loader = new THREE.ImageLoader(manager);
loader.load('/Scan/filet_1kg500-reposition-reduit_material_0.jpg', function (image) {
texture.image = image;
texture.needsUpdate = true;
});
var width = parseInt(document.getElementById("wdth").value) || 0;
//création du pavé
var paveGeom = new THREE.BoxGeometry(250, 250, width);
var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
// création du meshage parallélépipède avec material
var paveMesh = new THREE.Mesh(paveGeom, paveMaterial);
var z0 = -247 + widthH;
paveMesh.position.set(0, 0, z0);
var paveBSP = new ThreeBSP(paveMesh);
//scene.add(paveMesh);
//tableau des volumes
var tabVolumes = new Array();
// model
var loader = new THREE.OBJLoader(manager);
loader.load('/Scan/filet_1kg500-reposition-reduit.obj', function (object) {
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = texture;
var geo = new THREE.Geometry().fromBufferGeometry(child.geometry);
var filetMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
var filetMesh = new THREE.Mesh(geo, filetMaterial);
//scene.add(filetMesh);
var newBSPH, newBSPT, newBSPB, newBSP2, newBSP1, filletBSP
var filetBSP = new ThreeBSP(filetMesh);
newBSPH = filetBSP.intersect(EmportePieceBSPH);
newBSPT = filetBSP.intersect(EmportePieceBSPT);
newBSPB = filetBSP.intersect(paveBSPB);
newBSP2 = filetBSP.subtract(EmportePieceBSPH);
newBSP1 = newBSP2.subtract(paveBSPB);
filletBSP = newBSP1.subtract(EmportePieceBSPT);
////////////////////subtract//////////////////////////////
var newFilet = new THREE.Geometry();
newFilet = filletBSP.toGeometry();
var newFilletMesh = new THREE.Mesh(newFilet, new THREE.MeshBasicMaterial({ map: texture }));
newFilletMesh.position.set(0, 0, 0);
///////////////////////////////////création morceaux découpés///////////////////////////////////////////
var HeadFillet = new THREE.Geometry();
var TailFillet = new THREE.Geometry();
var degraissageFillet = new THREE.Geometry();
HeadFillet = newBSPH.toGeometry();
TailFillet = newBSPT.toGeometry();
degraissageFillet = newBSPB.toGeometry();
/////////////////////////////////calcul des volumes des 1ers morceaux/////////////////////////////////////////
if (widthH != 0) {
tabVolumes[0] = calculateVolume2(HeadFillet);
} else { tabVolumes[0] = 0;}
if (widthT != 0) {
//alert(tabVolumes[0]);
tabVolumes[1] = calculateVolume2(TailFillet);
} else { tabVolumes[1] = 0; }
if (height != 0) {
tabVolumes[2] = calculateVolume2(degraissageFillet);
} else { tabVolumes[2] = 0; }
var ind = 3;
var HeadFilletMesh = new THREE.Mesh(HeadFillet, new THREE.MeshBasicMaterial({ map: texture }));
var TailFilletMesh = new THREE.Mesh(TailFillet, new THREE.MeshBasicMaterial({ map: texture }));
var degraissageFilletMesh = new THREE.Mesh(degraissageFillet, new THREE.MeshBasicMaterial({ map: texture }));
HeadFilletMesh.position.set(0, 0, 20);
degraissageFilletMesh.position.set(-20, 0, 0);
TailFilletMesh.position.set(0, 0, -20);
scene.add(HeadFilletMesh);
scene.add(TailFilletMesh);
scene.add(degraissageFilletMesh);
//scene.add(newFilletMesh);
var cloneHeadFilletMesh = HeadFilletMesh.clone();
var cloneTailFilletMesh = TailFilletMesh.clone();
var clonedegraissageFilletMesh = degraissageFilletMesh.clone();
var mesh_decoupe = new THREE.Object3D;
mesh_decoupe.add(cloneHeadFilletMesh);
mesh_decoupe.add(cloneTailFilletMesh);
mesh_decoupe.add(clonedegraissageFilletMesh);
if (width != 0) {
var paveGeom = new THREE.BoxGeometry(300, 300, width);
var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
var fillet2BSP = new ThreeBSP(newFilletMesh);
var intersectionPave = new THREE.Geometry();
intersectionPave = fillet2BSP.intersect(paveBSP);
var geometryPave = new THREE.Geometry();
geometryPave = intersectionPave.toGeometry();
var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
//alert(geometryPave.faces.length);
while (geometryPave.faces.length != 0) {
var z = paveMesh.position.z + width + 5;
paveMesh.position.set(0, 0, z);
paveBSP = new ThreeBSP(paveMesh);
//scene.add(paveMesh);
fillet2BSP = new ThreeBSP(newFilletMesh);
intersectionPave = filletBSP.intersect(paveBSP);
geometryPave = intersectionPave.toGeometry();
tabVolumes[ind] = calculateVolume2(geometryPave);
ind = ind + 1;
var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
newMesh.position.set(0, 0, newMesh.position.z);
scene.add(newMesh);
var meshSave = newMesh.clone();
mesh_decoupe.add(meshSave);
}
document.body.style.cursor = '';
} else {
scene.add(newFilletMesh);
document.body.style.cursor = '';
tabVolumes[3] = 0;
tabVolumes[4] = calculateVolume2(newFilet);
}
// }
//}
//else {
// scene.add(newFilletMesh);
// tabVolumes[ind] = calculateVolume2(newFilet);
//}
//alert(calculateVolume2(newBSP.toGeometry()));
//afficher les volumes dans la textarea
var txtVolume = document.getElementById("txtVolume");
txtVolume.value = tabVolumes.join("\n");
//var exporter = new THREE.OBJExporter();
//var result = exporter.parse(mesh_decoupe);
//var blob = new Blob([result], { type: 'text/plain' });
//saveAs(blob, 'dechets.obj');
}
});
//scene.add(object);
}, onProgress, onError);
renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 500, false);
document.getElementById('canvas3D').innerHTML = "";
document.getElementById('canvas3D').appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
camin();
renderer.render(scene, camera);
}
function camin() {
camera.position.y -= .1;
}
function volumeOfT(p1, p2, p3) {
var v321 = p3.x * p2.y * p1.z;
var v231 = p2.x * p3.y * p1.z;
var v312 = p3.x * p1.y * p2.z;
var v132 = p1.x * p3.y * p2.z;
var v213 = p2.x * p1.y * p3.z;
var v123 = p1.x * p2.y * p3.z;
return (-v321 + v231 + v312 - v132 - v213 + v123) / 6.0;
}
function calculateVolume2(object) {
var volumes = 0.0;
for (var i = 0; i < object.faces.length; i++) {
var Pi = object.faces[i].a;
var Qi = object.faces[i].b;
var Ri = object.faces[i].c;
//alert (Pi);
var P = new THREE.Vector3(object.vertices[Pi].x, object.vertices[Pi].y, object.vertices[Pi].z);
//alert(object.vertices[Pi].x);
var Q = new THREE.Vector3(object.vertices[Qi].x, object.vertices[Qi].y, object.vertices[Qi].z);
var R = new THREE.Vector3(object.vertices[Ri].x, object.vertices[Ri].y, object.vertices[Ri].z);
volumes += volumeOfT(P, Q, R);
}
return Math.abs(volumes);
}
}

Related

Three.js all texture are white

I've changed the version of my three.js because i wanted to use projector but now all my texture went white. I can't find what is wrong with it. I'm not getting any error in the console, which makes me a bit lost.
I was using r122.
Any body know what is happening ?
most of the code here comes from a code pen :
https://codepen.io/yitliu/pen/bJoQLw
//----------VARIABLES----------
const dpi = window.devicePixelRatio;
const theCanvas = document.getElementById('canvas');
var h = window.innerHeight,
w = window.innerWidth;
aspectRatio = w / h,
fieldOfView = 25,
nearPlane = .1,
farPlane = 1000;
container = document.getElementById('container');
var dae, scene, camera, renderer;
var Colors = {
cyan: 0x248079,
brown: 0xA98F78,
brownDark: 0x9A6169,
green: 0x65BB61,
greenLight: 0xABD66A,
blue: 0x6BC6FF
};
function init() {
//----------SCENE----------
scene = new THREE.Scene();
//----------CAMERA----------
camera = new THREE.PerspectiveCamera(
fieldOfView,
aspectRatio,
nearPlane,
farPlane);
//----------RENDER----------
renderer = new THREE.WebGLRenderer({ canvas: canvas, alpha: true, antialias: true });
renderer.setSize(w * dpi, h * dpi);
theCanvas.style.width = `${w}px`;
theCanvas.style.height = `${h}px`;
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
camera.position.set(-5, 6, 8);
camera.lookAt(new THREE.Vector3(0, 0, 0));
//---------LIGHT---------
var light = new THREE.AmbientLight(0xffffff, .5);
var shadowLight = new THREE.DirectionalLight(0xffffff, .5);
shadowLight.position.set(200, 200, 200);
shadowLight.castShadow = true;
var backLight = new THREE.DirectionalLight(0xffffff, .2);
backLight.position.set(-100, 200, 50);
backLight.castShadow = true;
scene.add(backLight);
scene.add(light);
scene.add(shadowLight);
//---------CONTROLS---------
const controls = new THREE.OrbitControls(camera, renderer.domElement);
//---------GEOMETRY---------
var geometry_left = new THREE.CubeGeometry(2, .2, 4);
var material_grass = new THREE.MeshLambertMaterial({ color: Colors.greenLight });
var ground_left = new THREE.Mesh(geometry_left, material_grass);
ground_left.position.set(-1, 0.1, 0);
ground_left.receiveShadow = true;
scene.add(ground_left);
var geometry_bot = new THREE.CubeGeometry(4, .2, 1);
var material_grass = new THREE.MeshLambertMaterial({ color: Colors.greenLight });
var ground_bot = new THREE.Mesh(geometry_bot, material_grass);
ground_bot.position.set(0, 0.1, 2);
ground_bot.receiveShadow = true;
scene.add(ground_bot);
var geometry_top = new THREE.CubeGeometry(4, .2, 1);
var material_grass = new THREE.MeshLambertMaterial({ color: Colors.greenLight });
var ground_top = new THREE.Mesh(geometry_top, material_grass);
ground_top.position.set(0, 0.1, -2);
ground_top.receiveShadow = true;
scene.add(ground_top);
var geometry_river = new THREE.CubeGeometry(1, .1, 4);
var material_river = new THREE.MeshLambertMaterial({ color: Colors.blue });
var river = new THREE.Mesh(geometry_river, material_river);
river.position.set(.5, .1, 0);
river.receiveShadow = true;
scene.add(river);
var geometry_bed = new THREE.CubeGeometry(1, .05, 4);
var bed = new THREE.Mesh(geometry_bed, material_grass);
bed.position.set(.5, .025, 0);
scene.add(bed);
var geometry_right = new THREE.CubeGeometry(1, .2, 4);
var ground_right = new THREE.Mesh(geometry_right, material_grass);
ground_right.position.set(1.5, 0.1, 0);
ground_right.receiveShadow = true;
scene.add(ground_right);
var tree = function (x, z) {
this.x = x;
this.z = z;
var material_trunk = new THREE.MeshLambertMaterial({ color: Colors.brownDark });
var geometry_trunk = new THREE.CubeGeometry(.15, .15, .15);
var trunk = new THREE.Mesh(geometry_trunk, material_trunk);
trunk.position.set(this.x, .275, this.z);
trunk.castShadow = true;
trunk.receiveShadow = true;
scene.add(trunk);
var geometry_leaves = new THREE.CubeGeometry(.25, .4, .25);
var material_leaves = new THREE.MeshLambertMaterial({ color: Colors.green });
var leaves = new THREE.Mesh(geometry_leaves, material_leaves);
leaves.position.set(this.x, .2 + .15 + .4 / 2, this.z);
leaves.castShadow = true;
scene.add(leaves);
}
tree(-1.5, -1.5);
//tree(-1.25,.75);
tree(-.25, -.85);
tree(0.4, 2);
//tree(1.25,-2);
tree(1.75, .35);
var material_wood = new THREE.MeshLambertMaterial({ color: Colors.brown });
var geometry_block = new THREE.CubeGeometry(1.3, .02, .6);
var block = new THREE.Mesh(geometry_block, material_wood);
block.position.set(.5, .21, .2);
block.castShadow = true;
block.receiveShadow = true;
scene.add(block);
//---------CAR---------
var loader = new THREE.ColladaLoader();
loader.load('offroadcar.dae', function (collada) {
dae = collada.scene;
dae.scale.x = dae.scale.y = dae.scale.z = 0.1;
dae.position.set(-1, .2, 0);
dae.updateMatrix();
//customizeShadow(dae, .25)
scene.add(dae);
dae.castShadow = true;
dae.receiveShadow = true;
})
}// end of init
//---------STARTING---------
init();
animate();
//---------LISTENERS---------
theCanvas.addEventListener('click', function (evt) {
clickInfo.userHasClicked = true;
clickInfo.x = evt.clientX - theCanvas.offsetLeft;
clickInfo.y = evt.clientY - theCanvas.offsetTop;
}, false);
//---------METHODS---------
function animate() {
renderer.render(scene, camera);
requestAnimationFrame(function () { animate(); });
}

Draw a 2D line with width in three.js

I'm looking to draw a continuous line with a given thickness showing only the edges using three.js. I have achieved it. I'm trying to add thickness to the line but it is not getting reflected in the scene due to some angle in three.js. Can anyone help me out with the issue.
Here's the fiddle https://jsfiddle.net/16vhjm0y/1/
var renderer, scene, camera;
var line;
var count = 0;
var mouse = new THREE.Vector3();
var mesh3D;
var maxPoint = 6;
var height = window.innerHeight * .99;
var plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0); // facing us for mouse intersection
var raycaster = new THREE.Raycaster();
var point3ds = [];
var usePerspectiveCamera = false; // toggles back and forth
var perspOrbit;
var perspCam;
var orthoOrbit;
var orthoCam;
var labelRenderer, labelAjay;
var testBoolean = false;
var mouseDownBoolean = false;
var distanceData, showDistanceData;
var ajay;
var arrAjay = [];
var arrAjayFinal = [];
var mouseUpBoolean = false;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, height);
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
// camera perspective
perspCam = new THREE.PerspectiveCamera(45, window.innerWidth / height, 1, 10000);
perspCam.position.set(0, 0, 200);
// camera ortho
var width = window.innerWidth;
//var height = window.innerHeight;
orthoCam = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, 0, 1200);
// assign cam
camera = perspCam;
someMaterial = new THREE.MeshBasicMaterial({ color: 0xA9A9A9, side: THREE.DoubleSide, transparent: true, opacity: 0.3 });
// grid
var grid = new THREE.GridHelper(1024, 56);
grid.rotateX(Math.PI / 2);
// scene.add(grid);
// geometry
var geometry = new THREE.BufferGeometry();
var MAX_POINTS = 500;
positions = new Float32Array(MAX_POINTS * 3);
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
// material
var material = new THREE.LineBasicMaterial({
color: 0xff0000,
linewidth: 10
});
// line
line = new THREE.Line(geometry, material);
// line.position.z = 20;
scene.add(line);
// var geometry = new THREE.BoxBufferGeometry( 10, 2, 20 );
// var edgesPavement = new THREE.EdgesGeometry( geomPavement );
// var lineGeometry = new THREE.LineSegmentsGeometry().setPositions( edgesPavement.attributes.position.array );
// var lineMaterial = new THREE.LineMaterial( { color: 0xff0000, linewidth: 10 } );
// lineMaterial.resolution.set( window.innerWidth, window.innerHeight ); // important, for now...
// var line = new THREE.LineSegments2( lineGeometry, lineMaterial );
// scene.add( line );
document.addEventListener("mousemove", onMouseMove, false);
document.addEventListener('mousedown', onMouseDown, false);
document.addEventListener('mouseup', onMouseUp, false);
createUI();
labelRenderer = new THREE.CSS2DRenderer();
ajay = document.createElement('div');
ajay.className = 'ajay';
ajay.style.color = "black";
ajayInsert = document.createElement('div');
ajayInsert.className = 'ajay';
ajayInsert.style.color = "black";
// ajay.style.color = "black";
// console.log(ajay)
labelAjay = new THREE.CSS2DObject(ajay);
labelAjayFinal = new THREE.CSS2DObject(ajayInsert);
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0';
labelRenderer.domElement.style.pointerEvents = 'none';
ajay.style.display = "none";
ajayInsert.style.display = "none";
}
// update line
function updateLine() {
positions[count * 3 - 3] = mouse.x;
positions[count * 3 - 2] = mouse.y;
positions[count * 3 - 1] = mouse.z;
line.geometry.attributes.position.needsUpdate = true;
}
// mouse move handler
function onMouseMove(event) {
var rect = renderer.domElement.getBoundingClientRect();
mouse.x = (event.clientX - rect.left) / (rect.right - rect.left) * 2 - 1;
mouse.y = - ((event.clientY - rect.top) / (rect.bottom - rect.top)) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
mouse = raycaster.ray.intersectPlane(plane, mouse);
if (count !== 0 && count < maxPoint) {
updateLine();
}
testBoolean = true;
if (testBoolean == true) {
// scene.remove(labelAjay);
var geometry = line.geometry;
geometry.computeBoundingBox();
center = geometry.boundingBox.getCenter();
// line.localToWorld(center);
// console.log(center);
if (mouseDownBoolean == true) {
labelAjay.position.set(mouse.x, mouse.y, mouse.z);
// console.log(line.position)
scene.add(labelAjay);
document.body.appendChild(labelRenderer.domElement);
// console.log(positions);
distanceData = point3ds[0].distanceTo(new THREE.Vector3(mouse.x, mouse.y, mouse.z));
showDistanceData = Math.round(distanceData * 1000);
// console.log(point3ds[0]);
// console.log(point3ds[1]);
// console.log(distanceData);
// console.log(showDistanceData)
ajay.textContent = showDistanceData + ' mm';
// console.log(labelRenderer)
}
// console.log(labelRenderer.domElement)
// document.getElementsByClassName("ajay").remove();
// document.getElementsByClassName("ajay").outerHTML = "";
}
}
// add point
function addPoint(event) {
if (count < maxPoint) {
console.log("point nr " + count + ": " + mouse.x + " " + mouse.y + " " + mouse.z);
positions[count * 3 + 0] = mouse.x;
positions[count * 3 + 1] = mouse.y;
positions[count * 3 + 2] = mouse.z
count++;
line.geometry.setDrawRange(0, count);
updateLine();
point3ds.push(new THREE.Vector3(mouse.x, mouse.y, mouse.z));
} else {
console.log('max points reached: ' + maxPoint);
}
}
function getPointInBetweenByLen(pointA, pointB, length) {
var dir = pointB.clone().sub(pointA).normalize().multiplyScalar(length);
return pointA.clone().add(dir);
}
// mouse down handler
function onMouseDown(evt) {
mouseDownBoolean = true;
// force add an extra point on first click so buffer line can display
// buffer geometry requires two points to display, so first click should add two points
if (count === 0) {
addPoint();
}
if (count < maxPoint) {
addPoint();
}
}
function onMouseUp(event){
mouseUpBoolean = true;
if(mouseUpBoolean == true){
// showDistanceData = Math.round(distanceData * 1000);
arrAjay.push(showDistanceData);
console.log(arrAjay);
arrAjayFinal = arrAjay.splice(-1)[0];
var geometry = line.geometry;
geometry.computeBoundingBox();
center = geometry.boundingBox.getCenter();
if (mouseDownBoolean == true) {
labelAjayFinal.position.set(center.x, center.y, center.z);
scene.add(labelAjayFinal);
document.body.appendChild(labelRenderer.domElement);
// distanceData = point3ds[0].distanceTo(new THREE.Vector3(mouse.x, mouse.y, mouse.z));
// showDistanceData = Math.round(distanceData * 1000);
console.log('arrAjayFinal', arrAjayFinal);
ajayInsert.textContent = arrAjayFinal;
}
}
}
// render
function render() {
renderer.render(scene, camera);
labelRenderer.render(scene, camera);
}
// animate
function animate() {
requestAnimationFrame(animate);
render();
}
// loop through all the segments and create their 3D
function create3D() {
if (!mesh3D && point3ds && point3ds.length) {
console.log('creating 3D');
mesh3D = new THREE.Mesh(); // metpy mesh but is the root mesh for all 3D
scene.add(mesh3D);
// prepare create segments from point3ds - every two points create a segement
var index = 1;
var segmentHeight = 56;
point3ds.forEach(point3d => {
if (index < point3ds.length) {
var seg = new Segment(point3d, point3ds[index], someMaterial, segmentHeight);
mesh3D.add(seg.mesh3D);
index++;
}
});
}
}
function createUI() {
// create3D
var btn = document.createElement('button');
document.body.appendChild(btn);
btn.innerHTML = 'Create3D';
btn.addEventListener('mousedown', () => {
create3D();
// add orbiting controls to both cameras
var controls;
if (!perspOrbit) {
perspOrbit = new THREE.OrbitControls(perspCam, renderer.domElement);
perspOrbit.screenSpacePanning = true;
// raotation is enabled once create3D is pressed
setToFullOrbit(perspOrbit);
perspOrbit.enabled = true; // set to true by default
}
// add orbit to orthocam
if (!orthoOrbit) {
orthoOrbit = new THREE.OrbitControls(orthoCam, renderer.domElement);
orthoOrbit.screenSpacePanning = true;
orthoOrbit.enabled = false; // set to false by default
//orthoOrbit.enableDamping = true;
//orthoOrbit.dampingFactor = .15;
}
});
}
function switchCam() {
usePerspectiveCamera = !usePerspectiveCamera;
if (usePerspectiveCamera) {
if (perspCam) {
camera = perspCam;
perspOrbit.enabled = true;
orthoOrbit.enabled = false;
} else {
throw new Error('Switch to perspective cam failed, perspective cam is null');
}
} else {
if (orthoCam) {
camera = orthoCam;
orthoOrbit.enabled = true;
perspOrbit.enabled = false;
} else {
throw new Error('Switch to ortho cam failed, orthoCam is null');
}
}
}
function rotateCam90() {
if (camera instanceof THREE.OrthographicCamera) {
orthoOrbit.update();
camera.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI / 2));
}
}
function reset() {
scene.remove(mesh3D);
mesh3D = null;
for (var i = 0; i < 3 * 8; i++) {
positions[i] = 0;
}
count = 0;
line.geometry.setDrawRange(0, count);
updateLine();
point3ds = [];
}
function setToFullOrbit(orbitControl) {
// how far you can orbit vertically
orbitControl.minPolarAngle = 0;
orbitControl.maxPolarAngle = Math.PI;
// How far you can dolly in and out ( PerspectiveCamera only )
orbitControl.minDistance = 0;
orbitControl.maxDistance = Infinity;
orbitControl.enableZoom = true; // Set to false to disable zooming
orbitControl.zoomSpeed = 1.0;
orbitControl.enableRotate = true;
// allow keyboard arrows
orbitControl.enableKeys = true;
// Set to false to disable panning (ie vertical and horizontal translations)
orbitControl.enablePan = true;
}
// each segment knows how to create its 3D
class Segment {
constructor(start, end, material, height) {
this.start = start;
this.end = end;
this.height = height; // height of the segment's 3D
this.material = material;
this.mesh3D = null;
this.create3D();
}
create3D() {
if (this.start && this.end) {
//create the shape geometry
var distStartToEnd = this.start.distanceTo(this.end);
var vec2s = [
new THREE.Vector2(),
new THREE.Vector2(0, this.height),
new THREE.Vector2(distStartToEnd, this.height),
new THREE.Vector2(distStartToEnd, 0)
];
console.log('vec2s', vec2s);
var shape = new THREE.Shape(vec2s);
var geo = new THREE.BoxGeometry(5, 5, 5);
// console.log('shape', shape);
var geo = new THREE.ShapeGeometry(shape);
geo.applyMatrix(new THREE.Matrix4().makeRotationX(THREE.Math.degToRad(90)));
this.mesh3D = new THREE.Mesh(geo, this.material);
this.alignRotation();
this.alignPosition();
// the mesh3D should be added to the scene outside of this class
}
}
alignRotation() {
var p1 = this.start.clone();
var p2 = this.end.clone();
var direction = new THREE.Vector3();
direction.subVectors(p2, p1);
direction.normalize();
this.mesh3D.quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), direction);
}
alignPosition() {
if (this.mesh3D) {
this.mesh3D.position.copy(this.start);
} else {
throw new Error('mesh3D null');
}
}
}
The linewidth parameter relies on native WebGL support for drawing line thickness, but its performance is very spotty across browsers & operating systems. I think Windows doesn't support it, but MacOS does, so it shouldn't be relied upon. See this discussion on the Three.js Github for several bug reports.
As a workaround, they've created LineGeometry, which sort of re-builds a line with geometry to allow for thickness. See this example for how to use it. It even allows for dashed lines. After importing the module, you can implement it with:
const geometry = new LineGeometry();
geometry.setPositions( positions );
geometry.setColors( colors );
matLine = new LineMaterial( {
color: 0xffffff,
linewidth: 5, // in pixels
vertexColors: true,
dashed: false
} );
line = new Line2( geometry, matLine );
line.computeLineDistances();
scene.add( line );

Three JS: Add Zoom function to the Bounding Box (Rect)

Here I have created a rect in which it gets zoom in to the mid point of the scene. Here I'm looking to zoom in to the center of the rect (where we select the object) towards the object.
I have an idea to get the center point of the rect and and pass it to the zoom function where I'm struggling in.
Please help me out
Heres the snippet
/**
* #author HypnosNova / https://www.threejs.org.cn/gallery
* This is a class to check whether objects are in a selection area in 3D space
*/
THREE.SelectionBox = (function() {
var frustum = new THREE.Frustum();
var center = new THREE.Vector3();
function SelectionBox(camera, scene, deep) {
this.camera = camera;
this.scene = scene;
this.startPoint = new THREE.Vector3();
this.endPoint = new THREE.Vector3();
this.collection = [];
this.deep = deep || Number.MAX_VALUE;
}
SelectionBox.prototype.select = function(startPoint, endPoint) {
this.startPoint = startPoint || this.startPoint;
this.endPoint = endPoint || this.endPoint;
this.collection = [];
this.updateFrustum(this.startPoint, this.endPoint);
this.searchChildInFrustum(frustum, this.scene);
return this.collection;
};
SelectionBox.prototype.updateFrustum = function(startPoint, endPoint) {
startPoint = startPoint || this.startPoint;
endPoint = endPoint || this.endPoint;
this.camera.updateProjectionMatrix();
this.camera.updateMatrixWorld();
var tmpPoint = startPoint.clone();
tmpPoint.x = Math.min(startPoint.x, endPoint.x);
tmpPoint.y = Math.max(startPoint.y, endPoint.y);
endPoint.x = Math.max(startPoint.x, endPoint.x);
endPoint.y = Math.min(startPoint.y, endPoint.y);
var vecNear = this.camera.position.clone();
var vecTopLeft = tmpPoint.clone();
var vecTopRight = new THREE.Vector3(endPoint.x, tmpPoint.y, 0);
var vecDownRight = endPoint.clone();
var vecDownLeft = new THREE.Vector3(tmpPoint.x, endPoint.y, 0);
vecTopLeft.unproject(this.camera);
vecTopRight.unproject(this.camera);
vecDownRight.unproject(this.camera);
vecDownLeft.unproject(this.camera);
var vectemp1 = vecTopLeft.clone().sub(vecNear);
var vectemp2 = vecTopRight.clone().sub(vecNear);
var vectemp3 = vecDownRight.clone().sub(vecNear);
vectemp1.normalize();
vectemp2.normalize();
vectemp3.normalize();
vectemp1.multiplyScalar(this.deep);
vectemp2.multiplyScalar(this.deep);
vectemp3.multiplyScalar(this.deep);
vectemp1.add(vecNear);
vectemp2.add(vecNear);
vectemp3.add(vecNear);
var planes = frustum.planes;
planes[0].setFromCoplanarPoints(vecNear, vecTopLeft, vecTopRight);
planes[1].setFromCoplanarPoints(vecNear, vecTopRight, vecDownRight);
planes[2].setFromCoplanarPoints(vecDownRight, vecDownLeft, vecNear);
planes[3].setFromCoplanarPoints(vecDownLeft, vecTopLeft, vecNear);
planes[4].setFromCoplanarPoints(vecTopRight, vecDownRight, vecDownLeft);
planes[5].setFromCoplanarPoints(vectemp3, vectemp2, vectemp1);
planes[5].normal.multiplyScalar(-1);
};
SelectionBox.prototype.searchChildInFrustum = function(frustum, object) {
if (object.isMesh) {
if (object.material !== undefined) {
object.geometry.computeBoundingSphere();
center.copy(object.geometry.boundingSphere.center);
center.applyMatrix4(object.matrixWorld);
if (frustum.containsPoint(center)) {
this.collection.push(object);
}
}
}
if (object.children.length > 0) {
for (var x = 0; x < object.children.length; x++) {
this.searchChildInFrustum(frustum, object.children[x]);
}
}
};
return SelectionBox;
})();
/**
* #author HypnosNova / https://www.threejs.org.cn/gallery
*/
THREE.SelectionHelper = (function() {
function SelectionHelper(selectionBox, renderer, cssClassName) {
this.element = document.createElement('div');
this.element.classList.add(cssClassName);
this.element.style.pointerEvents = 'none';
this.renderer = renderer;
this.startPoint = new THREE.Vector2();
this.pointTopLeft = new THREE.Vector2();
this.pointBottomRight = new THREE.Vector2();
this.isDown = false;
this.renderer.domElement.addEventListener('mousedown', function(event) {
this.isDown = true;
this.onSelectStart(event);
}.bind(this), false);
this.renderer.domElement.addEventListener('mousemove', function(event) {
if (this.isDown) {
this.onSelectMove(event);
}
}.bind(this), false);
this.renderer.domElement.addEventListener('mouseup', function(event) {
this.isDown = false;
this.onSelectOver(event);
}.bind(this), false);
}
SelectionHelper.prototype.onSelectStart = function(event) {
this.renderer.domElement.parentElement.appendChild(this.element);
this.element.style.left = event.clientX + 'px';
this.element.style.top = event.clientY + 'px';
this.element.style.width = '0px';
this.element.style.height = '0px';
this.startPoint.x = event.clientX;
this.startPoint.y = event.clientY;
};
SelectionHelper.prototype.onSelectMove = function(event) {
this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX);
this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY);
this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX);
this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY);
this.element.style.left = this.pointTopLeft.x + 'px';
this.element.style.top = this.pointTopLeft.y + 'px';
this.element.style.width = (this.pointBottomRight.x - this.pointTopLeft.x) + 'px';
this.element.style.height = (this.pointBottomRight.y - this.pointTopLeft.y) + 'px';
};
SelectionHelper.prototype.onSelectOver = function() {
this.element.parentElement.removeChild(this.element);
};
return SelectionHelper;
})();
var container;
var camera, scene, renderer;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 5000);
camera.position.z = 1000;
scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);
scene.add(new THREE.AmbientLight(0x505050));
var light = new THREE.SpotLight(0xffffff, 1.5);
light.position.set(0, 500, 2000);
light.angle = Math.PI / 9;
light.castShadow = true;
light.shadow.camera.near = 1000;
light.shadow.camera.far = 4000;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
var geometry = new THREE.BoxBufferGeometry(20, 20, 20);
for (var i = 0; i < 200; i++) {
var object = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: Math.random() * 0xffffff
}));
object.position.x = Math.random() * 1600 - 800;
object.position.y = Math.random() * 900 - 450;
object.position.z = Math.random() * 900 - 500;
object.rotation.x = Math.random() * 2 * Math.PI;
object.rotation.y = Math.random() * 2 * Math.PI;
object.rotation.z = Math.random() * 2 * Math.PI;
object.scale.x = Math.random() * 2 + 1;
object.scale.y = Math.random() * 2 + 1;
object.scale.z = Math.random() * 2 + 1;
object.castShadow = true;
object.receiveShadow = true;
scene.add(object);
}
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
container.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
var selectionBox = new THREE.SelectionBox(camera, scene);
var helper = new THREE.SelectionHelper(selectionBox, renderer, 'selectBox');
document.addEventListener('mousedown', function(event) {
for (var item of selectionBox.collection) {
item.material.emissive = new THREE.Color(0x000000);
}
selectionBox.startPoint.set(
(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1,
0.5);
});
document.addEventListener('mousemove', function(event) {
if (helper.isDown) {
for (var i = 0; i < selectionBox.collection.length; i++) {
selectionBox.collection[i].material.emissive = new THREE.Color(0x000000);
}
selectionBox.endPoint.set(
(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1,
0.5);
var allSelected = selectionBox.select();
for (var i = 0; i < allSelected.length; i++) {
allSelected[i].material.emissive = new THREE.Color(0x0000ff);
}
}
});
document.addEventListener('mouseup', function(event) {
selectionBox.endPoint.set(
(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1,
0.5);
var allSelected = selectionBox.select();
for (var i = 0; i < allSelected.length; i++) {
allSelected[i].material.emissive = new THREE.Color(0x0000ff);
}
});
body {
background-color: #f0f0f0;
color: #000;
margin: 0;
}
canvas {
display: block;
}
a {
color: #08e;
}
.selectBox {
border: 1px solid #55aaff;
background-color: rgba(75, 160, 255, 0.3);
position: fixed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.min.js"></script>
You want to zoom in to the selected area? Based on what you're doing, you could try something like this:
function zoomToSelection() {
topLeft = helper.pointTopLeft;
bottomRight = helper.pointBottomRight;
// Get the centerpoint of the selection.
let center = new THREE.Vector2(topLeft.x + (bottomRight.x - topLeft.x) / 2, topLeft.y + (bottomRight.y - topLeft.y) / 2);
// Get the center position in world space.
var vector = new THREE.Vector3(
(center.x / window.innerWidth) * 2 - 1,
-(center.y / window.innerHeight) * 2 + 1,
0.5
);
vector.unproject(camera);
camera.lookAt(vector);
var movement = vector.clone();
// Get the ratio between the box size and the window.
let zoomNeeded = (bottomRight.y - topLeft.y) / window.innerHeight;
// Get a scalar by which to move the camera in the direction it's looking.
let distanceToOrigin = camera.position.distanceTo(new THREE.Vector3(0, 0, 0))
let distance = distanceToOrigin - distanceToOrigin * zoomNeeded;
movement.sub(camera.position).normalize().multiplyScalar(-zoom);
var toDirection = camera.position.clone().sub(movement);
camera.position.set(toDirection.x, toDirection.y, toDirection.z);
}
Now just add to your 'mouseup' event listener:
document.addEventListener('mouseup', function(event) {
//...
zoomToSelection();
});

Transparency update via slider doesn't work in Firefox Mobile

I've created a slider to change the transparency of a cube created with three.js. The code works well with all browsers in the desktop. However, in the Android System (version 5.0), the Firefox browser (version of May 8) is unable to update the transparency.
Here is the web page with the applet: http://www.im-uff.mat.br/tmp/how/simple-11.html
The code is here:
<!-- saved from url=(0016)http://localhost -->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Orthogonal Projections 1</title>
<!-- JavaScript Libraries -->
<script src="threejs.r91/build/three.js"></script>
<script src="threejs.r91/examples/js/controls/TrackballControls.js"></script>
<script src="threejs.r91/examples/js/loaders/DDSLoader.js"></script>
<script src="threejs.r91/examples/js/loaders/MTLLoader.js"></script>
<script src="threejs.r91/examples/js/loaders/OBJLoader.js"></script>
<!-- ThreeJS Code -->
<script type="text/javascript">
window.addEventListener('load',
function()
{
document.getElementById('tr').style.visibility = "visible";
});
var transparency_value = 0;
function MakeQuadrilateral(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4)
{
var geo = new THREE.Geometry();
// generate vertices
geo.vertices.push( new THREE.Vector3(x1,y1,z1));
geo.vertices.push( new THREE.Vector3(x2,y2,z2));
geo.vertices.push( new THREE.Vector3(x3,y3,z3));
geo.vertices.push( new THREE.Vector3(x4,y4,z4));
geo.faces.push( new THREE.Face3(0,1,2));
geo.faces.push( new THREE.Face3(0,2,3));
// Return the geometry object
return geo;
}
// Adds text to the screen
function makeSpriteText(text)
{
var canvas = document.createElement('canvas');
var size = 256; // CHANGED
canvas.width = size;
canvas.height = size;
var context = canvas.getContext('2d');
context.fillStyle = '#ffffff'; // CHANGED
context.textAlign = 'center';
context.font = '48px Times';
context.fillText(text, size / 2, size / 2);
var amap = new THREE.Texture(canvas);
amap.needsUpdate = true;
var mat = new THREE.SpriteMaterial({
map: amap,
transparent: false,
useScreenCoordinates: false,
color: 0x0000ff // CHANGED
});
var sp = new THREE.Sprite(mat);
return(sp);
}
// Check capabilities, and start if sufficient
var hasWebGl = (function() {try {return !! window.WebGLRenderingContext &&
!! document.createElement('canvas').getContext('experimental-webgl');}
catch(e){return false;}})();
var hasCanvas = !! window.CanvasRenderingContext2D; // Converts value to boolean
var hasVibration = navigator.vibrate;
window.onresize = function(event)
{
if (loaded == true)
{
loaded = false;
context0.controls = new THREE.TrackballControls(context0.camera, context0.renderer.domElement);
context0.controls.target.set(0, 0, 0);
context0.controls.noZoom = false;
context0.controls.noPan = true;
context0.controls.rotateSpeed = 1.2;
context0.controls.dynamicDampingFactor = 0.2;
context0.controls.staticMoving = false;
}
}
if (hasCanvas)
{
document.addEventListener( "DOMContentLoaded", init, false);
} // End of if()
function init()
{
// Setup idiom
document.getElementById("msgwebglcontext0").innerHTML = "<br>";
/* spawns the objects, scenes, cameras, renderers etc. */
context0 = {color: 0xccff33, name: "0", width: 440, height: 440, factor: 30, arrowLength: 25};
// set the scene
if (hasWebGl)
{
context0.renderer = new THREE.WebGLRenderer({alpha: true, antialias: true });
}
else
{
context0.renderer = new THREE.CanvasRenderer({alpha: true, antialias: true });
}
context0.renderer.setSize(context0.width, context0.height);
// Add the renderer to the document.
// This should be called before THREE.TrackballControls().
document.getElementById("webglcontext0").appendChild(context0.renderer.domElement);
context0.scene = new THREE.Scene();
context0.camera = new THREE.PerspectiveCamera(20, context0.height/context0.width, 2, 10000); // 20: small values cause z-buffer fighting
context0.camera.position.z = 70;
context0.camera.position.x = 70;
context0.camera.position.y = 70;
context0.scene.add(context0.camera);
context0.controls = new THREE.TrackballControls(context0.camera, context0.renderer.domElement);
context0.controls.target.set(0, 0, 0);
context0.controls.noZoom = false;
context0.controls.noPan = true;
// Model
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round(percentComplete, 2) + '% downloaded' );
}
};
var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'obj/' );
mtlLoader.load( 'platonic-cube.obj.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'obj/' );
objLoader.load( 'platonic-cube.obj', function ( object )
{
object.traverse(function (child)
{
if (child instanceof THREE.Mesh)
{
// Polyhedra
child.name = "pdp-faces";
context0.scene.add(child);
var geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
console.log('From loaded OBJ: ' + geometry.vertices.length);
if ( Array.isArray( child.material ) )
{
var n = child.material.length;
for (i = 0; i < n; i++)
{
child.material[i].transparent = true;
child.material[i].opacity = (1 - transparency_value/100.0);
};
}
else
{
child.material.transparent = true;
child.material.opacity = (1 - transparency_value/100.0);
}
// Edges
var edges = new THREE.LineSegments(new THREE.EdgesGeometry(child.geometry), new THREE.LineBasicMaterial( {color: 0x000000}) );
edges.name = "pdp-edges";
context0.scene.add(edges);
// Vertices
var geometry = new THREE.Geometry().fromBufferGeometry( edges.geometry );
console.log('Geometry vertices length: ' + geometry.vertices.length);
var vertices = [];
var isNew;
var tolerance = 0.0000001;
if (geometry.vertices.length > 0)
{
vertices.push(new THREE.Vector3(geometry.vertices[0].x, geometry.vertices[0].y, geometry.vertices[0].z));
}
for (i = 1; i < geometry.vertices.length; i++)
{
l = vertices.length;
isNew = true;
for (j = 0; j < l; j++)
{
var d = geometry.vertices[i].distanceTo(vertices[j]);
if (d < tolerance)
{
isNew = false;
}
}
if (isNew == true)
{
vertices.push(new THREE.Vector3(geometry.vertices[i].x, geometry.vertices[i].y, geometry.vertices[i].z));
}
}
/*
alert('Unique vertices: ' + vertices.length);
for (i = 0; i < vertices.length; i++)
{
alert(vertices[i].x);
}
*/
// https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Polyhedra.html
// https://stemkoski.github.io/Three.js/Polyhedra.html
// Fit screen
child.geometry.computeBoundingSphere();
var fov = context0.camera.fov * ( Math.PI / 180 );
var objectSize = child.geometry.boundingSphere.radius;
var distance = 0.7*Math.abs( objectSize / Math.sin( fov / 2 ) );
context0.camera.position.z = 2.5*distance;
context0.camera.position.x = 2.5*distance;
context0.camera.position.y = 2.5*distance;
// PLANE PROJECTIONS
var geometry_xy = new THREE.Geometry().fromBufferGeometry( edges.geometry );
var geometry_xz = new THREE.Geometry().fromBufferGeometry( edges.geometry );
var geometry_yz = new THREE.Geometry().fromBufferGeometry( edges.geometry );
geometry_xy.dynamic = true;
geometry_xz.dynamic = true;
geometry_yz.dynamic = true;
for (i = 0; i < geometry_xy.vertices.length; i++)
{
var xOld = geometry_xy.vertices[i].x;
var yOld = geometry_xy.vertices[i].y;
var zOld = geometry_xy.vertices[i].z;
geometry_xy.vertices[i].set(xOld, yOld, -distance/3);
geometry_xz.vertices[i].set(xOld, -distance/3, zOld);
geometry_yz.vertices[i].set(-distance/3, yOld, zOld);
// console.log(geometry_xy.vertices[i].x + ' ' + geometry_xy.vertices[i].y + ' ' + geometry_xy.vertices[i].z);
}
geometry_xy.verticesNeedUpdate = true;
geometry_xz.verticesNeedUpdate = true;
geometry_yz.verticesNeedUpdate = true;
var edges_xy = new THREE.LineSegments(geometry_xy, new THREE.LineBasicMaterial( {color: 0x000000}) );
var edges_xz = new THREE.LineSegments(geometry_xz, new THREE.LineBasicMaterial( {color: 0x000000}) );
var edges_yz = new THREE.LineSegments(geometry_yz, new THREE.LineBasicMaterial( {color: 0x000000}) );
edges_xy.name = "pdp-edges-xy";
edges_xz.name = "pdp-edges-xz";
edges_yz.name = "pdp-edges-yz";
context0.scene.add(edges_xy);
context0.scene.add(edges_xz);
context0.scene.add(edges_yz);
// VERTICES
var vertexGeometry = new THREE.SphereGeometry(child.geometry.boundingSphere.radius/35.0, 12, 6 );
var vertexMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
var vertexSingleMesh = new THREE.Mesh( vertexGeometry );
var vertexAmalgam = new THREE.Geometry();
for (var i = 0; i < vertices.length; i++)
{
var vMesh = vertexSingleMesh.clone();
vMesh.position.set(vertices[i].x, vertices[i].y, vertices[i].z);
THREE.GeometryUtils.merge( vertexAmalgam, vMesh );
}
var vertexMesh = new THREE.Mesh( vertexAmalgam, vertexMaterial );
vertexMesh.name = "pdp-vertices";
context0.scene.add(vertexMesh);
context0.scene.getObjectByName("pdp-vertices").visible = false;
// PLANES
var d = distance/3;
var xyGeometry = MakeQuadrilateral( d, -d, -d,
d, d, -d,
-d, d, -d,
-d, -d, -d);
var xyPlane = new THREE.Mesh(xyGeometry, new THREE.MeshBasicMaterial({color: 0x090909, side: THREE.DoubleSide, opacity: 0.2, transparent: true }));
xyPlane.name = "xyPlane";
context0.scene.add(xyPlane);
var d = distance/3;
var xzGeometry = MakeQuadrilateral( d, -d, d,
d, -d, -d,
-d, -d, -d,
-d, -d, d);
var xzPlane = new THREE.Mesh(xzGeometry, new THREE.MeshBasicMaterial({color: 0x090909, side: THREE.DoubleSide, opacity: 0.2, transparent: true }));
xzPlane.name = "xzPlane";
context0.scene.add(xzPlane);
var d = distance/3;
var yzGeometry = MakeQuadrilateral( -d, -d, d,
-d, -d, -d,
-d, d, -d,
-d, d, d);
var yzPlane = new THREE.Mesh(yzGeometry, new THREE.MeshBasicMaterial({color: 0x090909, side: THREE.DoubleSide, opacity: 0.2, transparent: true }));
yzPlane.name = "yzPlane";
context0.scene.add(yzPlane);
// AXES
var xVector = new THREE.ArrowHelper(new THREE.Vector3(1, 0, 0),
new THREE.Vector3(-d, -d, -d ),
2*d + 0.5*d, 0x0000ff, 0.2*d, 0.1*d);
xVector.name = "xVector";
xVector.line.visible = true;
xVector.cone.visible = true;
context0.scene.add( xVector );
var xLabel = makeSpriteText("y");
xLabel.name = "xLabel";
xLabel.position.set(d + 0.7*d, -d, -d);
xLabel.scale.set( d, d, d );
context0.scene.add(xLabel);
var yVector = new THREE.ArrowHelper(new THREE.Vector3(0, 1, 0),
new THREE.Vector3(-d, -d, -d),
2*d + 0.5*d, 0x0000ff, 0.2*d, 0.1*d);
yVector.name = "yVector";
yVector.line.visible = true;
yVector.cone.visible = true;
context0.scene.add(yVector );
var yLabel = makeSpriteText("z");
yLabel.name = "yLabel";
yLabel.position.set(-d, d + 0.6*d, -d);
yLabel.scale.set( 10, 10, 10 );
context0.scene.add(yLabel);
var zVector = new THREE.ArrowHelper(new THREE.Vector3(0, 0, 1),
new THREE.Vector3(-d, -d, -d),
2*d + 0.5*d, 0x0000ff, 0.2*d, 0.1*d);
zVector.name = "zVector";
zVector.line.visible = true;
zVector.cone.visible = true;
context0.scene.add(zVector );
var zLabel = makeSpriteText("x");
zLabel.name = "zLabel";
zLabel.position.set(-d, -d, d + 0.7*d);
zLabel.scale.set( 10, 10, 10 );
context0.scene.add(zLabel);
}
});
}, onProgress, onError );
});
// var ambLight = new THREE.AmbientLight(0x404040);
// context0.scene.add(ambLight);
context0.light = new THREE.DirectionalLight(0xffffff, 1);
context0.light.position = context0.camera.position;
context0.scene.add(context0.light);
// Run
context0.camera.updateProjectionMatrix();
render();
animate();
loaded = true;
} // End of init()
function animate()
{
/* One animation tick */
requestAnimationFrame(animate);
context0.controls.update();
render();
} // End of animate()
function render()
{
/* renders our little scene */
context0.renderer.render(context0.scene, context0.camera);
} // End of render()
</script>
</head>
<body> <!-- <body onload='disableScroll();'> -->
<center>
<table>
<tr>
<td>
<span id="webglcontext0" style="width:410px; height:50px; display: table-cell; text-align:center; vertical-align: middle; border-style: solid; border-width: 1px;"></span>
<div id="msgwebglcontext0" style="text-align:center; display: table; margin-left: -3px;">
<span style="width:743px; height:30px; display: table-cell; text-align:justify; padding:10px; vertical-align: middle; border-style: solid; border-width: 1px;">
Por favor, espere o navegador carregar a página. Caso
isto já tenha acontecido e o applet abaixo não executou, isto significa que seu navegador parece não suportar WebGL ou esta opção não está habilitada.
Em caso de dúvidas, entre em contato conosco pelo e-mail:
conteudosdigitais#im.uff.br.
</span>
</div>
</td>
<td align="center">
<input
name="transparency_range"
id="tr"
type="range"
min="0" // default 0
max="100" // default 100
step="1" // default 1
value="0" // default min + (max-min)/2
oninput="updateTransparency(this.value)" onchange="updateTransparency(this.value)" ondrag="updateTransparency(this.value)"
style="visibility: hidden"
>
<br>
<span id="texto">0</span>
</td>
</tr>
</table>
</center>
<script type="text/javascript">
function updateTransparency(val)
{
transparency_value = val;
if ((loaded == true))
{
if ( Array.isArray( context0.scene.getObjectByName("pdp-faces").material ) )
{
var n = context0.scene.getObjectByName("pdp-faces").material.length;
for (i = 0; i < n; i++)
{
context0.scene.getObjectByName("pdp-faces").material[i].transparent = true;
context0.scene.getObjectByName("pdp-faces").material[i].opacity = (1 - transparency_value/100.0);
context0.renderer.render(context0.scene, context0.camera);
};
}
else
{
context0.scene.getObjectByName("pdp-faces").material.transparent = true;
context0.scene.getObjectByName("pdp-faces").material.opacity = (1 - transparency_value/100.0);
context0.renderer.render(context0.scene, context0.camera);
}
}
document.getElementById("texto").innerHTML = val;
}
</script>
</body>
</html>
Any hint about what is happening here?
Thanks in advance, Humberto.

How to do collision between two cubes in cannon.js?

when i try to make collision between a platform created with cannon.js an another box... the collision depend of the position where i put this box. Sometimes the box go throught de plattform.
However if i make a collision between this platfmorm and a sphere its run pefectly.
My cuestion is,Why is happen this?
And most important... What can i do to solve its?
please excuse my posibles erros writting... my level of english is not good jeje.
Here is the code, thanks in advance:
<!DOCTYPE html>
<html>
<head>
<title>pruebas</title>
<style>canvas { width: 100%; height: 100% }
body {margin:0px; padding: 0px}
</style>
<script src="JS/ThreeJS/three.js"></script>
<script src="JS/cannon.js"></script>
</head>
<body>
<script>
//************************************** FISICA
var world = new CANNON.World();
world.gravity.set(0,-50,0);
world.broadphase = new CANNON.NaiveBroadphase();
//*************************************** RENDERER
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer( { antialias: true } );
document.body.appendChild(renderer.domElement);
renderer.setClearColor("#000000");
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
//**************************************** LIGHT
var light = new THREE.SpotLight("white");
light.position.set(-180,100,-90);
light.castShadow = true;
light.shadowDarkness = 1;
light.intensity = 3;
scene.add(light);
//****************************************** PLATFORMS
//plane_fisic
var groundShape = new CANNON.Plane();
var groundBody = new CANNON.RigidBody(0,groundShape);
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0),-Math.PI/2);
world.add(groundBody);
//plane_mesh
var geometry = new THREE.PlaneGeometry( 300, 300, 50, 50 );
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
var material = new THREE.MeshLambertMaterial( { color: 0xdddddd } );
var plano = new THREE.Mesh( geometry, material );
plano.castShadow = true;
plano.receiveShadow = true;
scene.add(plano);
//box_fisic
var forma = new CANNON.Box(new CANNON.Vec3(80,5,50));
var mass = 0;
var alma_table = new CANNON.RigidBody(mass,forma);
alma_table.position.y = 35;
alma_table.useQuaternion = true;
world.add(alma_table);
//box_mesh
var floorMaterial = new THREE.MeshPhongMaterial();
var tableGeometry = new THREE.CubeGeometry(160,10,100);
var table = new THREE.Mesh(tableGeometry,floorMaterial);
table.castShadow = true;
table.receiveShadow = true;
table.ambientLightColor = true;
scene.add(table);
//************************************** OBJETS
//BOX
//fisic
var forma = new CANNON.Box(new CANNON.Vec3(8,8,8));
var mass = 2;
var box_alma = new CANNON.RigidBody(mass,forma);
box_alma.position.y = 80;
box_alma.position.x = 0;
box_alma.position.z = 0;
box_alma.useQuaternion = true;
world.add(box_alma);
//mesh
var floorMaterial = new THREE.MeshPhongMaterial();
var tableGeometry =new THREE.CubeGeometry(16,16,16);
var box = new THREE.Mesh(tableGeometry,floorMaterial);
box.castShadow = true;
box.receiveShadow = true;
box.ambientLightColor = true;
scene.add(box);
//BOX2
//fisic
var forma = new CANNON.Box(new CANNON.Vec3(8,8,8));
var mass = 2;
var box_alma2 = new CANNON.RigidBody(mass,forma);
box_alma2.position.y = 80;
box_alma2.position.x = -40;
box_alma2.position.z = +20;
box_alma2.useQuaternion = true;
world.add(box_alma2);
//mesh
var floorMaterial = new THREE.MeshPhongMaterial();
var tableGeometry =new THREE.CubeGeometry(16,16,16);
var box2 = new THREE.Mesh(tableGeometry,floorMaterial);
box2.castShadow = true;
box2.receiveShadow = true;
box2.ambientLightColor = true;
scene.add(box2);
//BOX3
//fisic
var forma = new CANNON.Box(new CANNON.Vec3(8,8,8));
var mass = 2;
var box_alma3 = new CANNON.RigidBody(mass,forma);
box_alma3.position.y = 80;
box_alma3.position.x = 50;
box_alma3.position.z = 0;
box_alma3.useQuaternion = true;
world.add(box_alma3);
//mesh
var floorMaterial = new THREE.MeshPhongMaterial();
var tableGeometry =new THREE.CubeGeometry(16,16,16);
var box3 = new THREE.Mesh(tableGeometry,floorMaterial);
box3.castShadow = true;
box3.receiveShadow = true;
box3.ambientLightColor = true;
scene.add(box3);
//****************************************************** CÁMARA
var camera = new THREE.PerspectiveCamera(40, window.innerWidth/window.innerHeight, 0.1, 150000);
camera.position.z =300;
camera.position.y=130;
camera.position.x=0;
camera.lookAt(scene.position)
update = function(){
world.step(1/60);
alma_table.position.copy(table.position);
alma_table.quaternion.copy(table.quaternion);
box_alma2.position.copy(box2.position);
box_alma2.quaternion.copy(box2.quaternion);
box_alma.position.copy(box.position);
box_alma.quaternion.copy(box.quaternion);
box_alma3.position.copy(box3.position);
box_alma3.quaternion.copy(box3.quaternion);
}
var loop = function () {
requestAnimationFrame(loop);
renderer.render(scene,camera);
update();
}
loop();
</script>
</body>
</html>
Try using the latest development version of Cannon.js. Download it here.

Resources