Setting Appearance Attributes of Models

Is it possible to set appearance attributes for loaded models. In particular I wanted to be able to do this for models loaded using Kev’s 3ds loader. Right now the models I have all seem to be flat shaded and I want them to be smooth shaded. Is this something that is part of the model or can I change this in xith like you can with a Shape3D? Thanks!

~Shochu

Yes this is possible - I do this with the Ase loader, in my case it is applying a material so that the object is affected by lighting.

See this post: http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=xith3d;action=display;num=1070726483#7

Look at the methods of Shape3D in particular getAppearence and setAppearence (I use the getMaterial method of the got Appearence) in the javadoc/source code.

Specifically on the question on smooth shading - I don’t know the answer to that :slight_smile:

Cheers,

Will.

Normally when I’ve written loaders in the past of added a NodeFactory interface which the user can implement.

As the loader processes the geometry it calls back onto the NodeFactory to produce the actual Xith/Java 3D nodes. This the user direct control over the node creation. I haven’t implemented this for 3DS or OBJ loaders… but I can if it’d be useful.

Kev

Basically loaders produce normal Xith3D scenegraps, so you can always traverse scenegraph produced by any loader and change any attributes of nodes.

On the shading model, you can change shading model using appropriate methods from ColoringAttributes (accessible via Appearance object of Shape3D).

Yuri

Am I able to access the Shape3D that is the model in the 3ds loader? Since the TDSModel extends branchgroup it doesn’t have a setAppearance option.

What the above posts are suggesting is that you traverse the scenegraph for yourself and find the Shape nodes… I’ve always disliked the user having to do this, hence the NodeFactory idea.

Kev

[quote]I’ve always disliked the user having to do this, hence the NodeFactory idea.
[/quote]
Kev, I agree with you in this specific case. But for more generic solution the traverser should [OK, may] be also good. In this case there is no need to rely on the source of the model, etc.

This is more conceptual than implementation question. I think both approaches may/should easily co-exist in the same system. We can try to make it easier to traverse scene graph by providing unified traverser and implementing a Visitor design pattern, so it will be easy or even trivial to implement such functionality in the apps.

I agree that NodeFactory idea gives much more control over the scene loading process, but it does not void the later scene traversals that may be used, say, for subtree-level scenegraph changes.

[quote]Am I able to access the Shape3D that is the model in the 3ds loader? Since the TDSModel extends branchgroup it doesn’t have a setAppearance option.
[/quote]
You still should be able to get list of child nodes with getChildren() and then test instanceof Shape3D. Again, if specified child instanceof Group you call traversing recursively, so finally you will get access to all children for root BranchGroup.

Yuri

Oops, sorry, must have sounded a bit more absolute than I meant it, maybe I should use more smileys :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile:

Traversing the scenegraph is always going to be a valid method. In the case of model loaders its just a nice extra since the chances are every user will want to modify the models (lighting/shadows/caching appearances)

Kev

[quote]Oops, sorry, must have sounded a bit more absolute than I meant it
[/quote]
Have ABSOLUTELY no problems with this - you are welcome!

Yuri

Both are good suggestions :slight_smile:

Here’s an example of what Yuri is talking about (actually this code is taken from the linked topic in my first post, but here it is incase you don’t like following links ;))


 +  /**
+   * Recursivly adds the given material to all Shape3D objects
+   * in the passed group and all of its subgroups.
+   */
+  public static void addMaterial(Group group, Material mat) {
+
+     java.util.List nodes = group.getChildren();
+
+     for (int i = 0; i < nodes.size(); i++) {
+        SceneGraphObject obj = (SceneGraphObject) nodes.get(i);
+
+        if (obj instanceof Shape3D) {
+      Shape3D sh = (Shape3D) obj;
+      sh.getAppearance().setMaterial(mat);
+
+        } else if (obj instanceof Group) {
+      addMaterial( (Group) obj, mat);
+        }
+     }
+  } 

That specific example is for setting the same material across all Shape3D’s which may not be what you want but it still shows how you can traverse all Shape3D’s in a given Group.

fairly straight forward really, but if you want an example of this in action - run this: http://xith.org/jws/jws-com.xith3d.test.Xith3DAseGroupTest.jnlp and look at the source of the Xith3DAseGroupTest which is where that above code snippet is taken from.

Cheers,

Will.