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?