# Kugeln verschieben (Vektoren) und Schnitt prüfen



## Brügge (12. Dez 2005)

Hallo!
Ich habe 2 Probleme, die ich bislang nicht lösen konnte:

Problem 1:

Ich möchte in meinem Universum eine Kugel erzeugen und diese an eine durch einen Vektor gegebene Stelle im Raum
erscheinen lassen. Zum Beispel:
Kugel.koordinaten.x1 = 10
Kugel.koordinaten.x2 = 1023
Kugel.koordinaten.x3 = 23.5
Jetzt möchte ich mit einer Methode die Kugel an der Stelle 10,1023,23.5 anzeigen lassen.
Später soll sich die Position der Kugel ständig ändern. Wie mache ich das?

mein 2. Problem ist, dass ich prüfen will, ob sich 2 Kugeln schneiden oder berühren.
Ich will lediglich wissen ob sie dies tun, nicht etwa schnittmengen oder ähnliches bestimmen.



Danke schon im Voraus,

MFG Christian


----------



## Illuvatar (12. Dez 2005)

Als Kugeln nimmst du Spheres. Die musst du unterhalb einer TransformGroup einhängen und diesen verschieben.

Zum bewegen benötigst du einen entsprechenden TransformInterpolator.

Das mit intersection hab ich noch nie gemacht, da kann ich nur auf das zugegebenerweise sehr gute Tutorial der "Konkurrenz" verweisen:

http://www.javacore.de/tutorials.php


----------



## Soulfly (12. Dez 2005)

Anonymous hat gesagt.:
			
		

> Hallo!
> 
> Jetzt möchte ich mit einer Methode die Kugel an der Stelle 10,1023,23.5 anzeigen lassen.
> Später soll sich die Position der Kugel ständig ändern. Wie mache ich das?



Koordinaten ändern?!



			
				Anonymous hat gesagt.:
			
		

> Hallo!
> mein 2. Problem ist, dass ich prüfen will, ob sich 2 Kugeln schneiden oder berühren.
> Ich will lediglich wissen ob sie dies tun, nicht etwa schnittmengen oder ähnliches bestimmen.



Jede Kugel hat nen Radius gell?
Wenn der Abstand zwischen den Kugelpunkten kleiner als die Summe der Radien ist, schneiden sie sich. fertig!


----------



## Brügge (12. Dez 2005)

@Iluvatar:
Danke für die Hilfe, ich glaub damit kann ich was anfangen 

@Soulfly:
Sehr konstruktiver Beitrag.. Koordinaten ändern ... dann sag mir mal wie man drauf zugreift wenn man ein Objekt des Typs Sphere hat. und das der 2*r kleiner als der Abstand sein muss ist mir auch klar, aber da tritt wieder das Problem mit den Koordinaten auf..


----------



## Brügge (12. Dez 2005)

So, ich hab mich mal etwas reingehangen und bin nun so weit das ich Kugeln erzeugen, sie an die TransformGroup hängen und dies an den Scenegraphen hängen kann. eine Koordinate festlegen klappt auch, jedoch will ich die Koordinaten der Kugel später ändern, nur wie? Die Sache mit dem TransformInterpolator hab ich überhaupt nicht verstanden, was tut er und wie und wo setze ich ihn ein?

MFG Christian


----------



## Illuvatar (12. Dez 2005)

Du machst einen TransformInterpolator (brauchst halt die entsprechende Unterklasse, jenachdem wie die sich bewegen soll), den richtest du entsprechend ein und hängst ihn in den SceneGraph (also am besten du hast dann sowas:


```
BranchGroup
		|
	TransformGroup mit Koordinaten
		|
	TransformGroup, die verändert wird
	achtung: die koordinaten sind relativ zu denen der oberen TransformGroup
	achtung2: Capability (ALLOW_TRANSFORM_WRITE) setzen
	/																	\
Interpolator, der die untere TransformGroup ändert		Sphere
Achtung: SchedulingBounds setzen
```

Mehr auch hier:
http://www.java-forum.org/de/viewtopic.php?p=21408#21408


----------



## DeepBlue (13. Dez 2005)

Schöner kann mans eigentlich nicht erklären 

Was die Schnitterkennung angeht, musst du dir wie gesagt mal Intersection bzw. Collision Detection angucken. Da gibts ein paar nützliche Java3D Klassen. Leider habe ich da auch (noch) keine Ahnung von und kann dir da nicht weiterhelfen.


----------



## Brügge (14. Dez 2005)

Hallo nochmal...

Also ich hab leider immernoch keine Lösung gefunden  Aber ich kann ja meinen Code mal posten:


```
import java.awt.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.TextureLoader;
import javax.media.j3d.TransformInterpolator;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.mouse.*;

public class KugelSimulation extends Frame {
	Options opt = new Options();
	
	public KugelSimulation() {
		
		// Graphikkunfigurationi holen (Farbtiefe usw.)
		GraphicsConfiguration config = 
			SimpleUniverse.getPreferredConfiguration();
		
		// Neues Canvas erzeugen und hinzufügen
		Canvas3D canvas3d = 
			new Canvas3D (config);
        add(canvas3d);
        
        // Neues Universum hinzufügen und Betrachtungsebene erzeugen
        SimpleUniverse universe = new SimpleUniverse(canvas3d);
      
        // neue Branchgruppe
        BranchGroup bgScene = createScene();
       
        // ViewPlatform wird so eingestellt,
		// dass man die Objekte betrachten kann
		universe.getViewingPlatform().setNominalViewingTransform();
		
        // ... an das Universum hängen
        universe.addBranchGraph(bgScene);
        
	}
	
	public BranchGroup createScene() {
		
		BranchGroup objRoot = new BranchGroup(); // Wurzel
		
		Appearance KugelAppear = new Appearance(); // Aussehen der Kugeln
		KugelAppear.setTexture( new TextureLoader("Kugel.jpg", this).getTexture());
		
		Sphere[] Kugel = new Sphere[10]; // Initiierung der Kugeln
		for(int i = 0; i < 10; i++)
			Kugel[i] = new Sphere(0.04f, Primitive.GENERATE_TEXTURE_COORDS, KugelAppear );
		
		
		Transform3D[] t3dKugel = new Transform3D[10];
		TransformGroup[] tgKugel = new TransformGroup[10];
		
		TransformInterpolator[] piKugel = new PositionInterpolator[10];
		
		for(int i = 0; i < 10; i++) {
			t3dKugel[i] = new Transform3D();
			piKugel[i] = new PositionInterpolator (new Alpha (1,2000), tgKugel[i]);
			t3dKugel[i].setTranslation(new Vector3f(i,i * 2,i * 0.5f));
			tgKugel[i] = new TransformGroup(t3dKugel[i]);
			tgKugel[i].addChild(Kugel[i]);
			tgKugel[i].setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		}
		
			
		
		BoundingSphere bounds = new BoundingSphere();
		
		PointLight light = new PointLight();
		light.setInfluencingBounds(bounds);
		
		TransformGroup objRotate = new TransformGroup();
		objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		MouseRotate mouseRotate = new MouseRotate();
		MouseZoom mouseZoom = new MouseZoom(objRotate);
		mouseRotate.setTransformGroup(objRotate);
		mouseRotate.setSchedulingBounds(bounds);
		mouseZoom.setSchedulingBounds(bounds);
		
		
		
		
		
		objRoot.addChild(objRotate);
		objRotate.addChild(mouseRotate);
		objRotate.addChild(mouseZoom);
		for(int i = 0; i < 10; i++)
			objRotate.addChild(tgKugel[i]);
		
		objRotate.addChild(light);
		
		objRoot.compile();
		

		return objRoot;
	}
	
	public static void main(String[] args) {
		KugelSimulation Main = new KugelSimulation();
		Main.setSize(800,600);
		Main.setVisible(true);
	}
}
```

Im Moment passiert nicht mehr als das 10 Kugeln versetzt von einander angezeigt werden, das Mauszoomen und so funktioniert alles.

Meine eigentliche Überlegung ist die, dass ich für eine Kugel einen zufälligen Startpunkt haben will und sie in eine bestimmte Richtung "abschießen" will, sie soll durch den Raum fliegen und wenn sie eine bestimmte x- y- oder z-koordinate erreicht hat, soll sie gelöscht werden. ich habe bereits eine Methode geschrieben, mit der ich die jeweils neuen Koordinaten berechne. Im prinzip soll das so in etwa aussehen


```
while(kugel innerhalb bestimmter koordinaten) {
  zeichne Kugel;
  verschiebe Kugel um 1 Pixel;
  Warte 10 Millisekunden;
}
```


----------



## Illuvatar (14. Dez 2005)

Vielleich kann dir das Beispiel etwas helfen:


```
import javax.swing.*;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;  //SimpleUniverse
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.behaviors.vp.*;
import java.util.*;

public class KugelSimulation extends JFrame implements ActionListener  //JFrame um Vermischung von Swing <-> Canvas3D (AWT) zu zeigen
{
  public static final long serialVersionUID = 121121112l;  //Für Java1.5-Unterstützung
  //Konstruktor
  public KugelSimulation()
  {
    super ("Bla");
    setSize (800, 600);
    setLocationRelativeTo (null);  //zentrieren
    setDefaultCloseOperation (DO_NOTHING_ON_CLOSE);  //Schließen soll im Menu geschehen
    JPopupMenu.setDefaultLightWeightPopupEnabled (false);  //Damit das Menu funktioniert, lassts mal zum Test weg
    setCloseMenuBar (this);
    //Jetzt kommt der 3D-Teil
    Canvas3D c3d = new Canvas3D (SimpleUniverse.getPreferredConfiguration());  //So am besten
    SimpleUniverse simpleU = new SimpleUniverse (c3d);  //Das VirtualUniverse, hier wird auch schon der View hinzugefügt
    BranchGroup bg = new BranchGroup();  //Haupt-BranchGroup
    createScene (bg);
    OrbitBehavior orbit = new OrbitBehavior(c3d, OrbitBehavior.REVERSE_ALL);  //OrbitBehavior liegt in dem Paket com.sun.j3d.utils.behaviors.vp
    orbit.setSchedulingBounds (new BoundingSphere ());
    simpleU.getViewingPlatform().setViewPlatformBehavior (orbit);
    bg.compile();  //Optimiert das Rendern
    simpleU.addBranchGraph (bg);  //Fügt den SceneGraph hinzu
    Transform3D cam = new Transform3D();
    cam.setTranslation (new Vector3f (0, 0, 75));
    simpleU.getViewingPlatform().getViewPlatformTransform().setTransform(cam);
    c3d.getView().setBackClipDistance(150);
    add (c3d);  //Vor 1.5: getContentPane().add
    setVisible (true);
  }
  private Kugel[] spheres;
  private void createScene (BranchGroup scene)
  {
    int SPHERE_COUNT = 10;
    spheres = new Kugel[SPHERE_COUNT];
    Random r = new Random();
    for (int i = 0; i < SPHERE_COUNT; i++){
      Kugel k = new Kugel();
      spheres[i] = k;
      Vector3f pos = new Vector3f();
      pos.x = r.nextFloat() * 10 - 5;
      pos.y = r.nextFloat() * 10 - 5;
      pos.z = r.nextFloat() * 10 - 5;
      k.direction.x = r.nextFloat() * 10 - 5;
      k.direction.y = r.nextFloat() * 10 - 5;
      k.direction.z = r.nextFloat() * 10 - 5;
      k.direction.normalize();
      k.direction.scale (0.25f); //hier indirekt geschwindigkeit bestimmen
      Transform3D t3d1 = new Transform3D();
      t3d1.setTranslation(pos);
      TransformGroup transTG = new TransformGroup (t3d1);
      scene.addChild (transTG);
      TransformGroup move = new TransformGroup();
      k.move = move;
      move.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
      transTG.addChild (move);
      Sphere s = new Sphere (1, 0, 100);
      move.addChild (s);
    }
    Mover m = new Mover();
    scene.addChild (m);
  }
  //Beenden-Menu
  private void setCloseMenuBar (JFrame f)
  {
    JMenuBar jmb = new JMenuBar();
    JMenu jm = new JMenu ("Datei");
    jmb.add (jm);
    JMenuItem close = new JMenuItem ("Beenden");
    jm.add (close);
    close.addActionListener (this);
    f.setJMenuBar (jmb);
  }
  public void actionPerformed (ActionEvent evt)
  {
    System.exit (0);
  }
  //Startmethode
  public static void main (String[]args)
  {
    new KugelSimulation();
  }
  private class Kugel
  {
    public Point3f point = new Point3f();
    public Vector3f direction = new Vector3f();
    public TransformGroup move;
  }
  private class Mover extends Behavior
  {
    public Mover ()
    {
      setSchedulingBounds (new BoundingSphere(new Point3d(), 300));
    }
    private WakeupCondition wc = new WakeupOnElapsedTime(20);
    public void initialize()
    {
      wakeupOn (wc);
    }
    public void processStimulus (Enumeration criteria)
    {
      System.out.println("here");
      for (int i = 0; i < spheres.length; i++){
         spheres[i].point.add (spheres[i].direction);
         //hier evtl. Kugel löschen
         Transform3D t3d = new Transform3D();
         t3d.setTranslation (new Vector3f(spheres[i].point));
         spheres[i].move.setTransform (t3d);
      }
      wakeupOn (wc);
    }
  }
}
```


----------



## Bruegge (17. Dez 2005)

Hallo nochmal,

ich hab mich am Wochenende nochmal mit dem Code von dir beschäftigt, und er war wirklich sehr hilfreich!
Danke dafür!!! Momentan sieht mein ergbnis so aus:


```
import javax.swing.*;

import java.awt.GraphicsEnvironment;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.universe.*;  //SimpleUniverse
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.behaviors.vp.*;
import java.util.*;
import java.awt.Color;

public class KugelSimulation extends JFrame implements ActionListener  //JFrame um Vermischung von Swing <-> Canvas3D (AWT) zu zeigen
{
	public static final long serialVersionUID = 121121112l;  //Für Java1.5-Unterstützung
	//Konstruktor
	public KugelSimulation()
	{
		super ("Bla");
		setSize (800, 600);
		setLocationRelativeTo (null);  //zentrieren
		setDefaultCloseOperation (DO_NOTHING_ON_CLOSE);  //Schließen soll im Menu geschehen
		JPopupMenu.setDefaultLightWeightPopupEnabled (false);  //Damit das Menu funktioniert, lassts mal zum Test weg
		setCloseMenuBar (this);
		
		
		//Jetzt kommt der 3D-Teil
		Canvas3D c3d = new Canvas3D (SimpleUniverse.getPreferredConfiguration());  //So am besten
		SimpleUniverse simpleU = new SimpleUniverse (c3d);  //Das VirtualUniverse, hier wird auch schon der View hinzugefügt
		BranchGroup bg = new BranchGroup();  //Haupt-BranchGroup
		createScene (bg);
		OrbitBehavior orbit = new OrbitBehavior(c3d, OrbitBehavior.REVERSE_ALL);  //OrbitBehavior liegt in dem Paket com.sun.j3d.utils.behaviors.vp
		orbit.setSchedulingBounds (new BoundingSphere ());
		simpleU.getViewingPlatform().setViewPlatformBehavior (orbit);
		bg.compile();  //Optimiert das Rendern
		simpleU.addBranchGraph (bg);  //Fügt den SceneGraph hinzu
		Transform3D cam = new Transform3D();
		cam.setTranslation (new Vector3f (0, 0, 75));
		simpleU.getViewingPlatform().getViewPlatformTransform().setTransform(cam);
		c3d.getView().setBackClipDistance(150);
		add (c3d);  //Vor 1.5: getContentPane().add
		setVisible (true);
	}
	private Kugel[] spheres;
	private int anzahl = 100;
	private boolean mitte = true;
	private int groesse = 100;
	private final Color3f BLACK = new Color3f(0f, 0f, 0f);
	private final Color3f WHITE = new Color3f(1f, 1f, 1f);
	
	private void createScene (BranchGroup scene)
	{
		BoundingSphere bounds = new BoundingSphere();
		Appearance appKugel = new Appearance(); // Aussehen der Kugeln
		appKugel.setMaterial(new Material(BLACK, BLACK, WHITE, WHITE, 1f));
		spheres = new Kugel[anzahl];
		
		for (int i = 0; i < anzahl; i++){
			Kugel k = new Kugel();
			spheres[i] = k;
			Vector3f pos = new Vector3f();
			pos.x = k.point.x;
			pos.y = k.point.y; 
			pos.z = k.point.z; 
			k.direction.normalize();
			k.direction.scale (0.25f); //hier indirekt geschwindigkeit bestimmen
			Transform3D t3d1 = new Transform3D();
			t3d1.setTranslation(pos);
			TransformGroup transTG = new TransformGroup (t3d1);
			scene.addChild (transTG);
			TransformGroup move = new TransformGroup();
			k.move = move;
			move.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			transTG.addChild (move);
			Sphere s = new Sphere (1, 0, 100, appKugel);
			move.addChild (s);
		}
		
		Mover m = new Mover();
			
		
		// Sonne (Mittelkugel):
		Appearance appSun = new Appearance(); // Aussehen der Sonne
		appSun.setMaterial(new Material(BLACK, WHITE, WHITE, WHITE, 1f));
		appSun.setTexture( new TextureLoader("sun.jpg", this).getTexture());
		
		TransformGroup tgSun = new TransformGroup();
		Sphere Sun = new Sphere(0.9f, Primitive.GENERATE_TEXTURE_COORDS, appSun );
		tgSun.addChild(Sun);
		
		TransformGroup all = new TransformGroup();
				
		all.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		all.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		
		MouseRotate mouseRotate = new MouseRotate();
		MouseZoom mouseZoom = new MouseZoom(all);
		mouseRotate.setTransformGroup(all);
		mouseRotate.setSchedulingBounds(bounds);
		mouseZoom.setSchedulingBounds(bounds);
		
		// Licht
		PointLight sunlight = new PointLight();
		sunlight.setInfluencingBounds(bounds);
		
		scene.addChild(all);
		all.addChild(mouseRotate);
		all.addChild(mouseZoom);
		all.addChild(m);
		all.addChild(tgSun);
		all.addChild(sunlight);
	}
	//Beenden-Menu
	private void setCloseMenuBar (JFrame f)
	{
		JMenuBar jmb = new JMenuBar();
		JMenu jm = new JMenu ("Datei");
		jmb.add (jm);
		JMenuItem close = new JMenuItem ("Beenden");
		jm.add (close);
		close.addActionListener (this);
		f.setJMenuBar (jmb);
	}
	public void actionPerformed (ActionEvent evt)
	{
		System.exit (0);
	}
	//Startmethode
	public static void main (String[]args)
	{
		new KugelSimulation();
	}
	private class Kugel
	{
		public Kugel() {
			double rnd; 
			
			klebt = false;
			
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse; 
			point.x = (int) rnd;
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse;
			point.y = (int) rnd;
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse;
			point.z = (int) rnd;
			
			
			if (mitte == false) { 
				rnd = (java.lang.Math.random() * groesse);
				direction.x = (int) rnd;
				rnd = (java.lang.Math.random() * groesse);
				direction.y = (int) rnd;
				rnd = (java.lang.Math.random() * groesse);
				direction.z = (int) rnd;
				
			} else { 
				direction.x = -point.x;
				direction.y = -point.y;
				direction.z = -point.z;
			}
		}
		public Point3f point = new Point3f();
		public Vector3f direction = new Vector3f();
		public TransformGroup move;
		public boolean klebt;
		
		public boolean stoss(double i1, double i2, double i3) {
			double a1, a2, a3;
			
			a1 = point.x - i1;
			a2 = point.y - i2;
			a3 = point.z - i3;
			
			if ((Math.sqrt(a1 * a1 + a2 * a2 + a3 * a3)) > 1) {
				return false;
				
			} else {
				klebt = true; 
				return true; 
			}
		}
	}
	private class Mover extends Behavior
	{
		public Mover ()
		{
			setSchedulingBounds (new BoundingSphere(new Point3d(), 300));
		}
		private WakeupCondition wc = new WakeupOnElapsedTime(20);
		public void initialize()
		{
			wakeupOn (wc);
		}
		public void processStimulus (Enumeration criteria)
		{
			for (int i = 0; i < spheres.length; i++){
				spheres[i].point.add (spheres[i].direction);
				//hier evtl. Kugel löschen
				Transform3D t3d = new Transform3D();
				t3d.setTranslation (new Vector3f(spheres[i].point));
				spheres[i].move.setTransform (t3d);	
			}
			wakeupOn (wc);
		}
	}
}
```


Jedoch gibts noch einiges was ich nicht ganz verstehe:
1) Ich möchte gern das von der Sonne Licht ausgeht, dazu hab ich eigentlich schon alles nötige implementiert, jedoch
kann ich den Mover m nicht zu einer BoundingSphere zuordnen. Wie mache ich das möglich?
2) möchte ich gern, dass man mit der Maus um die Geschichte rotieren kann und sich so das Geschehen von allen Seiten angucken kann, und dass man zoomen kann. Auch hier habe ich schon einiges geschrieben, und das selbe Problem, dass ich den Mover m zu meiner BoundingSphere zuordnen muss. 

wenn ich dies mit:

```
m.setSchedulingBounds(bounds)
```
mache, so bleibt das Gesamtbild stehen und nichts passiert.  
Hätte da vielleicht jemand eine Idee?

Danke vielmals!!

Christian


----------



## Illuvatar (18. Dez 2005)

1. Das mit dem licht ist bei dir eigentlich gut, du hast nur vergessen, die Normals der Spheres generieren zu lassen, dann sieht man das Licht nämlich nicht.

```
Sphere s = new Sphere (1, Primitive.GENERATE_NORMALS, 100, appKugel);
```
Das Licht ist so allerdings nur in einem sehr begrenzten Bereich um die Sonne zu sehen, weil die BoundingSphere default recht klein ist. Deswegen solltest du die vllt möglichst groß machen.

```
BoundingSphere bounds = new BoundingSphere(new Point3d(), Double.MAX_VALUE);
```
Und ich finde es sieht mit folgenden Werten des Materials schöner aus, aber das ist deine Sache:
Ambient: 0.1/0.1/0.1
Emissive: 0.1/0.1/0.1
Diffuse: 0.7/0.7/0.7
Specular: 1/1/1
shininess: 64

2. Wenn die Bounds größer sind, funktioniert das - mehr oder weniger, man scheint nur die Sonne drehen/zoomen zu können. Die Scheduling Bounds bedeuten: Mach das mit dem Behavior nur, wenn die Kamera in den Bounds ist. Die Kamera ist ja auf 0/0/75 gesetzt, was weiter außerhalb als eine default BoundingSphere reicht, ist.
Weshalb sich das nur auf die Sonne auswirkt, weiß ich jetzt grad net ???:L musst mal rumprobieren, vllt noch den SceneGraph bissle anders aufbauen oder so was.

3. Siehe oben, bounds ist zu klein. Aber im Konstruktor von Mover werden die Bounds ja eh schon gesetzt.


----------



## Brügge (20. Dez 2005)

Hallo,
ich habe das Programm noch einmal modifiziert und die Kamera etwas näher dran gestellt, dies bewirkte, dass man nun alles rotieren lassen kann.  Das 2. Problem, dass ich beim rein- rauszoomen nur die Sonne bewege, ist immernoch da  aber erstmal nicht so wichtig.

Mein Hauptproblem ist, die Kollision der Kugeln zu simulieren.
Erstmal möchte ich die Kugeln nur mit der Sonne kollidieren lassen und (sobald sie sich berühren) die Kugel stoppen, sodass die an der Sonne haftet. (klingt unlogisch ich weiß.. aber macht hinterher sinn  )
Dazu errechne ich mir den Abstand der Kugel zum Punkt (0,0,0) mit der Formel  d = wurzel(x² + y² + z²).
Ich lasse die Kugel nur so lange fliegen, wie d > 1 ist.  (1 ist der Radius der Kugel).

Zunächst habe ich das Programm mit nur einer Kugel getestet und immer ausgegeben welche Koordinaten die Kugel hat. Dabei kam jedoch etwas sehr merkwürdiges zustande: die Kugel hatte irgendwann die Koordinaten 0,0,0 .. (das ist ja noch nicht schlimm, ist ja richtig so.) aber als sie diese Koordinaten hatte, war sie nicht am Punkt (0,0,0) zu sehen, sondern ein wenig davon entfernt!  In einigen Experimenten kam ich darauf, dass (wenn ich die Kugel bei 10,0,0 starten lasse) der Punkt 0,0,0 näher am echten Nullpunkt ist, als wenn ich die Kugel zum Beispiel bei 100,0,0 starten lasse.. und zwar vermute ich, um das 10fache. Wie ist dies zu erklären, und wie bekomme ich nun die tatsächlichen Koordinaten und im endeffekt, wie mache ich es, dass die Kugel genau an der Sonne haftet??? 
Hier mein Programmcode:


```
import javax.swing.*;

import java.awt.GraphicsEnvironment;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.universe.*;  //SimpleUniverse
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.behaviors.vp.*;
import java.util.*;
import java.awt.Color;

public class KugelSimulation extends JFrame implements ActionListener  //JFrame um Vermischung von Swing <-> Canvas3D (AWT) zu zeigen
{
	public static final long serialVersionUID = 121121112l;  //Für Java1.5-Unterstützung
	//Konstruktor
	public KugelSimulation()
	{
		super ("Bla");
		setSize (800, 600);
		setLocationRelativeTo (null);  //zentrieren
		setDefaultCloseOperation (DO_NOTHING_ON_CLOSE);  //Schließen soll im Menu geschehen
		JPopupMenu.setDefaultLightWeightPopupEnabled (false);  //Damit das Menu funktioniert, lassts mal zum Test weg
		setCloseMenuBar (this);
		
		//Jetzt kommt der 3D-Teil
		Canvas3D c3d = new Canvas3D (SimpleUniverse.getPreferredConfiguration());  //So am besten
		SimpleUniverse simpleU = new SimpleUniverse (c3d);  //Das VirtualUniverse, hier wird auch schon der View hinzugefügt
		BranchGroup bg = new BranchGroup();  //Haupt-BranchGroup		
		createScene (bg);
		OrbitBehavior orbit = new OrbitBehavior(c3d, OrbitBehavior.REVERSE_ALL);  //OrbitBehavior liegt in dem Paket com.sun.j3d.utils.behaviors.vp
		orbit.setSchedulingBounds (new BoundingSphere ());
		simpleU.getViewingPlatform().setViewPlatformBehavior (orbit);
		bg.compile();  //Optimiert das Rendern
		simpleU.addBranchGraph (bg);  //Fügt den SceneGraph hinzu
		Transform3D cam = new Transform3D();
		cam.setTranslation (new Vector3f (0, 0, 60));
		simpleU.getViewingPlatform().getViewPlatformTransform().setTransform(cam);
		c3d.getView().setBackClipDistance(150);
		add (c3d);  //Vor 1.5: getContentPane().add
		setVisible (true);
	}
	private Kugel[] spheres;
	private int anzahl = 100;
	private boolean mitte = true;
	private int groesse = 100;
	
	private void createScene (BranchGroup scene)
	{
		BoundingSphere bounds = new BoundingSphere(new Point3d(), Double.MAX_VALUE);
		Appearance appKugel = new Appearance(); // Aussehen der Kugeln
		appKugel.setMaterial(new Material(new Color3f(0.1f,0.1f,0.1f), new Color3f(0.1f,0.1f,0.1f), new Color3f(0.7f,0.7f,0.7f), new Color3f(1,1,1), 64));
		spheres = new Kugel[anzahl];
		
		for (int i = 0; i < anzahl; i++){
			Kugel k = new Kugel();
			spheres[i] = k;
			Vector3f pos = new Vector3f();
			pos.x = k.point.x;
			pos.y = k.point.y; 
			pos.z = k.point.z; 
			k.direction.normalize();
			k.direction.scale (0.25f); //hier indirekt geschwindigkeit bestimmen
			Transform3D t3d1 = new Transform3D();
			t3d1.setTranslation(pos);
			TransformGroup transTG = new TransformGroup (t3d1);
			scene.addChild (transTG);
			TransformGroup move = new TransformGroup();
			k.move = move;
			move.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			transTG.addChild (move);
			Sphere s = new Sphere (1, Primitive.GENERATE_NORMALS, 100, appKugel);
			move.addChild (s);
		}
		
		Mover m = new Mover();
			
		
		// Sonne (Mittelkugel):
		Appearance appSun = new Appearance(); // Aussehen der Sonne
		appSun.setTexture( new TextureLoader("sun.jpg", this).getTexture());
		
		TransformGroup tgSun = new TransformGroup();
		Sphere Sun = new Sphere(1, Primitive.GENERATE_TEXTURE_COORDS, 100, appSun );
		tgSun.addChild(Sun);
		
		
		TransformGroup all = new TransformGroup();
				
		all.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		all.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		
		MouseRotate mouseRotate = new MouseRotate();
		MouseZoom mouseZoom = new MouseZoom(all);
		mouseRotate.setTransformGroup(all);
		mouseRotate.setSchedulingBounds(bounds);
		mouseZoom.setSchedulingBounds(bounds);
		
		// Licht
		PointLight sunlight = new PointLight();
		sunlight.setInfluencingBounds(bounds);
			
		scene.addChild(all);
		all.addChild(mouseRotate);
		all.addChild(mouseZoom);
		all.addChild(m);
		all.addChild(tgSun);
		all.addChild(sunlight);
	}
	//Beenden-Menu
	private void setCloseMenuBar (JFrame f)
	{
		JMenuBar jmb = new JMenuBar();
		JMenu jm = new JMenu ("Datei");
		jmb.add (jm);
		JMenuItem close = new JMenuItem ("Beenden");
		jm.add (close);
		close.addActionListener (this);
		f.setJMenuBar (jmb);
	}
	public void actionPerformed (ActionEvent evt)
	{
		System.exit (0);
	}
	//Startmethode
	public static void main (String[]args)
	{
		new KugelSimulation();
	}
	private class Kugel
	{
		public Kugel() {
			double rnd; 
						
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse; 
			point.x = (int) rnd;
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse;
			point.y = (int) rnd;
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse;
			point.z = (int) rnd;
			
			
			if (mitte == false) { 
				rnd = (java.lang.Math.random() * groesse);
				direction.x = (int) rnd;
				rnd = (java.lang.Math.random() * groesse);
				direction.y = (int) rnd;
				rnd = (java.lang.Math.random() * groesse);
				direction.z = (int) rnd;
				
			} else { 
				direction.x = -point.x;
				direction.y = -point.y;
				direction.z = -point.z;
			}
		}
		public Point3f point = new Point3f();
		public Vector3f direction = new Vector3f();
		public TransformGroup move;
		
		public boolean collide(float bx, float by, float bz) {
			
			float ax = point.x;
			float ay = point.y;
			float az = point.z;
			
			//System.out.println(Math.sqrt(ax * ax + ay * ay + az * az) + "  " + ax + "  " + ay + "  " + az);
			
			if(Math.sqrt(ax * ax + ay * ay + az * az) < 1) {
				return true;
				
			} else {
				return false; 
			}
		}
	}
	private class Mover extends Behavior
	{
		public Mover ()
		{
			setSchedulingBounds (new BoundingSphere(new Point3d(), Double.MAX_VALUE));
		}
		private WakeupCondition wc = new WakeupOnElapsedTime(20);
		public void initialize()
		{
			wakeupOn (wc);
		}
		public void processStimulus (Enumeration criteria)
		{
			for(int i = 0; i < spheres.length; i++){
				if(spheres[i].collide(0, 0, 0) == false) {
					spheres[i].point.add (spheres[i].direction);
					Transform3D t3d = new Transform3D();
					t3d.setTranslation (new Vector3f(spheres[i].point));
					spheres[i].move.setTransform (t3d);
				}
			}
			wakeupOn (wc);
		}
	}
}
```


Vielen vielen Dank im Voraus!!!

Christian


----------



## Brügge (21. Dez 2005)

Hallo nochmals 

Ich habe gestern Nacht nochmal alles mögliche ausprobiert und hab schließlich selbst die Lösung für das Problem gefunden: die erzeugten Kugeln haben alle ein eigenes Bezugssystem, welches man mit der Urkugel "abgleichen" muss.
Ich habe das Programm nun fast vollständig (lediglich das Problem mit dem Zoomen ist noch da)
Hier der Code, falls er irgendjemandem mal weiterhelfen sollte :


```
import javax.swing.*;

import java.awt.GraphicsEnvironment;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.universe.*;  //SimpleUniverse
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.behaviors.vp.*;
import java.util.*;
import java.awt.Color;

public class KugelSimulation extends JFrame implements ActionListener  //JFrame um Vermischung von Swing <-> Canvas3D (AWT) zu zeigen
{
	public static final long serialVersionUID = 121121112l;  //Für Java1.5-Unterstützung
	//Konstruktor
	public KugelSimulation()
	{
		super ("Bla");
		setSize (800, 600);
		setLocationRelativeTo (null);  //zentrieren
		setDefaultCloseOperation (DO_NOTHING_ON_CLOSE);  //Schließen soll im Menu geschehen
		JPopupMenu.setDefaultLightWeightPopupEnabled (false);  //Damit das Menu funktioniert, lassts mal zum Test weg
		setCloseMenuBar (this);
		
		//Jetzt kommt der 3D-Teil
		Canvas3D c3d = new Canvas3D (SimpleUniverse.getPreferredConfiguration());  //So am besten
		SimpleUniverse simpleU = new SimpleUniverse (c3d);  //Das VirtualUniverse, hier wird auch schon der View hinzugefügt
		BranchGroup bg = new BranchGroup();  //Haupt-BranchGroup		
		createScene (bg);
		OrbitBehavior orbit = new OrbitBehavior(c3d, OrbitBehavior.REVERSE_ALL);  //OrbitBehavior liegt in dem Paket com.sun.j3d.utils.behaviors.vp
		orbit.setSchedulingBounds (new BoundingSphere ());
		simpleU.getViewingPlatform().setViewPlatformBehavior (orbit);
		bg.compile();  //Optimiert das Rendern
		simpleU.addBranchGraph (bg);  //Fügt den SceneGraph hinzu
		Transform3D cam = new Transform3D();
		cam.setTranslation (new Vector3f (0, 0, 60));
		simpleU.getViewingPlatform().getViewPlatformTransform().setTransform(cam);
		c3d.getView().setBackClipDistance(150);
		add (c3d);  //Vor 1.5: getContentPane().add
		setVisible (true);
	}
	private Kugel[] spheres;
	private int anzahl = 500;
	private boolean mitte = true;
	private int groesse = 100;
	
	private void createScene (BranchGroup scene)
	{
		BoundingSphere bounds = new BoundingSphere(new Point3d(), Double.MAX_VALUE);
		Appearance appKugel = new Appearance(); // Aussehen der Kugeln
		appKugel.setMaterial(new Material(new Color3f(0.1f,0.1f,0.1f), new Color3f(0.1f,0.1f,0.1f), new Color3f(0.7f,0.7f,0.7f), new Color3f(1,1,1), 64));
		spheres = new Kugel[anzahl];
		
		for (int i = 0; i < anzahl; i++){
			Kugel k = new Kugel();
			spheres[i] = k;
			Vector3f pos = new Vector3f();
			pos.x = k.point.x;
			pos.y = k.point.y; 
			pos.z = k.point.z; 
			k.direction.normalize();
			k.direction.scale (0.25f); //hier indirekt geschwindigkeit bestimmen
			Transform3D t3d1 = new Transform3D();
			t3d1.setTranslation(pos);
			TransformGroup transTG = new TransformGroup (t3d1);
			scene.addChild (transTG);
			TransformGroup move = new TransformGroup();
			k.move = move;
			move.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			transTG.addChild (move);
			Sphere s = new Sphere (1, Primitive.GENERATE_NORMALS, 100, appKugel);
			move.addChild (s);
		}		
		
		Mover m = new Mover();
			
		
		// Sonne (Mittelkugel):
		Appearance appSun = new Appearance(); // Aussehen der Sonne
		appSun.setTexture( new TextureLoader("sun.jpg", this).getTexture());
		
		TransformGroup tgSun = new TransformGroup();
		Sphere Sun = new Sphere(1, Primitive.GENERATE_TEXTURE_COORDS, 100, appSun );
		tgSun.addChild(Sun);
		
		
		TransformGroup all = new TransformGroup();
				
		all.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		all.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		
		MouseRotate mouseRotate = new MouseRotate();
		MouseZoom mouseZoom = new MouseZoom(all);
		mouseRotate.setTransformGroup(all);
		mouseRotate.setSchedulingBounds(bounds);
		mouseZoom.setSchedulingBounds(bounds);
		
		// Licht
		PointLight sunlight = new PointLight();
		sunlight.setInfluencingBounds(bounds);
		
		PointLight camLight1 = new PointLight();
		camLight1.setPosition(0, 0, 60);
		camLight1.setInfluencingBounds(bounds);
		
		PointLight camLight2 = new PointLight();
		camLight2.setPosition(0, 0, -60);
		camLight2.setInfluencingBounds(bounds);
				
		scene.addChild(all);
		all.addChild(mouseRotate);
		all.addChild(mouseZoom);
		all.addChild(m);
		all.addChild(tgSun);
		all.addChild(sunlight);
		all.addChild(camLight1);
		all.addChild(camLight2);
	}
	//Beenden-Menu
	private void setCloseMenuBar (JFrame f)
	{
		JMenuBar jmb = new JMenuBar();
		JMenu jm = new JMenu ("Datei");
		jmb.add (jm);
		JMenuItem close = new JMenuItem ("Beenden");
		jm.add (close);
		close.addActionListener (this);
		f.setJMenuBar (jmb);
	}
	public void actionPerformed (ActionEvent evt)
	{
		System.exit (0);
	}
	//Startmethode
	public static void main (String[]args)
	{
		new KugelSimulation();
	}
	private class Kugel
	{
		public Kugel() {
			double rnd; 
						
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse; 
			point.x = (int) rnd;
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse;
			point.y = (int) rnd;
			rnd = (java.lang.Math.random() * 2 * groesse) - groesse;
			point.z = (int) rnd;
			
			/*if(i == 1) {
				point.x = 1;
				point.y = 0;
				point.z = 0;
			} else {
				point.x = 7;
				point.y = 0;
				point.z = 0;
			}*/
			
			start.x = point.x;
			start.y = point.y;
			start.z = point.z;
			
			if (mitte == false) { 
				rnd = (java.lang.Math.random() * groesse);
				direction.x = (int) rnd;
				rnd = (java.lang.Math.random() * groesse);
				direction.y = (int) rnd;
				rnd = (java.lang.Math.random() * groesse);
				direction.z = (int) rnd;
				
			} else { 
				direction.x = -point.x;
				direction.y = -point.y;
				direction.z = -point.z;
			}
			
			//if(i == 1)
				//direction.x = 1;
		}
		public Point3f point = new Point3f();
		public Vector3f direction = new Vector3f();
		public TransformGroup move;
		public Point3f start = new Point3f();
		public boolean collided = false;
		
		public boolean collide(float bx, float by, float bz) {
			
			float ax = point.x;
			float ay = point.y;
			float az = point.z;
			
			//System.out.println(Math.sqrt((ax + start.x - bx) * (ax + start.x - bx) + (ay + start.y - by) * (ay + start.y - by) + (az + start.z - bz) * (az + start.z - bz)));
			
			if(Math.sqrt((ax + start.x - bx) * (ax + start.x - bx) + (ay + start.y - by) * (ay + start.y - by) + (az + start.z - bz) * (az + start.z - bz)) <= 2) {
				collided = true;
				return true;
				
			} else {
				return false; 
			}
		}
	}
	private class Mover extends Behavior
	{
		public Mover ()
		{
			setSchedulingBounds (new BoundingSphere(new Point3d(), Double.MAX_VALUE));
		}
		private WakeupCondition wc = new WakeupOnElapsedTime(20);
		public void initialize()
		{
			wakeupOn (wc);
		}
		public void processStimulus (Enumeration criteria)
		{
			for(int i = 0; i < spheres.length; i++){
				if(spheres[i].collided == false) {
					for(int j = 0; j < spheres.length; j++) {
						if( i != j) {
							spheres[i].collide(spheres[j].point.x + spheres[j].start.x, spheres[j].point.y + spheres[j].start.y, spheres[j].point.z + spheres[j].start.z);
						}
					}
					
					spheres[i].collide(0, 0, 0);
					
					if(spheres[i].collided == false) {
						spheres[i].point.add (spheres[i].direction);
						Transform3D t3d = new Transform3D();
						t3d.setTranslation (new Vector3f(spheres[i].point));
						spheres[i].move.setTransform (t3d);
					}
				}
			}
			wakeupOn (wc);
		}
	}
}
```

Danke für eure super große Hilfe!!!! Vielleicht fällt ja noch jemandem ein, wie ich das Zoomen implementieren kann.
In der Zeit versuch ichs einfach mal

Danke vor allem an Iluvatar!!!  :toll: 

Bye bye, 

Christian


----------

