[SOLVED] Best way to Obtain World Coordinates for Triangles in a Mesh?

I’m trying to utilize information about Triangles in my scene.

From my understanding, a particular branch of my scenegraph looks something like this:

rootNode → Custom Node → Spatial (.j3o, mesh.xml, etc.) → Geometry → Mesh → Triangles

Now, when I traverse down to any particular Triangle, its coordinates appear to default to a local offset from the origin of the Geometry. Unlike with the Spatial and with the Geometry, there doesn’t seem to be a built in option to obtain the Triangle’s values in World Coordinates (e.g. vertexes, center, etc.).

I can apply the Geometry’s localToWorld() method if necessary, but I’m simply curious if there is a preexisting method I have overlooked to obtain this information directly from the Triangle, without needing access to its parent Geometry.

For instance, if I extract a set of Triangles from disparate Geometries, and pass them to a method for some mathematical calculations, will I need to apply their transformations first, or can I obtain them directly from the Triangle objects?

For instance, if I wanted to set a different object’s location based on the location of a given Triangle, the default location values from that Triangle aren’t wrt the world. The Green Box in this picture is positioned based on a Triangle’s locations, which is offset from the actual placement of the Triangle in the world. The Red Box is at the world’s origin.

Some code (should work in default SDK)…

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package simplecodetest;

import com.jme3.app.SimpleApplication;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Triangle;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.SceneGraphVisitor;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author Christopher
 */
public class WorldCoordinatesTest extends SimpleApplication {
    
    private Node models;
    private Node tiles;
    protected Spatial control;
    protected Spatial test;
    HashMap<Vector3f, ArrayList<Integer>> triangleMap = new HashMap<Vector3f, ArrayList<Integer>>();
    
    public static void main(String[] args) {
        WorldCoordinatesTest app = new WorldCoordinatesTest();
        app.start();
    }
    
    @Override
    public void simpleInitApp() {
        inputManager.setCursorVisible(true);
        flyCam.setEnabled(true);
        flyCam.setMoveSpeed(25);
        flyCam.setDragToRotate(true);
        viewPort.setBackgroundColor(ColorRGBA.Black);
        
        DirectionalLight dl = new DirectionalLight();
        dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());
        rootNode.addLight(dl);
        
        tiles = new Node("tiles");
        models = new Node("models");
        
        Box b = new Box(0.03f, 0.03f, 0.03f);
        
        test = new Geometry("green cube", b);
        Material tMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        tMat.setColor("Color", ColorRGBA.Green);
        test.setMaterial(tMat);
        test.scale(3f);
        models.attachChild(test);

        control = new Geometry("red cube", b);
        Material cMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        cMat.setColor("Color", ColorRGBA.Red);
        control.setMaterial(cMat);
        control.scale(3f);
        models.attachChild(control);
        
        rootNode.attachChild(models);
        
        Spatial tile1 = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
        Material tile1Mat = new Material(assetManager,"Common/MatDefs/Light/Lighting.j3md");
        tile1Mat.setBoolean("UseMaterialColors", true);
        tile1Mat.setColor("Diffuse", ColorRGBA.Blue);
        tile1Mat.getAdditionalRenderState().setWireframe(true);
        tile1.setMaterial(tile1Mat);
        tile1.setLocalTranslation(new Vector3f((0*8.66f),0f,(0*10f) + (0*5f) - (10f*(13-1)/4)));
        tiles.attachChild(tile1);
        
        Spatial tile2 = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
        Material tile2Mat = new Material(assetManager,"Common/MatDefs/Light/Lighting.j3md");
        tile2Mat.setBoolean("UseMaterialColors", true);
        tile2Mat.setColor("Diffuse", ColorRGBA.Blue);
        tile2Mat.getAdditionalRenderState().setWireframe(true);
        tile2.setMaterial(tile2Mat);
        tile2.setLocalTranslation(new Vector3f((1*8.66f),0f,(-1*10f) + (1*5f) - (10f*(13-1)/4)));
        tiles.attachChild(tile2);
        
        rootNode.attachChild(tiles);
        
        Geometry testGeom = (Geometry) ((Node) tile1).getChild("Oto-geom-1");
        
        Triangle tri = new Triangle();
        testGeom.getMesh().getTriangle(3, tri);
        test.setLocalTranslation(tri.getCenter());
    }
}

Now, of course, I’m fine if there is no way to get the World Location without applying a transformation myself.

But at that point, I’m interested in knowing the recommended way for doing so. In a situation like the above, should I apply the localToWorld transformation from the Geometry, or the Spatial? (The Mesh does not have one available).

If I cycle through a few thousand triangles across a couple dozen Spatials should I be calling the localToWorld() method multiple times, or should I learn and utilize the getLocalToWorldMatrix() method once for each Spatial/Geometry?

Are there questions I haven’t asked?

I’ve never dealt with something quite like your specific use-case so I’d have to dig around in the Javadocs to answer your question about the most expedient way to get a triangle’s position in world coordinates.

You’re correct in that vertex positions (and hence, triangle positions) are relative to the coordinate origin of the mesh. This is necessary for many reasons - mesh exchange between programs would be drastically harder to do right, animation would be drastically harder to do right, correctly positioning meshes would be drastically harder to do right, etc.

What specifically are you trying to accomplish? Are you doing this every frame?

Yeah, I agree… tell us what you are really trying to do because your request is super strange.

Edit: I’ll refer to this post to make a point about why it’s better to tell us what you are really trying to do and not “How do I get myself out of this corner I’ve painted myself into?”

I definitely believe it. I just wasn’t sure if there was already a native implementation to also get world coordinates directly before I applied the appropriate transforms myself.

Goodness no :slight_smile:

As far as what I’m doing, I think an appropriate example would be generating cross-sections of a scene of multiple spatials. Having the correct location information up front is helpful for performing operations (though not necessary, since I could either transform the vertex coords of the spatials or transform the cutting surface for each spatial, and mosaic the cross-section back together).

There’s always tradeoffs here between memory and time, so as a last resort I could just keep world coordinates for all of my spatials’ vertexes somewhere else, and update those myself if a spatial’s location or mesh changes.

But I feel like I should have the leniency to apply the transforms on the fly when I need to conduct an operation.

This would be the right answer in almost every case… and will be more accurate overall as you are less likely to get floating point rounding errors in large quantity.

Great!

A recommendation for this is exactly what I’m looking for. I know of plenty of ways to solve the problem. But I wasn’t sure which would be appropriate or if there were other ways I didn’t know of that already existed.

Thanks :slight_smile:

E: Should I just edit the title with [SOLVED] or is there a flag for it?

1 Like

Transforming the “operation” once versus every vertex is almost always going to be the better answer. You’ll find this a lot… look at collisions for example, where the world ray is transformed into local coordinate space.

Just edit the title, I guess.

1 Like

Alright, thanks for giving me further insight and something to look into.