I have this sort of meshes (each is the child of above)
Scene
-scene.add(SpaceMesh)
-SpaceMesh.add(ShipMesh)
SpaceMesh is moving in scene.
ShipMesh is not moving.
if i request ShipMesh.position.x it returns 0 (logically)
How can i get coordinates of my ShipMesh in SpaceMesh?
--
Example:
SpaceMesh.position.x = 100
ShipMesh.position.x = 0
Logical result will have to be ShipMesh.PositionInSpaceMesh.x = -100
I don't know if is the best way, but from:
how to: get the global/world position of a child object
spaceMesh.updateMatrixWorld();
var vector = new THREE.Vector3();
vector.setFromMatrixPosition( spaceMesh.matrixWorld );
vector.multiplyScalar( -1 );
console.log(vector); // my coords in SpaceMesh
If is there better solution, or some "best practices", please correct me, thank you.
Related
I am working on customizing the transform controls available in three.js for my project.
I have already changed the rotation part and now working on translation part.
if you notice in translation Gizmo, there is a XYZ octahedron in the center. I have removed all other planes and arrows and wrote all functionality only on that center mesh, which is working fine.
Now I am only stuck at one small problem, that is the size and position of that controller. I changed that Octahedron to boxGeometry and writing the code to make the size of that controller to be exact size of the selected object. for that I get the idea to make the size of the controller, same as the boxHelper size, which act as outline of object.
when I tried this logic in sample code, where I created a box, and getting the size of box helper and creating another box of same size, it was working fine. but when I am writing same code in threejs transform controls, result is not the same.
below is the geometry code init
XYZ: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.1, 0.1, 0.1 ), pickerMaterial )]],
then I am getting the size of box3 when attaching to any object
this.addBoxHelper = function () {
this.removeBoxHelper();
if(this.object.box3) {
**this.object.box3.getSize(selectionBoxSize);**
console.log(selectionBoxSize)
this.objectBoxHelper = new THREE.Box3Helper(this.object.box3, 0xffff00);
this.objectBoxHelper.canSelect = function () {
return false;
}
this.object.add(this.objectBoxHelper);
}
}
then below is my update function of transform controls
this.update = function () {
if ( scope.object === undefined ) return;
scope.object.updateMatrixWorld();
worldPosition.setFromMatrixPosition( scope.object.matrixWorld );
worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( scope.object.matrixWorld ) );
scope.object.box3.getSize(selectionBoxSize);
scope.object.getWorldPosition(selectionBoxPos);
camera.updateMatrixWorld();
camPosition.setFromMatrixPosition( camera.matrixWorld );
camRotation.setFromRotationMatrix( tempMatrix.extractRotation( camera.matrixWorld ) );
**scaleT = selectionBoxSize;**
//below three lines are for dynamic size change based on camera position..for
//next level functionality
//scaleT.x = worldPosition.distanceTo( camPosition ) / 6 * selectionBoxSize.x;
//scaleT.y = worldPosition.distanceTo( camPosition ) / 6 * selectionBoxSize.y;
//scaleT.z = worldPosition.distanceTo( camPosition ) / 6 * selectionBoxSize.z;
this.position.copy( selectionBoxPos );
this.scale.set( scaleT.x, scaleT.y, scaleT.z);
this.updateMatrixWorld();
below is the output of console log
TransformControls.js:526 Vector3 {x: 10.020332336425781, y: 2.621583938598633, z: 3.503500819206238}
TransformControls.js:601 Vector3 {x: 10.020332336425781, y: 2.621583938598633, z: 3.503500819206238}
as you can see, the scale is the same, but the result is different. see the result in below images.
as you see in images, that red color box at bottom is translation controller but smaller than selection box.
another issue is that pivot of my objects are at bottom, and I want this controller to come at the center of the selection box, that is also not happening with getCenter method of box3.
Please help!! let me know if I am unclear in explaining the issue
If you are getting the bounding box of the object from its geometry, that will be wrong because it doesn't take the objects transform into account. You have to use box3.setFromObject (yourObject) instead. does that help?
Ive made a stick in the Three js editor, after loading it with the following code i can position it but not rotate it.
Its a stick made of 4 meshes, so i probably have to make a rotation point but i cant figure out how i get that to work.
The ideal situation :
x -------
The x represents the point where i want to rotate the dashes(stick) around
can anyone help me?
thx in advance
var loader = new THREE.ObjectLoader();
loader.load("scene.json", function ( obj )
{
stick =obj;
scene.add( stick );
stick.position.z = -9;
stick.position.y = .4;
stick.children[3].rotation.x(45);
});
If I understand aright, you have an object with 4 children that are meshes.
Object3D
-Mesh
-Mesh
-Mesh
-Mesh
First, I would translate all the children, and then rotate the parent object.
for(var i=0; i<stick.children.length; i++) {
stick.children[i].position.set(0, 0.4, -9); // or another offset
}
stick.rotateX( 45 * Math.PI / 180 ); // make sure to use Radians
this is the link of my work : maison.whiteplay.fr
What i am trying to do is a 3D PacMan, but look at th code, i'm using mesh to build my level, except for bubbles (yellow circle), that you need to eat to win.
They are all different objects, but because they are a lot, it's lagging, can i use the same technologie (mesh i think) to the bubbles ? If yes, how ?
code:
var geometrySphere = new THREE.SphereGeometry( 5, 32, 32 );
var bille = function(x,z){
this.bille = new THREE.Mesh(
geometrySphere,
new THREE.MeshBasicMaterial( {color: 0xffff00} )
);
this.bille.position.x = (x-15.5)*100; this.bille.position.y = 100;
this.bille.position.z = (z-15.5)*100; scene.add(this.bille);
}
Thank your for reading, and if you have any suggestions about my code, don't hesistate :D
You can also reuse your material instead of making a new instance all the time:
var geometrySphere = new THREE.SphereGeometry( 5, 32, 32 );
var billeMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00} );
var bille = function(x,z){
this.bille = new THREE.Mesh(
geometrySphere,
billeMaterial
);
this.bille.position.x = (x-15.5)*100; this.bille.position.y = 100;
this.bille.position.z = (z-15.5)*100; scene.add(this.bille);
}
Reusing materials has good influence on performance.
How do you duplicate your meshes/objects?
You're code is almost right.
In your specific case, with N equal balls, you must have N mesh but just one material.
In this way, if you want to colorize (just for example) only one ball, you have to apply it one new material, otherwise you will apply new color to all the balls.
In your case lagging may be due to the sphere construction.
You clearly copy and paste from the documentation without read it before.
var geometrySphere = new THREE.SphereGeometry( 5, 32, 32 );
Where, as explained in the documentation:
radius — sphere radius. Default is 50.
widthSegments — number of horizontal segments. Minimum value is 3, and the default is 8.
heightSegments — number of vertical segments. Minimum value is 2, and the default is 6.
32 * 32 is too much for your small-monocolor bubbles, doesn't have sense.
The higher are this values, the higher is the complexity for draw it for each frame.
I suggest you to create sphere with a minor number of vertical/horizontal segments (8*8 may be ok).
Take a look at this demo.
I have two squares in space which are something like front and back wall of cube one vith vertices
x=-2 y=-1138 z=-2;
x=-2 y=-1134 z=-2;
x=2 y=-1138 z=-2;
x=2 y=-1134 z=-2
second
x=-2 y=1134 z=2;
x=-2 y=1138 z=2;
x=2 y=1134 z=2;
x=2 y=1138 z=2
when I calculate distanceTo from camera like this
var point1 = this.camera.matrixWorld.getPosition().clone();
var point2 = this.mesh.cubePlane3.children[0].matrixWorld.getPosition().clone();
var distance = point1.distanceTo( point2 );
I have always the same distance for both 20,09. These squres are rotated in space, so only rotation is changed and I would need somehow find out which wall is closer to camera to be able to do something that in cube 3 walls closer to camera are not displayed and next 3 walls are displayed.
And obviously I do not understand math behind this, for example why walls which are next to each other one have positive coordinates for y and next negative + why distance is the same value, when one is closer on z axis than second. Can you pls someone help me how I can get closer walls? Thank you
Each geometry has a computeBoundingBox function. So you can do:
var bbox = geometry.computeBoundingBox();
for each geometry that you are interested in and then use the
bbox.center()
to get the center of your geometry. A much faster computation is to use the computeBoundingSphere on your geometry.
Then you just compare the relation of the centers to your camera position.
I used computeBoundingBox with this code
this.mesh[cubePlane[0]].children[0].geometry.computeBoundingBox();
var position = new THREE.Vector3();
position.sub( this.mesh[cubePlane[0]].children[0].geometry.boundingBox.max, this.mesh[cubePlane[0]].children[0].geometry.boundingBox.min );
position.multiplyScalar( 0.5 );
position.addSelf(this.mesh[cubePlane[0]].children[0].geometry.boundingBox.min );
this.mesh[cubePlane[0]].children[0].matrixWorld.multiplyVector3( position );
var point1 = this.camera.matrixWorld.getPosition().clone();
var point2 = position;
var distance = point1.distanceTo( point2 );
and it works so thank you for your advice :)
I have some objects added to an Object3D (for grouping elements) and I'm trying to detect clicks on it.
My scene has a size of 600x400, my camera is within a three-object and my event handler code looks like below:
function onDocumentMouseDown( event ) {
event.preventDefault();
var mouse = {};
mouse.x = ( event.clientX / 600 ) * 2 - 1;
mouse.y = - ( event.clientY / 400 ) * 2 + 1;
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, three.camera );
var ray = new THREE.Ray( three.camera.position, vector.subSelf( three.camera.position ).normalize() );
var intersects = ray.intersectObjects( group.children );
alert(intersects.length);
[...]
}
Actually I'm alerting the count of intersected objects. But it stays zero. It couldn't find any intersected objects. I've already played a bit aroud with the x, y and z values of my projection vector - without success.
I've added a stripped down sample for demonstrating this issue on jsfiddle. Maybe someone has a short hint for me what goes wrong with it?
In your fiddle, because you are calling THREE.SceneUtils.createMultiMaterialObject( ), which creates a hierarchical structure, you need to add the recursive flag to ray.intersectObjects().
var intersects = ray.intersectObjects( group.children, true );
EDiT: ray is now an instance of THREE.Raycaster -- not THREE.Ray.
three.js r.58
I had the same problem and WestLangley's answer provides the answer. Great job! For anybody struggling with mouse selection of objects grouped in Object3D wrapper too, I am posting my own solution.
First, I created an array of objects that are selectable - I hope this also saves some performance, as RayCaster doesnt need to search all objects in the scene, but only those you wish to respond to selection. I also attached this array to scene object directly (solely for the fact that it is already accessible from most parts of my app)
scene.selectable = [];
Next step is to push all objects that you wish to make selectable into this array. You will insert only meshes/sprites/etc from your group, not the whole group. Only last line is important here:
var myWrapper = new THREE.Object3D();
var myObject = new THREE.Mesh( something );
myWrapper.add( myObject );
scene.add ( myWrapper );
scene.selectable.push( myObject );
And lastly in your mouse selection routine you will call raycaster like this:
var intersects = ray.intersectObjects( scene.selectable );