Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

11991 Posts in 1587 Topics- by 3508 Members - Latest Member: PienueDut

26. May 2012, 09:12:47 am
Xith3D CommunityGeneral CategorySupport (Moderator: Marvin Fröhlich)How to get a OBJModel from picking?
Pages: [1] 2
Print
Author Topic: How to get a OBJModel from picking?  (Read 2953 times)
Dori
Enjoying the stay
*
Offline Offline

Posts: 90


View Profile
« on: 03. February 2007, 06:04:32 am »

Hi,

I'm trying to move a OBJModel from one place to another by picking it and pick the ground where it is supposed to go. Well picking works I think, but I cannot cast it to OBJModel, i only am able to get Shape3D by using nearest.getShape3D(), but how do I cast that to OBJModel?

Thanks
Logged
'n ddrylliog
Guru
*****
Offline Offline

Posts: 1188



View Profile WWW Email
« Reply #1 on: 03. February 2007, 11:07:44 am »

Hi,

You can't cast Shape3D to OBJModel, since OBJModel doesn't extend Shape3D Smiley

Picking is a well-known use case of a HashMap. You could have a HashMap<Shape3D, OBJModel>. But there has to be a better way...

.................(coding....)...................

Okay, I just did a class for you, org.xith3d.utility.general.NodeMap.

IT'S IN THE TOOLKIT but in case you don't use SVN version here's the source :

Code:
/**
 * A Node Map.<br>
 * <br>
 * Useful in picking, for example :<br>
 * <code>NodeMap<OBJModel> map = new NodeMap("obj");</code><br>
 * Each time you create a pickable OBJ Model :<br>
 * <code>map.prepare(model);</code><br>
 * You have a PickResult, want your OBJ model back</br>
 * <code>OBJModel model = map.get(pickResult.getShape3D());<br>
 * Then you can do whatever you want with it !<br>
 *
 * @author Amos Wenger (aka BlueSky)
 */
public class NodeMap<T extends NodeGroup> {

    String id;
   
    /**
     * Create a new NodeMap
     * @param id The ID which will be used when storing
     * the data in Nodes. If you have several NodeMap(s)
     * on same objects, have different IDs
     */
    public NodeMap(String id) {
       
        this.id = id;
       
    }
   
    @SuppressWarnings("unchecked")
    public void prepare(T group) {
        prepare(group, group);
    }
   
    @SuppressWarnings("unchecked")
    public void prepare(T group, Object object) {
        List<Node> nodes = group.getChildren();
        for (Node node : nodes) {
            node.setUserData(id, object);
            if(node instanceof NodeGroup) {
                prepare((T)node, object);
            }
        }
    }
   
    @SuppressWarnings("unchecked")
    public T get(Node node) {
        return (T) node.getUserData(id);
    }
   
}

Note : not tested yet, but should be right.
Logged
Dori
Enjoying the stay
*
Offline Offline

Posts: 90


View Profile
« Reply #2 on: 03. February 2007, 03:19:31 pm »

Wow this is what I call support. I try it when I go home  Smiley

But why isn't there an option to get a Node from pickResult? I haven't tested this yet but it looks like some kind of a hack. It should be simple as "OBJModel objModel = (OBJModel) nearest.getNode();" or "OBJModel objModel = (OBJModel) canvas.getNodeAt(location);

One other thing. Can Nodes only have BoundigSphere not BoundingBox?

Thanks again
Logged
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #3 on: 03. February 2007, 03:41:40 pm »

But why isn't there an option to get a Node from pickResult? I haven't tested this yet but it looks like some kind of a hack. It should be simple as "OBJModel objModel = (OBJModel) nearest.getNode();" or "OBJModel objModel = (OBJModel) canvas.getNodeAt(location);

Well, only Shape3D instances are the result of a picking. Models are always Groups, because a Model can contain several Shape3Ds and (sub-)Groups. A PickResult contains more than just the picked Shape3D. And it shouldn't be too hard to retrieve the Shape3D Node from the PickResult.

But I think, I have an idea to solve the problem. A Group could have a flag, telling that it is a host for picked shapes. Then you could get the pick-host Group from a Shape3D. The PickResult could then provide a method called getPickHost(), which returns the Group, which is the pickhost for the picked shape. Thsi group could then be casted to (e.g.) OBJModel.

One other thing. Can Nodes only have BoundigSphere not BoundingBox?

BoundingBox is one of the other possibilities. But currently only BoundingSphere is used. This is a task for the 1.0.0 branch, that I will work on in some days.

Marvin
Logged
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #4 on: 03. February 2007, 04:37:18 pm »

I have added setPickHost() / isPickHost() methods to the GroupNode class. The Shape3D class has a getPickHost() method to retrieve the deepest GroupNode, that is a pick-host. The PickResult class also provides a method getPickHost(), which simply returns the result of shape.getPickHost(). The Model class (and therefore all Model extensions like OBJModel) have the pick-host flag at true by default.

So you can just call:
Code:
OBJModel pickedModel = (OBJModel)pickResult.getPickHost();
if you exactly know, that the picked shape is part of an OBJModel.
Or
Code:
GroupNode pickHost = pickResult.getPickHost();
if ((pickHost != null) && (pickHost instanceof OBJModel))
{
    OBJModel pickedModel = (OBJModel)pickHost;
}
if you don't know exactly.

Does this solve your problem?

Marvin
Logged
Dori
Enjoying the stay
*
Offline Offline

Posts: 90


View Profile
« Reply #5 on: 03. February 2007, 05:05:53 pm »

It works great.

in
Code:
/**
 * A Node Map.<br>
 * <br>
 * Useful in picking, for example :<br>
 * <code>NodeMap<OBJModel> map = new NodeMap("obj");</code><br>
 * Each time you create a pickable OBJ Model :<br>
 * <code>map.prepare(model);</code><br>
 * You have a PickResult, want your OBJ model back</br>
 * <code>OBJModel model = map.get(pickResult.getShape3D());<br>
 * Then you can do whatever you want with it !<br>
 *
 * @author Amos Wenger (aka BlueSky)
 */
this line
Code:
* <code>OBJModel model = map.get(pickResult.getShape3D());<br>

should be
Code:
OBJModel model = map.get(pickResult.getShape());
Logged
Patheros
Getting respectable
***
Offline Offline

Posts: 267


Dead Dolphin


View Profile WWW Email
« Reply #6 on: 06. February 2007, 07:59:00 pm »

The Model class (and therefore all Model extensions like OBJModel) have the pick-host flag at true by default.

Is there a way to change the default value of pick-host on the Model Nodes?
Logged

"I like my method, what was my method again?" - Jon
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #7 on: 06. February 2007, 08:15:09 pm »

The Model class (and therefore all Model extensions like OBJModel) have the pick-host flag at true by default.

Is there a way to change the default value of pick-host on the Model Nodes?

Not yet. I will add it.

Marvin
Logged
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #8 on: 06. February 2007, 08:19:25 pm »

Added Smiley.

So the pick-host thing is working for you?

Marvin
Logged
Patheros
Getting respectable
***
Offline Offline

Posts: 267


Dead Dolphin


View Profile WWW Email
« Reply #9 on: 06. February 2007, 11:23:16 pm »

So the pick-host thing is working for you?

I haven't gotten around to implementing it (mainly because my project is built off of a xith jar rather than the newest SVN) but next time I go back to implementing new xith things I will defiantly try it out.

Out of curiosity how is its performance of getPickHost()? Is it O(n) where n is the depth of the graph? and does it cache the result?
Logged

"I like my method, what was my method again?" - Jon
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #10 on: 06. February 2007, 11:46:31 pm »

Out of curiosity how is its performance of getPickHost()? Is it O(n) where n is the depth of the graph? and does it cache the result?

The pick-host is cached. So it is O(1).
Logged
horati
Global Moderator
Getting respectable
*****
Offline Offline

Posts: 393


View Profile
« Reply #11 on: 09. February 2007, 03:19:29 pm »

This looks like a very nice addition.  Previously, I created a series of Shape3Ds so that I could determine which piece of shape got touched but there were problems due to the BoundingSphere vs BoundingBox w.r.t. picking.  Now that I understand a (little) bit more, I'm looking through PickResult itself.  I see various methods to transform coordinate systems but I don't see anything that directly answers this question:
Quote
At what point in local geometry was I intersected?
Given the answer to that question, all my picking problems go away because I can simply store my carry-along data in the user object with a map of local geometry regions to interesting data.
Logged

Kevin
"It may not seem like a big deal, but ignorance of character encoding issues leads to insidious code rot akin to y2k."
http://stackoverflow.com/users/3474/sylvarking
'n ddrylliog
Guru
*****
Offline Offline

Posts: 1188



View Profile WWW Email
« Reply #12 on: 09. February 2007, 04:02:17 pm »

Quote
At what point in local geometry was I intersected?
Given the answer to that question, all my picking problems go away because I can simply store my carry-along data in the user object with a map of local geometry regions to interesting data.
I'm interested, in what format you store local geometry regions? (I mean, what are you data structures?). And what are your algorithms to test if a point (e.g. from a PickResult) is in this region?
Logged
Patheros
Getting respectable
***
Offline Offline

Posts: 267


Dead Dolphin


View Profile WWW Email
« Reply #13 on: 09. February 2007, 04:07:56 pm »

Quote
At what point in local geometry was I intersected?

I believe if your using the PickingLibarary then getPos will get you the point you need. I know that the documentation says

Code:
The position of this PickResult's Shape3D in global-space

however at line 262 of PickingLibarary

Code:
                Point3f p = new Point3f();
                p.scaleAdd((float)Math.sqrt(pr.getMinimumDistance()), pickRay.direction, pickRay.origin);
                pr.setPos(p);

It looks like it sets pos to a point on the pick ray at the distance of intersection.

So either the PickingLibaray sets it incorrectly or the documentation is wrong.
Logged

"I like my method, what was my method again?" - Jon
'n ddrylliog
Guru
*****
Offline Offline

Posts: 1188



View Profile WWW Email
« Reply #14 on: 09. February 2007, 04:36:49 pm »

Please explain me, what's the difference between "the point of intersection" and "a point on the pick ray at the distance of intersection"...
Logged
Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic