Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (552)
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 Problem  (Read 1702 times)
0 Members and 1 Guest are viewing this topic.
Offline Grand Poeba

Junior Member





« Posted 2011-12-09 09:51:05 »

Hello, I was digging into picking the other day when I found an example about picking using 4 snowmen.

The tutorial was written in C++ so I converted it to JOGL 2.0 code but I ran into some trouble.

When I click 3 out of 4 snowmen I get 2 hits, instead of 1. How ever the eventual number of the snowman clicked
then matches (1 to 3). When i click the first snowman (bottom left), I get only 1 hit, like it is supposed to be i think but
I still get the result that I clicked snowmen nr 1 (instead of 0). I attached code here. Does any1 have any idea what i do wrong?
Also every time i click on my screen, it blinks black for a second. Is this normal and is there any way to avoid this?

Thx

The JFRame class and other GUI stuff
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  
package snowmanpicking;

import com.jogamp.opengl.util.FPSAnimator;

import java.awt.Dimension;
import java.awt.event.*;

import javax.media.opengl.*;
import javax.media.opengl.awt.GLJPanel;

import javax.swing.*;

/**
 *
 * @author Grand Poeba
 */

public class SnowmanFrame extends JFrame {
    private GLJPanel gljPanel;
   
    public SnowmanFrame(){
        this.initGUI();
    }
   
    private void initGUI(){
        // Choose the GL profile
       GLProfile glp = GLProfile.getMaxFixedFunc();
        // Configure the GL capabilities
       GLCapabilities caps = new GLCapabilities(glp);
       
        this.gljPanel = new GLJPanel(caps);
        final Render r = new Render();
        this.gljPanel.addGLEventListener(r);
       
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() != MouseEvent.BUTTON1) return;

                r.cursorX = e.getX();
                r.cursorY = e.getY();
                r.mode = GL2.GL_SELECT;
                System.out.println("Swapped mode to GL_SELECT");
            }
       
        });
        this.getContentPane().add(this.gljPanel);        
       
        this.setMinimumSize(new Dimension(800,600));  
       
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
   
    public GLJPanel getGLJPanel() {
        return this.gljPanel;
    }

    public static void main (String[] args){
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                SnowmanFrame sf = new SnowmanFrame();
                FPSAnimator animator = new FPSAnimator(sf.getGLJPanel(), 60);
                animator.add(sf.getGLJPanel());
                animator.start();
            }
        });
    }
}


The actual renderer with picking code
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  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
223  
224  
225  
226  
227  
228  
229  
230  
231  
232  
package snowmanpicking;

import com.jogamp.common.nio.Buffers;

import com.jogamp.opengl.util.gl2.GLUT;

import java.nio.IntBuffer;

import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;

/**
 *
 * @author Grand Poeba
 */

public class Render implements GLEventListener {

    public static int cursorX, cursorY;
    private float posX, posY, posZ, lookAtX, lookAtY, lookAtZ;
    public static int mode, hits;
   
    // Picking Stuff //
   int BUFSIZE = 1024;
    IntBuffer selectBuf = Buffers.newDirectIntBuffer(BUFSIZE);
    // display list of our snowman
   public static int snowman_display_list;

    void processKeyboard(char key, int x, int y) {
        System.out.printf("key: %d\n", key);
    }

    void picked(int name, int sw) {
        System.out.printf("my name = %d in %d\n", name, sw);
    }

    void drawSnowMan(GL2 gl, GLUT glut) {
        gl.glColor3f(1.0f, 1.0f, 1.0f);

// Draw Body  
       gl.glTranslatef(0.0f, 0.75f, 0.0f);
        glut.glutSolidSphere(0.75f, 20, 20);


// Draw Head
       gl.glTranslatef(0.0f, 1.0f, 0.0f);
        glut.glutSolidSphere(0.25f, 20, 20);

// Draw Eyes
       gl.glPushMatrix();
        gl.glColor3f(0.0f, 0.0f, 0.0f);
        gl.glTranslatef(0.05f, 0.10f, 0.18f);
        glut.glutSolidSphere(0.05f, 10, 10);
        gl.glTranslatef(-0.1f, 0.0f, 0.0f);
        glut.glutSolidSphere(0.05f, 10, 10);
        gl.glPopMatrix();

// Draw Nose
       gl.glColor3f(1.0f, 0.5f, 0.5f);
        gl.glRotatef(0.0f, 1.0f, 0.0f, 0.0f);
        glut.glutSolidCone(0.08f, 0.5f, 10, 2);
    }

    int createDL(GL2 gl) {
        int snowManDL;

        // Create the id for the list
       snowManDL = gl.glGenLists(1);

        gl.glNewList(snowManDL, GL2.GL_COMPILE);
        drawSnowMan(gl, new GLUT());
        gl.glEndList();

        return (snowManDL);
    }

    void draw(GL2 gl) {
        // Draw ground
       gl.glColor3f(0.9f, 0.9f, 0.9f);
        gl.glBegin(GL2.GL_QUADS);
        gl.glVertex3f(-100.0f, 0.0f, -100.0f);
        gl.glVertex3f(-100.0f, 0.0f, 100.0f);
        gl.glVertex3f(100.0f, 0.0f, 100.0f);
        gl.glVertex3f(100.0f, 0.0f, -100.0f);
        gl.glEnd();

        // Draw 4 SnowMen
       
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                gl.glPushMatrix();
                gl.glPushName(i * 2 + j);
                gl.glTranslated(i * 3.0, 0, -j * 3.0);
                gl.glCallList(snowman_display_list);
                gl.glPopName();
                gl.glPopMatrix();
            }
        }
    }

    @Override
    public void dispose(GLAutoDrawable drawable) {
    }

    @Override
    public void display(GLAutoDrawable drawable) {
        final GL2 gl = drawable.getGL().getGL2();

        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

        if (mode == GL2.GL_SELECT) startPicking(gl);

        gl.glLoadIdentity();

        GLU glu = new GLU();
        glu.gluLookAt(posX, posY, posZ, lookAtX, lookAtY, lookAtZ, 0.0f, 1.0f, 0.0f);

        draw(gl);

        if (mode == GL2.GL_SELECT) stopPicking(gl);
    }

    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        final GL2 gl = drawable.getGL().getGL2();
        GLU glu = new GLU();

        float ratio;
        // Prevent a divide by zero, when window is too short
       // (you cant make a window of zero width).

        if (height == 0) height = 1;
       
        ratio = 1.0f * width / height;
        // Reset the coordinate system before modifying
       gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();

        // Set the viewport to be the entire window
       gl.glViewport(0, 0, width, height);

        // Set the clipping volume
       glu.gluPerspective(45, ratio, 0.1, 1000);

        // setting the camera now
       gl.glMatrixMode(GL2.GL_MODELVIEW);
    }

    @Override
    public void init(GLAutoDrawable drawable) {
        final GL2 gl = drawable.getGL().getGL2();

        posX = 1.5f;
        posY = 3.75f;
        posZ = 3f;

        lookAtX = 1.5f;
        lookAtY = 1.75f;
        lookAtZ = 0f;

        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glEnable(GL2.GL_CULL_FACE);

        snowman_display_list = createDL(gl);
       
        // enable vsync
       gl.setSwapInterval(1);    
    }

    void startPicking(GL2 gl) {
        System.out.println("Start Picking");
        IntBuffer viewport = Buffers.newDirectIntBuffer(4);
        float ratio;

        gl.glSelectBuffer(BUFSIZE, selectBuf);

        gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport);

        gl.glRenderMode(GL2.GL_SELECT);

        gl.glInitNames();

        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glPushMatrix();
        gl.glLoadIdentity();

        GLU glu = new GLU();
        glu.gluPickMatrix(cursorX, viewport.get(3) - cursorY, 5, 5, viewport);

        ratio = (float) (viewport.get(2) + 0.0f) / (float) viewport.get(3);
        glu.gluPerspective(45, ratio, 0.1, 1000);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
    }

    void stopPicking(GL2 gl) {
        System.out.println("Stop Picking");

        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glPopMatrix();
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glFlush();

        hits = gl.glRenderMode(GL2.GL_RENDER);

        if (hits > 0) {
            System.out.println("# of hits: " + hits);
            processHits(hits, selectBuf);
        } else {
            System.out.println("no hits");
        }
        mode = GL2.GL_RENDER;
    }

    void processHits(int hits, IntBuffer buffer) {        
        int name = -1;
        int i = 0, nrOfHits = 0;
        while(nrOfHits < hits && i < BUFSIZE) {
            if(buffer.get(i) > 0){
                name = buffer.get(i);
                nrOfHits++;
            }
            i++;
        }
       
        if (name < 0) {
            System.out.printf("You didn't click a snowman!");
        } else {
            System.out.printf("You picked snowman  ");
            System.out.printf("%d ",  name);
        }
        System.out.printf("\n");
    }
}
Offline gouessej
« Reply #1 - Posted 2011-12-09 14:11:22 »

Hi

I had the same problem last years, you forgot something when converting unsigned integers obtained for OpenGL into signed integers, I fixed this in an official example, I'm going to find it...

Edit.: http://jogamp.org/jogl-demos/src/demos/misc/Picking.java

Edit2.: I explained my problem here:
http://forum.jogamp.org/bad-use-of-depths-in-Picking-java-td1446213.html
It is a very common pitfall, many programmers did the same mistake when porting OpenGL code from C++ to Java, I even found this mistake in an example using the competitor of JOGL.

Edit3.: Some things are completely wrong in your source code in processHits. You do like there were only names whereas an hit contains depths too. Please look at the documentation of glSelectBuffer():
http://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml
Quote
The hit record consists of the number of names in the name stack at the
            time of the event, followed by the minimum and maximum depth values
            of all vertices that hit since the previous event,
            followed by the name stack contents,
            bottom name first.
       

Offline Grand Poeba

Junior Member





« Reply #2 - Posted 2011-12-13 10:05:55 »

Thank you for the solution but I still get a black flicker when I click my snowman, is that normal?
Also why do I keep getting 2 hits? I only hit one snowman so I should only get 1 hit i think no?

Also another question, If i use a lot of models (self made with vertexes and textures) should I use displaylists
or go for VBO's?

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

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #3 - Posted 2011-12-13 10:37:35 »

Potentially silly question - why do you need OpenGL picking? It's slow, dated and IMHO redundant. Graphics apis should not be used for application login. Just code up some proper ray collision detection and properly separate your rendering from your logic.

If you don't want to code your own ray collision detection yourself then the various game engines (Ardor3d, JME) have it built in.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline theagentd
« Reply #4 - Posted 2011-12-13 10:58:13 »

Potentially silly question - why do you need OpenGL picking? It's slow, dated and IMHO redundant. Graphics apis should not be used for application login. Just code up some proper ray collision detection and properly separate your rendering from your logic.

If you don't want to code your own ray collision detection yourself then the various game engines (Ardor3d, JME) have it built in.
In my experience it is usually better, and in all cases more efficient, to do the ray-tracing on the CPU instead of reading back data in any way from the GPU.

Myomyomyo.
Offline gouessej
« Reply #5 - Posted 2011-12-13 11:11:22 »

In my experience it is usually better, and in all cases more efficient, to do the ray-tracing on the CPU instead of reading back data in any way from the GPU.
I used OpenGL picking for years and it is so easy to break... Some drivers even on modern machines have a very poor implementation of this feature, using it causes a huge decrease of the frame rate even on simple scenes. I agree with Orangy Tang, we should not use OpenGL picking and several scenegraphs do it nicely.

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.

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

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

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

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

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

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

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

BurntPizza (41 views)
2014-08-09 21:09:32

BurntPizza (31 views)
2014-08-08 02:01:56

Norakomi (41 views)
2014-08-06 19:49:38
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!