Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (491)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (556)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Picking  (Read 3475 times)
0 Members and 1 Guest are viewing this topic.
Offline DonCrudelis

Junior Member





« Posted 2004-08-15 18:36:05 »

Hi all.

I have made a picking demo but when I pick the delay is up to 50 ms (!!), that's a long delay if we want a fast engine...
I have a terrain (which is pretty big), and that's the problem..

Does the picking code pick behind objects, in my case, behind a hill?

How to make it faster?

Thanks in advance!

Emil Alonzo
Offline Jacke

Junior Newbie




Java games rock!


« Reply #1 - Posted 2004-08-16 11:23:57 »

Hi,
here my solution for terrainpicking:

I cast a ray from eye through intersection with a ground plane. Then i go step by step on this ray forward. If the y-coordinate on the ray at x,y is smaler than the y- coordinate on the terrain(x,y) i go back on the ray, in smaller steps. If the y-coordinate of the ray at x,y is close enough to the y-coordinate at terrain(x,y) i got the intersection point with the terrain.
You do not get the 100% right position with this solution, but you can fit the solution to your needs(performance,precision) by changing the variables precision and heightModifer
I think this solution could be pretty fast if you find the right values for the variables.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
//Umwandlung von Screen- in Worldkoordinaten auf einem Terrain
   public Vector3f getTerrainIntersection(Point mousePos, Point3f camPos, Point3f lookat)
    {
          double r=(mousePos.x - screenWidth/2.0f)/(screenWidth/2.0f)*0.935f;
            double s=((screenHeight/2.0f - mousePos.y)/(screenHeight/2.0f)) * (screenHeight/screenWidth)*0.935f;
           
            //Vector d from Camera to Lookat
           Vector3f d=new Vector3f();
            d.x=camPos.x-lookat.x;
            d.y=Math.abs(camPos.y-lookat.y);
            d.z=camPos.z-lookat.z;
           
            //Vector  v1 parallel to Ground and perpendicularly to Vector d
           Vector3f v1=new Vector3f();
            v1.x=d.z;
            v1.y=0;
            v1.z=-d.x;
            v1.normalize();
           
            // Crossproduct of d and v1
           Vector3f v2= new Vector3f();
            v2.cross(d,v1);
            v2.normalize();
           
            //Plane to project the pointer
           Vector3f v=new Vector3f();
            v.x=(float)(lookat.x+r*v1.x+s*v2.x); //rayDir=v.x
           v.y=(float)(lookat.y+s*v2.y);
            v.z=(float)(lookat.z+r*v1.z+s*v2.z);
           
            /*Intersection with x,z-Plane
             *Line: l=camPos+w(v-camPos)
             *Plane: p=sx*(1;0;0)+sz*(0;0;1)
             *l=p ....
             */
           
            float w=(float)(-camPos.y/(v.y-camPos.y));
            float sx=(float)(camPos.x+w*(v.x-camPos.x));
            float sz=(float)(camPos.z+w*(v.z-camPos.z));
           
            //Plane
           Vector3f planeInter=new Vector3f();
            planeInter.x=sx;
            planeInter.y=0;
            planeInter.z=sz;
                                     
         
          /*Find Intersection with Terrain
           Eine Gerade wird durch Auge und Planeintersection gezogen
           Dann wird sich schrittweise vom Auge aus der planeintersection genährt
           und dabei überprüft um die y-Koordinate der Geraden mit der y-koordinaten
           des Terrains an diesem x,z punkt übereinstimmt.
           Ist dies in etwa der Fall(Präzisionsgrad) dann ist der Schnittpuntk mit dem
           Terrain gefunden.
           Durch Einstellen der Werte von heightModifer und precision kann sowohl
           Qualität als auch Rechenaufwand angepasst werden.
          */

         
          Vector3f pointerPos=new Vector3f(camPos);
         
          planeInter.x-=camPos.x;
          planeInter.y=camPos.y;
          planeInter.z-=camPos.z;
                   
          rayDir.x=v.x-camPos.x;
          rayDir.y=v.y-camPos.y;
          rayDir.z=v.z-camPos.z;
          heightModifer=planeInter.length()/70;
         
          rayDir.normalize();
                                       
          precision=heightModifer/15; //Präzision der Berechnung
         n=1;
          runs=0;
                   
                   
          if(rayDir.y<-0.01f)
          {
                                                         
          while(Math.abs(pointerPos.y - Globals.terrain.getY(pointerPos.x,pointerPos.z))>precision
                                  && pointerPos.y > 0 && runs<200 && n< 15000)
          {
                if(pointerPos.y > Globals.terrain.getY(pointerPos.x,pointerPos.z))
                n+=heightModifer;
                           
                 else
                n-=precision/3;
               
                         
                pointerPos.x=camPos.x+n*rayDir.x;
                pointerPos.y=camPos.y+n*rayDir.y;
                pointerPos.z=camPos.z+n*rayDir.z;
               
                runs++;
                                     
          }
          }
         
          else
          {
                pointerPos.x=camPos.x+5000*rayDir.x;
                pointerPos.y=camPos.y+5000*rayDir.y;
                pointerPos.z=camPos.z+5000*rayDir.z;
          }
         
             //System.out.println("Runs: "+runs);
         /*if(runs>mostRuns)
          mostRuns=runs;
          stem.out.println("Most runs: "+mostRuns);
          System.out.println("Heightmodifer: "+heightModifer);
          System.out.println("Precision: "+precision);*/

   
          return pointerPos;
    }


Hope it helps

Jacke
Offline DonCrudelis

Junior Member





« Reply #2 - Posted 2004-08-16 11:32:06 »

Thanks for the help! Smiley

Alonzo
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Zorqu

Senior Newbie




Java games rock!


« Reply #3 - Posted 2005-03-03 00:49:28 »

can someone tell me what "rayDir" is and how do I get it?
Offline Macca

Senior Newbie




Java games rock!


« Reply #4 - Posted 2005-03-03 12:15:19 »

It think it's a vector (correct me if i'm wrong).

So add
1  
Vector3f rayDir = new Vector3f();
above the
1  
2  
3  
rayDir.x=v.x-camPos.x;
                rayDir.y=v.y-camPos.y;
                rayDir.z=v.z-camPos.z;
bit and it should work ok.
Offline Amos Wenger

Senior Member




Everything's possible, but not everything's fun...


« Reply #5 - Posted 2005-03-03 14:37:44 »

Have anybody a function to get :
 - The Shape3D that is picked
 - The Triangle that is picked
 - ( Optionally ) the coordinates of the intersection

"Once you start working on something, don't be afraid of failure and don't abandon it. People who work sincerely are the happiest"
Offline ewills

Junior Member




Java skeletal animation systems rock!


« Reply #6 - Posted 2005-03-03 15:18:47 »

A thread on picking:

http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=xith3d;action=display;num=1104393946
Offline DonCrudelis

Junior Member





« Reply #7 - Posted 2005-03-03 15:43:39 »

Have a look for the geometry directory in xithtk, there is some code.

Please report to me if some code is missing or buggy.

This is the picking code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
            Point3f point= new Point3f();
            Vector3f vec = new Vector3f();
            getCanvas3D().createPickRay(x, y, point, vec);
            Ray ray = new Ray(point, vec);
            Point3f p = null;
            Triangle triangle = null;
           
            for (Triangle t : getTriangles(shape)) {
                Point3f temp = t.intersects(ray);
                if (temp != null) {
                    p = temp;
                    triangle = t;
                    System.out.println("Coordinate of intersection=" + p);
                    break;
                }
            }
           


getTriangles() :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
    public Triangle[] getTriangles(Shape3D poShape3D) {
        Triangle[] aoTriangle = null;
        Vector3f oVector3f = new Vector3f();
        poShape3D.getLocalToVworld().getTranslation(oVector3f);
        Geometry oGeometry = poShape3D.getGeometry();
        if (oGeometry instanceof GeomIndexedContainer) {
            GeomIndexedContainer oGeomIndexedContainer = (GeomIndexedContainer)oGeometry;
            int[] aiIndices = oGeomIndexedContainer.getIndex();
            aoTriangle = new Triangle[aiIndices.length / 3];
            for (int i = 0, j = 0; i < aiIndices.length; i++, j++) {
                Point3f oPoint3f1 = new Point3f();
                Point3f oPoint3f2 = new Point3f();
                Point3f oPoint3f3 = new Point3f();
                oGeometry.getVertex(aiIndices[i], oPoint3f1);
                oGeometry.getVertex(aiIndices[i + 1], oPoint3f2);
                oGeometry.getVertex(aiIndices[i + 2], oPoint3f3);
                oPoint3f1.add(oVector3f);
                oPoint3f2.add(oVector3f);
                oPoint3f3.add(oVector3f);
                aoTriangle[j] = new Triangle(oPoint3f1, oPoint3f2, oPoint3f3);
                i += 2;
            }
        } else {
            aoTriangle = new Triangle[oGeometry.getVertexCount() / 3];
            for (int i = 0, j = 0; i < oGeometry.getVertexCount(); i++, j++) {
                Point3f oPoint3f1 = new Point3f();
                Point3f oPoint3f2 = new Point3f();
                Point3f oPoint3f3 = new Point3f();
                oGeometry.getVertex(i, oPoint3f1);
                oGeometry.getVertex(i + 1, oPoint3f2);
                oGeometry.getVertex(i + 2, oPoint3f3);
                oPoint3f1.add(oVector3f);
                oPoint3f2.add(oVector3f);
                oPoint3f3.add(oVector3f);
                aoTriangle[j] = new Triangle(oPoint3f1, oPoint3f2, oPoint3f3);
                i += 2;
            }
        }
        return aoTriangle;
    }
   


I don't know how to optimize it but please somebody try.
I don't even know how to pick the whole universe, I only know how to check if a shape is being picked, but triangle and point of intersection is in for the moment Wink.

Good luck and please optimize and add code.

Alonzo
Offline Zorqu

Senior Newbie




Java games rock!


« Reply #8 - Posted 2005-03-04 23:55:12 »

Thanks Macca, I've had some more time to look at this and realized Globals.terrain.getY is also undefined.  Any ideas about that one?

Globals.terrain.getY(pointerPos.x, pointerPos.z)
Offline Zorqu

Senior Newbie




Java games rock!


« Reply #9 - Posted 2005-03-05 12:03:14 »

I am getting so frustrated with this, I can't get this to work.  Most of this stuff I am not following.  I either need a detailed tutorial to follow or some code I can plug in and run with.

I have my eye at (camX, camY, camZ) and I have it looking at (viewX, viewY, 0)  I'm just trying to get the X,Y coords where the user clicked Z will always be 0 its a flat terrain... I've spent so much time on this and still have nothing Sad

please help!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Macca

Senior Newbie




Java games rock!


« Reply #10 - Posted 2005-03-05 14:17:57 »

Yeah i know, it can be really frustrating to do something so obvious i spent ages trying to understand this!

The terrain.getY() is getting the height of point x, z on your terrain. y is up, not z!

The Globals.terrain is your Terrain class (if you're using the demo i think you can just delete the "Globals." bit.) otherwise replace this with the name of your Terrain object. I'm not sure you need this if your terrain's going to be flat because its always going to return 0, but i guess its best to leave it in incase you have mountains and stuff later.

Are you using Terrain or have you just got a flat shape? If so, this method won't help you, check out DonCrudelis' code above. You should be able to just plug it in, though you might have to change the getCanvas3D() bit for the name of your canvas object. 'x' and 'y' are your mouse points on the screen, 'shape' is your terrain shape. I think p will return the point you're looking for.

Hope this helps!
Offline Zorqu

Senior Newbie




Java games rock!


« Reply #11 - Posted 2005-03-05 14:53:25 »

I have got a flat shape... a quad.  So I should try DonCrudelis' code or is that just for terrain object?  Here is what I'm doing now, I changed Global.terrain.getY to 0, and I pass in Z for Y and Y for Z since I have Y as up.  

1  
2  
3  
4  
5  
6  
7  
8  
9  
      public void mouseClicked(MouseEvent e) {
            Vector3f vect = new Vector3f();
            vect = getTerrainIntersection(e.getPoint(), new Point3f(camX, camZ,
                        camY), new Point3f(viewX, 0, viewY));
            System.out.println(vect.x); // x coord
           System.out.println(vect.z); // y coord
           
            isViewChangeScheduled = true;
      }


What I get out of this are values very close to my viewX and viewY I put into it.  My viewX=5 and viewY=5 i get output like:
X = 5.0227056
Y = 4.992122
X = 5.004961
Y = 5.0184546
X = 4.9696717
Y = 5.014441

clicking in various places - this is obviously not what I want =/

oh yeah, and this is with the camera overhead looking straight down, if I change the angle of it then it gives me different numbers, but still nothing close to what I want
Offline arne

Senior Member




money is the worst drug- we should not let it rule


« Reply #12 - Posted 2005-03-07 14:57:12 »

Hi

As far as I got to know this stuff, we still have to enumerate through all Triangles in the world - this is for big worlds a really big problem. Has anybody got a solution for this? I think a good selection algorithm could very much increase the  speed.
I don't even know if something of this kind already exists in xith/jogl, because a good renderer should also use this kind of thingi, because a renderer that tries to render something behind the view is a lot slower than a renderer thet only renders stuff in front of the view.

:: JOODE :: Xith3d :: OdeJava ::
Offline Zorqu

Senior Newbie




Java games rock!


« Reply #13 - Posted 2005-03-08 03:25:10 »

I found another post mentioning Canvas3D.createPickRay().  I had to download the method from CVS but it was worth it, helped me a ton I think I got it figured out now.  Thanks guys!

createPickRay() from CVS
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
    public void createPickRay(int x, int y, Point3f o, Vector3f d) {
        float w = (float) canvas.getWidth();
        float h = (float) canvas.getHeight();
        float a = h / w;
        if (view.getProjectionPolicy() == View.PERSPECTIVE_PROJECTION) {
            // normalize the pixel location to between -1.0 and 1.0 and modify the x
           // coordinate to take aspect ratio into account.
           float rx = (2.0f * (float) x / w - 1.0f) / a;
            float ry = 2.0f - 2.0f * (float) y / h - 1.0f;

            // calculate the distance between viewer and view plane.
           float vpd = 1.0f / (float) Math.tan(view.getFieldOfView());

            // originate the ray at the local origin of the viewer and direct it
           // toward the local position of the click in the view plane.
           o.set(0.0f, 0.0f, 0.0f);
            d.set(rx, ry, -vpd);
            d.normalize();
        } else {
            // normalize the pixel location to between -1.0 and 1.0 and modify the y
           // coordinate to take aspect ratio into account.
           float rx = 2.0f * (float) x / w - 1.0f;
            float ry = a * (2.0f - 2.0f * (float) y / h - 1.0f);

            // originate the ray at local position of the click in the view plane
           // and direct it along the -Z axis.
           float s = view.getScreenScale();
            o.set(s * rx, s * ry, 0.0f);
            d.set(0.0f, 0.0f, -1.0f);
        }

        // transform the ray into world space.
       view.getTransform().transform(o);
        view.getTransform().transform(d);
    }
Offline arne

Senior Member




money is the worst drug- we should not let it rule


« Reply #14 - Posted 2005-03-08 14:13:22 »

Hi

I've got two things to say:
1.
I've got a very good way of checking collisions with the whole scene, without calculating intersections with all Triangles. It works like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
Vector toLookCloserAt = new Vector();
Stack s = new Stack();
s.push(root);
while(!s.empty()) {
  Node n = (Node) s.pop();
  if(n.getVworldBounds().intersect(origin, direction) { //Intersection with ray
   if(n instanceof Group) {
       s.addAll( ((Group) n).getChildren);
    }
    else toLookCloserAt.add(n);
  }
}
//now you only have to test the Shape3D's in toLookCloserAt


2.
DonCrudelis had some code for getting the triangles from a Shape3D. But it only seems to work for GeomIndexedContainer and not for any other kinds of Geometry, too.
Has anybody a better solution to get the Triangles than by testing for all kinds of Geometry. The major problem here for me is, that GeometryStripArray saves the stuff differently than a simple Trianglearray. At least I think so!

:: JOODE :: Xith3d :: OdeJava ::
Offline Amos Wenger

Senior Member




Everything's possible, but not everything's fun...


« Reply #15 - Posted 2005-03-08 16:58:08 »

Quote
Hi

I've got two things to say:
1.
I've got a very good way of checking collisions with the whole scene, without calculating intersections with all Triangles. It works like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
Vector toLookCloserAt = new Vector();
Stack s = new Stack();
s.push(root);
while(!s.empty()) {
  Node n = (Node) s.pop();
  if(n.getVworldBounds().intersect(origin, direction) { //Intersection with ray
   if(n instanceof Group) {
       s.addAll( ((Group) n).getChildren);
    }
    else toLookCloserAt.add(n);
  }
}
//now you only have to test the Shape3D's in toLookCloserAt


2.
DonCrudelis had some code for getting the triangles from a Shape3D. But it only seems to work for GeomIndexedContainer and not for any other kinds of Geometry, too.
Has anybody a better solution to get the Triangles than by testing for all kinds of Geometry. The major problem here for me is, that GeometryStripArray saves the stuff differently than a simple Trianglearray. At least I think so!


Okay, this advance the Picking discussion.
I'll see if I can do a little function to get all Triangle in it ( even if there is TriangleStrip information, or Quad ).
I think there is a problem only if the Geom is composed of segments instead of faces ( triangles or quads ).

"Once you start working on something, don't be afraid of failure and don't abandon it. People who work sincerely are the happiest"
Offline arne

Senior Member




money is the worst drug- we should not let it rule


« Reply #16 - Posted 2005-03-09 12:24:21 »

I think there really has to be a way, because the renderer has to do it in some way too - and testing for all kinds of classes would be no good object oriented programming.

Some things I found out Wink :

GeomContainer has a Function called getVertexFormat() - it seems to return an integer - what the int means i think is saved in the static variables of GeomContainer. This might be the way to get an idea of how to interpret the VertexData without testing for all kinds of Geometry classes. We would still have to test for all the different types  Embarrassed .

Actually I think there must be a better way, because the Geometry stuff wouldn't be able to be extended then.
Something I also stepped across is GeometryTranslocator. Where does it fit in?

:: JOODE :: Xith3d :: OdeJava ::
Offline Macca

Senior Newbie




Java games rock!


« Reply #17 - Posted 2005-03-11 17:05:36 »

I'm having some trouble with picking. I've got my pickable objects arranged in a BranchGroup. When I add a node to the group its bounds get set to some default value which is totally wrong.

All the nodes also get set to this same value even if I manually set the bounds and turn off autocompute before hand. When I try and pick them they all intersect no matter where I click.

Anyone got any ideas what I'm doing wrong?
Offline arne

Senior Member




money is the worst drug- we should not let it rule


« Reply #18 - Posted 2005-03-11 17:37:25 »

The Bounds should autocompute correctly.

Are you testing this, by showing the bounds with setShowBounds ? - It doesn't work correctly.

:: JOODE :: Xith3d :: OdeJava ::
Offline Macca

Senior Newbie




Java games rock!


« Reply #19 - Posted 2005-03-12 18:09:28 »

Was using breakpoints but I've got this sorted now thanks, used the view.pick instead
Offline aNt

Senior Member




AFK


« Reply #20 - Posted 2005-05-05 07:33:01 »

i seem to be running into problems with all this Sad

i have tryed useing the view.pick(...) and the also
implemented the createPickRay(...)...

1. view.pick(...) just doesnt seem to work.. my nodes
are node.setPickable(true); When i click the mouse
sending the x, y location of the mouseClick (over a
shape) it doesnt work. i have pritty much copyed the
test case and its just not having it Sad- do the PolygonAttributes
matter with picking? what is if am using transparancy?

2. createPickRay(..) i just dont no how to get this to
work? how do i implement it so it returns me what
i clicked on? every time i use it with:
1  
2  
3  
4  
5  
     Point3f point = new Point3f(0, 0, 50f);
    Vector3f vec = new Vector3f(0, 0, 1);
    createPickRay(x, y, point, vec);
    Ray ray = new Ray(point, vec);
    System.out.println("ray, x, y: " + ray + ", " + x + ", " + y);
the ray doesnt seem to change when i click the mouse
all over the canvas? I dont need to no where on a shape
i clicked for now- just what shape got clicked..

can anyone help here? i guess i've missed the point
somewhere....
Offline arne

Senior Member




money is the worst drug- we should not let it rule


« Reply #21 - Posted 2005-05-05 08:06:53 »

Here's the whole code for picking that also gets you the position and the shape:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
Vector branchGroups;

public PickResult pick(int x, int y) {
  Point3f o = new Point3f();
  Vector3f d = new Vector3f();
  canvas.createPickRay(x,y,o,d);
  TreeSet intersecting = new TreeSet();
  Stack s = new Stack();
  Point3f pos = new Point3f();
  Vector3f pos1 = new Vector3f();
  Vector3f pos2 = new Vector3f();
  Vector3f pos3 = new Vector3f();
  boolean result;
  boolean nopos;
  for(Enumeration e = branchGroups.elements(); e.hasMoreElements(); ) {
     BranchGroup tg = (BranchGroup) e.nextElement();
     s.clear();
     s.push(tg);
     while(!s.empty()) {
       Node n = (Node) s.pop();
       Bounds b = n.getVworldBounds();
       result = false;
       nopos = false;
       if(b instanceof Sphere) result = ((Sphere) b).rayIntersection(o, d, pos);
       else if(b instanceof Box) result = ((Box) b).rayIntersection(o, d, pos);
       else if(b instanceof ConvexHull) result = ((ConvexHull) b).rayIntersection(o, d, pos);
       else {
         result = b.intersect(o,d);
         nopos = true;
       }
       if(result) {
         if(Group.class.isInstance(n)) {
           Group g = (Group) n;
           s.addAll(g.getChildren());
         }
         else {
           float dist;
           if(!nopos) dist = pos.distanceSquared(o);
           else dist = 0;
           if(n instanceof Shape3D) intersecting.add(new PickResult(c.getVObject(),(Shape3D) n, dist));
         }
       }
     }
   }
   Triangle t = new Triangle();
   Point3f transOrigin = new Point3f();
   Vector3f transDirection = new Vector3f();
   float closestIntersect = Float.POSITIVE_INFINITY;
   PickResult nearest = null;
   for(Iterator i = intersecting.iterator(); i.hasNext(); ) {
     PickResult r = (PickResult) i.next();
     Geometry geom = r.getGeom();
     GeometryArray geomArr;
     if(geom instanceof GeometryArray) geomArr = (GeometryArray) geom;
     else if(geom instanceof GeometryTranslocator) geomArr = ((GeometryTranslocator) geom).getGeometry();
     else geomArr = null; //User-defined Geometry is not supported - should be changed
    transOrigin.set(o);
     r.transform(transOrigin);
     transDirection.set(d);
     r.transform(transDirection);
     if(geomArr != null) {
       if(geomArr instanceof QuadArray) {
         System.out.println("quad");
       }
       if(geomArr instanceof TriangleArray) {
         int length = geomArr.getVertexCount();
         for(int j = 0; j < length; j+=3) {
           geomArr.getVertex(j,pos1);
           geomArr.getVertex(j+1,pos2);
           geomArr.getVertex(j+2,pos3);
           t.set(pos1,pos2,pos3);
           float f = t.test(transOrigin,transDirection,closestIntersect);
           if(f != -1) {  // there is a collision
            f = f/transDirection.length();
             if(f < closestIntersect) {
               closestIntersect = f;
               r.setDistance(f);
               nearest = r;
             }
           }
         }
       }
       if(geomArr instanceof TriangleFanArray) {
         System.out.println("tri-fan");
       }
       if(geomArr instanceof TriangleStripArray) {
         System.out.println("tri-strip");
       }
     }
   }
   if(nearest != null) {
   Point3f p  = new Point3f();
   p.scaleAdd((float)Math.sqrt(nearest.getDistance()),d,o);
   nearest.setPos(p);
   return(nearest);
  }
  return(null);
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
    public class Triangle {
        Vector3f p1;
        Vector3f p2;
        Vector3f p3;
        Point3f temp;
        Vector3f t1,t2,t3;
        public Triangle() {
            temp = new Point3f();
            t1 = new Vector3f();
            t2 = new Vector3f();
            t3 = new Vector3f();
        }
       
        public void set(Vector3f p1, Vector3f p2, Vector3f p3) {
            this.p1 = p1;
            this.p2 = p2;
            this.p3 = p3;
        }
       
        public boolean testForIntersection(Tuple3f q, Vector3f dir) {
            temp.scaleAdd(100000,dir,q);
            int i = sign3D(temp,p1,q,p2);
            int j = sign3D(temp,p3,p2,q);
            int k = sign3D(temp,p1,p3,q);
            if(i == 0 && j == 0) return true; // intersects in C
           if(i == 0 && k == 0) return true; // intersects in A
           if(j == 0 && k == 0) return true; // intersects in B
           if(i == 0 && j == k) return true; // intersects in AC
           if(j == 0 && i == k) return true; // intersects in BC
           if(k == 0 && j == i) return true; // intersects in AB
           if(i == j && j == k) return true; // intersects inside
           return false; // does not intersect
       }

        public int sign3D(Tuple3f a, Tuple3f b, Tuple3f c, Tuple3f d) {
            Matrix3f m = new Matrix3f(a.x-d.x, a.y-d.y, a.z-d.z,
                                      b.x-d.x, b.y-d.y, b.z-d.z,
                                      c.x-d.x, c.y-d.y, c.z-d.z);
            float det = m.determinant();
            if(det > 0.00001) return 1;
            else if(det < -0.00001) return -1;
            else return(0);
        }

        public float intersect(Point3f orig, Vector3f dir) {
            t3.set(orig);
            float     r, a, b;
            p2.sub(p1);
            p3.sub(p1);
            t1.cross(p2, p3);

            if (t1.length() == 0) {
                return(-1);
            }

            t3.sub(p1);
            a = -t1.dot(t3);
            b = t1.dot(dir);

            if ((float)Math.abs(b) < 0.00001) {
                return(-1);
            }
            r = a / b;
            if (r < 0.0) {
                return -1;
            }
            return r*r;
        }
        public float test(Point3f start, Vector3f dir, float nearestDist) {
            // first check, if any intersection with the triangle can result in a nearer result
           if(testForIntersection(start,dir)) { // if this is possible, check if there is an intersection with the triangle
               // if there is an intersection calculate the exact position
               float r = intersect(start,dir);
                return(r);
            }
            return(-1);
        }
    }


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
public class PickResult implements Comparable{
    VObject vobject;
    Shape3D l;
    Point3f pos = null;
    Point3f direction = null;
    Point3f origin = null;
    float distance;
    Transform3D temp;
    Vector3f tvec;
    /** Creates a new instance of PickResult */
    public PickResult(VObject v, Shape3D l, float dist) {
        vobject = v;
        this.l = l;
        distance = dist;
        temp = new Transform3D();
        tvec = new Vector3f();
    }
   
    public VObject getVObject() {
        return(vobject);
    }
   
    public Geometry getGeom() {
        return(l.getGeometry());
    }
   
    public void transform(Vector3f v) {
        l.getLocalToVworld(temp);
        temp.invert();
        temp.transform(v);
    }
   
    public void transform(Point3f p) {
        l.getLocalToVworld(temp);
        temp.invert();
        temp.transform(p);
    }
   
    public Point3f getPos() {
        return(pos);
    }
   
    public void setPos(Point3f p) {
        pos = p;
    }
   
    public float getDistance() {
        return(distance);
    }
   
    public void setDistance(float f) {
        distance = f;
    }
   
    public Vector3f getRayDir() {
        return(null);
    }
   
    public Point3f getRayStart() {
        return(null);
    }
   
    public String toString() {
        return(vobject+": Leaf: "+l+" Pos:"+pos);
    }
   
    public int compareTo(Object o) {
        if(o instanceof PickResult) {
            PickResult r = (PickResult) o;
            if(distance - r.distance > 0) return(1);
            if(distance - r.distance < 0) return(-1);
        }
        return(0);
    }
   
    public boolean equals(Object o) {
        if(o instanceof PickResult) {
            PickResult r = (PickResult) o;
            if(r.vobject == vobject && r.l == l && r.pos == pos && r.direction == direction) {
                return(true);
            }
        }
        return(false);
    }
}


Please note, that there is still need to improvement, and it also works only for Trianglearrays.

:: JOODE :: Xith3d :: OdeJava ::
Offline Amos Wenger

Senior Member




Everything's possible, but not everything's fun...


« Reply #22 - Posted 2005-05-07 07:39:42 »

You can also include it in Gamma, arne.

"Once you start working on something, don't be afraid of failure and don't abandon it. People who work sincerely are the happiest"
Offline arne

Senior Member




money is the worst drug- we should not let it rule


« Reply #23 - Posted 2005-05-10 11:31:31 »

Yeah, but it's not even a java class it's just a function, but I think I could encapsulate it in a class. But I think it should then go to xith-tk anyways.

:: JOODE :: Xith3d :: OdeJava ::
Offline Amos Wenger

Senior Member




Everything's possible, but not everything's fun...


« Reply #24 - Posted 2005-05-10 15:04:47 »

You're right. ( in fact, we should merge jogl, xith3d, odejava in gamma  Smiley ).
You can include it in the org.magicspark.gamma.util.Util class. It's made for that !  Wink

"Once you start working on something, don't be afraid of failure and don't abandon it. People who work sincerely are the happiest"
Offline aNt

Senior Member




AFK


« Reply #25 - Posted 2005-05-12 09:34:15 »

arne thanks dude... Smiley
Offline aNt

Senior Member




AFK


« Reply #26 - Posted 2005-05-20 14:42:30 »

VObject? is it the View? or somthing? also the lines:
1  
2  
3  
4  
5  
6  
Bounds b = n.getVworldBounds(); 
  result = false;
  nopos = false;
  if(b instanceof Sphere) result = ((Sphere) b).rayIntersection(o, d, pos);
  else if(b instanceof Box) result = ((Box) b).rayIntersection(o, d, pos);
  else if(b instanceof ConvexHull) result = ((ConvexHull) b).rayIntersection(o, d, pos);


n.getVworldBounds(); returns a BoundingSphere not
a Bounds.. so that doesnt compile so i changed it.

All the if elses dont work because its a BoundingSphere
so there not all needed. At this point. not sure if u are
using other packages here.

1  
if(n instanceof Shape3D) intersecting.add(new PickResult(c.getVObject(),(Shape3D) n, dist));


no joy at all because i dont no what a VObject is...
c.getVObject()? whats 'c'?
Offline arne

Senior Member




money is the worst drug- we should not let it rule


« Reply #27 - Posted 2005-05-20 15:33:23 »

You can remove the VObject stuff, because that's just something I use for my Game (to know which Object got picked and not only the Shape) - I thought I removed everything of this stuff, when I posted the code.

Quote
n.getVworldBounds(); returns a BoundingSphere not  
a Bounds.. so that doesnt compile so i changed it.


Oh yeah you're right. n.getBounds() returns Bounds(), so I  probably just had Bounds there  because I used getBounds() before which was wrong and I haven't noticed, that it changed to BoundingSphere when I corrected it.
But it should work anyways: BoundingSphere implements Bounds. That's simply in com.xith3d.scenegraph. BoundingSphere extends Sphere in com.xith3d.spatial.bounds. So it should work, but your's is simpler.

+ you will have to move all this instance creating out of this, if you want to use it frequently, so this will leave you with a lot of temporary variables.

If you have questions don't bother asking!!

Arne

:: JOODE :: Xith3d :: OdeJava ::
Offline Amos Wenger

Senior Member




Everything's possible, but not everything's fun...


« Reply #28 - Posted 2005-12-07 17:44:45 »

THANKS A LOT ARNE !!!

It's so wonderful ! After a few minutes trying to understand something to the Picking posts in the JOGL/LWJGL sections, I remembered you had made some code and rushed on it.
I adapted it a bit :
 - I removed the VObject stuff entirely
 - I put it in a class (GraphicUtils, in Gamma)
 - I made it use the Triangle3D class in Gamma (and added your functions to this class)
You can take a look at the code in the SVN repository.
I'm actually making a pre-"level editor" (for now it's just a test for the line intersection test in 2D).

"Once you start working on something, don't be afraid of failure and don't abandon it. People who work sincerely are the happiest"
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Nickropheliac (15 views)
2014-08-31 22:59:12

TehJavaDev (23 views)
2014-08-28 18:26:30

CopyableCougar4 (29 views)
2014-08-22 19:31:30

atombrot (41 views)
2014-08-19 09:29:53

Tekkerue (39 views)
2014-08-16 06:45:27

Tekkerue (35 views)
2014-08-16 06:22:17

Tekkerue (25 views)
2014-08-16 06:20:21

Tekkerue (36 views)
2014-08-16 06:12:11

Rayexar (72 views)
2014-08-11 02:49:23

BurntPizza (49 views)
2014-08-09 21:09:32
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!