# CubeMap auf glutSolidSpheere legen



## JavaKing (15. Sep 2008)

Hallo zusammen,

ich möchte innerhalb meines Würfels ( 6 Quads) nun eine Kugel platzieren die sozusagen die Wände spiegelt.
Ich kann mich innerhalb des Würfels ein wenig bewegen und die Kugel sollte sich dementsprechend mit verändern.
Da ich keine vorgefertige Texturen für die Spiegelung verwende, habe ich mir diese selber zusammengestellt aus den unterschiedlichen Texturflächen des Würfels. Mit unten stehendem Source Code habe ich das soweit auch hingebracht.
Leider sind meine Texturen noch nicht richtig, diese kann ich aber noch entsprechenden anpassen.

Meine Probleme sind :

1.Es wirkt als wenn ich in die Kugel hineinschauen kann und innerhalb die Texture aufgetragen ist. Aber natürlich soll die Texture aussen auf die Kugel aufgetragen werden.

2. Ich möchte das sich die Kugel dreht, so wie sich z.b. eine Disco Kugel dreht aber die Spiegelung muss natürlich beibehalten werden. Ich verändere meine Position im Raum ja nicht.

3.Wie kann ich über diese Texture so ein Disco Schimmern erzeugen so das die Spiegelung ein wenig abgeschwächt wird ? Also das man im Prinzip eine Discokugel hat mit leichten bis mittleren Spiegelung der Wände.

EDIT:
4.Irgendwie sind die Texturen auch spiegelverkehrt aufgetragen, also oben ist unten, links ist rechts usw.


```
gl.glPushMatrix();
        
        gl.glEnable(GL_TEXTURE_CUBE_MAP);

        gl.glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
        gl.glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
        gl.glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
        gl.glEnable(GL_TEXTURE_GEN_S);
        gl.glEnable(GL_TEXTURE_GEN_T);
        gl.glEnable(GL_TEXTURE_GEN_R);

        gl.glMatrixMode(GL_TEXTURE);
        gl.glLoadIdentity();
        gl.glRotated(180-alpha, 0, 1, 0);
        gl.glScaled(-1, -1, -1);
        gl.glMatrixMode(GL_MODELVIEW);

        gl.glDisable(GL_LIGHTING);
        gl.glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
        gl.glColor3d(1, 1, 1);

        glut.glutSolidSphere(2, 30, 30);
        gl.glEnable(GL_LIGHTING);

        gl.glMatrixMode(GL_TEXTURE);
        gl.glLoadIdentity();
        gl.glMatrixMode(GL_MODELVIEW);
        gl.glLoadIdentity();

        gl.glDisable(GL_TEXTURE_CUBE_MAP);
        gl.glDisable(GL_TEXTURE_GEN_S);
        gl.glDisable(GL_TEXTURE_GEN_T);
        gl.glDisable(GL_TEXTURE_GEN_R);
```



```
// Laden der 6 Texturen für die Spiegelungen
            Cubemap xobj = new Cubemap();

           cubemap = xobj.loadFromStreams("data\\images\\bilder_","jpg",true);
```


----------



## Fancy (15. Sep 2008)

Moin,

also Rotation der Kugel an sich ist kein Problem. Dazu musst Du vor dem zeichnen mit glutSolidSphere lediglich ein glRotate auf Deine ModelView Matrix anwenden. Das größere Problem ist, dass die Texturkoordinaten im Weltkoordinatensystem berechnet werden. Bewegst Du Deinen lokalen Standpunkt (z.B. mit gluLookAt) beeinflusst dies nicht den sichtbaren Teil der Reflektion. Damit dies geschieht, kann z.B. die Texturmatrix mit dem inversen Rotationsanteil der ModelView multipliziert werden.

Als Beispiel z.B. so:
(Achtung: Scheinbar hast Du eine andere Cubemap Klasse (andere jogl Version?) sollte die aus dem aktuellen jogl demo pack sein, die uffizi cubemap Bilder sind ebenfalls von da)


```
package fancy.jf.cubemap;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

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.GLUT;
import com.sun.opengl.util.texture.Texture;

import demos.util.Cubemap;

public class CMap implements GLEventListener {

   private GL          gl      = null;
   private GLU         glu     = null;
   private GLUT        glut    = null;

   private Texture     cubemap = null;

   private float       angle   = 0;

   // we need the inverse rotation part from the modelview matrix
   private final float mv[]    = new float[16];
   private final float inv[]   = new float[16];


   @Override
   public void init(GLAutoDrawable drawable) {

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

       // setup gl basics
       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);

       // setup cubemap texture
       try {
           cubemap = Cubemap.loadFromStreams(this.getClass().getClassLoader(), "uffizi_", "png", false);
           cubemap.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
           cubemap.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
           cubemap.bind();

       } catch (final Exception e) {
           e.printStackTrace();
       }

       // setup cubemap parameter
       gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP);
       gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP);
       gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP);

       gl.glEnable(GL.GL_TEXTURE_GEN_S);
       gl.glEnable(GL.GL_TEXTURE_GEN_T);
       gl.glEnable(GL.GL_TEXTURE_GEN_R);

       gl.glEnable(GL.GL_NORMALIZE);
       gl.glEnable(GL.GL_AUTO_NORMAL);

       gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL);
   }


   private void inversRotationMatrix() {

       // calculate the inverse rotation matrix
       // it is the upper left 3x3 transpose from the modelview
       gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, mv, 0);
       inv[0] = mv[0];
       inv[1] = mv[4];
       inv[2] = mv[8];
       inv[4] = mv[1];
       inv[5] = mv[5];
       inv[6] = mv[9];
       inv[8] = mv[2];
       inv[9] = mv[6];
       inv[10] = mv[10];
       inv[15] = mv[15];
   }


   @Override
   public void display(GLAutoDrawable drawable) {

       gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
       gl.glLoadIdentity();

       // setup current look at point
       final double time = System.currentTimeMillis();
       final float camX = (float) (Math.sin(time / 1500.0) * 5);
       final float camY = (float) (Math.sin(time / 2000.0) * 5);
       glu.gluLookAt(camX, camY, 8, 0, 0, 0, 0, 1, 0);

       // correct texture matrix with respect to look at point
       gl.glMatrixMode(GL.GL_TEXTURE);
       gl.glLoadIdentity();
       inversRotationMatrix();
       gl.glMultMatrixf(inv, 0);
       gl.glMatrixMode(GL.GL_MODELVIEW);

       // rotate sphere
       gl.glPushMatrix();
       gl.glRotatef(90, 1, 0, 0);
       gl.glRotatef(angle += 0.5, 0, 0, 1);

       // draw cubemap sphere
       gl.glEnable(GL.GL_TEXTURE_CUBE_MAP);
       glut.glutSolidSphere(1.5, 12, 12);
       gl.glDisable(GL.GL_TEXTURE_CUBE_MAP);

       // draw black outlines on sphere
       gl.glPolygonMode(GL.GL_FRONT, GL.GL_LINE);
       gl.glColor3f(0.1f, 0.1f, 0.1f);
       glut.glutSolidSphere(1.5, 12, 12);
       gl.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);
       gl.glPopMatrix();

       // draw some static to see the camera movement
       gl.glPushMatrix();
       gl.glColor3f(0.5f, 0.5f, 0.5f);
       gl.glScalef(0.3f, 8.0f, 0.3f);
       glut.glutSolidCube(1);
       gl.glScalef(26.0f, 0.03f, 1.0f);
       glut.glutSolidCube(1);
       gl.glPopMatrix();
   }


   @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 displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}


   public static void main(String[] args) {

       final CMap cmap = new CMap();
       final Frame frame = new Frame();
       final GLCanvas canvas = new GLCanvas();
       final Animator animator = new Animator(canvas);
       canvas.addGLEventListener(cmap);

       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


----------



## Marco13 (15. Sep 2008)

Wowy - endlich mal jemand, der sich tatsächlich die Arbeit macht, zu irgendwelchen abstrakten GL-Fragen mit (teilweise ZU) minimalistischem Code ein vollständiges KSKB zu bauen ->  :toll:  :applaus:


----------



## Fancy (16. Sep 2008)

Moin,

danke Dir! 

Aber Du gehörst ja auch zu denen hier die viele sinnvolle Antworten und Code beisteuern, insofern geb ich das auch gerne direkt wieder zurück:



			
				Marco13 hat gesagt.:
			
		

> ->  :toll:  :applaus:



:wink:

Gruß,
Michael


----------



## JavaKing (16. Sep 2008)

> Als Beispiel z.B. so:
> (Achtung: Scheinbar hast Du eine andere Cubemap Klasse (andere jogl Version?) sollte die aus dem aktuellen jogl demo pack sein, die uffizi cubemap Bilder sind ebenfalls von da)


Ja meine Version ist leicht abgewandelt funktioniert aber einwandfrei.

@Fancy & Marco13
Ich muss hier auch mal ein dickes Lob abgeben ! Ihr habt mir sehr gut weitergeholfen mit Source Code aber auch die passenden Erklärungen dazu. Manchmal waren es nämlich einfach nur Verständnis fragen, manchmal fehlte der passende Sourcecode. Absolute Spitzen Arbeit von euch beiden !

@Fancy
Deine Anwendungen sind echt spitzen Klasse, danke das du dir soviel Arbeit machst !

Natürlich schiebe ich gleich eine Frage hinterher ;-)
Meine Punkte 1,2,4 habe ich mit deiner Anwendung einwandfrei lösen können.
Punkt 3 wäre für mich noch interessant.

Punkt1: Das liegt wohl an meinen Texturen die ich gebastelt habe, das dies so wirkt. Mit einem von der Seite "codemaster" sieht das ganze wesentlich besser aus.

Punkt2: Supi gelöst !!!!!

Punkt 3:
Wie kann ich über diese Texture so ein Disco Schimmern erzeugen so das die Spiegelung ein wenig abgeschwächt wird ? Also das man im Prinzip eine Discokugel hat mit leichten bis mittleren Spiegelung der Wände der Rest ist grau mit so leuchteten Punkten drauf z.b. ?

Dazu fällt mir leider nichts ein. Ich hatte soeben versucht einfach mal mit glColor3f grau über die Kugel zu legen, hat nicht funktioniert. Ich denke auch nicht dass das gut ausgesehen hätte.
Dazu Ideen ?


----------



## Fancy (16. Sep 2008)

Moin,



			
				JavaKing hat gesagt.:
			
		

> Ich denke auch nicht dass das gut ausgesehen hätte.



und genau das ist leider auch das Problem, denn eigentlich ist so eine Discokugel alles andere als ein triviales Unterfangen. Damit das vernünftig aussieht, muss da letztendlich ne ganze Menge Effekte drauf. Dynamische Reflektion, Spitzlichter, Verschattungen, Glanz, Lichtbrechung,... Praktisch würde das in mehrere Renderdurchläufe und jeweils mehrere dazu passende Shader ausarten. Im Verhältnis zum Rest Deines Programms ist das also vielleicht ehr was für "später".

Was Du alternativ machen könntest, wäre eine zusätzliche zweite Textur verwenden, diese mit den gewünschten Farbflecken versehen und z.B. als normal map aufzulegen. Das passende Stichwort wäre hierzu Multitextur. 

Z.B. so:
(Rest wie oben, die star Texturen sollten hellgrau mit dunklen farbigen Flecken sein)


```
private Texture     cubemap = null;
   private Texture     starmap = null;

   @Override
   public void init(GLAutoDrawable drawable) {

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

       // setup gl basics
       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.glEnable(GL.GL_NORMALIZE);
       gl.glEnable(GL.GL_AUTO_NORMAL);

       // setup cubemap reflection texture
       gl.glActiveTexture(GL.GL_TEXTURE0);
       try {
           cubemap = Cubemap.loadFromStreams(this.getClass().getClassLoader(), "uffizi_", "png", false);
           cubemap.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
           cubemap.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
           cubemap.bind();

       } catch (final Exception e) {
           e.printStackTrace();
       }

       // setup cubemap reflection parameter
       gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP);
       gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP);
       gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP);

       gl.glEnable(GL.GL_TEXTURE_GEN_S);
       gl.glEnable(GL.GL_TEXTURE_GEN_T);
       gl.glEnable(GL.GL_TEXTURE_GEN_R);

       gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL);

       // setup cubemap star texture
       gl.glActiveTexture(GL.GL_TEXTURE1);
       try {
           starmap = Cubemap.loadFromStreams(this.getClass().getClassLoader(), "star_", "png", false);
           starmap.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
           starmap.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
           starmap.bind();

       } catch (final Exception e) {
           e.printStackTrace();
       }

       // setup cubemap star parameter
       gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP);
       gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP);
       gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP);

       gl.glEnable(GL.GL_TEXTURE_GEN_S);
       gl.glEnable(GL.GL_TEXTURE_GEN_T);
       gl.glEnable(GL.GL_TEXTURE_GEN_R);

       gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_BLEND);
   }


   @Override
   public void display(GLAutoDrawable drawable) {

       gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
       gl.glLoadIdentity();

       // setup current look at point
       final double time = System.currentTimeMillis();
       final float camX = (float) (Math.sin(time / 1500.0) * 5);
       final float camY = (float) (Math.sin(time / 2000.0) * 5);
       glu.gluLookAt(camX, camY, 8, 0, 0, 0, 0, 1, 0);
       inversRotationMatrix();

       // cubemap reflection
       // correct texture matrix with respect to look at point             
       gl.glActiveTexture(GL.GL_TEXTURE0);
       gl.glEnable(GL.GL_TEXTURE_CUBE_MAP);
       gl.glMatrixMode(GL.GL_TEXTURE);
       gl.glLoadIdentity();
       gl.glMultMatrixf(inv, 0);
       gl.glMatrixMode(GL.GL_MODELVIEW);

       // cubemap star
       // correct texture matrix with respect to look at point
       gl.glActiveTexture(GL.GL_TEXTURE1);
       gl.glEnable(GL.GL_TEXTURE_CUBE_MAP);
       gl.glMatrixMode(GL.GL_TEXTURE);
       gl.glLoadIdentity();
       gl.glMultMatrixf(inv, 0);
       gl.glMatrixMode(GL.GL_MODELVIEW);

       // rotate sphere
       gl.glPushMatrix();
       gl.glRotatef(90, 1, 0, 0);
       gl.glRotatef(angle += 0.5, 0, 0, 1);

       // draw cubemap sphere
       glut.glutSolidSphere(1.5, 12, 12);
       
       gl.glActiveTexture(GL.GL_TEXTURE0);
       gl.glDisable(GL.GL_TEXTURE_CUBE_MAP);
       gl.glActiveTexture(GL.GL_TEXTURE1);
       gl.glDisable(GL.GL_TEXTURE_CUBE_MAP);

       // draw black outlines on sphere
       gl.glPolygonMode(GL.GL_FRONT, GL.GL_LINE);
       gl.glColor3f(0.1f, 0.1f, 0.1f);
       glut.glutSolidSphere(1.5, 12, 12);
       gl.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);
       gl.glPopMatrix();

       // draw some static to see the camera movement
       gl.glPushMatrix();
       gl.glColor3f(0.5f, 0.5f, 0.5f);
       gl.glScalef(0.3f, 8.0f, 0.3f);
       glut.glutSolidCube(1);
       gl.glScalef(26.0f, 0.03f, 1.0f);
       glut.glutSolidCube(1);
       gl.glPopMatrix();
   }
```

Gruß,
Michael


----------

