# Würfel per Mausklick rotieren



## TulPe (15. Dez 2015)

Hey, ich habe vier Würfel und eigentlich sollte man jeden Würfel einzeln anklicken und DANN erst drehen können (y-Achse), doch als ich den Code (aus dem Zitat hier) angewendet habe, konnte ich alle auf einmal drehen. Das ist wie gesagt eigentlich nicht so gedacht.
Die Grundidee ist ein "Puzzle", wobei die Würfel unterschiedliche Texturen haben (TOP,BOTTOM ausgeschlossen) und bei richtiger Positionierung (rotieren) sollte ein Gesamtbild ergeben.
Leider habe ich auch Schwierigkeiten mit pickCanvas gehabt, weshalb ich das anklicken der Objekte immer noch nicht mit drin habe.


> //der BoxTG die Transformationen mit der Maus erlauben
> BoxTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
> BoxTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
> 
> ...





```
import java.awt.Color;
import java.awt.Container;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.vecmath.*;

import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.universe.*;

import javax.media.j3d.*;

import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.vp.*;

import javax.swing.JFrame;

public class Wuerfel6 extends JFrame implements MouseListener {
    //Der Canvas, auf den gezeichnet wird
    public Canvas3D myCanvas3D;

    Box pl1;
    Box pl2;
    Box pl3;
    Box pl4;

    TextureLoader loader1;
    TextureLoader loader2;
    TextureLoader loader3;
    TextureLoader loader4;

    Texture texture1;
    Texture texture2;
    Texture texture3;
    Texture texture4;

    Appearance ap1_1 = new Appearance();
    Appearance ap1_2 = new Appearance();
    Appearance ap1_3 = new Appearance();
    Appearance ap1_4 = new Appearance();
    Appearance ap1_5 = new Appearance();
    Appearance ap1_6 = new Appearance();

    Appearance ap2_1 = new Appearance();
    Appearance ap2_2 = new Appearance();
    Appearance ap2_3 = new Appearance();
    Appearance ap2_4 = new Appearance();
    Appearance ap2_5 = new Appearance();
    Appearance ap2_6 = new Appearance();

    Appearance ap3_1 = new Appearance();
    Appearance ap3_2 = new Appearance();
    Appearance ap3_3 = new Appearance();
    Appearance ap3_4 = new Appearance();
    Appearance ap3_5 = new Appearance();
    Appearance ap3_6 = new Appearance();

    Appearance ap4_1 = new Appearance();
    Appearance ap4_2 = new Appearance();
    Appearance ap4_3 = new Appearance();
    Appearance ap4_4 = new Appearance();
    Appearance ap4_5 = new Appearance();
    Appearance ap4_6 = new Appearance();

    PickCanvas pickCanvas;

    TransformGroup tgPlatform1;


    public Wuerfel6() {
        //Schließen und Beenden
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Standardeinstellung fuer das Betrachteruniversum
        myCanvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());

        //Aufbau des SimpleUniverse:
        //Zuerst Erzeugen zusammen mit dem Canvas
        SimpleUniverse simpUniv = new SimpleUniverse(myCanvas3D);

        //Standardpositionierung des Betrachters
        simpUniv.getViewingPlatform().setNominalViewingTransform();

        //Die Szene wird erzeugt.
        createSceneGraph(simpUniv);

        //Hinzufuegen von Licht
        addLight(simpUniv);

        /*OrbitBehavior ob = new OrbitBehavior(myCanvas3D);
        ob.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE));
        simpUniv.getViewingPlatform().setViewPlatformBehavior(ob);*/

        //Fenster erstellen
        setTitle("Avatar Puzzle");
        setSize(1200, 1000);
        getContentPane().add("Center", myCanvas3D);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Wuerfel6();
    }

    protected void BuildShape() {
        //Platformen erstellen
        pl1 = new Box(1.5f,1.5f,1.5f,Box.GENERATE_TEXTURE_COORDS,new Appearance());
        pl2 = new Box(1.5f,1.5f,1.5f,Box.GENERATE_TEXTURE_COORDS,new Appearance());
        pl3 = new Box(1.5f,1.5f,1.5f,Box.GENERATE_TEXTURE_COORDS,new Appearance());
        pl4 = new Box(1.5f,1.5f,1.5f,Box.GENERATE_TEXTURE_COORDS,new Appearance());

        //Texturen 1. Platform (links unten)
        loader1 = new TextureLoader("Air1.jpg",this);
        texture1 = loader1.getTexture();
        ap1_1.setTexture(texture1);
        pl1.setAppearance(Box.BACK,ap1_1);
        pl1.setUserData("Box1");
        pl1.getUserData();

        loader1 = new TextureLoader("Earth1.jpg",this);
        texture1 = loader1.getTexture();
        ap1_4.setTexture(texture1);
        pl1.setAppearance(Box.LEFT,ap1_4);

        loader1 = new TextureLoader("Fire1.jpg",this);
        texture1 = loader1.getTexture();
        ap1_5.setTexture(texture1);
        pl1.setAppearance(Box.RIGHT,ap1_5);

        loader1 = new TextureLoader("Water1.jpg",this);
        texture1 = loader1.getTexture();
        ap1_6.setTexture(texture1);
        pl1.setAppearance(Box.FRONT,ap1_6);


        //Texturen 2.Platform (rechts unten)
        loader2 = new TextureLoader("Fire2.jpg",this);
        texture2 = loader2.getTexture();
        ap2_1.setTexture(texture2);
        pl2.setAppearance(Box.BACK,ap2_1);

        loader2 = new TextureLoader("Air2.jpg",this);
        texture2 = loader2.getTexture();
        ap2_4.setTexture(texture2);
        pl2.setAppearance(Box.LEFT,ap2_4);

        loader2 = new TextureLoader("Earth2.jpg",this);
        texture2 = loader2.getTexture();
        ap2_5.setTexture(texture2);
        pl2.setAppearance(Box.RIGHT,ap2_5);

        loader2 = new TextureLoader("Water2.jpg",this);
        texture2 = loader2.getTexture();
        ap2_6.setTexture(texture2);
        pl2.setAppearance(Box.FRONT,ap2_6);

        //Texturen 3.Platform (rechts oben)
        loader3 = new TextureLoader("Earth3.jpg", this);
        texture3 = loader3.getTexture();
        ap3_1.setTexture(texture3);
        pl3.setAppearance(Box.BACK,ap3_1);

        loader3 = new TextureLoader("Water3.jpg",this);
        texture3 = loader3.getTexture();
        ap3_4.setTexture(texture2);
        pl3.setAppearance(Box.LEFT,ap3_4);

        loader3 = new TextureLoader("Fire3.jpg",this);
        texture3 = loader3.getTexture();
        ap3_5.setTexture(texture3);
        pl3.setAppearance(Box.RIGHT,ap3_5);

        loader3 = new TextureLoader("Air3.jpg",this);
        texture3 = loader3.getTexture();
        ap3_6.setTexture(texture3);
        pl3.setAppearance(Box.FRONT,ap3_6);

        //Texturen 4.Platform (links oben)
        loader4 = new TextureLoader("Water4.jpg", this);
        texture4 = loader4.getTexture();
        ap4_1.setTexture(texture4);
        pl4.setAppearance(Box.BACK,ap4_1);

        loader4 = new TextureLoader("Fire4.jpg",this);
        texture4 = loader4.getTexture();
        ap4_4.setTexture(texture2);
        pl4.setAppearance(Box.LEFT,ap4_4);

        loader4 = new TextureLoader("Air4.jpg",this);
        texture4 = loader4.getTexture();
        ap4_5.setTexture(texture4);
        pl4.setAppearance(Box.RIGHT,ap4_5);

        loader4 = new TextureLoader("Earth4.jpg",this);
        texture4 = loader4.getTexture();
        ap4_6.setTexture(texture4);
        pl4.setAppearance(Box.FRONT,ap4_6);
    }

    public void createSceneGraph(SimpleUniverse su) {
        // Eine Appearance, um die Plattform Rot zu faerben
        Appearance redApp = new Appearance();

        setToMyDefaultAppearance(redApp,new Color3f(0.8f,0.0f,0.0f));

        //Die folgenden drei Zeilen erzeugen einen weißen Hintergrund.
        Background bg = new Background(new Color3f(0.8f,2.8f,3.0f));
        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
        bg.setApplicationBounds(bounds);

        //Die Transformationsgruppe der Plattform
        BuildShape();

        Transform3D tfPl1 = new Transform3D();
        tfPl1.setTranslation(new Vector3f(-2.0f, -2.0f,-12.0f));
        tgPlatform1 = new TransformGroup(tfPl1);
        tgPlatform1.addChild(pl1);

        Transform3D tfPl2 = new Transform3D();
        tfPl2.setTranslation(new Vector3f(2.0f, -2.0f,-12.0f));
        TransformGroup tgPlatform2 = new TransformGroup(tfPl2);
        tgPlatform2.addChild(pl2);

        Transform3D tfPl3 = new Transform3D();
        tfPl3.setTranslation(new Vector3f(2.0f, 2.0f,-12.0f));
        TransformGroup tgPlatform3 = new TransformGroup(tfPl3);
        tgPlatform3.addChild(pl3);

        Transform3D tfPl4 = new Transform3D();
        tfPl4.setTranslation(new Vector3f(-2.0f, 2.0f,-12.0f));
        TransformGroup tgPlatform4 = new TransformGroup(tfPl4);
        tgPlatform4.addChild(pl4);

        tgPlatform1.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        tgPlatform1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgPlatform2.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        tgPlatform2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgPlatform3.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        tgPlatform3.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgPlatform4.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        tgPlatform4.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

        BoundingBox boundBox=new BoundingBox (new Point3d(-1000,-1000,-1000),new Point3d(1000,1000,1000));
        BoundingBox boundBox2=new BoundingBox (new Point3d(-1000,-1000,-1000),new Point3d(1000,1000,1000));

        //rotieren mit der linken Maustaste
        MouseRotate behavior = new MouseRotate(tgPlatform1);
        behavior.setTransformGroup(tgPlatform1);
        behavior.setSchedulingBounds(boundBox);
        tgPlatform1.addChild(behavior);
      
        //rotieren mit der linken Maustaste
        MouseRotate behavior2 = new MouseRotate(tgPlatform1);
                behavior2.setTransformGroup(tgPlatform2);
                behavior2.setSchedulingBounds(boundBox2);
                tgPlatform2.addChild(behavior2);
               
        BranchGroup theScene = new BranchGroup();
        theScene.addChild(tgPlatform1);
        theScene.addChild(tgPlatform2);
        theScene.addChild(tgPlatform3);
        theScene.addChild(tgPlatform4);
        theScene.addChild(bg);
        theScene.compile();
        su.addBranchGraph(theScene);
    }

    public static void setToMyDefaultAppearance(Appearance app, Color3f col) {
        app.setMaterial(new Material(col, col, col, col, 120.0f));
    }

    public void addLight(SimpleUniverse su) {
        BranchGroup bgLight = new BranchGroup();
        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
        Color3f lightColour1 = new Color3f(1.0f,1.0f,1.0f);
        Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.5f);
        DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
        light1.setInfluencingBounds(bounds);
        bgLight.addChild(light1);
        su.addBranchGraph(bgLight);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub
        new mouseBehavior(tgPlatform1);
        System.out.println("Es funktioniert!");
    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
    }
}
```


----------



## Joose (15. Dez 2015)

Lies dir mal die Dokumentation zur BoundingBox durch für was diese zuständig ist, dann sollte dir klar werden warum du nicht unbedingt deine beiden Punkte an den Konstruktor übergeben solltest.

Anmerkung zu deinen Code:
Anstatt 4x6 Objekte von Appearcance zu deklarieren könntest du eine Klasse Wuerfel schreiben, welche eine Liste von max. 6 Appearance Objekte enthält.

Du hast viel doppelten Code den du einfach auslagern könntest in Methoden.


----------



## TulPe (15. Dez 2015)

Danke, für deine Antwort, aber es geht mir im Moment um die Rotation und nicht darum, wie ich den Code geschrieben habe, sofern er verständlich ist, so wie ich ihn gepostet habe. 
Ich würde mich also auf eine Antwort bzgl meines Problems sehr freuen. Tipps zum "besseren" Schreiben des Codes sind im Moment eher zweitrangig.  

Falls du mir also helfen kannst, dann hier noch mal der geänderte Code. Habe mithilfe eines Freundes einiges geändert und kann nun auf die Objekte klicken. Beim rotieren passiert jedoch nicht das, was eigentlich passieren sollte. 

```
Shape3D[] faces1 = new Shape3D[6];
        faces1[0] = pl1.getShape(pl1.BACK);
        faces1[1] = pl1.getShape(pl1.LEFT);
        faces1[2] = pl1.getShape(pl1.RIGHT);
        faces1[3] = pl1.getShape(pl1.FRONT);
        faces1[4] = pl1.getShape(pl1.BOTTOM);
        faces1[5] = pl1.getShape(pl1.TOP);
       
        for(int i = 0; i < faces1.length; i++){
            faces1[i].setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
```


----------



## Joose (15. Dez 2015)

TulPe hat gesagt.:


> Danke, für deine Antwort, aber es geht mir im Moment um die Rotation und nicht darum, wie ich den Code geschrieben habe, sofern er verständlich ist, so wie ich ihn gepostet habe.


Ich habe in meinen Post auch einen Vorschlag gepostet was du bezüglich deinem Problem machen kannst/sollst.
Meiner Meinung nach hast du die BoundingBox über alle Objekte "gespannt" und damit dann natürlich auch alle gleichzeitig gedreht.



TulPe hat gesagt.:


> ..... die Objekte klicken. Beim rotieren passiert jedoch nicht das, was eigentlich passieren sollte.



Heißt was genau? Was passiert und was sollte stattdessen passieren?


----------



## TulPe (15. Dez 2015)

1. ich hatte die Bounding Box verkleinert, das hat nichtd gebracht 
2. der Würfel soll sich um die y-Achse drehen, aber irgendwie macht es was komisches. Wenn man auf den Würfel klickt erscheint ein Teil der Textur ganz groß im Fenster, als hätte man reinhezoomt.


----------



## Joose (16. Dez 2015)

Dann bitte deinen aktuellen Code posten, da du ja selbst gesagt er wurde angepasst.


----------



## TulPe (16. Dez 2015)

```
if (aktuell.getUserData() != null){
                    if(aktuell.getUserData().equals("Box1")){
                        Transform3D rot = new Transform3D();
                        Transform3D rot_2 = new Transform3D();
                        tgPl1.getTransform(rot_2);
                        rot_2.rotY(Math.PI/2);
                        rot.mul(rot_2);
                        tgPl1.setTransform(rot_2);
                    }
}
```


Hier ist der Code für die Rotation (Box 1, die unten rechts).


----------



## TulPe (16. Dez 2015)

Update: 

Wir haben den Fehler entdeckt. Der Würfel rotiert, doch nicht auf seiner ursprünglichen Position. Er rotiert um die Kamera herum. Hat jemand eine Idee, woran das liegt, bzw. welche Änderungen wir vornehmen müssen, damit der Würfel sich um seine eigene Achse dreht?

```
Alpha pl1Alpha = new Alpha(1, 20000);
//        pl1Alpha.setStartTime(Long.MAX_VALUE);
       
        RotationInterpolator pl1Rotation = new RotationInterpolator(pl1Alpha, tgPl1);
        BoundingSphere pl1Bound = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), Double.MAX_VALUE);
        pl1Rotation.setSchedulingBounds(pl1Bound);

        tgPl1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgPl1.addChild(pl1);
        tgPl1.addChild(pl1Rotation);
```


Der restliche Code ist soweit unverändert.


----------



## Exdroid (17. Dez 2015)

Kann man nicht einfach die Kamera falschherum um den Würfel rotieren lassen, das es so aussieht als würde sich der Würfel um die eigene Achse drehen? Das wäre so das erste was mir einfallen würde...
oder liege ich da komplett falsch?
btw, wird das am Ende wie ein Rubiks Cube mit mehreren Ebenen?

L'Exdroid


----------



## TulPe (17. Dez 2015)

Ich denke theoretisch wäre es natürlich machbar, aber das ist so gar nicht das, was wir brauchen. Die einzelnen Würfel sollen sich ja drehen, damit die Texturen so liegen, dass ein Gesamtbild ergibt. Wenn sie aber nur die Kamera um den jeweiligen Würfel dreht, dann passt es am Ende mit den Texturen nicht.


----------



## Exdroid (17. Dez 2015)

Asou, ich beginne zu verstehen 
Ich habe zwar keine Ahnung aber ist das hier eher Hilfreich?
Oder hast du das schon gesehen?

http://www.java-forum.org/thema/grafikobjekt-drehen.110692/


----------

