Picking Selection auf ein Objekt begrenzen !

Status
Nicht offen für weitere Antworten.

JavaKing

Mitglied
Hallo zusammen,

ich habe leider wieder ein Problem :

Code:
public void display(GLAutoDrawable drawable) {

        gl.glSelectBuffer(MAXSELECT, selectBuf); //Den Puffer zuordnen
        gl.glRenderMode(GL_SELECT);
        // clear name stack
        gl.glInitNames(); // Name-Stack initialisieren
        gl.glPushName(~0); // "Name" "0" auf diesen Stack gelegt wird. Nötig sonst Exception
        
        IntBuffer vp = IntBuffer.allocate(15);
        gl.glGetIntegerv(GL_VIEWPORT, vp); //Die Sicht speichern
        
        gl.glMatrixMode(GL.GL_PROJECTION); 
        gl.glPushMatrix(); //Um die Matrix zu sichern
        gl.glLoadIdentity(); //Und dieselbige wieder zurückzusetzen
        glu.gluPickMatrix(x_mouse, vp.get(3) - y_mouse,  5.0, 5.0, vp);
        glu.gluPerspective(100.0,((float)width)/((float)height),0.1, 100); 
        gl.glMatrixMode(GL.GL_MODELVIEW);  // now back to model view so that we
        drawScene(gl,true);
        
        int hits = gl.glRenderMode(GL_RENDER);
        System.out.println("hits: "+hits);
          if (hits>1) {
            gl.glEnable(GL_LIGHT1);
            int index = (hits-1)*4+3;
            if ((index<0) || (index>selectBuf.capacity())) {
            } else {
                selectedName = selectBuf.get((hits-1)*4+3);
                if (selectedName==1) {
                    wu1 = true;
                    System.out.println("Name getroffen: "+selectedName+" ! ");
                }
                if (selectedName==2) {
                    wu2 = true;
                    System.out.print("Name getroffen: "+selectedName+" ! ");
                } 
                if (selectedName==3) {
                    wu3 = true;
                    System.out.print("Name getroffen: "+selectedName+" ! ");
                } 
              
            }
        }
        select = false; 
        gl.glMatrixMode(GL_PROJECTION);
        gl.glPopMatrix();  // vorherige Projektionsmatrix vom Stack laden
        gl.glMatrixMode(GL_MODELVIEW);       // now back to model view so that we
}

Code:
  public void mousePressed(MouseEvent e) {
        x_mouse = e.getX();
        y_mouse = e.getY();
        //if(m!=null && !m.getWait()) 
        select = true;

       if ((e.getModifiers() & e.BUTTON1_MASK) != 0) {
             select = true;
       }
       if ((e.getModifiers() & e.BUTTON3_MASK) != 0) {
             menu.show(gui,x_mouse,y_mouse);
       }
    }

Code:
    private void drawScene(GL gl, boolean select)
    { 
        gl.glPushMatrix();
        gl.glTranslated(0,-6.48,-5);
        if (select)
            gl.glLoadName(1);
        StartRotation(gl,gewuerfelt1);
        gl.glPopMatrix();
        gl.glPushMatrix();
             if(wu1){
                gl.glTranslatef(-0.6f, 0.0f,0.15f);
                 paintRotated(gl,gewuerfelt1);
            }
        gl.glPopMatrix(); 
        
        gl.glPushMatrix();
        gl.glTranslated(1,-6.48,-6);
            if (select)
                gl.glLoadName(2);
        StartRotation(gl,gewuerfelt2);
        gl.glPopMatrix();
        gl.glPushMatrix();
            if(wu2){
               gl.glTranslatef(-5.6f, 0.0f,0.15f);
               paintRotated(gl,gewuerfelt2);
            }
        gl.glPopMatrix(); 

}

Warum wird beim Mausklick nun egal WO ich hinklicke immer die paintRotated(gl,gewuerfelt1); ausgeführt ?? Also gl.glLoadName(1); ??
Er sagt mir immer Hits=2, das ist ja soweit klar, leider weiß ich nicht wie ich den Bereich eingrenzen kann. Den er soll das nur ausführen wenn Würfel1 geklickt wird.
 

Marco13

Top Contributor
Hab unter JOGL noch nichts mit Picking gemacht (nur mal ein bißchen, unter "normalem" OpenGL). Grob für den Überblick:
Code:
int index = (hits-1)*4+3;
            if ((index<0) || (index>selectBuf.capacity())) {
            } else {
                selectedName = selectBuf.get((hits-1)*4+3);
                if (selectedName==1) {
                    wu1 = true;
                    System.out.println("Name getroffen: "+selectedName+" ! ");

Was wird dort ausgegeben ... und was bedeutet das magische (hits-1)*4+3 !?!
 

JavaKing

Mitglied
Marco13 hat gesagt.:
Hab unter JOGL noch nichts mit Picking gemacht (nur mal ein bißchen, unter "normalem" OpenGL). Grob für den Überblick:
Code:
int index = (hits-1)*4+3;
            if ((index<0) || (index>selectBuf.capacity())) {
            } else {
                selectedName = selectBuf.get((hits-1)*4+3);
                if (selectedName==1) {
                    wu1 = true;
                    System.out.println("Name getroffen: "+selectedName+" ! ");

Was wird dort ausgegeben ... und was bedeutet das magische (hits-1)*4+3 !?!

Ausgegeben wird :
hits: 3
Name getroffen: 2 !


Zur Erläuterung des "magischen " :

http://wiki.delphigl.com/index.php/Tutorial_Selection

Um nun nur das Objekt herauszubekommen, welches der Kamera am nächsten lag, ließt man nun in einer Schleife alle Z-Werte "Puffer[(i*4)+1]" der getroffenen Objekte aus und vergleicht sie mit dem bislang niedrigsten Wert. Ist der ausgelesene Wert niedriger, als der bislang kleinste, dann wird der neue Z-Wert gespeichert und der Name des bislang nächsten Objektes wird gespeichert.
Ist die Schleife durchgelaufen, dann steht am Ende also in der Variable "getroffen" der Integer-Name des nächsten, getroffenen Objektes, welches wir dann auch als Rückgabewert der Funktion verwenden.



Soweit die Theorie *g*
 

Marco13

Top Contributor
Also gibt er bei "Name getroffen" doch das aus, was angeklickt wurde (d.h. die Nummer des Würfels)? Dann könnte man sich doch irgendwo merken, dass NUR der mit Index 1 ausgewählt werden können soll!? ???:L
 

JavaKing

Mitglied
Also gibt er bei "Name getroffen" doch das aus

Wie oben angegeben im Source Code. Ist mein Würfel 2 auch "Name 2". Mein Problem ist aber egal wo ich in die szene hinklicke ob auf würfel 1 oder würfel 2 oder sonst wohin was man sieht. Er gibt immer "Name 2" zurück !!
z.b. auch niemals Name 1.

Entweder ich speicher die Szene falsch ab :
Code:
gl.glGetIntegerv(GL_VIEWPORT, vp); //Die Sicht speichern

oder das klappt nicht wie gewünscht.

Code:
        gl.glPushMatrix();
        gl.glTranslated(0,-6.48,-5);
[b]        if (select)
            gl.glLoadName(1);[/b]
        StartRotation(gl,gewuerfelt1);
        gl.glPopMatrix();
        gl.glPushMatrix();
             if(wu1){
                gl.glTranslatef(-0.6f, 0.0f,0.15f);
                 paintRotated(gl,gewuerfelt1);
            }
        gl.glPopMatrix();
 

Marco13

Top Contributor
Sorry, da müßt' ich mir selbst den Picking-Kram nochmal (an einem KSKB) ansehen, da werd' ich aber die nächsten Wochen kaum dazu kommen.... Im Moment kapier ich nichtmal warum er da "hits 3" ausgeben soll, aber dann nur EINE Zeile mit "Name getroffen" ...... Es müßten ja mehrerer Objekt-Infos im "Puffer" liegen (und du betrachtest immer nur die letzte, mit "hits-1")
 

Fancy

Aktives Mitglied
Moin,

also auf Anhieb sehe ich leider auch nicht warum sich der obige code nicht wie erwartet verhält. Aber beim drüber sehen ist mir folgendes aufgefallen:

1. wu* wird immer nur auf true gesetzt, wird dies auch "sinnvoll" wieder zurückgesetzt?
2. Du hast eine Objektvariable "select", diese wird gesetzt, aber nie gelesen.
3. Obwohl Du mehrere hits hast, betrachtest Du immer nur den letzten.
4. hat gluPerspective die selben Parameter wie im normal render mode?
5. Du benutzt so häufig glPushMatrix() / glPopMatrix() dann könntest Du auch äquivalent glPushName() / glPopName() nutzen.
6. Was macht die Methode "StartRotation()" zeichnet diese?
Falls nein: Warum wird ein glTranslate drauf angewendet?
Falls ja: Dir ist bewusst das glLoadName gültig bleibt, bis zur nächsten Änderung des NameStack?

Wahrscheinlich nützt Dir dies jedoch alles nichts, da hits maximal Eins sein sollte (bei Dir) und keiner der oben angesprochenen Punkte führt unmittelbar dazu das zu viele hits gefunden werden.

Aber als Hintergrundinfo zur Analyse: Das Zusammenspiel von glRenderMode(GL_SELECT), gluPickMatrix() und gluPersective() dient einzig und alleine dazu die OpenGL Render Pipeline soweit einzugrenzen das nicht mehr die gesamte Szene gerendert wird, sondern nur noch ein (in Deinem Fall) 5x5 Pixel großes Rechteck um den letzten Mausklick herum. Alle Elemente die in diesem Rechteck sichtbar wären, bekommen dann einen Eintrag in Deinem "selectBuf".

So wie Du schreibst, sollte in diesem Rechteck nur ein Element sichtbar sein. OpenGL ist aber der Meinung es wären Drei. Dummerweise wird innerhalb des glRenderMode(GL_SELECT) nicht in den Framebuffer gerendert, so das nicht direkt sichtbar ist was OpenGL da "sieht". Wenn Du jedoch innerhalb Deiner display() das glRenderMode(GL_SELECT) auskommentierst, wird wieder in den Framebuffer gerendert (dann geht das Picking natürlich nicht mehr). Wenn Du dann noch Dein gluPickMatrix() auf 100x100 Pixel änderst, siehst Du nach einem Mausklick exakt den Bereich aufblitzen den OpenGL für das Picking heranzieht (und zwar in voller Fenstergröße). Und dann kannst Du versuchen herauszubekommen was OpenGL da "sieht" und warum es nicht das ist was Du glaubst.

Alternativ kannst Du auch einen Blick auf das folgende Beispiel werfen und versuchen ob Du einen Unterschied zwischen Deinem Code und diesem Beispiel findest. Evtl. findest Du dann ja auch Deinen Fehler.

Code:
package fancy.jf.pick;

import java.awt.Frame;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

import com.sun.opengl.util.Animator;
import com.sun.opengl.util.BufferUtil;

public class Pick implements GLEventListener, MouseListener {

    /*
     * quick and dirty inner named cube representation
     */
    private class Cube {

        private static final int animationFrames = 120;

        private final float[]    staticVertices  = new float[] {
            1.0f,  1.0f,  1.0f,  -1.0f,  1.0f,  1.0f,  -1.0f, -1.0f,  1.0f,   1.0f, -1.0f,  1.0f,
            1.0f, -1.0f, -1.0f,  -1.0f, -1.0f, -1.0f,  -1.0f,  1.0f, -1.0f,   1.0f,  1.0f, -1.0f};
        
        private final int[]      staticIndices   = new int[] {
            0, 1, 2, 3,  4, 5, 6, 7,  7, 6, 1, 0,  3, 2, 5, 4,  1, 6, 5, 2,  7, 0, 3, 4};
        
        
        private GL               gl              = null;

        private FloatBuffer      vaVertices      = null;
        private IntBuffer        vaIndices       = null;
        private int              angleRotate     = 0;
        private int              name            = 0;


        private Cube(GL gl, int name) {

            this.gl = gl;
            this.name = name;

            // prepare vertex array
            vaVertices = BufferUtil.newFloatBuffer(staticVertices.length);
            vaVertices.put(staticVertices, 0, staticVertices.length);
            vaVertices.rewind();

            vaIndices = BufferUtil.newIntBuffer(staticIndices.length);
            vaIndices.put(staticIndices, 0, staticIndices.length);
            vaIndices.rewind();
        }
        
        
        private void start() {

            angleRotate = animationFrames;
        }


        private void render() {

            if (angleRotate > 0) angleRotate--;

            // draw named cube
            gl.glPushMatrix();
            gl.glPushName(name);
            gl.glColor3f(0.9f, 0.9f, 0.9f);
            gl.glTranslatef(name * 3.0f - Pick.quantityCube * 1.5f + 1.5f, 0.0f, 0.0f);
            gl.glRotatef(angleRotate, 1.0f, 1.0f, 1.0f);
            gl.glVertexPointer(3, GL.GL_FLOAT, 0, vaVertices);
            gl.glDrawElements(GL.GL_QUADS, staticIndices.length, GL.GL_UNSIGNED_INT, vaIndices);
            gl.glPopName();
            gl.glPopMatrix();
        }

    }
    

    
    private static final int quantityCube = 5;
    private Cube[]           cubes        = null;

    private GL               gl           = null;
    private GLU              glu          = null;
    private IntBuffer        viewport     = null;
    private IntBuffer        selection    = null;

    private int              mouseX       = -1;
    private int              mouseY       = -1;


    @Override
    public void init(GLAutoDrawable drawable) {

        gl = drawable.getGL();
        glu = new GLU();

        // for GL_SELECT render mode
        viewport = BufferUtil.newIntBuffer(4);
        selection = BufferUtil.newIntBuffer(64);

        // basic gl initialization
        gl.glShadeModel(GL.GL_SMOOTH);
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
        gl.glClearDepth(1.0f);
        gl.glEnable(GL.GL_DEPTH_TEST);
        gl.glDepthFunc(GL.GL_LEQUAL);
        gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
        gl.glEnableClientState(GL.GL_VERTEX_ARRAY);

        gl.glPolygonMode(GL.GL_BACK, GL.GL_LINE);
        gl.glPolygonMode(GL.GL_FRONT, GL.GL_LINE);

        cubes = new Cube[quantityCube];
        for (int i = 0; i < quantityCube; i++)
            cubes[i] = new Cube(gl, i);
    }


    @Override
    public void display(GLAutoDrawable drawable) {

        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();
        glu.gluLookAt(0, 0, 12, 0, 0, 0, 0, 1, 0);

        // additional selection render pass if necessary
        if (mouseX >= 0 || mouseY >= 0) {

            gl.glSelectBuffer(selection.capacity(), selection);
            gl.glRenderMode(GL.GL_SELECT);
            gl.glInitNames();

            // setup new selection render matrices
            gl.glMatrixMode(GL.GL_PROJECTION);
            gl.glPushMatrix();
            gl.glLoadIdentity();
            glu.gluPickMatrix(mouseX, mouseY, 8, 8, viewport);
            glu.gluPerspective(45.0f, (float) viewport.get(2) / (float) viewport.get(3), 1.0, 50.0);
            gl.glMatrixMode(GL.GL_MODELVIEW);

            // render cubes to selection buffer
            for (final Cube cube : cubes)
                cube.render();

            // back to normal render mode
            gl.glMatrixMode(GL.GL_PROJECTION);
            gl.glPopMatrix();
            gl.glMatrixMode(GL.GL_MODELVIEW);
            gl.glFlush();

            final int hits = gl.glRenderMode(GL.GL_RENDER);

            // handle hits
            for (int i = 0; i < hits; i++)
                cubes[selection.get(i * 4 + 3)].start();

            // no more selection render pass necessary
            mouseX = -1;
            mouseY = -1;
        }

        // always render to normal backbuffer
        for (final Cube cube : cubes)
            cube.render();
    }


    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {

        if (height <= 0) height = 1;

        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(45.0f, (float) width / (float) height, 1.0, 50.0);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

        // save viewport for selection render pass
        gl.glGetIntegerv(GL.GL_VIEWPORT, viewport);
    }

    
    @Override
    public void mousePressed(MouseEvent e) {
        
        mouseX = e.getX();
        mouseY = viewport.get(3) - e.getY();
    }

    
    @Override
    public void mouseClicked(MouseEvent e) {}


    @Override
    public void mouseEntered(MouseEvent e) {}


    @Override
    public void mouseExited(MouseEvent e) {}


    @Override
    public void mouseReleased(MouseEvent e) {}


    @Override
    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}


    public static void main(String[] args) {

        final Pick pick = new Pick();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);
        canvas.addGLEventListener(pick);
        canvas.addMouseListener(pick);
        frame.add(canvas);
        frame.setSize(1000, 500);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                new Thread(new Runnable() {
                    public void run() {
                        animator.stop();
                        System.exit(0);
                    }
                }).start();
            }
        });
        frame.setVisible(true);
        animator.start();
        canvas.requestFocusInWindow();
    }
}

Gruß,
Michael
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
C LWJGL Color Picking Textures deaktivieren Spiele- und Multimedia-Programmierung 0
R LWJGL: 3D Picking Spiele- und Multimedia-Programmierung 4
J LWJGL 3D Picking Identifizierung Spiele- und Multimedia-Programmierung 11
C Frage zu Ray-Picking mit JOGL Spiele- und Multimedia-Programmierung 13
M Java3D Picking - falsche Objekte werden gepickt Spiele- und Multimedia-Programmierung 3
truesoul Picking und Farbe ändern Spiele- und Multimedia-Programmierung 3
B Picking + Translation Spiele- und Multimedia-Programmierung 6
Quaxli Picking: Vom Shape3D zum eigentlichen Objekt Spiele- und Multimedia-Programmierung 2
F Fehlermeldung(Picking)Shape3D: nocapability to get geometrie Spiele- und Multimedia-Programmierung 7
I Beim Picking werden alle Behaviors angesprochen Spiele- und Multimedia-Programmierung 4
S JOGL Selection By Color Spiele- und Multimedia-Programmierung 3
pcfreak9000 Objekt-Vorlagen Spiele- und Multimedia-Programmierung 0
Arif Maus-Objekt im Player Klasse implementieren !? Spiele- und Multimedia-Programmierung 2
H Objekt der Klasse A in der Klasse B verwenden und manipulieren Spiele- und Multimedia-Programmierung 6
M [JOGL] Maus über einem gezeichnetem Objekt abfragen? Spiele- und Multimedia-Programmierung 5
U Kann nur ein Objekt mit LWJGL rendern Spiele- und Multimedia-Programmierung 2
kaoZ Graphics Objekt liefert null Spiele- und Multimedia-Programmierung 14
E Java3D Objekt skalieren per JSlider/JButton Spiele- und Multimedia-Programmierung 10
D Probleme mit objekt initializirung mit Mouselistener Spiele- und Multimedia-Programmierung 10
S Java3D: Primitives zu einem Objekt kombinieren Spiele- und Multimedia-Programmierung 7
T LWJGL 3D Objekt Collision: Wie? Spiele- und Multimedia-Programmierung 11
S Wie erkennt ein Objekt ein anderes? Spiele- und Multimedia-Programmierung 7
B j3d mehr als ein Objekt rotieren Spiele- und Multimedia-Programmierung 18
G Hindernis vor Objekt erkennen Spiele- und Multimedia-Programmierung 6
W Java3D: Kanten die hinter einem Objekt liegen werden gezeigt Spiele- und Multimedia-Programmierung 2
S Graphics Objekt weiterreichen? Spiele- und Multimedia-Programmierung 4
H Eigenes 3D Objekt Spiele- und Multimedia-Programmierung 20
D 2D Objekt fragmentieren Spiele- und Multimedia-Programmierung 3
V Jogl: Objekt trotz Rotation immer in gleiche Richtung bewegen Spiele- und Multimedia-Programmierung 5
M [J3D]Dynamische Erzeugung vom Objekt Box Spiele- und Multimedia-Programmierung 5
Kr0e OpenGL .. Pixel Buffer Objekt oder Frame Buffer Object? Spiele- und Multimedia-Programmierung 2
B String zu Objekt einer eigenen Klasse casten Spiele- und Multimedia-Programmierung 13
N Objekt entgegengesetzt bewegen Spiele- und Multimedia-Programmierung 8
M BoundingBox ist nicht bündig am Objekt Spiele- und Multimedia-Programmierung 5
K Kanten anzeigen lassen in einem Shape3D-Objekt Spiele- und Multimedia-Programmierung 4
S geladenes Objekt -> Material Zuweisen. Spiele- und Multimedia-Programmierung 4
C Objekt bei Buttonklick zeichnen Spiele- und Multimedia-Programmierung 16
G JOGL: per Mausbewegung Objekt verschieben Spiele- und Multimedia-Programmierung 2
C Objekt zwischen 2 Geraden? Spiele- und Multimedia-Programmierung 3
D 3D Objekt entlang Geraden Spiele- und Multimedia-Programmierung 4
G Objekt nicht ins negative oder null skalieren Spiele- und Multimedia-Programmierung 2
G Objekt verschieben Spiele- und Multimedia-Programmierung 6
G Textur laden auf ein eingelesenes 3D Objekt Spiele- und Multimedia-Programmierung 4
I ScaleInterpolator verschiebt Objekt immer in den Ursprung. Spiele- und Multimedia-Programmierung 2
V Objekt per Tastendruck anzeigen/verschwinden lassen? Spiele- und Multimedia-Programmierung 4
R Objekt mit cos/sin verschieben Spiele- und Multimedia-Programmierung 27
G Kein Licht in Box-Objekt Spiele- und Multimedia-Programmierung 2
K Ein 3D-Objekt mit Maus auswählen Spiele- und Multimedia-Programmierung 5
D Alpha Objekt Spiele- und Multimedia-Programmierung 8
H Kompliziertes 3D-Objekt Spiele- und Multimedia-Programmierung 16
G Einen gif oder jpg Datei aus einem Graphics Objekt o. JFrame Spiele- und Multimedia-Programmierung 2
C Wie kann ich ein Objekt auf Tastendruck vor & zurück bew Spiele- und Multimedia-Programmierung 3
M Position der ViewingPlatform als Point3d-Objekt? Spiele- und Multimedia-Programmierung 12
S 3D Objekt erstellen und darstellen Spiele- und Multimedia-Programmierung 4
G RotationInterp. setzt Objekt an Ursprungsposition zurück Spiele- und Multimedia-Programmierung 2
N Shape3D Objekt auf dem Bildschirm zentrieren Spiele- und Multimedia-Programmierung 2

Ähnliche Java Themen

Neue Themen


Oben