Get 3D cube from an Obb3 - three.js

given an Obb3 (Center, HalfVector and axis[3]),
how can I create a cube that has the same bounds as this Obb3 ?
I'll then use this cube to display my obb3 bounds.
I use vector_math and three.dart libraries
So far, my code is :
Matrix3 rot_mat = new Matrix3(node.box.axis0[0], node.box.axis1[0], node.box.axis2[0],
node.box.axis0[1], node.box.axis1[1], node.box.axis2[1],
node.box.axis0[2], node.box.axis1[2], node.box.axis2[2]);
Vector3 diag = rot_mat.absoluteRotate(node.box.halfExtents.clone());
var geometry = new CubeGeometry(diag[0] * 2.0, diag[1] * 2.0, diag[2] * 2.0);
var material = new MeshBasicMaterial(color: 0x00ff00,
wireframe: true,
blending: NormalBlending,
side: DoubleSide,
shading: FlatShading);
var obj = new Mesh(geometry, material);
obj.position = node.box.center;
obj.matrix.setRotation(rot_mat);
obj.updateMatrix();
scene.add(obj);
Thanks a lot for your help :]

Related

how to get the boundingSphere for a whole scene in three.js?

How to get the bounding sphere for a whole scene in three.js?
I may try to get the bounding sphere for each object and compute the resulting union of them, but I think there may be a more straight forward method.
There are different methods to get a boundingSphere of multiple objects dynamically. You can get first the bounding box of all of them, and then create a sphere of that bounding box... here is a sample fiddle I have shaped on boundingSphere of a boundingBox.
Basically you put all the geometries into a Group, you get the Box3 of the group, and then you do getBoundingSphere from the Box3 and position at the center. Code in the fiddle would be this.
let g = new THREE.Group();
scene.add(g);
for (let i = 0; i < 5; i++) {
// geometry
var geometry = new THREE.BoxGeometry(20, 20, 20);
// material
var material = new THREE.MeshToonMaterial({
color: 0xff0000,
opacity: 0.7,
});
// mesh
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(100 * Math.random(), 100 * Math.random(), 100 * Math.random());
g.add(mesh);
}
//g.updateWorldMatrix(true);
var gridHelper = new THREE.GridHelper(400, 40, 0x0000ff, 0x808080);
gridHelper.position.y = 0;
gridHelper.position.x = 0;
scene.add(gridHelper);
let bbox = new THREE.Box3().setFromObject(g);
let helper = new THREE.Box3Helper(bbox, new THREE.Color(0, 255, 0));
scene.add(helper);
const center = new THREE.Vector3();
bbox.getCenter(center);
let bsphere = bbox.getBoundingSphere(new THREE.Sphere(center));
let m = new THREE.MeshStandardMaterial({
color: 0xffffff,
opacity: 0.3,
transparent: true
});
var geometry = new THREE.SphereGeometry(bsphere.radius, 32, 32);
let sMesh = new THREE.Mesh(geometry, m);
scene.add(sMesh);
sMesh.position.copy(center);
EDITED: If you want to include in the boundingSphere for the scene including the lights (which could get you a huge sphere), just start from let bbox = new THREE.Box3().setFromObject(scene)

Get world position of plane

I'm very new to three.js so I'm sure I'm miss-understanding something here.
I've created a plane in the following way:
var planeGeom = new THREE.PlaneGeometry(0.2, 0.2);
planeGeom.rotateX(-Math.PI / 2);
var plane = new THREE.Mesh(planeGeom, new THREE.MeshBasicMaterial({color: 0xffff00, side: THREE.DoubleSide}));
plane.position.set(0, 0.1, 0);
scene.add(plane);
var mathPlane = new THREE.Plane();
planePointA.copy(plane.geometry.vertices[plane.geometry.faces[0].a]);
planePointB.copy(plane.geometry.vertices[plane.geometry.faces[0].b]);
planePointC.copy(plane.geometry.vertices[plane.geometry.faces[0].c]);
plane.localToWorld(planePointA);
plane.localToWorld(planePointB);
plane.localToWorld(planePointC);
mathPlane.setFromCoplanarPoints(planePointA, planePointB, planePointC);
var helper = new THREE.PlaneHelper( mathPlane, 1, 0xffff00 );
scene.add( helper );
Why is my PlaneGeometry object and Plane positioned differently? Why doesn't .localToWorld() get the world position of the plane?
https://jsfiddle.net/sek0yzLp/
Use .updateMatrixWorld() on the plane after setting its position:
plane.position.set(0, 0.1, 0);
plane.updateMatrixWorld();
scene.add(plane);

ThreeJS raycasting is different in R81 than R71

I have a plane with a mesh on it. My code draws a ball when the user double clicks on the mesh. This works just fine in R71 but as soon as I switched to R81 raycaster doesn't return an intersect. Here's the code:
In init():
// Plane
plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 1000, 1000, 3, 3 ),
new THREE.MeshBasicMaterial( { color: 0xff0000, opacity: .5, transparent: true } )
);
plane.visible = false;
scene.add( plane );
planes.push(plane);
In doubleClickEvent():
event.preventDefault();
var mouse = new THREE.Vector2((event.clientX / window.innerWidth ) * 2 - 1, -(((event.clientY / window.innerHeight ) * 2 - 1)));
var directionVector = new THREE.Vector3();
directionVector.set(mouse.x, mouse.y, 0.1);
directionVector.unproject(camera);
directionVector.sub(camera.position);
directionVector.normalize();
raycaster.set(camera.position, directionVector);
intersects = raycaster.intersectObjects(planes);
if (intersects.length) {
var sphereParent = new THREE.Object3D();
var sphereGeometry = new THREE.SphereGeometry(.1, 16, 8);
var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphereParent.add(sphere);
sphereParent.position.set(intersects[0].point.x, intersects[0].point.y, 0.0);
scene.add(sphereParent);
objects.push(sphereParent);
}
If I change
intersects = raycaster.intersectObjects(planes);
to
intersects = raycaster.intersectObjects(scene.children);
the ball gets drawn but it gets drawn on the wrong position.
Any ideas?
I found the answer. The reason why the raycast isn't working is because the plane's visibility is false. The solution is to change the visibility of the material visibility rather the plane.

Textures and RingGeometry / CylinderGeometry

UPDATE:
I made jsfiddle example - jsfiddle.net/NEXny/1/
[ignore this - just including a code block so stackoverflow will
let me post the above JSFiddle link. Yeah, seriously.]
I'm having trouble with applying texture to RingGeometry and CylinderGeometry, hope this image will explain my issue.
It is possible to apply texture by one of this ways ?
Currently i'm getting very unexpected results...
You have to modify the geometry vertex UVs to your liking.
Instead, why not just use CircleGeometry for your cylinder end-caps. That is, construct the end-caps yourself?
// cylinder
geometry = new THREE.CylinderGeometry( 192, 192, 40, 64, 1, true ); // open-ended
geometry1 = new THREE.CircleGeometry(192, 64);
// end-cap material
material1 = new THREE.MeshBasicMaterial({
map: textures.circle,
overdraw: 0.5 // for canvas renderer only
});
// cylinder material
material = new THREE.MeshBasicMaterial({
map: textures.line,
overdraw: 0.5 // for canvas renderer only
});
object = new THREE.Object3D();
scene.add(object);
// end-caps
var mesh1 = new THREE.Mesh(geometry1, material1);
mesh1.rotation.x = - Math.PI / 2;
mesh1.position.y = 20
object.add(mesh1);
var mesh2 = new THREE.Mesh(geometry1, material1);
mesh2.rotation.x = Math.PI / 2;
mesh2.position.y = -20
object.add(mesh2);
// cylinder
var mesh = new THREE.Mesh(geometry, material);
object.add(mesh);
fiddle: http://jsfiddle.net/NEXny/2/
three.js r.61

How to change width of CubeGeometry with Three.js?

I have a cube geometry and a mesh, and i don't know how to change the width (or height... i can change x, y and z though).
Here's a snippet of what i have right now:
geometry = new THREE.CubeGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
// WebGL renderer here
function render(){
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
function changeStuff(){
mesh.geometry.width = 500; //Doesn't work.
mesh.width = 500; // Doesn't work.
geometry.width = 500; //Doesn't work.
mesh.position.x = 500// Works!!
render();
}
Thanks!
EDIT
Found a solution:
mesh.scale.x = 500;
Just to complete comment and solution from question (and have an answer present with example code):
// create a cube, 1 unit for width, height, depth
var geometry = new THREE.CubeGeometry(1,1,1);
// each cube side gets another color
var cubeMaterials = [
new THREE.MeshBasicMaterial({color:0x33AA55, transparent:true, opacity:0.8}),
new THREE.MeshBasicMaterial({color:0x55CC00, transparent:true, opacity:0.8}),
new THREE.MeshBasicMaterial({color:0x000000, transparent:true, opacity:0.8}),
new THREE.MeshBasicMaterial({color:0x000000, transparent:true, opacity:0.8}),
new THREE.MeshBasicMaterial({color:0x0000FF, transparent:true, opacity:0.8}),
new THREE.MeshBasicMaterial({color:0x5555AA, transparent:true, opacity:0.8}),
];
// create a MeshFaceMaterial, allows cube to have different materials on each face
var cubeMaterial = new THREE.MeshFaceMaterial(cubeMaterials);
var cube = new THREE.Mesh(geometry, cubeMaterial);
cube.position.set(0,0,0);
scene.add( cube );
cube.scale.x = 2.5; // SCALE
cube.scale.y = 2.5; // SCALE
cube.scale.z = 2.5; // SCALE
A slightly advanced, dynamic example (still the same scaling) implemented here:
You can dispose the geometry of cube and affect the new one like this :
let new_geometry = new THREE.CubeGeometry(500,200,200);
geometry.dispose();
cube.geometry = new_geometry;
Scale properties can be used to for changing width, height and and depth of cube.
//creating a cube
var geometry = new THREE.BoxGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color:"white"});
var cube = new THREE.Mesh(geometry, material);
//changing size of cube which is created.
cube.scale.x = 30;
cube.scale.y = 30;
cube.scale.z = 30;

Resources