Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (476)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (532)
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  
  Collision/intersection help  (Read 2889 times)
0 Members and 1 Guest are viewing this topic.
Offline matt878

Junior Newbie





« Posted 2012-01-27 10:20:24 »

Hi,

Im trying to do some simple picking.

Ive got a number of different objects, spheres/triangles and some oddly shaped objects. Given a 3d vector i want to know the 3d locations where the vector intersects any of the objects. For example from location 0,0,0 looking at direction 1,1,1 at what x,y,z location (if any) does this vector intersect my teapot.

Ive tried using GL_SELECT but that doesn't give me x,y,z locations where a ray would intersect.

Thanks for your help
Offline theagentd
« Reply #1 - Posted 2012-01-27 10:29:17 »

The best way is just to do all the calculations on the CPU. Just mathematically check if your ray is intersecting anything.

The second way is "easier", but costs a lot of performance and doesn't tell you which object the ray is intersecting with, only where the ray intersected. There's a convenient function in GLU which allows you to do the  OpenGL transformations "backwards", meaning that if you have the screen coordinates and the scene depth of a pixel it will give you the 3D world space coordinates of that pixel. The problem is acquiring the depth value, which forces the CPU to wait for the GPU to finish rendering, which then forces the GPU to wait because it doesn't have any other commands. Anyway, I just copy-pasted this code from somewhere so I don't take credit for it (but it does work):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
    private FloatBuffer getMousePosition(int mouseX, int mouseY) {
        IntBuffer viewport = BufferUtils.createIntBuffer(16);
        FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
        FloatBuffer projection = BufferUtils.createFloatBuffer(16);
        FloatBuffer winZ = BufferUtils.createFloatBuffer(1);
        FloatBuffer position = BufferUtils.createFloatBuffer(3);

        GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
        GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
        GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);

        GL11.glReadPixels(mouseX, mouseY, 1, 1, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, winZ);

        if (winZ.get(0) == 1) {
            return null;
        }

        GLU.gluUnProject(mouseX, mouseY, winZ.get(), modelview, projection, viewport, position);

        return position;
    }

Myomyomyo.
Offline gouessej
« Reply #2 - Posted 2012-01-27 10:31:19 »

Hi

You can use OpenGL picking to get this kind of information, you have to analyse the hits correctly. There is an example here:
http://jogamp.org/jogl-demos/src/demos/misc/Picking.java

I advise you to have a look at the manual of the method glSelectBuffer to understand the hit contents:
http://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml

The use of OpenGL picking is discouraged according to the OpenGL FAQ, I agree with the first sentence of the previous post (thanks theagentd).

Edit.: replace BufferUtils.createFloatBuffer() by Buffers.newDirectFloatBuffer(), do the same thing for int NIO buffers. Rather use drawable.getGL().getGL2() or GL2 instead of GL11, replace GLU by "new GLUgl2()" and it should work.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline theagentd
« Reply #3 - Posted 2012-01-27 11:14:47 »

Oh, this was in the JOGL Development section... T__T Sorry...

Myomyomyo.
Offline matt878

Junior Newbie





« Reply #4 - Posted 2012-01-27 15:24:31 »

@theagentd

i used the following instead which seemed to compile for me:

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  
    private DoubleBuffer getMousePosition(int mouseX, int mouseY, GL GL11) {
       
        IntBuffer viewport = BufferUtil.newIntBuffer(16);
        DoubleBuffer modelview = BufferUtil.newDoubleBuffer(16);
        DoubleBuffer projection = BufferUtil.newDoubleBuffer(16);
        DoubleBuffer winZ = BufferUtil.newDoubleBuffer(1);
        DoubleBuffer position = BufferUtil.newDoubleBuffer(3);


        GL11.glGetDoublev(GL11.GL_MODELVIEW_MATRIX, modelview);
        GL11.glGetDoublev(GL11.GL_PROJECTION_MATRIX, projection);
        GL11.glGetIntegerv(GL11.GL_VIEWPORT, viewport);

        GL11.glReadPixels(mouseX, mouseY, 1, 1, GL11.GL_DEPTH_COMPONENT, GL11.GL_DOUBLE, winZ);

        if (winZ.get(0) == 1) {
            return null;
        }

        glu.gluUnProject((double)mouseX, (double)mouseY, (double)winZ.get(0), modelview, projection, viewport, position);


        System.out.println(position.get(0)+" "+position.get(1)+" "+position.get(2)+" "+winZ.get(0));
   
        return position;
    }


Thanks for your reply man but it didn't give me the correct z positions. I had a simple sphere, and used a mouse click coordinates to run the getMousePosition method, however it only ever returned winZ as 0 (converting to a projection.get(2) of 0.5 for everything). Whereas i want to know the different z-values for different parts of the sphere.

@gouessej

Ive been trying to use openGL picking but have been getting depth-values of like 1578192816 and even after reading about glSelectBuffer I still don't know how to turn this into a z-coordinate. I know to divide by 2^31 but even then im not sure what it means.
Offline theagentd
« Reply #5 - Posted 2012-01-27 16:13:22 »

@Matt878
Like Gouessej pointed out the code I posted was for LWJGL but you're using JOGL which has the OpenGL functions organized a little differently. Since the OpenGL functions are in the GL variable you have to use it instead of the static GL11 of LWJGL. The code is a simple port to JOGL of the function I posted which simply names the GL object you have GL11 so that everything compiles without any changes. Again, sorry about that.

If you get weird depth values make sure what you're reading is correct. The correct use of this method would be something like this:
1  
2  
3  
4  
5  
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
drawAllObjects(gl);
DoubleBuffer pos = getMousePosition(mouseX, mouseY, gl);
doStuffWithThe3DMousePos(pos);
draw2DStuffLikeUI(gl);


Also make sure that depth testing and writing is working properly, that glClearDepth has a good value (should be 1.0 in 99% of all cases) and that your projection matrix is set up properly.

Myomyomyo.
Offline matt878

Junior Newbie





« Reply #6 - Posted 2012-01-27 16:31:53 »

Yea thats how I was using it but I would like to get the 3d coordinate of the object im picking, instead it seems to just give the 3d coordinates of my mouse.

I think i may just rely on manually casting a ray and seeing what it intersects (unforunately wont work for complex objects), though I thought there would be a simple way to do this.
Offline theagentd
« Reply #7 - Posted 2012-01-27 16:45:00 »

This method just gets the 3D coordinates of your mouse, which I explained in my first post...
The second way is "easier", but costs a lot of performance and doesn't tell you which object the ray is intersecting with, only where the ray intersected.
In the end I think what you really want is just plain picking, but I have no experience at all with. Try to read up on the links Gouessej posted.

It's possible to emulate picking by for example writing an object ID to the alpha channel of the screen buffer. Instead of reading back depth, you'd read back the alpha component instead and use that value to determine which object was clicked on. Using the alpha channel limits you to 255 different objects (0 would be reserved for no object), but this can be worked around if you really want by using a separate pass or using multiple render targets.

Myomyomyo.
Offline matt878

Junior Newbie





« Reply #8 - Posted 2012-01-27 16:50:55 »

Right, yea I just want picking, but I want to know the x,y,z coordinate of the intersection, Im not sure how to determine this given the depth-value returned by the GL_SELECTION method.
Offline gouessej
« Reply #9 - Posted 2012-01-30 12:02:18 »

Yea thats how I was using it but I would like to get the 3d coordinate of the object im picking, instead it seems to just give the 3d coordinates of my mouse.

I think i may just rely on manually casting a ray and seeing what it intersects (unforunately wont work for complex objects), though I thought there would be a simple way to do this.
You have forgotten to use gluUnProject:
http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml

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.

pw (14 views)
2014-07-24 01:59:36

Riven (14 views)
2014-07-23 21:16:32

Riven (13 views)
2014-07-23 21:07:15

Riven (15 views)
2014-07-23 20:56:16

ctomni231 (43 views)
2014-07-18 06:55:21

Zero Volt (40 views)
2014-07-17 23:47:54

danieldean (32 views)
2014-07-17 23:41:23

MustardPeter (36 views)
2014-07-16 23:30:00

Cero (50 views)
2014-07-16 00:42:17

Riven (50 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!