Picking ASE models

I’ve added some models to my project using the ASE loader and would like to be able to select them with the mouse. I have picking enabled all the way down the tree up to the point that the BranchGroup is returned from aseFile.getModel() but I noticed I couldn’t pick the model. I fixed this by getting the BranchGroups subnodes and naming them the same thing. Right now I only want to know if the model was picked, not which component of the model was picked. Is this the proper (or only) way to do this?

  
protected void buildBranch() {
    // Default model position
    float x = 50;
    float y = 0;
    float z = 50;
                                                                                                                                                              
    setPickable(true); // Because we want selection
                                                                                                                                                              
    // Our model
    BranchGroup bg = aseFile.getModel();
    bg.setPickable(true);
    bg.setName("Truck");
                                                                                                                                                              
    // Iterate over the child nodes, naming each and setting pickable
    List l = bg.getChildren();
    Iterator i = l.iterator();
                                                                                                                                                              
    while(i.hasNext()) {
        Node n = (Node) i.next();
        n.setPickable(true);
        n.setName("Truck");
    }
                                                                                                                                                              
    TransformGroup tg1 = new TransformGroup();
    tg1.setPickable(true);
                                                                                                                                                              
    Transform3D t1 = new Transform3D();
    t1.setTranslation(new Vector3f(x, y, z));
    tg1.setTransform(t1);
                                                                                                                                                              
    tg1.addChild(bg);
                                                                                                                                                              
    addChild(tg1);
  }

As an addendum to this, what is a good way to manage the objects being picked? I have a primary GUI class that manages the mouse/keyboard interactions and scenegraph. The display and object model behind it are represented as layers that can display arbitrary data. These could be single nodes or whole subtrees of visualized data. Selections are intercepted via mouse clicks and I get an array of Nodes. If I want to modify the node (for example if I wanted to highlight my model), how can I do this in a nice object-oriented (ie NON-DEMO-ized) way?

It’s correct that you need to mark all the nodes of a model as pickable. You can find a function to do this in the GSG Picking tutorial.

Good to know I was on the right track. So why isn’t setPickableRecursive(Group group) part of Xith instead of tucked away in the tutorial? ;D

[quote]So why isn’t setPickableRecursive(Group group) part of Xith instead of tucked away in the tutorial?
[/quote]
This is a part of more generic scene-traversal question. I believe that such tasks should be inplemented as a part of utillity package and included either in Xith3D core or in xith-tk project.

Yuri

Anyone have an answer for the 2nd half of his question? I am running into the same thing.

For instance, when we do click on a model and we want to modify it at the object level, how can this be done?

In my example, I want to highlight the object, and then move it to a different area after another click is made. This must be a common scenerio, the picking tutorial in GSG doesnt deal with models… would be a nice addition.

Thanks!

His original:

[quote]As an addendum to this, what is a good way to manage the objects being picked? I have a primary GUI class that manages the mouse/keyboard interactions and scenegraph. The display and object model behind it are represented as layers that can display arbitrary data. These could be single nodes or whole subtrees of visualized data. Selections are intercepted via mouse clicks and I get an array of Nodes. If I want to modify the node (for example if I wanted to highlight my model), how can I do this in a nice object-oriented (ie NON-DEMO-ized) way?
[/quote]

Noone?

[quote]Noone?
[/quote]
I’m not sure I fully understand the question, but in case you want to get your “logical” object of a clicked node, why not use the Node’s UserData to reference to it?
This is what I do: when I make the entire node of a 3d-model pickable, I also store the reference to my logic object in the node’s Shape3Ds. When one Shape3D gets clicked you get its “logical object” and voila.
For example:


BrainObject myBrainObject; // ...

List allelements = getAllelements(the3dModelsRootnode);
for (Iterator i = allelements.iterator(); i.hasNext(); ) {
  Node node = (Node) i.next();
  node.setPickable(true);
  if (node instanceof Shape3D) {
    node.setUserData(myBrainObject);
  }
}

...
    
public static List getAllelements(Node knoten)
{
  List liste = new ArrayList();
  addThem(knoten, liste);
  return liste;
}

private static void addThem(Node node, List addlist)
{
  addlist.add(node);
  if (node instanceof Group) {
    Group group = (Group) node;
    List childlist = group.getChildren();
    for (Iterator n = childlist.iterator(); n.hasNext(); ) {
      newnode = (Node) n.next();
      setWas(newnode, addlist);   // Recursion!
    }
  }
}

Yes, that sounds like what I’m trying to do. For instance when you click on a model in a game, you want to bring up statistics of the unit or whatever. So you’d have to have some way of referencing this from the click.

I will research the method you posted above.

Thanks for the reply.

I tend to implement a bespoke object for each game entity. In the case of units for instance…

class Unit - contains all the data associated with a unit

class Unit3D - extends BranchGroup and has a reference to a “Unit” class. The branch group contains all the shapes that represent the unit (which each have their user data set to the Unit3D instance).

Then when you click on a shape you can go straight to the unit3d that its part of and in turn straight to the unit data represented.

Kev

Thanks Kev, I was waiting for you to see this thread. I like that approach, I will try to mimic your basic idea.

I did something similar with the “units” in my app, except I use a generic model class to store visibility traits and models that wraps the actual units so there is a separation between the model and view. A model management class handles the assignment of model branchgroups to the classes based on their type and the values in a configuration file.