11

With the below code, position of a mesh is returned as (0, 0, 0) but it is not. So is the positioın vector calculated after render process?

me.scene.add(objMesh); //me is a project class
objMesh.updateMatrixWorld(true);
alert(objMesh.position.x + ',' + objMesh.position.y + ',' + objMesh.position.z);

objMesh is created from objfile, it is added to the scene correctly and centroid is approx (-8, 3, 0) but position vector of objMesh is (0, 0, 0) do we have to auto calculate something first or should i calculate it manually from geometry vertices of the mesh ?

http://81.214.75.32:8181/admin is the url

the site is in Turkish so i will translate the UI items

in the site there is "Dosya" menu item oppen the menu item and select "Proje Aç" a dialog appears in that dialog select MUTFAK_1 scene will appear in that scene, every meshes position is (0, 0, 0) is that possible :)

mrdoob
  • 19,334
  • 4
  • 63
  • 62
Tezcan
  • 690
  • 2
  • 6
  • 16

7 Answers7

29

Update:

The function getPositionFromMatrix() has been renamed to setFromMatrixPosition().


r58

object.position is always local to the object. If you want to get the position in world space you need to get it from object.matrixWorld.

Try with this:

scene.add(objMesh);
scene.updateMatrixWorld(true);
var position = new THREE.Vector3();
position.getPositionFromMatrix( objMesh.matrixWorld );
alert(position.x + ',' + position.y + ',' + position.z);
Gangula
  • 5,193
  • 4
  • 30
  • 59
mrdoob
  • 19,334
  • 4
  • 63
  • 62
  • 2
    mrdoob, that was something i tried before... this code returns (0, 0, 0) also. Could you please check the application from the above url? On the parquatte ground there should be a cubeCamera for reflection. The importing of the scene is done by FileManager.js. You will see the code for adding the mesh inside if block in the 290th line. I could not get the world position of any mesh. i updated the project to automatically load the scene At the right pane ("Nesne Ozellikleri"), there is "Yansima Merkez" text boxes. Those values change the position of the cubeCamera – Tezcan Jan 08 '13 at 15:31
  • the ground plane is approx on (-8, 3, 0) so the cubeCamera has to be located at this point. – Tezcan Jan 08 '13 at 15:37
  • then the problem must be that, either the geometry has the offset applied or you're trying to get the position of the wrong object. – mrdoob Jan 08 '13 at 16:35
  • It is not the wrong object i am sure about that. Cos every object in the scene pisution returns 0. I create custom geometry for each mesh and give vertices to that geom. This vertex points make the object located in its place in the scene – Tezcan Jan 08 '13 at 17:13
  • The main question is if we create a custom geometry with adding vertices to it and create a mesh with this geometry, and add this mesh to the scene without setting any position, can we get real world position of this mesh? If so, how? – Tezcan Jan 08 '13 at 18:09
  • You mean the center of the object taking in consideration all its vertices? That's a different kind of position. – mrdoob Jan 08 '13 at 20:53
  • Thanks to mrdoob and to all of you. O got the solution from another stackowerflow question, i am answering my own question. Please see below – Tezcan Jan 09 '13 at 09:23
  • @Tezcan: Below is nothing? Did you get the solution? – Timo Kähkönen Apr 22 '13 at 01:06
  • If anyone is wondering 'position.getPositionFromMatrix()' is now deprecated use: position = new THREE.Vector3(); position.setFromMatrixPosition( objMesh.matrixWorld ); – James Milner Jul 04 '14 at 15:13
16

For finding where in world space is the geometry centroid, try this:

objMesh.geometry.computeBoundingBox();

var boundingBox = objMesh.geometry.boundingBox;

var position = new THREE.Vector3();
position.subVectors( boundingBox.max, boundingBox.min );
position.multiplyScalar( 0.5 );
position.add( boundingBox.min );

position.applyMatrix4( objMesh.matrixWorld );

alert(position.x + ',' + position.y + ',' + position.z);

r58

mrdoob
  • 19,334
  • 4
  • 63
  • 62
  • r58: Matrix4's .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead. What is the above code for r58? – Timo Kähkönen Apr 22 '13 at 00:52
  • @mrdoob, can you please explain the above steps meaning. Atleast this step position.multiplyScalar( 0.5 ); – Rajkamal Subramanian Dec 21 '13 at 00:16
  • @rajkamal multiplying something by .5 means to get the half of it. In fact, multiplying anything by a number between 0 and 1 means to get its percentage; .5 is 50%, .85 is 85% – Absulit Aug 12 '16 at 16:24
5

Yeah. after some talk with mrdoob, i realized that .position of objects are local to theirselves. My situation was to find the center point of my mesh considering the vertices. Below is the code to get the centroid which came from an answer #447 ( https://github.com/mrdoob/three.js/issues/447 )

geom.centroid = new THREE.Vector3();
for (var i = 0, l = geom.vertices.length; i < l; i++) {
    geom.centroid.addSelf(geom.vertices[i]);
}
geom.centroid.divideScalar(geom.vertices.length);

Now we have centroid of geometry...

Update according to https://github.com/mrdoob/three.js/wiki/Migration, the .addSelf had been renamed to .add after r55

lhrec_106
  • 630
  • 5
  • 18
Tezcan
  • 690
  • 2
  • 6
  • 16
2
alert(objMesh.matrixWorld.getPosition().x + ',' + objMesh.matrixWorld.getPosition().y + ',' + objMesh.matrixWorld.getPosition().z);
Gero3
  • 2,817
  • 1
  • 22
  • 21
  • 2
    Please explain what is your solution, don't paste only the code. – Julien Lafont Jan 08 '13 at 10:19
  • 4
    No my friend, this also returns (0, 0, 0) i tried objMesh.matrixWorld.getPosition() also. None returned me the correct position of the mesh. I am uploading the whole project to a server. May be that would be more clear to examine. – Tezcan Jan 08 '13 at 10:34
1

You can use .getWorldPosition() method of a mesh, to get its absolute position.

Docs here: https://threejs.org/docs/#api/en/core/Object3D.getWorldPosition

Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
0

According to this post the center of gravity C for a mesh can be found by

C = [sum of all (A*R)] / [sum of all A]
A = (area of a face * 2)
R = face centroid = average of vertices making the face

and here is the code in three.js

function calculateCenterOfMass( mesh ){

    var centroid = new THREE.Vector3();

    // centroid = centroidNominator / centroidDenominator;
    var centroidNominator = new THREE.Vector3(); 
    var centroidDenominator = 0;

    for(var i = 0; i < mesh.geometry.faces.length; i++){

        var Pi = mesh.geometry.faces[i].a;
        var Qi = mesh.geometry.faces[i].b;
        var Ri = mesh.geometry.faces[i].c;

        var a = new THREE.Vector3(mesh.geometry.vertices[Pi].x, mesh.geometry.vertices[Pi].y, mesh.geometry.vertices[Pi].z);
        var b = new THREE.Vector3(mesh.geometry.vertices[Qi].x, mesh.geometry.vertices[Qi].y, mesh.geometry.vertices[Qi].z);
        var c = new THREE.Vector3(mesh.geometry.vertices[Ri].x, mesh.geometry.vertices[Ri].y, mesh.geometry.vertices[Ri].z);

        var ab = b.clone().sub(a);
        var ac = c.clone().sub(a);

        var cross = new THREE.Vector3();
        cross.crossVectors( ab, ac );

        var faceArea = cross.lengthSq() / 2;
        var faceCentroid = new THREE.Vector3( (a.x + b.x + c.x)/3, (a.y + b.y + c.y)/3, (a.z + b.z + c.z)/3 );

        if (!isNaN(faceArea)){
            centroidNominator.add(faceCentroid.multiplyScalar(faceArea));
            centroidDenominator += faceArea;
        }
    }


    centroid = centroidNominator.divideScalar(centroidDenominator);

    return centroid;
}
Dimitrios Ververidis
  • 1,118
  • 1
  • 9
  • 33
0

Tip. If you are getting the position of a mesh within an imported model (e.g. GLTF) make sure that the mesh has it's origin set to it's own centre before exporting. i.e. don't apply transforms to it. Otherwise it's world centre will be the centre of the gltf and not the mesh itself.

Doug
  • 665
  • 2
  • 8
  • 22