# Brauche (kleine)InterpolatorHilfe



## mattn (25. Aug 2010)

mein ziel ist es, an ein objekt einer szene ranzuzoomen....
habe mir das wie folgt gedacht....

das objekt in der scene(nicht mittig^^) wird angeklickt und ich zoom an dieses ran...

ich dachte mir...ich schalte 3 PositionInterpolatoren hintereinander und die sollen gleichzeitig(jeder hat das selbe alpha- und somit zeitliche definition) in x, y und z richtung hinzoomen...

nur leider klappt das nicht ... es geht nur in horizontaler richtung(wenn nur der interpolator an ist) wenn ich die anderen (auch wenn ich die einzeln an mache) an mach... dann geh ich(mein sichtpunkt) komischerweise nah ran ..so das ich manchmal nur was flackern sehe...

im prinzip geht das so... 

ich richte den würfel (nicht zentriert) aus - damit was passiert...
dann klick ich auf "fly" ... dann wähl ich per klick den würfel aus...

koordinaten das würfels werden ausgelesen
koordinaten des view´s werden ausgelesen

dann werden die werte als start bzw endpunkt der interpolatoren angegeben...

auch wenn ich absolute werte für die interpolatoren per hand angebe... "zoomt der rein""

ich zeig euch mal den code
	
	
	
	





```
package testPackage;

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.GraphicsConfiguration;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.media.j3d.Alpha;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.PointLight;
import javax.media.j3d.PositionInterpolator;
import javax.media.j3d.SpotLight;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import com.eigeneImports.PickTranslateBehavior;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.behaviors.picking.PickZoomBehavior;
import com.sun.j3d.utils.behaviors.picking.PickingCallback;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.universe.SimpleUniverse;

	public class jumpTo extends Applet implements MouseListener {
		
		BoundingSphere BigBounds = new BoundingSphere(new Point3d(),100000);
		Canvas3D c;
		GraphicsConfiguration config;
		SimpleUniverse u ;
		BranchGroup sceneBG,rootBG,boxBG;
		TransformGroup mTG, boxTG;
		PickCanvas pickC;
		TransformGroup vpTG;
		Transform3D vpT3D;
		TextField modeTF;
		MouseTranslate mt;
		MouseRotate mr;
		MouseZoom mz;
		BranchGroup navBG;
		PickTranslateBehavior pickT;
		PickZoomBehavior pickZ;
		Boolean foo = false;
		
		
		public void init(){
			System.out.println("init");
			setLayout(new BorderLayout());
		    config = SimpleUniverse.getPreferredConfiguration();
		    c= new Canvas3D(config);
		    add("Center", c);
		    u = new SimpleUniverse(c);
		 // verschiebe ViewingPlatform:
			vpT3D = new Transform3D();
			vpTG = u.getViewingPlatform().getViewPlatformTransform();
			vpT3D.set(new Vector3f(0.0f, 0.0f, 10.0f));
			vpTG.setTransform(vpT3D);
			
			Vector3f vec = new Vector3f();
			vpT3D.get(vec);
			
			
			
			// Einstellung für die Größe des SimpleUniverse 
			View v = u.getViewer().getView();
			v.setFrontClipDistance(0.01);
			v.setBackClipDistance(1000000); // backDistance = 1000000;z.B
			v.getPhysicalBody().setNominalEyeOffsetFromNominalScreen(0.0);
			Gui();
			u.addBranchGraph(createSceneGraph());
		    
	}

		private void Gui() {
			// TODO Auto-generated method stub
			Panel panel = new Panel();
			
			Button neu = new Button ("neu");
			neu.setName("neu");
			neu.addMouseListener(this);
			panel.add(neu);
			
			Button fly = new Button ("fly");
			fly.setName("fly");
			fly.addMouseListener(this);
			panel.add(fly);
	
			add("South", panel);
		}

		private BranchGroup createSceneGraph() {
			sceneBG = new BranchGroup();
			rootBG = new BranchGroup();
			rootBG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
			rootBG.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
			rootBG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
//			rootBG.setCapability(BranchGroup.ALLOW_DETACH);
			
			mTG = new TransformGroup();
			mTG.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
			mTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			mTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			rootBG.addChild(mTG);
			
			sceneBG.addChild(rootBG);
			
			licht();
			
			pickC = new PickCanvas(c, rootBG);
			pickC.setTolerance((float) 10.0);
			c.addMouseListener(this);

			PickingCallback myCallback = new MyCallbackClass();
			pickT = new PickTranslateBehavior(rootBG, c, BigBounds);
			pickZ = new PickZoomBehavior(rootBG, c, BigBounds);
			pickT.setupCallback(myCallback);
			pickZ.setupCallback(myCallback);
			
			pick();
			
			
			sceneBG.compile();
			return sceneBG;
		}
		
		private void fly(Point3d pt){
			//Koordinaten vom gepicktenObjekt
			float boxX = (float)pt.x;
			float boxY = (float)pt.y;
			float boxZ = (float)pt.z;
			//Koordinaten vom PoV
			Vector3f vec = new Vector3f();
			vpT3D.get(vec);
			float povX = (float) vec.x;
			float povY = (float) vec.y;
			float povZ = (float) vec.z;
			
			System.out.println("Koordinaten vom Objekt:");
			System.out.println("x: " + boxX);
			System.out.println("y: " + boxY);
			System.out.println("z: " + boxZ);
			System.out.println("Koordinaten vom PoV:");
			System.out.println("x: " + povX);
			System.out.println("y: " + povY);
			System.out.println("z: " + povZ);
			
			
			BranchGroup flyBG = new BranchGroup();
			TransformGroup vpTrans = u.getViewingPlatform().getViewPlatformTransform();
			Transform3D axisOfTranslation = new Transform3D();
			
			Alpha transAlpha = new Alpha(	-1,
						      				Alpha.INCREASING_ENABLE,
						      				0, 0,
						      				5000, 0, 0,
						      				5000, 0, 0);
			
		
			//Flug in die Tiefe(Richtung X)
			axisOfTranslation.rotX(-Math.PI/2.0);
			PositionInterpolator translatorX = new PositionInterpolator(	transAlpha,
						     											vpTrans,
						     											axisOfTranslation,
						     											povX, boxX);
			translatorX.setSchedulingBounds(BigBounds);
//			flyBG.addChild(translatorX);

			//Flug in die Tiefe(Richtung Y)
			axisOfTranslation.rotZ(-Math.PI/2.0);
			PositionInterpolator translatorY = new PositionInterpolator(	transAlpha,
						     											vpTrans,
						     											axisOfTranslation,
						     											0f, -1f);
			translatorY.setSchedulingBounds(BigBounds);
			flyBG.addChild(translatorY);

			//Flug in die Tiefe(Richtung Z)
			axisOfTranslation.rotY(-Math.PI/2.0);
			PositionInterpolator translatorZ = new PositionInterpolator(	transAlpha,
						     											vpTrans,
						     											axisOfTranslation,
						     											0, -1);
			translatorZ.setSchedulingBounds(BigBounds);
//			flyBG.addChild(translatorZ);
			
			
			mTG.addChild(flyBG);
			
//			OrbitBehavior ob = new OrbitBehavior(c);
//		    ob.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE));
//		    u.getViewingPlatform().setViewPlatformBehavior(ob);
			
		}
		
		private void pick(){
			BranchGroup pickBG = new BranchGroup();
			pickBG.addChild(pickT);
			pickBG.addChild(pickZ);			
			rootBG.addChild(pickBG);	
		}
		
		private Appearance boxApp(){
			//Box-Settings
			Color3f ambientColourBox = new Color3f(0.8f,0.0f,0.0f);
		    Color3f emissiveColourBox = new Color3f(0.0f,0.0f,0.0f);
		    Color3f diffuseColourBox = new Color3f(0.8f,0.0f,0.0f);
		    Color3f specularColourBox = new Color3f(1.0f,0.0f,0.0f);
		    float shininessBox = 10.0f;
		    
		    Appearance app = new Appearance();
		    app.setMaterial(new Material(ambientColourBox,emissiveColourBox,diffuseColourBox,specularColourBox,shininessBox));		    
		    return app;
		}

		private void wuerfel(float x,float y,float z){
			boxBG = new BranchGroup();
			boxTG  = new TransformGroup();
			boxTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			boxTG.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
			boxBG.addChild(boxTG);
			boxTG.setName("boxTG");
			Transform3D boxT3D = new Transform3D();
			boxT3D.set(new Vector3f(0f,0f,0f));
			boxTG.setTransform(boxT3D);
			Box box = new Box(0.5f,0.5f,0.5f, boxApp());
			boxTG.addChild(box);
			mTG.addChild(boxBG);
		}
		
//		private void changeView(Point3d pt) {
//			// TODO Auto-generated method stub
//			vpT3D.set(new Vector3f(pt));
//			vpTG.setTransform(vpT3D);
//		}
//	
		private void licht(){
			BranchGroup bgLight = new BranchGroup();
			bgLight.setName("bgLight");
			bgLight.setCapability(BranchGroup.ALLOW_DETACH);
		    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);
		    BoundingSphere bounds1 = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);

		    //Licht Nr.1: direktionales Licht
		    Color3f lightColour1 = new Color3f(0.8f, 0.8f, 0.8f);
		    Vector3f lightDir1  = new Vector3f(-30f, -30f, 30f);
		    Vector3f lightDir2  = new Vector3f(30f, 30f, -30f);
		    DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
		    light1.setInfluencingBounds(bounds1);
//		    bgLight.addChild(light1);
	   
		    //Licht Nr.1: direktionales Licht2
		    DirectionalLight lightN = new DirectionalLight(lightColour1, lightDir2);
		    lightN.setInfluencingBounds(bounds1);
//		    bgLight.addChild(lightN);
		    

		    //Licht Nr.2: Eine punktfoermige Lichtquelle
		    Color3f lightColour2 = new Color3f(0.3f, 0.3f, 0.3f);
		    PointLight light2 = new PointLight(lightColour2,
		                                       new Point3f(0.505f,0.505f,0.505f),
		                                       new Point3f(0.1f,0f,0f));
		    light2.setInfluencingBounds(bounds);
		    bgLight.addChild(light2);


		    //Licht Nr.3: Ein Scheinwerfer
		    Color3f lightColour3 = new Color3f(0.3f, 0.3f, 0.3f);
		    SpotLight light3 = new SpotLight(lightColour3,
		                                     new Point3f(0.0f,0.0f,1.0f),
		                                     new Point3f(0.1f,0.1f,0.01f),
		                                     new Vector3f(0.0f,0.0f,-1.0f),
		                                     (float) (Math.PI/20),
		                                     0.0f);
		    light3.setInfluencingBounds(bounds);
//		    bgLight.addChild(light3);

		    //Licht Nr.4: Streulicht
		    Color3f lightColour4 = new Color3f(0.5f, 0.5f, 0.5f);
		    AmbientLight light4 = new AmbientLight(lightColour4);
		    light4.setInfluencingBounds(bounds);
		    bgLight.addChild(light4);
		    
		    sceneBG.addChild(bgLight);	
		}
	
		private void navigate(){
			
			mr = new MouseRotate();
			mr.setTransformGroup(mTG);
			mr.setSchedulingBounds(BigBounds);
			
			mt = new MouseTranslate();
			mt.setTransformGroup(mTG);
			mt.setSchedulingBounds(BigBounds);
			
			mz = new MouseZoom();
			mz.setTransformGroup(mTG);
			mz.setSchedulingBounds(BigBounds);
			
			navBG = new BranchGroup();
			navBG.setCapability(BranchGroup.ALLOW_DETACH);
			navBG.addChild(mr);
			navBG.addChild(mt);
			navBG.addChild(mz);
			rootBG.addChild(navBG);
		}
	

		
		@Override
		public void mouseClicked(MouseEvent e) {
			
			if (e.getComponent().getName().equals("neu")){
				wuerfel(0f,0f,0f);
			}
			
			if (e.getComponent().getName().equals("fly")){
				System.out.println("fly");
				foo=true;
				
			}
		
			
			else{
				pickC.setShapeLocation(e);
				pickC.setTolerance((float) 0.0);
			    PickResult result = pickC.pickClosest();
			    //kein Objekt getroffen
			    if (result == null) {
			       System.out.println("Nothing picked");
			    } 
			    else{
			    	//es wurde ein Würfel getroffen
			    	Node picktPrimitive = result.getNode(PickResult.PRIMITIVE);
			    	if (picktPrimitive != null) {
			    		System.out.println(picktPrimitive.getName());
			    		if(picktPrimitive.getParent().getParent().getBounds() instanceof BoundingSphere){
				        	BoundingSphere sphere = (BoundingSphere)picktPrimitive.getParent().getParent().getBounds(); //Bounds von der BG 
					        Point3d pt = new Point3d();
					       	sphere.getCenter(pt);
				        	System.out.println(pt);
				        	if (foo){
				        		fly(pt);
				        	}
				       	}
			       }
			    }
			}
		}
		public class MyCallbackClass extends Object implements PickingCallback{
	        public void transformChanged(int type, TransformGroup tg) {  
	        	
	        	System.out.println("df");
	        	//System.out.println(tg.getParent().getBounds());
	        	//System.out.println("vergleich " + tg.getParent());
//	        	if(tg!=null){
//	        		if (tg.getParent().getName() != null){
//	                	String compBox = new String(tg.getParent().getName());
//	                	System.out.println("compBox " + compBox);
//	                	line.updateCheck(compBox);
//	                	pt = new Point3d();
//	                	BoundingSphere sphere = (BoundingSphere)tg.getParent().getBounds();
//	        			sphere.getCenter(pt); }
	            }
	        }
	        
		@Override
		public void mouseEntered(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

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

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

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


----------



## Marco13 (25. Aug 2010)

Der PositionInterpolator interpoliert in X-Richtung. Für alles andere müßte man das Ergebnis noch auf die gewünschte Achse umrechnen. Schon mal einen PathInterpolator versucht?


----------



## mattn (26. Aug 2010)

nein noch nicht..ich versuch mich mal mit dem...

naja das es nur in x richtung geht is glaub ich nicht ganz richtig..:bahnhof:

mit Transform3D 
axisOfTranslation = new Transform3D();
axisOfTranslationY.rotY(-Math.PI/2.0);

rotX - horizonal
rotY - vor-zurück
rotZ - vertikal

oder seh ich das falsch


----------



## truesoul (26. Aug 2010)

Der Marco13 hat da schon recht.
Mit dem PositionInterpolator interpoliert nur auf der x-achse und PathInterpolator ist dafür am besten geeignet.
Mit rotX,rotY und rotZ rotiert man dementsprechend das Objekt oder den Viewer, wie auch immer .
Siehe Java3D Api:



> Sets the value of this transform to a counter clockwise rotation about the Y axis.


----------



## mattn (26. Aug 2010)

und was ist mit 



> PositionInterpolator
> The PositionInterpolator varies the position of a visual object(s) along an axis. The specification of the end
> points of interpolation is made with two floating point values and an axis of translation. The *default *axis of
> translation is the x-axis



beim PositionPathInterpolator  kommen doch mehrere Punkte dazu, die der "abfahren" soll und beim RotPosPathInterpolator noch zusätzlich eine Rotation .. oder versteh ich das falsch


mir reicht es ja, wenn der nur auf ein objekt ohne rotation "zugeht" ... sind ja nur 2 punkte


----------



## truesoul (26. Aug 2010)

mattn hat gesagt.:


> und was ist mit
> 
> 
> 
> ...



Ja das siehst du vollkommen richtig  
Mit PositionPathInterpolator kann man dein vorhaben auch umsetzen.


----------



## mattn (27. Aug 2010)

nur eine frage...
was macht das knots array....
das Pont3f[] sind ja sicherlich die punkte die "abgefahren" werden... aber knots?


----------



## Marco13 (27. Aug 2010)

Wenn man z.B. drei Positionen hat und er innerhalb von 5 Sekunden da durchlaufen soll, kann man mit den knots das Zeitverhalten bestimmen:

```
(0,0,0) knots[0]=0.0 // Sei nach 0.0 * 5 = 0.0 Sekunden hier
(0,0,1) knots[0]=[b]0.5 // Sei nach 0.5 * 5 = 2.5 Sekunden hier[/b]
(0,0,2) knots[0]=1.0 // Sei nach 1.0 * 5 = 5.0 Sekunden hier
```
vs.

```
(0,0,0) knots[0]=0.0 // Sei nach 0.0 * 5 = 0.0 Sekunden hier
(0,0,1) knots[0]=[b]0.2 // Sei nach 0.2 * 5 = 1.0 Sekunden hier[/b]
(0,0,2) knots[0]=1.0 // Sei nach 1.0 * 5 = 5.0 Sekunden hier
```


----------



## mattn (30. Aug 2010)

ok danke... macht sinn

hab nun aber noch 2 abschließende fragen...
die erste bezieht sich noch auf den *pospathinterpolator* besser gesagt auf das *alpha*
ziel ist es, wenn ich ein objekt(hier wieder würfel) anklicke...das der zentral auf dem bildschirm ist...
nun hab ich ein problem (wahrscheinlich) mit dem alpha...

wenn ich  den loopcount auf 1 habe 
springt die komplette transformationgruppe ohne animation zum gewünschten punkt

wenn ich  den loopcount auf -1 habe - endlosschleife
macht der das was er machen soll...aber halt unendlich lang

wenn ich  den loopcount auf 2 habe 
springt die tg kurz und "fährt" dann zur richtigen position(beim ersten mal)
beim 2. durchlauf ist alles korrekt

bei allen fällen springt der wenn ich denn zu einem andern würfel zoomen möchte sofort hin...
was is da falsch 

:/

_________
nun zum rotpospathinterpolator....
die rotation erfolgt, so wie ich mir das denk über die quats....
ich find in der api nur was über (x,y,z,w) nun hab ich gesucht wie ich die rotation in grad um eine bestimmte achse(x oder y oder z) angeben kann ...nachdem ich nix brauchbares gefunden habe...hab ich ein bisschen rumprobiert...blick aber immernoch nicht durch....
könnt ihr mir nen brauchbaren link geben oder es mir fix erklären....

ich zip mal schnell den code...falls ihr zeit und lust habt mir zu helfen...wär sehr dankbar...


jumpto- funktion ist in der Init.java Zeile 490 und wird bei 473 aufgerufen


----------



## Marco13 (30. Aug 2010)

Zum ersten:

```
Alpha a = new Alpha(
		    1, // loop count
		    Alpha.INCREASING_ENABLE, // mode
		    0, // triggerTime
		    50, // phaseDelayDuration,
		    500, //increasingAlphaDuration 
		    250, // increasingAlphaRampDuration
		    1000, //alphaAtOneDuration 
		    0, // decreasingAlphaDuration 
		    0, // decreasingAlphaRampDuration,
		    0//  alphaAtZeroDuration
		    );
		[b][u]a.setStartTime(System.currentTimeMillis()); // WICHTIG[/u][/b]
```

Er startet die Animation natürlich jetzt immer beim _ursprünglichen_ ausgangspunkt. Der müßte noch irgendwie auf den Enpunkt der letzten Animation gesetzt werden.

Zum zweiten: AxisAngle4f ist sehr anschaulich: Rotationsachse und Winkel. Und das kann mit quat.set(asxisAngle) in ein Quaternion gepackt werden.

BTW: Der Codestyle ist ... :autsch: Faszinierend, dass das überhaupt funktioniert


----------



## mattn (31. Aug 2010)

Marco13 hat gesagt.:


> BTW: Der Codestyle ist ... :autsch: Faszinierend, dass das überhaupt funktioniert




ja ich weiß ... ist chaotisch da ich mein richtiges projekt nicht verfuschen wollt...
hab ich code teile einfach rein gepackt...und wenig auf die "form geachtet da ich hier nur was testen wollt 
mein richtiger code ist anders 

ich test nachher mal 
_________________________________________
Edit
na toll war also echt nur das  a.setStartTime was gefehlt hat.... is ja doof...nagut die triggertime brauch ja irgendwoher nen bezugspunkt

aber leider habe ich das mit dem rotpospath noch nicht drauf...
ich will z.b. zum punkt -10,0,0 und dabei eine rotation um 90° machen.... so, das ich von diesen punkt auf das zentrum der scene schauen kann...
das alles natürlich flüssig animiert... so meine idee war folgende (vermutlich komplett falsch)


```
knots[0] = 0;
knots[1] = 1;

q1.set(new AxisAngle4f(0f,0f,0f, 0));
q2.set(new AxisAngle4f(0f,1f,0f, (float) (Math.PI/2)));
quat[0] = q1;
quat[1] = q2;

position[0] = new Point3f(0f,0f,0f);
position[1] = new Point3f(-10f,0f,0f);

RotPosPathInterpolator inter = new RotPosPathInterpolator(a,
                              tg,
                              t3d,
                              knots,
                              quat,
                              position);
```


----------



## mattn (1. Sep 2010)

edit geht nicht ... nach ein bisschen "rumspielen" macht der jetzt was der soll...
er fliegt zum angegebenen punkt und rotiert um 90° gegen den uhrzeigersinn
aber ich hab keinen schimmer wieso... 

```
q1.set(new AxisAngle4f(0f,1f,0f, (float) (Math.PI/0.5)));
                q2.set(new AxisAngle4f(0f,1f,0f, (float) (Math.PI/2)));
```
rotationsachse ist die y ... is klar... aber wieso ich die rotations-werte so angeben muss ist mir nen räzel

(Math.PI/0.5) gibt 360°  an
und
(Math.PI/2) gibt 90° an

wieso macht der bei einer anfangsrotation um 0° - keine rotation um 90° wie er machen sollte....

alls bisschen komisch -.-


----------



## truesoul (1. Sep 2010)

Vielleicht so: 

new AxisAngle4f(0f,1f,0f, (float) Math.toRadians(90))

Edit: Bei RotPosPathInterpolator dann so:
new Quat4f(0f,1f,0f, (float) Math.toRadians(90))

Gruß


----------



## mattn (1. Sep 2010)

truesoul hat gesagt.:


> Vielleicht so:
> 
> new AxisAngle4f(0f,1f,0f, (float) Math.toRadians(90))
> 
> ...



naja kommt auf das selbe raus... aber ich muss wohl irgendwas vergessen haben(vorhin) jetzt gets mit dem wert 0 -> also 0° egal es geht halt ^^


----------



## truesoul (1. Sep 2010)

Warum verwendest du 
	
	
	
	





```
Math.Pi/Zahl
```
 anstatt 
	
	
	
	





```
Math.toRadians( 0 )
```
 ?

toRadians( ) ; rechnet dir doch den Winkel direkt aus?!?


----------



## mattn (1. Sep 2010)

truesoul hat gesagt.:


> Warum verwendest du
> 
> 
> 
> ...



weil mir das als erstes eingefallen ist...(bisschen mathe hab ich noch im kopf gehabt ^^)  
und da ich ja nur die winkelwerte 0, 90, 180, 360 brauche sah ich darin kein problem

aber stimmt schon...toRadians(); ist auf jeden fall übersichtlicher


----------



## mattn (24. Sep 2010)

mhh ich nochmal :autsch:

hab ein problem mit dem RotationPathInterpolator
also erstmal das hauptziel.... so
ich habe eine szene welche aus würfeln mit einer caption... (also text3d drunter) besteht...
würfel und caption sind in folgender BG


```
-->box
boxBG --> boxTg--|                           
                 -->captionTg -->text3d
```

diese ganze szene kann gefreht gewendet werden und so weiter dies geschied in einer übergeordneten transformgroup...--> nur zum verständis also

nun berechne ich viewpunkte links, rechts, oben, unten, vorn, hinten 
--> die komplette szene(also die haupt-transformgroup ) dreht sich so, das ich von diesem punkt von der linken oder rechten seite auf die szene schauen kann(in richtung zentrum also)...
das geht schonmal...

allerdings muss ich jeden einzelnen knoten so drehen, das diese auch zu meinem punkt schauen damit ich die caption lesen kann...

ich habe mir also gedacht... ich nehm die boxTg(siehe oben) und dreh die box und die caption mit dem rotationpathinterpolator 

ich hab folgendes gemacht


```
RotPosPathInterpolator rotPosPathInt = new RotPosPathInterpolator(	a,
																				TG, 
																				t3d,
																				knots,
																				quat,
																				positions);
```

TG ist die boxTg
t3d ist TG.getTransform(t3d);

quat 1 wird ausgelesen
quat 2 ist auch korrekt....


das problem besteht darin, das sich die box und die caption nicht um die eigene achse drehen sondern 
um eine andere.....

das hat irgendwas damit zu tun, das die box erst via transform verschoben und dann erst rotiert wird...
wie im folgenden link zusehen
Chapter 3 - OpenGL Programming Guide

nun weiß ich aber nicht wie ich die rotationsachse richtig versetze... 

kann mir da jemand helfen

EDIT: oh ich seh grad ich hab den rotpospathinterpolator genomm(war ein test- da der rotpath ins zentrumgesprungen ist) ist aber nicht so tragisch, weil ich als end und anfangspos den selben wert habe....darin liegt das problem 100% nicht 

grüße


----------



## Marco13 (24. Sep 2010)

Nur als kleine Nachfrage (die nicht unbedingt was mit dem Problem zu tun hat) : Warum verwendest du überall interpolatoren? Da die Änderungen interpolierend reinzudengeln ist halt immer frickelig. Man kann auch direkt die Transform3D verändern...

Zur eigentlichen Frage: Du willst also so eine Art "Billboarding" für den Text!? Schon das alleine kann ziemlich fummelig werden (und bei der Erinnerung an den Code, den ich bisher gesehen habe, schaudert's mir immernoch :bae: ). Eigentlich sollten die (teilweise für Anfänger "unintuitiven") Verhaltensweisen bzw. Unterschiede zwischen "Drehen,dannVerschieben" und "Verschieben,dannDrehen" ja gerade durch den Szenegraphen nicht mehr auftreten. Bist du sicher, dass der Interpolator das macht, was du dir vorstellst? 

Wenn es nur um die finale Ausrichtung ginge, würde ich sowas versuchen(!) wie
F = Vektor, der senkrecht auf der Vorderseite des Textes steht (also dem Betrachter zugewandt sein muss, damit er den Text lesen kann)
C = Position der Kamera (mit getViewPlatformTransform & Co, in Weltkoordinaten)
T = Position des Textknotens (aus der Transform, die man sich mit getLocalToVWorld holen kann)
D = (C-T) = Richtung in die der Vektor F (die Vorderseite des Textes) zeigen muss, damit sie auf die Kamera gerichtet ist
R = (F x D) Kreuzprodukt als Rotationsachse des Textes
a = F.angleTo(D)
M = Matrix, die die Rotation um die Achse R um den Winkel 'a' beschreibt...
Das sollte dann die Matrix sein, die man auf den Textknoten anwenden muss (also mit der captionTg  multiplizieren, oder als eigene TG dahinterhängen, damit man die Ausrichtung unabhängig von der captionTg in einer eigenen TransformGroup hat) damit der Text in Richtung kamera gedreht ist. Da gibt's dann nochmal einen Freiheitsgrad für die Rotation, aber ... das würde man wohl irgendwie hinkriegen: Man müßte irgendwie sicherstellen, dass der Text auch _waagerecht_ steht. 

Aber das ist nur ein grober, erster Gedanke... nicht hauen, wenn's nicht funktioniert... Vielleicht gibt es aber auch irgendwo in den Tiefen von Java3D eine Funktion wie "alignTransformToViewPosition"  bin da nicht mehr so drin


----------



## mattn (24. Sep 2010)

hehe ja wie gesagt mein"richtiger code" ist schon einigermaßen übersichtlich......aber naja 
ich nutze interpolatoren, weil ich nicht sagen willl ... mache das und das bääm da ist es ... sondern es soll halt eine art animation sein.... sieht einfach besser aus....

wie gesagt mein problem ist "nur" das ich die komkplette transformgroup drehen will .... un zwar um die eigene achse.... also die rotationsachse sollte durch den mittelpunkt der transformgroup gehen... mehr will ich nicht... das andere was ich geschrieben habe....sollte nur zum verständnis dienen


----------



## Marco13 (24. Sep 2010)

Ja, das Ziel ist an sich schon klar. Interpolation und flüssige Bewegung ist das Alpha (  ) und Omega wenn es darum geht, den Überblick zu behalten. Aber in diesem Fall hängt die Bewegung ja von der Kameraposition ab. Also, der Text bewegt sich ja nicht "von sich aus", sondern passt sich nur der (schon durchgeführt werdenden) Bewegung anderer Objekte an !?

Wie auch immer: Wenn ein Objekt an einer TransformGroup hängt, und man die Transform verändert (rotiert), dann dreht sich das Objekt in bezug auf seinen lokalen Ursprung. Ein bißchen spekuliert: Läuft das ganze vielleicht darauf raus, das das Text-Objekt z.B. so

```
^
   | T E X T
   o-------->
```
liegt, und es für das, was du erreichen willst, so

```
^
        |
     T EoX-T--->
```
liegen müßte? 
Ach, habe mir gerade mal die Text3D-Klasse angesehen (kannte ich gar nicht  ) - das bezieht sich dann wohl auf den "alignment"-Parameter: Welche Position und welches Alignment verwendest du denn?


----------



## truesoul (25. Sep 2010)

Hallo mattn,

wie Marco schon fragte, warum den alles mit Interpolatoren machen?
Man könnte im weitesten Sinne einen eigenen Interpolator schreiben bzw in deinem fall eine eigene Animationsklasse.
Wie könnte so eine Klasse aussehen?

Nunja, man macht eine Threadklasse und dort dann, was sonst, das hier:

```
public void run()
{

     while(true)
     { 
          Thread.sleep(100);
          starteAnimation();

     }
}
```
(Pseudocode)
Und in der Methode (starteAnimation) könntest du z.B die Transformation eines oder von vielen Objekten ausführen.

Du kannst also Rotationen oder Positionieren selbst definieren und die würden, auch wie bei Interpolatoren, wie eine Animation angezeigt weren. Und wenn man noch ein wenig weiter denkt, könnte man hunderte unterschiedliche Animation zeigen ohne die zu Codieren, Informationen für Animation läd man von einer Datei, die man nach seinen wünsch anpasst.

Bei meinen Projekt im Praktikum musste ich mir auch Gedanken darüber machen wie man viele Varianten einer Animation zeigen könnte. Und es ist wirklich sehr fummelig, dafür Interpolatoren zu verwenden.

Es geht definitiv viel schneller wenn man eine eigene Klasse erstellt.

In meinen Augen war das eine super Lösung. 

MfG


----------



## Marco13 (25. Sep 2010)

Es gibt Stellen, wo Interpolatoren Sinn machen. Wie bei "allen" Standardklassen: Sie erfüllen einen bestimmten Zweck, und wenn man _genau das_ erreichen will, was sie machen, nimmt man sie. Aber je weiter das, was man machen will, von dem abweicht, was die Standardfunktion ist (und je mehr Tweaks und Kniffe und Anpassungen der vorhandenen Klasse zum Erreichen des Zieles notwendig sind) umso genauer sollte man sich überlegen, ob man nicht eine eigene Klasse dafür nehmen sollte.


----------



## mattn (26. Sep 2010)

so ich habe mal fix folgendes zusammengebaut...
ja das liegt alles in einer klasse und sieht nicht sonderlich schön aus... aber das problem wird dadurch exakt dargestellt... ich lad es mal hoch....

der rechte würfel dreht sich nicht um die eigene sondern um eine andere achse ... 
der soll halt an der seleben position bleiben und sich nur drehen


----------



## Marco13 (26. Sep 2010)

Oh ja, wenn in der boxTG der Translationsanteil direkt drin steckt funktioniert das natürlich nicht. Am einfachsten wäre da ein weiterer Zwischenschritt (d.h. Translation und Rotation trennen). Alternativ könnte man die Transform3D selbst passend ausrechnen, aber warum rechnen, wenn man einen Szenegraphen hat 

Reingehackt als "boxTg2", DIE enthält dann die Drehung (boxTg nurnoch die Translation)

```
// From [url]http://www.java-forum.org/spiele-multimedia-programmierung/104996-brauche-kleine-interpolatorhilfe-2.html#post679650[/url]
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Panel;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Line2D;
import java.util.Vector;
import com.sun.j3d.utils.applet.MainFrame;

import javax.media.j3d.Alpha;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Font3D;
import javax.media.j3d.FontExtrusion;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.RotPosPathInterpolator;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Text3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class BoxDummy extends Applet implements MouseListener{
    private static BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);
    private static  Button check;
    public static Vector<TransformGroup> boxTgContainer = new Vector<TransformGroup>();
    private static BranchGroup rootBg;

    public static void main(String[] args)
    {
        MainFrame f = new MainFrame(new BoxDummy(),500,500);
    }


    public void init(){
        setLayout(new BorderLayout());
        Canvas3D c = canvas();
        add("Center", c);

        Panel panel = new Panel();
        check = new Button ("check");
        check.setName("check");
        panel.add(check);
        check.addMouseListener(this);

        add("South", panel);
        setUniverse(c);
    }

    private static BranchGroup newScene(Canvas3D c) {
                        rootBg = rootBranchGroup();
        TransformGroup  rootTg = rootTransformGroup();
        Transform3D     rootT3d = new Transform3D();
        BranchGroup     localBg = localBg();
        BranchGroup     lichtBg = licht();
        rootTg.setTransform(rootT3d);

        rootBg.addChild(lichtBg);
        rootBg.addChild(rootTg);
        rootTg.addChild(localBg);

        localBg.addChild(BoxBg(1.5f,0.5f,0.5f, "eins"));
        localBg.addChild(BoxBg(0.0f,0.5f,0.5f, "zwei"));

        rootBg.compile();
        return rootBg;
    }



    private static BranchGroup ani(){
        BranchGroup ani = new BranchGroup();
        //RotationPath
        Alpha a = alpha();
        float[] knots = knots();

            Point3f interpolatorStart = new Point3f();
            TransformGroup TG = boxTgContainer.elementAt(0);
            Transform3D t3d = new Transform3D();
            Vector3f v = new Vector3f();
            TG.getTransform(t3d);

            System.out.println("got\n"+t3d);

            t3d.get(v);
            t3d.setTranslation(v);
            System.out.println(t3d);
//          //*****Startpunkt*****//
            interpolatorStart.x = v.x;//target.x;
            interpolatorStart.y = v.y;//target.y;
            interpolatorStart.z = v.z;//target.z;

            Point3f[] positions = new Point3f[2];
            positions[0] = interpolatorStart;
            positions[1] = interpolatorStart;
//
            Quat4f q1 = new Quat4f();
            t3d.get(q1);
            Quat4f q2 = new Quat4f();
            q2.set(new AxisAngle4f(0f,1f,0f, (float) Math.toRadians(90)));

            Quat4f[] quat = new Quat4f[2];
            quat[0] = q1;
            quat[1] = q2;
            RotPosPathInterpolator rotPosPathInt = new RotPosPathInterpolator(  a,
                                                                                TG,
                                                                                t3d,
                                                                                knots,
                                                                                quat,
                                                                                positions);
            rotPosPathInt.setSchedulingBounds(bounds);
            ani.addChild(rotPosPathInt);
        return ani;
    }

    private static Alpha alpha(){
        Alpha alpha = new Alpha(    1,                  //loop count
                Alpha.INCREASING_ENABLE,//mode
                0,                      //triggerTime
                50,                     //phaseDelayDuration,
                5000,                   //increasingAlphaDuration
                5000,                   //increasingAlphaRampDuration
                1000,                   //alphaAtOneDuration
                0,                      //decreasingAlphaDuration
                0,                      //decreasingAlphaRampDuration,
                0                       //alphaAtZeroDuration
               );
        alpha.setStartTime(System.currentTimeMillis()); // WICHTIG
        return alpha;
    }
    private static float[] knots(){
        float[] knots = new float[2];
        knots[0] =  0;
        knots[1] =  1;
        return knots;
    }
    private static BranchGroup BoxBg(float x,float y,float z, String caption){
        BranchGroup boxBg = new BranchGroup();
        boxBg.setName("boxBg");
        boxBg.setCapability(BranchGroup.ALLOW_DETACH);

        TransformGroup  boxTg = new TransformGroup();
        Vector3f    boxPos = new Vector3f(x,y,z);
        Transform3D boxT3d = new Transform3D();
        boxT3d.set(boxPos);
        boxTg.setTransform(boxT3d);
        boxTg.setName("boxTg");
        boxTg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        boxTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        boxTg.setCapability(TransformGroup.ENABLE_PICK_REPORTING);

        TransformGroup  boxTg2 = new TransformGroup();
        Transform3D boxT3d2 = new Transform3D();
        boxTg2.setTransform(boxT3d2);
        boxTg2.setName("boxTg2");
        boxTg2.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        boxTg2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        boxTg2.setCapability(TransformGroup.ENABLE_PICK_REPORTING);

        TransformGroup captionTg = new TransformGroup();
        Transform3D    captionT3d= new Transform3D();
        captionT3d.set(new Vector3f(-0.05f, -0.9f, 0f));
        captionT3d.setScale(0.3);
        captionTg.setTransform(captionT3d);
        FontExtrusion fontEx     = new FontExtrusion(new Line2D.Double(0, 0, 0.01, 0));
        Font3D        font3D     = new Font3D(new Font("Helvetica", Font.PLAIN, 1),fontEx);
        Text3D        textGeom   = new Text3D(font3D,caption);
        textGeom.setAlignment(Text3D.ALIGN_CENTER);
        Shape3D       textShape  = new Shape3D();
        textShape.setGeometry(textGeom);
        textShape.setAppearance(new Appearance());
        captionTg.addChild(textShape);

        Box box = new Box(0.5f,0.5f,0.5f, new Appearance());


        boxTgContainer.add(boxTg2);

        boxTg2.addChild(box);
        boxTg.addChild(boxTg2);
        boxTg.addChild(captionTg);
        boxBg.addChild(boxTg);

        return boxBg;
    }
    private static void setUniverse(Canvas3D c){
        SimpleUniverse u = new SimpleUniverse(c);

        //----- verschiebe ViewingPlatform: -----
        TransformGroup  vpTG    = u.getViewingPlatform().getViewPlatformTransform();
        Transform3D vpT3D       = new Transform3D();
        vpT3D.set(new Vector3f(0.0f, 0.0f, 15.0f));
        vpTG.setTransform(vpT3D);

        //----- Einstellung für die Größe des SimpleUniverse -----
        View v  = u.getViewer().getView();
        v.setFrontClipDistance(0.01);
        v.setBackClipDistance(1000000);
        v.getPhysicalBody().setNominalEyeOffsetFromNominalScreen(0.0);

        u.addBranchGraph(newScene(c));
    }
    private static Canvas3D canvas(){
        GraphicsConfigTemplate3D template  = new GraphicsConfigTemplate3D();
        template.setSceneAntialiasing(1);  //1 = Multisampling Antialiasing
        Canvas3D canvas = new Canvas3D( GraphicsEnvironment.
                                        getLocalGraphicsEnvironment().
                                        getDefaultScreenDevice().
                                        getBestConfiguration(template));
        return canvas;
    }
    private static BranchGroup rootBranchGroup(){
        BranchGroup rootBg = new BranchGroup();
        rootBg.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        rootBg.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
        rootBg.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        rootBg.setCapability(BranchGroup.ALLOW_DETACH);
        return rootBg;
    }
    private static TransformGroup rootTransformGroup(){
        TransformGroup rootTg = new TransformGroup();
        rootTg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        rootTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        rootTg.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        return rootTg;
    }
    private static BranchGroup localBg(){
        BranchGroup localBg = new BranchGroup();
        localBg.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        localBg.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
        localBg.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        localBg.setCapability(BranchGroup.ALLOW_DETACH);
        return localBg;
    }
    private static BranchGroup licht(){
        BranchGroup lichtBg = new BranchGroup();
        Color3f lightColour4 = new Color3f(0.5f, 0.5f, 0.5f);
        AmbientLight light4 = new AmbientLight(lightColour4);
        light4.setInfluencingBounds(bounds);
        lichtBg.addChild(light4);
        return lichtBg;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getComponent().getName().equals("check")){
            rootBg.addChild(ani());
        }

    }

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

    }

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

    }

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

    }

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

    }



}
```


----------



## mattn (29. Sep 2010)

ok auf die idee wär ich sicher erst nach einigen stunden gekommen ... weil irgendwie hab ich mich im kopf darauf festgelegt, das ich die bezugsachse verschieben kann aber hab halt nicht gewusst wie...
aber klar das ist die einfachste methode ... dank dir


----------

