# Frage zu Transform3D.mul()



## jagdfalke (27. Mai 2006)

Hi,
ich habe meinem Tutorial gefolgt und mal eine einfach Animation in meinen SceneGraph eingebaut. Das ganze sieht so aus:


```
public class Main extends JFrame implements ActionListener {

        private SimpleUniverse un;

        private Timer timer;
        private float currAngle;
        private TransformGroup superGroup;
        private Transform3D superTrans;
	
	public Main() {
            setLayout(new BorderLayout());
            setSize(500,500);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
            GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
		
            Canvas3D c=new Canvas3D(config);
            getContentPane().add(c);
	
            un = new SimpleUniverse(c);
            un.getViewingPlatform().setNominalViewingTransform();
            un.addBranchGraph(createSceneGraph());

            currAngle = 0f;
            timer = new Timer(60, this);
            timer.start();	
	    
            setVisible(true);
	}
	
        public void actionPerformed(ActionEvent e) {
            if(e.getSource().equals(timer)) {
                handleTimer();
            }
	}

	private void handleTimer() {
            Transform3D tempT3D=new Transform3D();
            currAngle+=1f;
            if (currAngle>=360) {
                currAngle-=360;
            }
            superTrans.setRotation(new AxisAngle4f(1f,0f,0f,(float)Math.toRadians(20)));
            tempT3D.rotY(Math.toRadians(currAngle));
            superTrans.mul(tempT3D);
            superGroup.setTransform(superTrans);
	}
	
	private BranchGroup createSceneGraph() {
            BranchGroup bg = new BranchGroup();

            // ...
            // das lass ich mal alles weg
            // aus Gründen der Übersichtlichkeit
            // ...

            bg.addChild(superGroup);
            bg.compile();
            return bg;
	}
	

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

}
```

superGroup beinhaltet also alle Objekte (Box, Sphere, etc) und das ganze soll um die Y-Achse gedreht werden. Ich versteh schon wie das hier geht, also Timer triggert alle 60ms den ActionListener der das wieder weitergibt an handleTimer(). Nur was da abgeht check ich nicht so ganz.

```
Transform3D tempT3D=new Transform3D();
            currAngle+=1f;
            if (currAngle>=360) {
                currAngle-=360;
            }
```
Bis da hin komm ich mit, aber warum wird dann aus superTrans wieder die Rotation überschrieben??? Die wird ja wieder komplett zurückgesetzt bis auf das was neu angegeben wird. Warum kann nicht die alte Rotation beibehalten werden und nur die Y-Achse zurückgesetzt werden, oder die Rotation ausgelesen und dann neu gesetzt werden?
Und dieser Methode mul() aus Transform3D kapier ich nicht ganz:


> Sets the value of this transform to the result of multiplying itself with transform t1 (this = this * t1).


Macht der this = this * t1 für alle Werte oder wie kann ich mir das vorstellen??? Wenn das so ist das müsse das ja so aussehen:

```
private void handleTimer() {
           Transform3D tempT3D=new Transform3D();
           currAngle+=1f;
           if (currAngle>=360) {
        	currAngle-=360;
           }
           superTrans.setRotation(new AxisAngle4f(1f,0f,0f,(float)Math.toRadians(20))); //x-Rot=20; y-Rot=0; z-Rot=0
           tempT3D.rotY(Math.toRadians(currAngle));  // y-Rot-tmp = z.B. 20
           superTrans.mul(tempT3D); ///y-Rot * y-Rot-tmp = 0 * 20 = 0 ????
           superGroup.setTransform(superTrans);
	}
```
Also müsste da ja immer 0 Grad stehen. Kann aber nicht sein, denn das Ding dreht sich ja  Also was ist da los?

mfg
jagdfalke


----------



## Illuvatar (27. Mai 2006)

Hm ich hab mir das jetzt nicht alles so genau angeschaut (v.a., weil man es nicht ausführen kann  ), aber a) außerhalb von Behaviors solltest du nichts im SceneGraph verändern b) für so etwas gibt es, soweit ich das verstehe, schon einen vorgefertigten Behavior, nämlich den RotationInterpolator.


----------



## jagdfalke (27. Mai 2006)

Mag sein aber soweit bin ich noch nicht und ich möchte immer gerne erst das verstehen was ich abgeschrieben habe bevor ich einfach weiter mache.

Hier nochmal die vollständige ausführbare Version:

```
import javax.swing.JFrame;
import javax.media.j3d.*;
import com.sun.j3d.utils.universe.*;
import javax.vecmath.*;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.*;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import javax.swing.Timer;
import java.awt.event.*;

public class Main extends JFrame implements ActionListener {

	private SimpleUniverse un;
	private Timer timer;
	private float currAngle;
	private TransformGroup superGroup;
	private Transform3D superTrans;
	
	public Main() {
		setLayout(new BorderLayout());
		setSize(500,500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
		
		Canvas3D c=new Canvas3D(config);
		getContentPane().add(c);
		
		un = new SimpleUniverse(c);
	    	un.getViewingPlatform().setNominalViewingTransform();
	    	un.addBranchGraph(createSceneGraph());

	    currAngle = 0f;
	    timer = new Timer(60, this);
	    timer.start();	
	    
		setVisible(true);
	}
	
	public void actionPerformed(ActionEvent e) {
		if(e.getSource().equals(timer)) {
			handleTimer();
		}
	}

	private void handleTimer() {
        Transform3D tempT3D=new Transform3D();
        currAngle+=1f;
        if (currAngle>=360) {
        	currAngle-=360;
        }
        superTrans.setRotation(new AxisAngle4f(1f,0f,0f,(float)Math.toRadians(20)));
        tempT3D.rotY(Math.toRadians(currAngle));
        superTrans.mul(tempT3D);
        superGroup.setTransform(superTrans);
	}
	
	private BranchGroup createSceneGraph() {
		BranchGroup bg = new BranchGroup();
		
		superTrans = new Transform3D();
			superTrans.setRotation(new AxisAngle4d(1f, 0f, 0f, Math.toRadians(20)));
			superTrans.setTranslation(new Vector3d(0f, 0f, -2f));
		superGroup = new TransformGroup(superTrans);
			superGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			superGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); 
		
		///////////////////////////////////////////////////
		// LIGHT
		///////////////////////////////////////////////////
		BoundingSphere bndSphere = new BoundingSphere(new Point3d(0f,0f,0f),100000);
		AmbientLight ambLight = new AmbientLight(new Color3f(1f,1f,1f));
			ambLight.setInfluencingBounds(bndSphere);
		bg.addChild(ambLight);
	    
		
		/////////////////////////////////////////////////
	    // BOX
	    /////////////////////////////////////////////////
		Appearance boxAppearance = new Appearance();
			boxAppearance.setMaterial(new Material(new Color3f(1f,0.5f,0.5f),new Color3f(0f,0f,0f),new Color3f(0.9f,0.9f,0.9f),new Color3f(0.8f,0.8f,0.8f),1f));
			boxAppearance.setTexture(new TextureLoader("./img/035.jpg", null).getTexture());
			boxAppearance.setTextureAttributes(new TextureAttributes(TextureAttributes.REPLACE,new Transform3D(),new Color4f(), TextureAttributes.NICEST)); 
		Box box = new Box(1f,0.0001f,1f,Primitive.GENERATE_NORMALS | Primitive.GENERATE_TEXTURE_COORDS, boxAppearance);
        superGroup.addChild(box);
			
		///////////////////////////////////////////////////
		// SPHERE
		///////////////////////////////////////////////////
		Transform3D t3d = new Transform3D();
			t3d.setTranslation(new Vector3f(0.6f,0f,-0.6f));
		TransformGroup tg = new TransformGroup();
			tg.setTransform(t3d);
		Appearance sphereAppearance = new Appearance();
        	sphereAppearance.setMaterial(new Material(new Color3f(0.1f,0.1f,0.1f),new Color3f(0.5f,0.5f,0.5f),new Color3f(0.8f,0.8f,0.8f),new Color3f(0.6f,0.6f,0.6f),1f));
        	sphereAppearance.setTexture(new TextureLoader("./img/texture.jpg", null).getTexture());
        	sphereAppearance.setTextureAttributes(new TextureAttributes(TextureAttributes.REPLACE,new Transform3D(),new Color4f(), TextureAttributes.NICEST)); 
    	Sphere sphere = new Sphere(.5f,Sphere.GENERATE_TEXTURE_COORDS, 100,sphereAppearance);
		tg.addChild(sphere);
		superGroup.addChild(tg);
		
		/////////////////////////////////////////////////
	    // Cylinder
	    /////////////////////////////////////////////////
		Transform3D cylinderT3D = new Transform3D();
			cylinderT3D.setTranslation(new Vector3d(-0.6, 0f,-1f));
		TransformGroup cylinderTG = new TransformGroup();
		cylinderTG.setTransform(cylinderT3D);
		Appearance cylinderAppearance = new Appearance();
	     	cylinderAppearance.setMaterial(new Material(new Color3f(0f,0f,1f),new Color3f(0f,0f,0f),new Color3f(1f,0f,0f),new Color3f(1f,1f,1f),100f));
	     	cylinderAppearance.setTexture(new TextureLoader("./img/Board12.jpg", null).getTexture());
	     	cylinderAppearance.setTextureAttributes(new TextureAttributes(TextureAttributes.REPLACE,new Transform3D(),new Color4f(), TextureAttributes.NICEST)); 
	    Cylinder cylinder = new Cylinder(0.3f,1f,Cylinder.GENERATE_TEXTURE_COORDS,40,1,cylinderAppearance);
     	cylinderTG.addChild(cylinder);
     	superGroup.addChild(cylinderTG);
		
	    
     	///////////////////////////////////////////////
     	// Box 2
     	///////////////////////////////////////////////
     	Transform3D box2T3D = new Transform3D();
     		box2T3D.setTranslation(new Vector3d(-0.7f,0f,0.7f));
 		TransformGroup box2TG = new TransformGroup(box2T3D);
		Appearance box2Appearance = new Appearance();
			box2Appearance.setMaterial(new Material(new Color3f(0.8f,0.8f,0.8f),new Color3f(0f,0f,0f),new Color3f(0.9f,0.9f,0.9f),new Color3f(0.8f,0.8f,0.8f),1f));
			box2Appearance.setTexture(new TextureLoader("./img/cobblestone.gif", null).getTexture());
			box2Appearance.setTextureAttributes(new TextureAttributes(TextureAttributes.REPLACE,new Transform3D(),new Color4f(), TextureAttributes.NICEST)); 
		Box box2 = new Box(0.3f,0.3f,0.3f,Sphere.GENERATE_TEXTURE_COORDS, box2Appearance);
 		box2TG.addChild(box2);
 		superGroup.addChild(box2TG);
     	
 		
        bg.addChild(superGroup);
		bg.compile();
		return bg;
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main();
	}

}
```


----------

