# 3D Stoß



## Sibbo (2. Jul 2010)

Moin!

Ich bastle gerade an einer Physikengine, die ein realistisches Verhalten im Raum simulieren soll. Von der Gravitation her läuft schon alles, aber bei Kollisionen bekomme ich keinen richtigen Ansatz. Ich habe zwar schon Lösungen per Vektorrechnung gesehen, aber mit Mathematik aus der 11 komm ich da leider nicht hinter...

Hier erstmal ein Ausschnitt des bisherigen Codes:

```
class Matter
{
	private double mass; // Kilogram
	private double x, y, z; // Meters
	private double xMove, yMove, zMove; // Newton
	private double xyRotation, xzRotation, yzRotation; // Newtonmeter

	public synchronized void interact(Matter matter)
	{
		double xPart = matter.x - x;
		double yPart = matter.y - y;
		double zPart = matter.z - z;
		double mulMass = mass * matter.mass;
		double totalMass = mass + matter.mass;
		
		double distance = Physics.pythagoras(xPart, yPart);
		distance = Physics.pythagoras(distance, zPart);
		
		double vectorSpeedSelf = Physics.pythagoras(xMove, yMove);
		distance = Physics.pythagoras(vectorSpeedSelf, zMove);
		double vectorSpeedMatter = Physics.pythagoras(matter.xMove, matter.yMove);
		distance = Physics.pythagoras(vectorSpeedMatter, matter.zMove);
		
//		Collision
		boolean collided = false;
		
		switch (form)
		{
		case FORM_SPHERE:
			if (checkCollision && distance <= dimension[0] + matter.dimension[0])
			{
				collided = true;
				massEffect = false;
				checkCollision = false;
				
				xMove = -xMove * matter.mass / totalMass;
				yMove = -yMove * matter.mass / totalMass;
				zMove = -zMove * matter.mass / totalMass;
				
				matter.xMove = -matter.xMove * mass / totalMass;
				matter.yMove = -matter.yMove * mass / totalMass;
				matter.zMove = -matter.zMove * mass / totalMass;
			}
			else
				checkCollision = true;
			break;
		}
		
//		Mass Acceleration
		
		if (massEffect)
		{
			double massAcceleration = Physics.G * mulMass / Physics.sqr(distance) * Physics.TIME_PER_UPDATE;
			
			double newXPart = xPart;
			double newYPart = yPart;
			double newZPart = zPart;
			
			/*double newXPart = Math.signum(xPart) * Math.sqrt(distance - Physics.pythagoras(yPart, zPart));
			double newYPart = Math.signum(yPart) * Math.sqrt(distance - Physics.pythagoras(xPart, zPart));
			double newZPart = Math.signum(zPart) * Math.sqrt(distance - Physics.pythagoras(yPart, xPart));*/
			
			newXPart /= distance * 2;
			newYPart /= distance * 2;
			newZPart /= distance * 2;
			
			xMove += newXPart * massAcceleration;
			yMove += newYPart * massAcceleration;
			zMove += newZPart * massAcceleration;
			
			matter.xMove += -newXPart * massAcceleration;
			matter.yMove += -newYPart * massAcceleration;
			matter.zMove += -newZPart * massAcceleration;
		}
		else
			massEffect = true;
	}
}
```

Bisher invertiere ich einfach nur die Geschwindigkeiten...
Ich hoffe mal, ihr könnt mir nen guten Ansatz geben...
Danke im Voraus, Sibbo


----------



## Marco13 (2. Jul 2010)

Soll das richtig mit Drehimpuls und so laufen? Das kann dann schon beliebig aufwändig werden. Für Kugeln geht's noch, aber bei beliebig geformten Körpern braucht man da sowas wie hier http://www.matthiasmueller.info/realtimephysics/coursenotes.pdf in Kapitel 6.


----------



## Sibbo (2. Jul 2010)

Also Drehimpuls war auch geplant, aber wie gesagt, wenn möglich mit 11er Mathematik, und Vektoren und Matrizen hatten wir noch nicht...
Trotzdem danke erstmal.
Die Körper sollen erstmal als Kugeln simuliert werden.


----------



## Sibbo (3. Jul 2010)

Ich hab mal nen Bischen gegoogelt, dabei is das rausgekommen, funktioniert aber eher weniger 

```
if (checkCollision && distance <= dimension[0] + matter.dimension[0])
			{
				Vector self = new Vector(xMove / mass, yMove / mass, zMove / mass).unitVector();
				Vector other = new Vector(matter.xMove / matter.mass, matter.yMove / matter.mass, matter.zMove / matter.mass).unitVector();
				Vector distanceVector = new Vector(x - matter.x, y - matter.y, z - matter.z);
				
				double vrel = distanceVector.scalar(self.sub(other));
				
				if (vrel >= 0)
					break;
				
				/**The strength of the collision*/
				double j = -(1 + Physics.FLEXIBILITY) * vrel / (1 / mass + 1 / matter.mass);
				
				/**Vector of collision*/
				Vector J = distanceVector.mul(j);
				
				self = self.add(J.div(mass));
				other = other.sub(J.div(matter.mass));
				
				xMove = self.getX() * mass;
				yMove = self.getY() * mass;
				zMove = self.getZ() * mass;
				
				matter.xMove = other.getX() * matter.mass;
				matter.yMove = other.getX() * matter.mass;
				matter.zMove = other.getX() * matter.mass;
			}
```

Hier noch die Klasse Vector

```
package core;

public class Vector
{
	public static final int PARALLEL = 0;
	public static final int ANTIPARALLEL = 1;
	public static final int NULL = 2;
	public static final int NOTHING = 3;
	
	private double x, y, z;
	
	public Vector(double x, double y, double z)
	{
		this.x = x;
		this.y = y;
		this.z = z;
	}
	
	public Vector(Vector v)
	{
		this.x = v.x;
		this.y = v.y;
		this.z = v.z;
	}
	
	public Vector() {}

	public double getX()
	{
		return x;
	}

	public void setX(double x)
	{
		this.x = x;
	}

	public double getY()
	{
		return y;
	}

	public void setY(double y)
	{
		this.y = y;
	}

	public double getZ()
	{
		return z;
	}

	public void setZ(double z)
	{
		this.z = z;
	}

	public Vector add(Vector v)
	{
		Vector w = new Vector(this);
		
		w.x += v.x;
		w.y += v.y;
		w.z += v.z;
		
		return w;
	}
	
	public Vector sub(Vector v)
	{
		Vector w = new Vector(this);
		
		w.x -= v.x;
		w.y -= v.y;
		w.z -= v.z;
		
		return w;
	}
	
	public Vector mul(Vector v)
	{
		Vector w = new Vector(this);
		
		w.x *= v.x;
		w.y *= v.y;
		w.z *= v.z;
		
		return w;
	}
	
	public Vector mul(double f)
	{
		Vector w = new Vector(this);
		
		w.x *= f;
		w.y *= f;
		w.z *= f;
		
		return w;
	}
	
	public Vector div(Vector v)
	{
		Vector w = new Vector(this);
		
		w.x /= v.x;
		w.y /= v.y;
		w.z /= v.z;
		
		return w;
	}
	
	public Vector div(double d)
	{
		Vector w = new Vector(this);
		
		w.x /= d;
		w.y /= d;
		w.z /= d;
		
		return w;
	}
	
	public double length()
	{
		return Physics.pythagoras(x, Physics.pythagoras(y, y));
	}
	
	public Vector unitVector()
	{
		Vector w = new Vector(this);
		
		return w.div(w.length());
	}
	
	public double scalar(Vector v)
	{
		v = v.mul(this);
		
		return v.addAll();
	}
	
	public double addAll()
	{
		return x + y + z;
	}
	
	public double angle(Vector v)
	{
		Vector uThis = unitVector();
		Vector uV = v.unitVector();
		
		return Math.acos(uThis.scalar(uV));
	}
	
	public int parallel(Vector v)
	{
		double tx = v.x / x;
		double ty = v.y / y;
		double tz = v.z / z;
		
		if (Physics.similar(1e-15, tx, ty, tz))
		{
			if (Physics.similar(1e-15, tx, ty, tz, 0))
				return NULL;
			
			if (tx > 0)
				return PARALLEL;
			else
				return ANTIPARALLEL;
		}
		else
			return NOTHING;
	}
	
	public Vector crossProduct(Vector v)
	{
		Vector w = new Vector();
		
		w.x = y * v.z - z * v.y;
		w.y = z * v.x - x * v.z;
		w.z = x * v.y - y * v.x;
		
		return w;
	}
	
	public static void main(String[] args)
	{
		Vector a = new Vector(-1, 0, 0);
		Vector b = new Vector(1, 0, 0);
		
		System.out.println(a.angle(b) * 180 / Math.PI);
	}
}
```


----------



## Marco13 (3. Jul 2010)

Wenn ich jetzt sage, dass man da ohne Vektorrechnung nicht weit kommt, soll das nicht entmutigen, sondern eher im Gegenteil: Schau's dir mal an. Und in einem Jahr kannst du wenn dein Mathelehrer anfängt mit "Ein Vektor das ist sowas wie ein Pfeil" mit einem mitleidigen Lächeln rausgehen und Kippenpause machen :smoke: 
Konkrete Fragen kann man versuchen zu beantworten, aber wenn es (überspitzt gesagt) rausläuft auf "ich will ein Kreuzprodukt berechnen, aber bitte ohne Vektorrechung - wie geht das?" wird die Luft dünn...


----------



## Sibbo (3. Jul 2010)

Hab ich auch getan...
Der Algorithmus macht auch nicht alles falsch, sondern bekommt im Verhältnis zum Anfang immerhin eine einigermaßen annehmbare Geschwindigkeit und Richtung hin (+/- 45°):applaus:... Gut ernsthaft das Ergebnis ist Müll, aber ich hab immerhin was zum drauf aufbauen...


----------



## Sibbo (3. Jul 2010)

Ok, also ich komm mit google nicht mehr weiter...
Hat sich vielleicht schonmal jemand mit dem Thema beschäftigt? Oder kennt jemand eine Seite die das ganze in 3D erklärt?


----------



## Antoras (3. Jul 2010)

Ohne mathematische Grundkenntnisse zu besitzen wirst du nicht weiterkommen.

Außerdem solltest du dir bewusst werden was du überhaupt machen willst. Du hast eine Vektorklasse realisiert, die aber in erster Linie überhaupt nichts mit einer Physik-Engine zu tun hat, sondern mit der Graphik-Engine. Arbeite dich erst mal in bestehende Software Rasterizer wie OpenGL ein, dann kannst du irgendwann mal anfangen selbst Implementierungen anzufertigen.
Bei OpenGL hast du eine minimal-Library die dir nichts abnimmt - mit Ausnahme der Rasterisierung. Wenn dich eine Graphik-Engine nicht sonderlich interessiert, dann kannst du auch Java3D, die jMonkeyEngine oder etwas vergleichbares nehmen; die nehmen dir wenigstens ein bisschen was ab.

Aber um Vektoren wirst du dennoch nicht drumherum kommen, denn selbst bei deiner Physik-Engine musst du verstehen wie Räumen von Computern dargestellt werden. Und stell dich schon mal darauf ein, dass du *keine* animierten Bildchen finden wirst, bei der noch die Source-Codes neben dran stehen, die du nur abzutippen hast. Das ist alles trockene mathematische Theorie, deren Umsetzung in Source-Code das kleinste Problem darstellen wird...


----------



## Marco13 (3. Jul 2010)

Wenn du konkrete Hilfe brauchst, für die Kollision zwischen zwei Kugeln, dann solltest du versuchen, eine klare Methode zu posten, an der man sieht, was du versucht hast, und was nicht funktioniert. Wobei Foren- und Websuche da ja schon einiges liefert.


----------



## Sibbo (3. Jul 2010)

Das das wahrscheinlich viel Mathematik wird war mir schon klar, war auch Sinn der Sache das zu lernen, aber hätte nicht gedacht das das so schwer wird... Das grafische hab ich zum testen erstmal 2D gelassen, einfach die z-Achse ignoiert, funktioniert auch soweit...
Kennst du vielleicht eine Physikengine mit der man arbeiten könnte? In Java3D wollte ich mich sowieso mal eingearbeitet haben, bin bisher nicht über ne statische Szene rausgekommen...


----------



## Siassei (3. Jul 2010)

Servus,

nicht gleich den Kopf in den Sand stecken, wenns mal nicht so glabt wie du willst ;-)
Wenn du etwas erreichen willst, dann musst du auch durchhalten und lasse dich von anderen nicht beeinflussen.

Bei einem derartigen Vorhaben sollte man kleine Schritte wählen. Als erstes solltest du dich Fragen, was du erreichen möchtest? Ein komplettes Physik-System mit 3D Darstellung bei dem man nur einen Körper platzieren muss und der Rest von der Engine erledigt wird.
ODER erstmal einen simplen Körper (Kugel) darstellen.
Das zweite Ziel könnte dann in der Kollisionserkennung von zwei Kugeln sein.
Weiter gehts mit ....

Kleine Ziele haben den Vorteil, dass man sich immer wieder über etwas freuen und darauf stolz sein kann 

Gruß,
  Thomas


----------



## Sibbo (4. Jul 2010)

Dankeschön 
Ich hab mir erstmal überlegt, den Kugel "Triebwerke" zu geben, erstmal ohne Rückstoß sondern einfach wie so nen Impulsantrieb...
Ne Lösung für die Kollision wäre ja einfach ne Explosion der Kugeln, sodass vllt 10 kleinere mit in alle Richtungen zufällig wegfliegen...
"Aufgrund von ncdlmvg-Strahlung ist die Materie so instabil, dass sie beim kleinsten zerfällt" oder so...
Schaun wa mal...
Wer noch ne Lösung für die Hauptfrage kennt kann sie gerne posten


----------



## Antoras (4. Jul 2010)

Was war denn deine Hauptfrage? Doch nur, dass wir dir einen Ansatz geben sollen wie du dein Problem lösen kannst. Und den haben wir dir gegeben: Arbeite dich in die Vektorgeometrie ein.

Deine Ziele sind schon viel zu hoch gegriffen. Erstmal solltest du doch wissen wie man Kugeln zeichnet, dann wie man sie bewegt und dann wie eine Kollision funktioniert. Und nicht gleich Impulsantrieb->Explosion->Mega geiler Effekt. Wenn du das hast, dann kannst du mal weitergucken, aber nicht vorher.
Dafür brauchst du aber eine Engine. Entweder du schreibst sie selbst oder du benutzt was fertiges. In beiden Fällen ist die Einarbeitungszeit enorm, bei beiden Fällen hat das erst mal nichts mit einer Physik-Engine zu tun (sondern mit der Graphik-Engine) und bei beiden musst du wissen wie Vektorgeometrie funktioniert.

Und niemand will dich hier entmutigen. Du solltest dir nur der Komplexität des Themas bewusst werden.


----------



## Sibbo (4. Jul 2010)

Mir gehts erstmak garnicht ums aussehen.
Ich hab erstmal die zAchse gesperrt und alles 2D dargestellt.
Mein Impulsantrieb wäre dann nen Vektor, der ne Beschleunigung darstellt und jeden Frame auf die Geschwindigkeit aufaddiert wird. Impulsantrieb nur, weil da ja nichts rauskommt (glaub ich, is ja eh nur Science Fiktion)...

Die Explosion steht schon, halt in Form von neuen Kugeln die von der kaputten wegfliegen...
Als Grafikengine würd ich erstmal Java3D nehmen, man kann sicher per Translation in jedem Frame die Szene verändern oder?


----------

