Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

11

17.07.2005, 12:11

Man kann das ganze übrigens auch anders ausdrücken:
Punkt bzw. Kreuzprodukt geben einem den Cosinus bzw. Sinus des Winkels. Für einen "eindeutigen" Winkel brauche ich einen Bereich von 360 Grad bzw 2*pi, also z.B. 0 bis 2*pi oder -pi bis +pi. Auf einem solchen Bereich ist aber weder der Sinus noch der Cosinus eindeutig. Malt Euch den Sinus auf, markiert den Bereich 0 bis 2pi, nehmt irgend einen Wert auf der y Achse (z.b: 0.5) und Ihr findet mehrere Winkel. Daher KANN es keine Arcus Sinus Funktion geben, die einen Wertebereich von -pi bis +pi hat. In der C+++ Doku steht:

Zitat


The asin function returns the arcsine of x in the range –π/2 to π/2 radians


D.h. wenn man nur Kreuzprodukt oder nur Skalarprodukt anwendet, kann man den "wahren" Winkel nicht bestimmen, man braucht beide.

Es ist auch anschaulich klar dass z.B. +30 und -30 beide das selbe Skalarprodukt liefern da beide die selbe Projektion ergeben (sie liefern aber ein unterschoedliches Kreuzprodukt - es ist genau das Vorzeichen anders).
"Games are algorithmic entertainment."

12

17.07.2005, 12:32

"Zusätzlich kann man aber noch erwähnen, dass dieser Vektor mit den beiden anderen Vektoren immer ein rechtshändiges"

aber wohl nur wenn die zwei ausgangsvektoren bereits orthogonal
zu einerander waren oder?

13

18.07.2005, 09:29

Zitat von »"Phil_GDM"«

stimmt, man bekommt einen Vektor der zu den beiden anderen Vektoren im rechten Winkel steht.
Zusätzlich kann man aber noch erwähnen, dass dieser Vektor mit den beiden anderen Vektoren immer ein rechtshändiges Koordinatensystem aufbaut. Deshalb kann ich mit dem Kreuzprodukt auch die Drehrichtung für meinen Vektor herausfinden

z.B.:
Vektor A soll immer an Vektor B angeglichen werden
A=[0, 1, 0] B=[1,0,0]; crossp(A, B) = [0, 0, -1] die Z-Komponente ist negativ => Drehung nach rechts
A=[1,0,0] B=[0, 1, 0]; crossp(A, B) = [0, 0, 1] die Z-Komponente ist positiv => Drehung nach links

mfg Philipp


Aber ist es immer die Z-Komponente, deren Vorzeichen man untersuchen muss?

Phil_GDM

Alter Hase

  • »Phil_GDM« ist der Autor dieses Themas

Beiträge: 443

Wohnort: Graz

Beruf: Student-Softwareentwicklung u. Wissensmanagement

  • Private Nachricht senden

14

18.07.2005, 10:09

Nein.
Ich poste hier mal den Code, so wie er in meinem Projekt zur Zeit ist denn ein paar Zeilen Code erklären mehr als tausend Worte :-D .
Er berechnet die Differenzwinkel zwischen der Y-Achse eines Objekts und einem beliebigen Vektor v.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
VECTOR3F Object::getRotationDiffToYAxis(const VECTOR3F& v)
{
  VECTOR3F myrot(0.0f, 1.0f, 0.0f);
  MATRIX m;

  VECTOR3F vRot = m_pSceneNode->getRotation();
  m.setRotationDegrees(vRot);
  m.transformVect(myrot);

  myrot.normalize();
  
  VECTOR3F rotdiff;
  VECTOR2F rot1(myrot.Y, myrot.Z);
  VECTOR2F rot2(v.Y, v.Z);

  if( (COMPF_NA(rot1.X, 0.0f) && COMPF_NA(rot1.Y, 0.0f)) || 
      (COMPF_NA(rot2.X, 0.0f) && COMPF_NA(rot2.Y, 0.0f)) )
    rotdiff.X = 0.0f;
  else
    rotdiff.X = static_cast<float>(rot1.getAngleWith(rot2));


  rot1 = VECTOR2F(myrot.X, myrot.Z);
  rot2 = VECTOR2F(v.X, v.Z);
  if( (COMPF_NA(rot1.X, 0.0f) && COMPF_NA(rot1.Y, 0.0f)) || 
      (COMPF_NA(rot2.X, 0.0f) && COMPF_NA(rot2.Y, 0.0f)) )
    rotdiff.Y = 0.0f;
  else
    rotdiff.Y = static_cast<float>(rot1.getAngleWith(rot2));

  rot1 = VECTOR2F(myrot.X, myrot.Y);
  rot2 = VECTOR2F(v.X, v.Y);
  if( (COMPF_NA(rot1.X, 0.0f) && COMPF_NA(rot1.Y, 0.0f)) || 
      (COMPF_NA(rot2.X, 0.0f) && COMPF_NA(rot2.Y, 0.0f)) )
    rotdiff.Z = 0.0f;
  else
    rotdiff.Z = static_cast<float>(rot1.getAngleWith(rot2));

  VECTOR3F vCross = v.crossProduct(myrot);
  if(vCross.X > 0)
    rotdiff.X = -rotdiff.X;
  if(vCross.Y > 0)
    rotdiff.Y = -rotdiff.Y;
  if(vCross.Z > 0)
    rotdiff.Z = -rotdiff.Z;

  return rotdiff;
}

template<typename T>
f64 vector2f<T>::getAngleWith(const vector2d<T>& b) const
{
    f64 tmp = X*b.X + Y*b.Y;
    if (tmp == 0.0)
      return 90.0;

    return (acos(tmp / (sqrt(X*X + Y*Y) * sqrt(b.X*b.X + b.Y*b.Y))));
}


Zuerst wird für jede Ebene der Winkel berechnet (getAngleWith). Die if-Abfragen sind da, um Spezialfälle die nicht berechnet werden können (z.B.: 1 Vektor ist ein Nullvektor) zu umgehen.
Nun habe ich einen Vektor rotdiff, in dem die Rotationen um alle drei Raumachsen gespeichert sind.
Dann wird das Kreuzprodukt zwischen den beiden Ausgangsvektoren gebildet.
Für die Rotation um die X-Achse nehme ich die X-Komponente des Kreuzprodukts, für die Y-Achse die Y-Komponente und für die Z-Achse die Z-Komponente. Je nachdem, ob die Komponente des Kreuzprodukts größer 0 ist oder nicht, wird das Vorzeichen der Rotation geändert oder nicht.

mfg Philipp

15

18.07.2005, 11:34

ich werde es mal ausprobieren, ob das so funktioniert, vielen Dank dir also.

kleiner Hinweis noch:
-ich glaube in der getAngleWith() vermischt du ein wenig Radiants mit
Grad, die acos liefert doch Radiant, während das andere 90 Grad sind.
-Dabei fällt mir noch der Hinweis ein, dass es vernünftig ist den Maschinen- acos durch eine eigene acos zu ersetzen, weil: entsteht der Wert, von dem man den Arcus-Cosinus haben will aus einer float-Rechnung gibt es Rundungsfehler und das Ergebnis kann leicht um auch nur wenige Bits über 1 bzw unter -1 sein, und dann liefert der Maschinen-Arcus-Cosinus kein Ergebnis mehr. Also z.B. so:
float arc_cosf(float val)
{
if (val <= -1) return acosf(-1);
else if(val >= 1) return acosf( 1);
else return acosf(val);
};

greez
Tschismo

Phil_GDM

Alter Hase

  • »Phil_GDM« ist der Autor dieses Themas

Beiträge: 443

Wohnort: Graz

Beruf: Student-Softwareentwicklung u. Wissensmanagement

  • Private Nachricht senden

16

18.07.2005, 13:19

Stimmt.
Die GetAngleWith-Funktion ist ein Teil der Irrlicht-Engine, die ich ein wenig modifiziert habe. Gestern hab ich meinen Computer neu aufgesetzt und natürlich vergessen, die modifizierte Version zu sichern :(.
Der richtige Code ist

C-/C++-Quelltext

1
 return (acos(tmp / (sqrt(X*X + Y*Y) * sqrt(b.X*b.X + b.Y*b.Y)))) * GRAD_PI;

Danke für den Hinweis, hat mir vermutlich viel Debugarbeit erspart :) .
Ob der acos in dieser Funktion der Maschinen-acos ist weiß ich nicht, so genau, hab ich mir die Engine bis jetzt noch nicht angesehen.

mfg Philipp

Anonymous

unregistriert

17

29.10.2005, 18:28

Hallo,

Wie ist das den bei 2-Dimensonalen Vektoren? Da kann ich doch das Kreuzprodukt nicht benutzen oder, da ich ja nen z-wert brauche

In meinem Programm(2D) soll sich ein Objekt immer mit dem Mauscursor drehen. Aber bei dem punktprodukt kommen ja nur positive Werte raus, sprich das Objekt dreht sich nur gegen den Uhrzeigersinn. Finde dazu leider keine Lösung....

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

18

29.10.2005, 20:09

Klar kannst du auch ein 2D Kreuzprodukt errechnen.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Anonymous

unregistriert

19

29.10.2005, 21:14

und wie würde das gehen?

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

20

29.10.2005, 21:57

Ach habe mist erzähl das Punktprodukt geht, aber nicht das Kreuz. Das Kreuz ist ja um einen auf beiden Vektoren 90° stehenden Winkel zu bekommen.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Werbeanzeige