Seite 1 von 1

PQ-Formel bei Vektoren

Verfasst: 29.04.2009, 16:03
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?

Re: PQ-Formel bei Vektoren

Verfasst: 29.04.2009, 16:27
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))
{
...
}

Re: PQ-Formel bei Vektoren

Verfasst: 29.04.2009, 17:35
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();
}

Re: PQ-Formel bei Vektoren

Verfasst: 29.04.2009, 18:10
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.

Re: PQ-Formel bei Vektoren

Verfasst: 30.04.2009, 00:38
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.

Re: PQ-Formel bei Vektoren

Verfasst: 30.04.2009, 09:21
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.

Re: PQ-Formel bei Vektoren

Verfasst: 30.04.2009, 13:17
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);