# Würfel Augenzahl richtig anzeigen



## JavaKing (28. Aug 2008)

Hallo zusammen,

ich bastel gerade an einem Würfel mit dem man ganz normal wie beim Mensch Ärger dich nicht würfeln kann.

Würfel:

```
spiel_wuerfel1 = gl.glGenLists(1);
        gl.glNewList(spiel_wuerfel1, GL_COMPILE); 
        gl.glPushMatrix();
        gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, FloatBuffer.wrap(new float[] { 0, 0, 0}));
        gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, FloatBuffer.wrap(new float[] { 0.0f, 0.0f, 0.0f}));
        gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, FloatBuffer.wrap(new float[] { 1.0f, 1.0f, 1.0f}));
        gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, 10);   
            
        gl.glScaled(0.5f, 0.5f, 0.5f);
        gl.glColor4d(1,1,1,1);    
        glut.glutSolidCube(2);
        
        gl.glMaterialfv(GL_FRONT, GL_AMBIENT, FloatBuffer.wrap(new float[] { 1, 1, 1}));
        gl.glMaterialfv(GL_FRONT, GL_DIFFUSE, FloatBuffer.wrap(new float[] { 0.6f, 0.6f, 0.6f}));
        gl.glMaterialfv(GL_FRONT, GL_SPECULAR, FloatBuffer.wrap(new float[] { 0.1f, 0.1f, 0.1f}));
        gl.glMaterialf(GL_FRONT, GL_SHININESS, 50);
        
        //1
        gl.glPushMatrix();
        gl.glTranslated(0, 0, 0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        //6
        gl.glPushMatrix();
        gl.glTranslated(0.5f, 0, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glTranslated(-0.5f, 0, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glTranslated(0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glTranslated(-0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glTranslated(0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glTranslated(-0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        //2
        gl.glPushMatrix();
        gl.glRotated(-90, 0, 1, 0);
        gl.glTranslated(-0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(-90, 0, 1, 0);
        gl.glTranslated(0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        //4        
        gl.glPushMatrix();
        gl.glRotated(90, 0, 1, 0);
        gl.glTranslated(-0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
       
        gl.glPushMatrix();
        gl.glRotated(90, 0, 1, 0);
        gl.glTranslated(-0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(90, 0, 1, 0);
        gl.glTranslated(0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(90, 0, 1, 0);
        gl.glTranslated(0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(90, 0, 1, 0);
        gl.glTranslated(0, 0, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        //4      
        gl.glPushMatrix();
        gl.glRotated(-90, 1, 0, 0);
        gl.glTranslated(-0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
       
        gl.glPushMatrix();
        gl.glRotated(-90, 1, 0, 0);
        gl.glTranslated(-0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(-90, 1,0, 0);
        gl.glTranslated(0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(-90, 1, 0, 0);
        gl.glTranslated(0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        //3
        gl.glPushMatrix();
        gl.glRotated(90, 1,0 , 0);
        gl.glTranslated(-0.5f, 0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(90, 1, 0, 0);
        gl.glTranslated(0.5f, -0.5, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        
        gl.glPushMatrix();
        gl.glRotated(90, 1, 0, 0);
        gl.glTranslated(0, 0, -0.9f);
        gl.glColor4d(0,0,0,0);
        glut.glutSolidSphere(0.2, 10, 10);
        gl.glPopMatrix();
        gl.glPopMatrix();
        gl.glEndList();
```

Würfelroutine:

```
public void wuerfeln(){
        for(int i=Math.round((float)Math.random()*14+1); i>0; i--) gewuerfelt=Math.round((float)Math.random()*5+1);
        System.out.println("Gewürfelt: "+gewuerfelt);
    }
```

Wie bekomme ich jetzt gewuerfelt und die Ansicht des echten Würfels zusammen ? Hat hier jmd. vll. noch Codestücke rumliegen? Oder gehe ich die Sache vollkommen falsch an ?


----------



## Marco13 (28. Aug 2008)

Wenn ich das jetzt richtig verstanden habe, musst du den Würfel so drehen, dass die gegebene Zahl oben liegt. Wenn man davon ausgeht, dass im Moment die 1 oben, die 2 rechts und die 3 vorne ist, könnte man grob sowas machen wie

```
void paintRotated(int gewürfelt)
{
    glPushMatrix();
    switch (gewürfelt)
    {
        case 1: /* nix zu tun */ break;

        case 2: 
            glRotatef( 90 grad um z-Achse );
            break;

        case 3: 
            glRotatef( 90 grad um x-Achse );
            break;
 ...
        case 6: 
            glRotatef( 180 grad um x-Achse );
            break;
    }
    maleWürfel();
    glPopMatrix();
}
```


----------



## JavaKing (28. Aug 2008)

```
Wenn ich das jetzt richtig verstanden habe, musst du den Würfel so drehen, dass die gegebene Zahl oben liegt.
```
Genau richtig.

Ich habe wohl vergessen zu erwähnen, das ich den Würfel mit Rotatef, ganz schnell um die x und y Achse drehen lassen wollte damit es so aussieht als wenn man würfelt. Und bei tastendruck, tataaaa auf der richtigen Seite oben liegen bleibt. Und beim Tastendruck weiß ich ja nicht wie der Würfel gerade steht.

Vielleicht ist das aber auch eine ganz blöde Idee und man löst das mit einer schönen Animation. Also wenn die Würfel wirklich auf den Tisch aufschlagen und dann liegen bleiben. Hat das schon wer umgesetzt zufällig ? *liebguck*


----------



## Marco13 (28. Aug 2008)

Ach, weiß doch keiner was da rauskommen soll. Man könnte sich eine Animation per Hand basteln, die dann abspeichern und abspielen, oder eine Rigid-Body-Simulation mit Kollisionserkennung und allem PiPaPo schreiben, um toll fallende Würfel zu haben.... Aber ... wenn die Würfel sich einfach irgendwie drehen, und dann irgendwann stehenbleiben sollen, wäre das vmtl. nicht so aufwändig - anhand der Werte, die man bei glRotate übergibt, kennt man ja immer alle Winkel. Und sobald die Taste gedrückt ist, animiert man die Winkel passend auf 0, 90 oder 180 Grad...


----------



## JavaKing (3. Sep 2008)

Hallo zusammen,

ich habe nun meine Würfel zusammen ;-) Rotieren etc. geht auch schon alles. Es sieht aber ziemlich "billig" aus.
Ich würde gerne eine kleine Animation von fallenden Würfeln einbauen. Wie könnte man das einbauen bzw. wie könnte so ein Aufruf aussehen ?

Mit nacheinander folgenden Translate und Rotate könnte man ja den Ablauf festlegen. In der Methode drawScene kann ich aber nicht den Aufruf starten, da dies ja ständig wiederholt wird. Das ganz sollte ja nach Tastendruck einmalig ablaufen bis zum nächsten Tastendruck.


----------



## Marco13 (3. Sep 2008)

Ja, wie auch immer du es machst: Wenn keine Physiksimulation oder auf Basis einer Physiksimulation erstellte Animation dahinter ist, wird es nie realistisch aussehen. Grundsätzlich gibt es zwei Möglichkeiten: Mit Keyframes, oder "funktional". Letzteres könnte man mit einem http://java.sun.com/javase/technolo...J3D_1_3_API/j3dapi/javax/media/j3d/Alpha.html machen. Das liefert zeitabhängig einen Wert zwischen 0 und 1, und den kann man (z.B. für einen Fallenden Gegenstand) dann in eine Position umrechnen. Die Alternative wären Keyframes, wobei man z.B. 3 "Situationen" (bestehend aus Winkeln und Positionen) hat, und zeitabhängig zwischen denen interpoliert - ggf. auch mit einem Alpha. Schau vielleicht auch mal hier http://www.developer.com/java/data/article.php/3706721


----------



## Fancy (3. Sep 2008)

Moin,

wie Marco schon schrieb, ohne Physik wird es nie wie ein natürlich fallender Würfel aussehen. 

Zwar ist das hier wahrscheinlich physikalisch nicht so schwer wie es zu erwarten wäre (fallender Würfel auf ebener Fläche, Masse des Würfels 1, Masse der Fläche unendlich, Einschlag eines Vertices löst lediglich eine Spiegelung des jeweiligen Geschwindigkeitsvektors um die Normale der Fläche aus, usw. – da sollten die meisten Terme zusammenfallen). Aber im Verhältnis zum Rest Deines Programms...

Alternativ könntest Du natürlich auch eine Physik Bibliothek einbinden, aber auch da: Kanonen auf Spatzen.

Mein Vorschlag, mach lieber irgendeine "Animation" mit Deinem Würfel.  Grundsätzlich kannst Du eine Animation als kontinuierliche Abfolge von Verschiebung und Rotation auf einzelne Objekte ansehen. Dann brauchst Du nur die nötigen Parameter als Objektvariablen anlegen, bei jedem Aufruf Deiner drawScene() kontinuierlich zu erhöhen / verringern / was auch immer und anschließend mit glRotate / glTranslate auf deine ModelView anwenden.

Als Beispiel, in ganz billig:
(keine Physik, nur Rotation, "Animation" läuft nach Testendruck genau 10 Sekunden und der Würfel bleibt immer gerade zur Kamera liegen)   


```
package fancy.jf.key;

import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Random;

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 Rotate implements GLEventListener, KeyListener {
    

    private static 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 static 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 GLU                  glu               = null;

    private FloatBuffer          vaVertices        = null;
    private IntBuffer            vaIndices         = null;

    
    // animation variables
    private static final double  animationTime     = 10000;

    private double               animationStopTime = 0;

    private float                rotateSpeedX      = 0;
    private float                rotateSpeedY      = 0;
    private float                rotateSpeedZ      = 0;

    private float                rotateAngleX      = 0;
    private float                rotateAngleY      = 0;
    private float                rotateAngleZ      = 0;


    @Override
    public void init(GLAutoDrawable drawable) {

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

        // vertex array for cube
        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();

        // 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);
    }


    @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);

        final double time = System.currentTimeMillis();

        // calculate new rotation values 
        if (animationStopTime > time) {

            final double downspeed = (animationStopTime - time) / animationTime;

            rotateAngleX += rotateSpeedX * downspeed;
            rotateAngleY += rotateSpeedY * downspeed;
            rotateAngleZ += rotateSpeedZ * downspeed;

            final double upspeed = Math.pow((1 - ((animationStopTime - time) / animationTime)), 8);
            
            rotateAngleX -= (rotateAngleX % 90) * upspeed;
            rotateAngleY -= (rotateAngleY % 90) * upspeed;
            rotateAngleZ -= (rotateAngleZ % 90) * upspeed;
            
        }

        // set calculated rotation values
        gl.glRotatef(rotateAngleX, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(rotateAngleY, 0.0f, 1.0f, 0.0f);
        gl.glRotatef(rotateAngleZ, 0.0f, 0.0f, 1.0f);

        // draw cube
        gl.glColor3f(0.9f, 0.9f, 0.9f);
        gl.glVertexPointer(3, GL.GL_FLOAT, 0, vaVertices);
        gl.glDrawElements(GL.GL_QUADS, staticIndices.length, GL.GL_UNSIGNED_INT, vaIndices);
    }


    @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();
    }


    @Override
    public void keyPressed(KeyEvent arg0) {

        //setup for new "animation"
        final Random random = new Random();

        rotateSpeedX = (random.nextFloat() - 0.5f) * 10;
        rotateSpeedY = (random.nextFloat() - 0.5f) * 10;
        rotateSpeedZ = (random.nextFloat() - 0.5f) * 10;

        animationStopTime = System.currentTimeMillis() + animationTime;
    }


    @Override
    public void keyReleased(KeyEvent arg0) {}


    @Override
    public void keyTyped(KeyEvent arg0) {}


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


    public static void main(String[] args) {

        final Rotate main = new Rotate();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);
        canvas.addGLEventListener(main);
        canvas.addKeyListener(main);
        frame.add(canvas);
        frame.setSize(500, 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


----------



## JavaKing (5. Sep 2008)

> Alternativ könntest Du natürlich auch eine Physik Bibliothek einbinden, aber auch da: Kanonen auf Spatzen.



Ja natürlich, so etwas wollte ich jetzt nicht umsetzen. Es ist ja immernoch ein Einsteiger Projekt ;-)
Dein Beispiel gefällt mir sehr gut, auch wenn es kein "fallen" des Würfels ist.




> Als Beispiel, in ganz billig:
> (keine Physik, nur Rotation, "Animation" läuft nach Testendruck genau 10 Sekunden und der Würfel bleibt immer gerade zur Kamera liegen)



Der Würfel bleibt zwar immer gerade zur Kamera liegen, allerdings mit unterschiedlichen Seiten des Würfels.
Ich müsste irgendwie die Ausgangsposition mit angeben können um dann auch später die richtige Zahl anzeigen zu können.


----------



## Marco13 (5. Sep 2008)

Die Ausgangsposition wird nicht viel helfen: Wenn ich das richtig überflogen habe, sind die Roationsgeschwindigkeiten am anfang zufällig, und die Dauer der Animation mit System.currentTimeMillis festgelegt. Letzteres ist relativ ungenau, d.h. man wird (selbst bei konstanter Rotationsgeschwindigkeit) nicht verhindern können, dass der Würfel sich mal 20 oder 30 ms länger oder weniger lang dreht. Zusammen mit den zufälligen Geschwindigkeiten wird das aber vollkommen unvorhersehbar .... das gewünschte Ende muss irgendwie geschickt in die rotateAngles reingerechnet werden ... vielleicht dafür sorgen, dass die rotateAngles am anfang "zufällig" und "groß" sind, und immer geringer werden, und am Ende alle 0.0 sind, und bei dem glRotate dann nicht
gl.glRotatef(rotateAngleX, 1.0f, 0.0f, 0.0f);
schreiben, sondern
gl.glRotatef(desiredFinalRotateAngleX + rotateAngleXthatWillBeZeroAtTheEnd, 1.0f, 0.0f, 0.0f);
... oder so... aber das kriegst du bestimmt hin


----------



## JavaKing (9. Sep 2008)

Ich könnte hier nochmal einen Denkanstoss gebrauchen. Ich habe es so halbwegs verstanden, dass rotatef zum Schluss auf 0 stehen soll bzw. die richtige Zahl.

Ich habe eine Methode :


```
void PaintRotated(gl,wuerfelaugenzahl)
{
    switch (augenzahl) 
    { 
        case 1:
            gl.glRotated(-90,1,0,0);// ( 90 grad um x-Achse )
            break; 
        case 2: 
            //glRotatef( 90 grad um z-Achse ); 
            gl.glRotated(90,0,0,1);
            break; 
        case 3: /* nix zu tun */
            break;
        ....
    } 
    gl.glCallList(spiel_wuerfel); 

}
```

Diese habe ich bis jetzt immer aufgerufen um meinen Würfel richtig zu drehen. Wie schaffe ich es oben genanntes mit meinem zu kombinieren ? Ich steh gerade auf dem Schlauch...


----------



## Marco13 (9. Sep 2008)

Grob und ungetestet

```
void PaintRotated(gl,wuerfelaugenzahl)
{
    switch (augenzahl)
    {
        case 1:
            //gl.glRotated(-90,1,0,0);// ( 90 grad um x-Achse ) // WEG
            
            // HIN:
           desiredFinalRotateAngleX = -90;
           desiredFinalRotateAngleY = 0;
           desiredFinalRotateAngleZ = 0;

            break;

        case 2:
        ....
    }

}
```
In der display-Methode von Fancy dann das hier

```
rotateAngleX -= (rotateAngleX % 90) * upspeed;
            rotateAngleY -= (rotateAngleY % 90) * upspeed;
            rotateAngleZ -= (rotateAngleZ % 90) * upspeed;
           
        }

        // set calculated rotation values
        gl.glRotatef(rotateAngleX, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(rotateAngleY, 0.0f, 1.0f, 0.0f);
        gl.glRotatef(rotateAngleZ, 0.0f, 0.0f, 1.0f);
```
[/code]
ersetzen durch

```
rotateAngleX -= rotateAngleX * upspeed;
            rotateAngleY -= rotateAngleY * upspeed;
            rotateAngleZ -= rotateAngleZ * upspeed;
           
        }

        // set calculated rotation values
        gl.glRotatef(desiredFinalRotateAngleX + rotateAngleX, 1.0f, 0.0f, 0.0f); 
        gl.glRotatef(desiredFinalRotateAngleY + rotateAngleY, 0.0f, 1.0f, 0.0f); 
        gl.glRotatef(desiredFinalRotateAngleZ + rotateAngleZ, 0.0f, 0.0f, 1.0f);
```

.... so in etwa ....


----------



## Fancy (9. Sep 2008)

Moin,

oder z.B. so (da gibt’s wahrscheinlich 1001 Möglichkeiten):


```
// animation variables
   private static final double  animationTime       = 10000;

   private double               animationStopTime   = 0;

   private float                startRotateAngleX   = 0;
   private float                startRotateAngleY   = 0;
   private float                startRotateAngleZ   = 0;

   private float                currentRotateAngleX = 0;
   private float                currentRotateAngleY = 0;
   private float                currentRotateAngleZ = 0;

   private float                finalRotateAngleX   = 0;
   private float                finalRotateAngleY   = 0;
   private float                finalRotateAngleZ   = 0;


   @Override
   public void display(GLAutoDrawable drawable) {

      // [..]

       final double time = System.currentTimeMillis();

       // calculate new rotation values
       if (animationStopTime > time) {

           final float downspeed = (float) ((animationStopTime - time) / animationTime);
           final float logspeed = (float) ((-1) * Math.log(1 - downspeed));

           currentRotateAngleX = startRotateAngleX * downspeed * logspeed;
           currentRotateAngleY = startRotateAngleY * downspeed * logspeed;
           currentRotateAngleZ = startRotateAngleZ * downspeed * logspeed;

       }

       // set calculated rotation values
       gl.glRotatef(finalRotateAngleX + currentRotateAngleX, 1.0f, 0.0f, 0.0f);
       gl.glRotatef(finalRotateAngleY + currentRotateAngleY, 0.0f, 1.0f, 0.0f);
       gl.glRotatef(finalRotateAngleZ + currentRotateAngleZ, 0.0f, 0.0f, 1.0f);

       // [..]
   }


   @Override
   public void keyPressed(KeyEvent arg0) {

       // setup for new "animation"
       final Random random = new Random();

       final int augenzahl = Math.round(random.nextFloat() * 5) + 1;
              
       switch (augenzahl) {
           case 1: finalRotateAngleX = -90; break;
           case 2: finalRotateAngleZ =  90; break;
           case 3:                          break;
           case 4: finalRotateAngleZ = 180; break;
           case 5: finalRotateAngleZ = -90; break;
           case 6: finalRotateAngleX =  90; break;
       }

       startRotateAngleX = (random.nextFloat() - 0.5f) * 1000;
       startRotateAngleY = (random.nextFloat() - 0.5f) * 1000;
       startRotateAngleZ = (random.nextFloat() - 0.5f) * 1000;

       animationStopTime = System.currentTimeMillis() + animationTime;
   }
```

Btw. wo ist der semantische Unterschied, ob ich einen Würfel zufällig drehe oder erst zufällig eine Augenzahl wähle und dann deterministisch drehe?
(Wenn die Augenzahl noch im weiteren Verlauf des Programms benötigt würde, ließe sich diese auch aus den Rotationsparametern bestimmen)

Gruß,
Michael


----------



## Marco13 (10. Sep 2008)

Fancy hat gesagt.:
			
		

> Btw. wo ist der semantische Unterschied, ob ich einen Würfel zufällig drehe oder erst zufällig eine Augenzahl wähle und dann deterministisch drehe?
> (Wenn die Augenzahl noch im weiteren Verlauf des Programms benötigt würde, ließe sich diese auch aus den Rotationsparametern bestimmen)



Da ist ein gewaltiger Unterschied: Die Augenzahl, die in irgendeiner Methode gewählt wird, gehört zum Daten_modell_ - die Rotationswinkel gehören zur sichtbaren Repräsentation (d.h. zur _View_). Man sollte NICHT davon ausgehen oder darauf aufbauen, dass in diesem Spiel der Würfel immer über irgendwas mit einer Rotation um zufällig gewählte Euler-Winkel in JOGL dargestellt wird. Wenn man das ganze mal (übertrieben, nur zur Verdeutlichung) im Text-Modus auf der Konsole laufen lassen will, hat man die nicht...


----------



## JavaKing (10. Sep 2008)

@Fancy

Ich hab deine Routinen mal so eingebaut. Habe allerdings ein Problem. Sobald einmal eine 1 oder 6 gewürfelt wurde, werden nur noch 1en oder 6en gewürfelt keine andere Zahl mehr. Bis dahin wird eigentlich alles richtig gewürfelt. Sehr merkwürdig. Irgendwas stimmt mit den Winkeln noch nicht...

Edit:
Ok also die Z-Achse scheint zu funktionieren.
Die X-Achse also 1 und 6 spinnt.
Und die 3 (nichts tun) schlägt leider auch fehl....


----------



## Fancy (10. Sep 2008)

Moin,

@Marco
ganz Deiner Meinung!

Allerdings denke ich, das es hier nur so vermatscht aussieht, da die Rotationswinkel, der Einfachheit halber, innerhalb der display() berechnet werden und nicht irgendwo innerhalb des dazugehörigen Modells.

Bei einer Entscheidung des Softwaredesigns, würde ich z.B. dahin tendieren die Bestimmung der Rotationsparameter in das Modell zu packen und die Veränderung der ModelView Matrix (durch die Rotationsparameter) in die View zu legen.

Wenn ich dann z.B. das obige Zufall-Rotation-Modell später durch ein Physik-Modell ersetze, müsste ich nichts an der View ändern, da ich, solange die übergebenen Winkelebenen senkrecht zueinander liegen, keine Änderung der Schnittstelle bräuchte. Andererseits kann ich das Physik-Modell aber nie dazu bringen eine bestimmte Augenzahl zu würfeln (zumindest nicht ohne die Physik zu verbiegen).

Wenn ich die View von JOGL auf Konsole ändern wollte, könnte ich aus den übergebenen Winkelparametern hingegen immer noch eindeutig die Augenzahl bestimmen und entsprechend Darstellen. 

Allerdings empfinge ich die MVC Trennung hierbei oft als schwammig.  Du hast nicht zufällig Tipps / Links / Literaturhinweise, die sich mit den einzelnen Varianten des Softwaredesigns in der 3D Computergrafik beschäftigen und behandeln was sich in der Praxis, insbesondere in größeren Projekten bewärt hat?


@JavaKing

Setze mal die finalRotateAngle vor dem neu Würfeln alle auf Null. Also:


```
finalRotateAngleX = 0;
finalRotateAngleY = 0;
finalRotateAngleZ = 0;
```

Gruß,
Michael


----------



## JavaKing (10. Sep 2008)

> Setze mal die finalRotateAngle vor dem neu Würfeln alle auf Null. Also:





```
finalRotateAngleX = 0;
finalRotateAngleY = 0;
finalRotateAngleZ = 0;
```

Ja das scheint es gewesen zu sein. Hatte das schon eingesetzt, leider in die falsche Methode   
Danke !


----------



## Marco13 (10. Sep 2008)

Fancy hat gesagt.:
			
		

> Bei einer Entscheidung des Softwaredesigns, würde ich z.B. dahin tendieren die Bestimmung der Rotationsparameter in das Modell zu packen und die Veränderung der ModelView Matrix (durch die Rotationsparameter) in die View zu legen.


Hmja, das würde sicher Sinn machen - aber wenn du sagst in "DAS" Modell, stellt sich die Frage: In welches? 

_Allerdings empfinge ich die MVC Trennung hierbei oft als schwammig.  Du hast nicht zufällig Tipps / Links / Literaturhinweise, die sich mit den einzelnen Varianten des Softwaredesigns in der 3D Computergrafik beschäftigen und behandeln was sich in der Praxis, insbesondere in größeren Projekten bewärt hat?_

Ja, sie IST (imho) auch schwammig (und mehr als die üblichen "ersten 100 Google-Ergebnisse" könnte ich jetzt spontan auch nicht auflisten). MVC ist ja nichts was nur in einer Form exisitiert, und wo man alles, was man macht, reinpressen muss. Es beschreibt ja vielmehr eine Idee, der man folgen sollte. In diesem Sinne spricht ja nichts dagegen, dass die View ein eigenes Modell enthält. Im ernsten Moment klingt das vielleicht komisch, aber es ist ja nur eine Frage der Interpreation - nämlich welche _Rolle_ eine bestimmte Klasse in bezug auf eine andere Klasse einnimmt. Als Beispiel: Wenn man eine Klasse "DatensatzModell" hat, und eine Klasse "DatensatzView", dann wäre das ""MVC-konform"". Dass die DatensatzView vielleicht eine JTable enthält, und diese JTable (also die View) dann wieder ein Table_Model_, ändert daran ja nichts.

Auf dieses Beispiel übertragen, GANZ grob und sinngemäß, könnte man ja ein Modell für das Spiel (und die gewürfelte Augenzahl) machen, und in der "GameView3D" gibt es dann noch ein "DiceModel3D", das die Augenzahl in Rotationswikel umrechnet - und dieses DiceModel3D wird dann letztendlich durch einen DiceModel3DRenderer dargestellt.

```
class GameModel
{
    void rollDice()
    {
        diceValue = random();
        notifyDiceRolled();
    }
}

class GameView3D implements GameModelListener
{
    GameModel gameModel;
    DiceModel3D diceModel3D;
    DiceModel3DRenderer renderer;

    void diceRolled()
    {
        diceModel3D.setDiceValue(gameModel.getDiceValue());
    }

    void render()
    { 
        renderer.render();
    }
}

class DiceModel3D
{
    private float finalAngleX,Y,Z;

    void setDiceValue(int n)
    {
        finalAngleX = 123;
        finalAngleY = 123;
        finalAngleZ = 123;
    }
    
    void threadedRotation()
    {
        changeAngles();
        notifyRotationChanged();
    }
}


class DiceModel3DRenderer implements DiceModel3DListener
{
    void rotationChanged()
    {
        float currentRotation = diceModel3D.getRotationX();
    }

    void render()
    {
        gl.glRotate(currentRotation...); 
    }
}
```

Oder kurz: Man könnte die Augenzahl in ein Modell packen, und die Rotationswinkel in ein anderes :roll:

Aber da gibt's 1001 Möglichkeiten :wink:


----------

