[SOLVED] Issue Using Mesh in Geometry and Spatials

So I create spatials using a loop using something like this (depending on a user defined input):

[java]for (int i=0; i<= spatialNumber - 1; i++)

{

spatial_create = new Box(new Vector3f(0,0,0), 1, .25f, .5f);

geom = new Geometry(SpatialCreationEvents.id, spatial_create);

geom.setLocalTranslation(x, y,z);

geom.updateModelBound();

model = geom; // model is an array of spatials

[/java]

this works fine however I am importing an object from blender instead of the Mesh BOX and I can’t seem to figure out how to go around this.

since Geometry takes String and Mesh (and not spatial or any other type) how can I pass the SpatialCreationEvents.id to geom when drawing it?

For example:

[java]

spatial_create= (Geometry) assetManager.loadModel(“Models/Teapot/Teapot.obj”);

spatial_create.setMaterial(mat_default);

spatial_create.setLocalTranslation(x,y,z);

spatial_create.updateModelBound();

model = spatial_create; // this is missing the SpatialCreationEvents.id that is necessary for later parts

[/java]

i tried to understand what you mean(and i dont understand everything), but maybe some code will help you:

[java] for (Spatial s : node.getChildren()) {

if (s instanceof Geometry) { // or other instance

Geometry g = (Geometry)s;

// you have it

}

}

[/java]

Let me clarify more:



in the 1st part of the example the id for geom is Spatial_1 (this is read from SpatialCreationEvents.id) which is essential to have cuz that’s how I differentiate the spatials from each other (by a unique id).



in the 2nd part of the example the id is not being read (cuz there’s no place to pass it) and automatically is set to Teapot-geom-0 which I don’t want. So my question is how do I do something like:



[java] spatial_create = CONVERT OBJ TO MESH MAYBE;

geom = new Geometry(SpatialCreationEvents.id, spatial_create);

geom.setLocalTranslation(x, y,z);

geom.updateModelBound();

model = geom; // model is an array of spatials[/java]

[java]

Spatial spat = assetManager.loadModel(obj);

Geometry geo = (Geometry)spat;

geo.getMesh(); // its it?

[/java]

then it would be like create geometry(with your unique IDs of elements as i understand) from Mesh created from geometry created from spatial ;p

1 Like

Awesome! that’s exactly what I was looking for. didn’t know it was that simple!!!



Thanks!!

@oxplay2 said:
for your model yes, but remember that when you use "assetManager.loadModel()" it can return Geometry too. That it why it return Spatial, becouse we need to check what it return by "instanceof" or just know it and cast it into it ;)

Does it make sense to cast it on model load? Because as I'll be working with my own assets I would know which of them have hierarchy or multiple sub meshes and which won't.

@oxplay2 said:
everything here was created by clever people, so dont try to seek stupidity :P

Had no intention to do that.

@oxplay2 said:
so if you dont want to cast into Node all the time, just have all your models in Geometry form, without Nodes
becouse you know it can be Node -> Node -> Node -> Geometry, Node -> Geometry, Geometry. Its good when you need to use parts of your element :)
somethin like:
StarShip Node -> Hull Node(with geometry within), Turret Node(with geometry within), etc...

It perfectly makes sense. I assume that it is not possible for Geometry to have a collection of sub-meshes (surfaces). So if I have an OBJ model, which has two surfaces with different materials, after import it will be a Node->GeometryMaterial1, GeometryMaterial2
@oxplay2 said:
[java]
Spatial spat = assetManager.loadModel(obj);
Geometry geo = (Geometry)spat;
geo.getMesh(); // its it?
[/java]
then it would be like create geometry(with your unique IDs of elements as i understand) from Mesh created from geometry created from spatial ;p


Somehow it doesn't work for me at all

[java]
Spatial shipMesh = assetManager.loadModel("Models/Boat/boat.mesh.xml");
Geometry shipHull = (Geometry)shipMesh;
MeshCollisionShape colShipShape = new MeshCollisionShape(shipHull.getMesh());
[/java]

I get this:
java.lang.ClassCastException: com.jme3.scene.Node cannot be cast to com.jme3.scene.Geometry

I've tried getChildren() but it looks like Spatial doesn't have such method.

[java] public Geometry findGeom(Spatial spatial) {

if (spatial instanceof Node) {

Node findingnode = (Node) spatial;

for (int i = 0; i < findingnode.getQuantity(); i++) {

Spatial child = findingnode.getChild(i);

Geometry result = findGeom(child);

if (result != null) {

return result;

}

}

} else if (spatial instanceof Geometry) {

return (Geometry) spatial;

}

return null;

}[/java]



use somethin like this for one geometry… you must just seek all geometries if you need. Spatial can be Node or Geometry :wink:



there were many topics about it.





btw: this topic is 6 month old. i forgot i writed somethin like this :stuck_out_tongue:

1 Like

It’s because (as the exception says) your shipMesh is a Node.

To get the child nodes, just cast the Spatial to a Node (as Spatial is the parent class of Node and Geometry).

Then iterate over the children (and perhaps their children and so on) until you find the Geometry you’re looking for or just use ((Node)shipMesh).getChild(“Name-of-geom”);.



Edit: oxplay2 is too fast!

Thank you for such a fast reply! It works perfectly!

viik:



im happy that you solved it, but you should understand how it work :slight_smile:



for example if your node will have 2 geometries, this method i gived you will give you only one geometry.

if you would want to have a list of geometries you need a modified version.



a hand version, somethin like this to get all geometries from Node:

[java]public void findGeom(Spatial spatial, ArrayList<Geometry> geometries) {

if (spatial instanceof Node) {

Node findingnode = (Node) spatial;

for (int i = 0; i < findingnode.getQuantity(); i++) {

Spatial child = findingnode.getChild(i);

Geometry result = findGeom(child, geometries);

}

} else if (spatial instanceof Geometry) {

geometries.add((Geometry) spatial);

}

}[/java]



to understand it you need to read all JME tutorials and documentations about Scene Graph:

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:the_scene_graph

Node are containers, Geometries are meshes at all. Spatial can be Node or Geometry.



i write it, becouse i dont want to write next method for you in future :wink: You need to understand it and know how to use it.

I understand how that function works.



According to https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:the_scene_graph:

“A Spatial is an abstract data structure that stores transformations (translation, rotation, scale).” So I was a bit confused that assetManager.loadModel() returns you a Spatial, which is actually a Node, which can have Geometry as it’s child, while it’s described as an object more abstract than Node.



Wasn’t aware that only Node have getChild() but not a Spatial. Now it makes more sense.

Geometry = Spatial (becouse it store translation, rotation, scale) - it is superslass of Spatial

Node = Spatial (becouse it store translation, rotation, scale) - it is superslass of Spatial


which is actually a Node, which can have Geometry as it’s child, while it’s described as an object more abstract than Node.


for your model yes, but remember that when you use "assetManager.loadModel()" it can return Geometry too. That it why it return Spatial, becouse we need to check what it return by "instanceof" or just know it and cast it into it ;)

everything here was created by clever people, so dont try to seek stupidity :P

so if you dont want to cast into Node all the time, just have all your models in Geometry form, without Nodes
becouse you know it can be Node -> Node -> Node -> Geometry, Node -> Geometry, Geometry. Its good when you need to use parts of your element :)
somethin like:
StarShip Node -> Hull Node(with geometry within), Turret Node(with geometry within), etc...

and don't answer me that you understand, becouse you propably understand, but i just like write.

http://www.javabeginner.com

1 Like
Does it make sense to cast it on model load? Because as I’ll be working with my own assets I would know which of them have hierarchy or multiple sub meshes and which won’t.


if you would know, then yes :) you can create by default Node -> Geometry, so it will be easier later to add highlights, etc into it. and casting would be like this:
(Geometry)((Node)spatial).getChild(0); :)

It perfectly makes sense. I assume that it is not possible for Geometry to have a collection of sub-meshes (surfaces). So if I have an OBJ model, which has two surfaces with different materials, after import it will be a Node->GeometryMaterial1, GeometryMaterial2


indeed.