PQ-Formel bei Vektoren

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Cobi
Beiträge: 11
Registriert: 13.05.2004, 19:31

PQ-Formel bei Vektoren

Beitrag von Cobi »

Hola,
Also mein Problem ist dass ich einen Vektor mit einer quadratischen Gleichung berechne.
v*t² + 1/2 g*t² = m
Nun gibt eine Kollisionserkennung ggf. einen gekürzten Vektor zurück und ich will daraus wieder ein t berechnen. Muss also folgende Gleichung nach t auflösen:
v*t + 1/2 g*t² = m'
Ein bewegtes Ding fällt auf den Boden quasi.
v und a sind 3d Vektoren.
Mein erster Ansatz nur die Länge zu vergleichen führt über eine Gleichung vierten Grades zu einer kubischen Gleichung und letztendlich zu einem ziemlichen Bastard von einer Lösung.
Daher habe ich nun versucht für alle 3 Komponenten die PQ-Formel aufzustellen.
Die Lösung ist leider inkosistent (fällt manchmal durch den Boden) und ich bin mir nicht sicher ob mein Ansatz prinzipiell hinkt oder ob es nur auf Fließkommavergleiche zurückzuführen ist. Wobei ich weder für das eine noch für das andere spontan eine Lösung parat hätte..
Also der Code sieht bis jetzt so aus:

Code: Alles auswählen

	float p, q, a,
		  tx1, tx2,
		  ty1, ty2,
		  tz1, tz2;

	p = m_Velocity.x / m_Gravity.x,
	q = (2 * Movement.x) / m_Gravity.x;

	a = p * p + q;
	a = sqrtf(a);

	tx1 = -p + a;
	tx2 = -p - a;

	p = m_Velocity.y / m_Gravity.y;
	q = (2 * Movement.y) / m_Gravity.y;

	a = p * p + q;
	a = sqrtf(a);
	ty1 = -p + a;
	ty2 = -p - a;

	p = m_Velocity.z / m_Gravity.z;
	q = (2 * Movement.z) / m_Gravity.z;

	a = p * p + q;
	a = sqrtf(a);
	tz1 = -p + a;
	tz2 = -p - a;

	if(tx1 > 0.0f){

		if((Movement.y == 0.0f || tx1 == ty1 || tx1 == ty2) && (Movement.z == 0.0f || tx1 == tz1 || tx1 == tz2)) return tx1;
	}
	if(tx2 > 0.0f){

		if((Movement.y == 0.0f || tx2 == ty1 || tx2 == ty2) && (Movement.z == 0.0f || tx2 == tz1 || tx2 == tz2)) return tx2;
	}
	if(ty1 > 0.0f){

		if(Movement.z == 0.0f || ty1 == tz1 || ty1 == tz2) return ty1;
	}
	if(ty2 > 0.0f){

		if(Movement.z == 0.0f || ty2 == tz1 || ty2 == tz2) return ty2;
	}
	if(max(tz1, tz2) > 0.0f) return max(tz1, tz2);

	return -1.0f;
Wie würdet ihr das angehen?
DSG
Beiträge: 9
Registriert: 24.04.2009, 13:27
Kontaktdaten:

Re: PQ-Formel bei Vektoren

Beitrag von DSG »

Hallo

Ich hab die Gleichung nicht überprüft aber ich kann dir schon mal folgendes sagen:

Konstrukte wie Movement.y == 0.0f, tx2 == ty2 usw würde ich vermeiden. Du arbeitest ja mit floats, daher ist die Genauigkeit recht "ungenau". Zwei floats würde ich nicht mit == vergleichen sondern mit einer Funktion/Makro mit einem bestimmten Toleranzwert. Also etwas in der Art:

Code: Alles auswählen

#define EPSILON  0.01f   // Toleranzwert
#define FloatsAreEqual(x,y)  (fabs(x - y) < EPSILON)   // Makro
Dann im Code:

Code: Alles auswählen

if (FloatsAreEqual(tx2, ty2))
{
...
}
www.deltasoftgames.ch - swiss game development
Benutzeravatar
Biolunar
Establishment
Beiträge: 154
Registriert: 27.06.2005, 17:42
Alter Benutzername: dLoB

Re: PQ-Formel bei Vektoren

Beitrag von Biolunar »

Wieso eigentlich immer Makros? Eine Funktion tut es genau so gut und ist auch noch typensicher. Ansonsten würde ich jetzt spontan auch mal auf die Vergleiche tippen.

Code: Alles auswählen

bool equal(float a, float b)
{
    return std::abs(a - b) < std::numeric_limits<float>::epsilon();
}
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 577
Registriert: 05.07.2003, 11:17

Re: PQ-Formel bei Vektoren

Beitrag von Lord Delvin »

So wie ich das sehe, ist g bei dir eine konstante Richtung. In dem Fall könntest du auch einfach die parallelanteile zu g berechnen und dann mit skalaren weitermachen, wie gewohnt. Eventuell musst du dann nach was mit |g| machen, jenachdem wie dein code halt aussieht.
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Cobi
Beiträge: 11
Registriert: 13.05.2004, 19:31

Re: PQ-Formel bei Vektoren

Beitrag von Cobi »

Also wenn ich das gerade richtig über den Daumen gepeilt habe dann dürfte das ermitteln des Parallelanteils noch einiges aufwendiger zu berechnen sein als die Sache ohnehin schon ist. Werden da nicht LGS benötigt? G ist zwar die Schwerkraft aber die Möglichkeit damit rumzuspielen möchte ich mir offenhalten. ;)
Versuche es mal mit dem equal() ansatz, kann allerdings sein dass ich dazu erst in einem Monat komme (Asienurlaub *juche*).
Melde mich dann zurück obs klappt. :)
Danke schonmal.
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 577
Registriert: 05.07.2003, 11:17

Re: PQ-Formel bei Vektoren

Beitrag von Lord Delvin »

Cobi hat geschrieben:Also wenn ich das gerade richtig über den Daumen gepeilt habe dann dürfte das ermitteln des Parallelanteils noch einiges aufwendiger zu berechnen sein als die Sache ohnehin schon ist. Werden da nicht LGS benötigt?
Kann man so machen, ist aber sicher nicht sinnvoll:P

Code: Alles auswählen

real len = (v.x*x + v.y*y + v.z*z)/(v.x*v.x + v.y*v.y + v.z*v.z);
return Vector3(v.x*len, v.y*len, v.z*len);
Wobei du den ganzen /(...) kram weglassen kannst, wenn v schon normiert ist, was zumindest bei uns oft vorkommt und erheblich schneller ist. Das Ergebniss ist der parallele Anteil von this an v.
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Cobi
Beiträge: 11
Registriert: 13.05.2004, 19:31

Re: PQ-Formel bei Vektoren

Beitrag von Cobi »

Funktioniert blendend :D

Code: Alles auswählen


	D3DXVECTOR3 NormalMovement;
	D3DXVECTOR3 ParallelGravity, ParallelVelocity;

	D3DXVec3Normalize(&NormalMovement, &Movement);

	ParallelGravity = NormalMovement * D3DXVec3Dot(&m_Gravity, &NormalMovement);
	ParallelVelocity = NormalMovement * D3DXVec3Dot(&m_Velocity, &NormalMovement);

	float pG = D3DXVec3Length(&ParallelGravity),
		  pV = D3DXVec3Length(&ParallelVelocity),
		  pM = D3DXVec3Length(&Movement);

	float p = pV / pG,
		  q = 2 * pM / pG,
		  a = sqrtf(p * p + q);

	return max(-p + a, -p - a);
Antworten