Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
ich schreib mir grad ne Methode, die eine Matrix rotieren soll, allerdings will es nich ganz so wie ich will. Hier erstma der Code, den ich bis jetzt hab:
Code:
///////////////////////////////////////////////////////////////////////////////////////////////// //läd die Standartwerte einer Matrix //@Matrix: Zeiger auf die Matrix die geladen werden soll; procedure gluLoadMatrixIdentity(const Matrix: PgluMatrix); begin Matrix^[maXAxis] := gluMatrixAxis(1, 0, 0, 0); Matrix^[maYAxis] := gluMatrixAxis(0, 1, 0, 0); Matrix^[maZAxis] := gluMatrixAxis(0, 0, 1, 0); Matrix^[maPos] := gluMatrixAxis(0, 0, 0, 1); end;
///////////////////////////////////////////////////////////////////////////////////////////////// //dreht die Matrix um die angegebene Achse bezüglich ihrer eigenen Achsen //@Matrix: Matrix die gedreht werden soll; //@Angle: Winkel um den gedreht werden soll (im Bogenmaß); //@X: X-Wert der Achse um die gedreht werden soll; //@X: Y-Wert der Achse um die gedreht werden soll; //@X: Z-Wert der Achse um die gedreht werden soll; procedure gluRotateMatrix(const Matrix: PgluMatrix; const Angle: Single; Axis: TglVector3f); var RotMatrix: TgluMatrix; X, Y, Z: Single; a, c, s: Single; begin gluNormalize(Axis); X := Axis[0]; Y := Axis[1]; Z := Axis[2]; a := Angle/180*Pi; c := cos(a); s := sin(a); gluLoadMatrixIdentity(@RotMatrix); RotMatrix[maXAxis] := gluMatrixAxis( SQR(X) + (1-SQR(X))*c, X*Y*(1-c) + Z*s, X*Z*(1-c) - Y*s, 0); RotMatrix[maYAxis] := gluMatrixAxis( X*Y*(1-c) - Z*s, SQR(Y) + (1-SQR(Y))*c, Y*Z*(1-c) + X*s, 0); RotMatrix[maZAxis] := gluMatrixAxis( X*Z*(1-c) + Y*s, Y*Z*(1-c) - X*s, SQR(Z) + (1-SQR(Z))*c, 0); gluMatrixMul(Matrix, @RotMatrix); end;
///////////////////////////////////////////////////////////////////////////////////////////////// //Mutlipliziert Matrix1 mit Matrix2 und speichert das Ergebniss in Matrix1 //@Matrix1: 1. Multiplikator; //@Matrix2: 2. Multiplikator; procedure gluMatrixMul(const Matrix1, Matrix2: PgluMatrix); type TMatrix = array[0..3, 0..3] of glFloat; PMatrix = ^TMatrix; var x, y, i: Integer; sum : Single; M1, M2, MRes: PMatrix; begin new(MRes); gluLoadmatrixIdentity(PgluMatrix(MRes)); M1 := PMatrix(Matrix1); M2 := PMatrix(Matrix2); for x := 0 to 3 do begin for y := 0 to 3 do begin sum := 0; for i := 0 to 3 do begin sum := sum + M1^[i][y] * M2^[x][i]; end; MRes^[x][y] := sum; end; end; for x := 0 to 3 do for y := 0 to 3 do M1^[x][y] := MRes^[x][y]; dispose(MRes); end;
Ich hab mal zum testen bei der OpenGL Matrix un bei meiner die gleichen Operationen durgeführt (Translate(0,0,-10) und Rotate(45, 1, 0, 0)) und mir anzeigen lassen. Es stimmen alle Werte, bis auf den Z-Wert der Z-Achse (mein Wert ist 0 und er sollte SQRT(2) sein). Ich weiß auch nich wo ich den Fehler suchen soll. Die RotationsMatrix hab ich so wie sie da steht von Wikipedia abgeschrieben. Wäre nett, wenn sich das ma jmd angucken könnte, der in der Schule bei Matricen aufgepasst hat
€: hab ne Andere Rotationsmatrix genommen (vom englischen Wiki) und mit gehts (Code ist angepasst). Jetzt hab ich aber noch n anderes Problem. Und zwar dreht sich die Matrix ja jetz immer um ihre eigenen Achsen, ich würde sie aber gern um die Norm-Achsen drehen (Norm-Achsen klingt iwie komisch, halt um die Achsen, die man direkt nach dem initialisieren der Matrix hat). Aber ich wei0 nich wie ich das anstellen soll...
Die RotationsMatrix hab ich so wie sie da steht von Wikipedia abgeschrieben.
Also da sollte an jeder Stelle der Matrix der Term (1-c) vorkommen für "1 - cos alpha". Bei dir aber irgendwie nicht
Zitat:
Und zwar dreht sich die Matrix ja jetz immer um ihre eigenen Achsen, ich würde sie aber gern um die Norm-Achsen drehen
Mit deiner Methode kannst du doch eine beliebige Achse als Drehachse angeben, so auch (1,0,0), (0,1,0) und (0,0,1). Alternativ kannst du die Matrizen nehmen die in dem von dir verlinkten Artikel der Wikipedia für die X, Y und Z-Achse stehen.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
Coolcat hat geschrieben:
Also da sollte an jeder Stelle der Matrix der Term (1-c) vorkommen für "1 - cos alpha". Bei dir aber irgendwie nicht
steht doch oben drin?! siehe gluRotateMatrix...
Coolcat hat geschrieben:
Mit deiner Methode kannst du doch eine beliebige Achse als Drehachse angeben, so auch (1,0,0), (0,1,0) und (0,0,1). Alternativ kannst du die Matrizen nehmen die in dem von dir verlinkten Artikel der Wikipedia für die X, Y und Z-Achse stehen.
Die Achse die ich da angeb ist aber eine Achse in dem System der Matrix, ich will aber um die Achsen des WeltSystems drehen, und da weiß ich nich, wie ich die Achse berechnen soll, um die ich da drehen muss, oder ob es da einen komplett anderen Weg gibt.
Öhm, nehmen wir das Element in der ersten Spalte, erste Zeile: SQR(X) + (1-SQR(X))*c Ich sehe da kein 1-c....mir ist auch ein Rätsel wie du da auf 1-x² kommst. Das sollte eigentlich X*X*(1-c) + c sein. Übrigens fördert es in diesem Fall die Leserlichkeit enorm wenn du nicht die SQR-Funktion benutzt sondern einfach X*X schreibst. Dann fällt dir nämlich auf das es immer "Achse*Achse*(1-c) + Irgendwas" ist.
Zitat:
Die Achse die ich da angeb ist aber eine Achse in dem System der Matrix, ich will aber um die Achsen des WeltSystems drehen, und da weiß ich nich, wie ich die Achse berechnen soll, um die ich da drehen muss, oder ob es da einen komplett anderen Weg gibt.
Wenn mich nicht alles täuscht brauchst du zuerst eine Matrix die ins Weltsystem zurückrechnet, nennen wir sie W und deine gewünschte Rotation nennen wir R. Deine Matrix ist: W^(-1)*R*W
Zusatz: Wenn M deine aktuelle Matrix ist würde das ja so aussehen: W^(-1)*R*W*M wobei M = W^(-1)....es kommt also auf das gleiche hinaus als wenn du von der anderen Seite aus dran multiplizierst: M * R
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Tschuldigung, dass ich mich hier einmische. Ich wollte nur auf Folgendes aufmerksam machen:
Ich habe vor ziemlich genau einem Jahr eine Matrix für Shaddow gepostet, die mittels Winkel und Achse erzeugt werden kann. Diese Funktion gibt die gleichen Ergebnisse wie glRotate. Der Beitrag ist hier zu finden: http://www.delphigl.com/forum/viewtopic.php?f=3&t=8476&hilit=Kamera&start=15, runterscrollen bis zu meinem Beitrag vom Do Jun 25, 2009 13:55.
HINWEIS: gleich zu Beginn wird Sinus und Cosinus berechnet, und zwar getrennt voneinander. Man kann NICHT den Cosinus aus dem Sinus berechnen, denn man würde das Vorzeichen verlieren, leicht zu ersehen aus Cos = Wurzel(1-sin²). Klarerweise würde die Matrix in gewissen Fällen dann Rubbish erzeugen.
Noch ein HINWEIS: Die Funktion wird schneller, wenn man die Parameter als "Const" deklariert (ein Hinweis von Lossy, danke nochmal).
Und der letzte HINWEIS: Ich weiß, Du wirst jetzt die Augen verdrehen, aber ich empfehle Dir, nicht mit Matrizen zu arbeiten, sondern gleich Quaternionen zu nehmen. Zwar geht das zunächt wunderbar mit den Matrizen, aber es kommt der Tag, an dem man ansteht. Matrizen lassen sich nicht interpolieren. Oder Du beginnst zwar mit Matrizen, aber gestaltest Deine Lib so, dass Du später leicht umsteigen kannst. Quaternionen lassen sich genauso verwenden wie Matrizen mit dem zusätzlichen Vorteil, interpolierbar zu sein.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
@Coolcat: Jetzt stimmts, du hast aber noch n dreher drin. Bis jetzt war es M = M * R und jetzt ist es M = R * M. Dabei muss aber vorher an den Koordinatenursprung (bzw an den Fixpunkt der Drehung) verschoben werden un danach wieder zurück. Dankeschön Warum ich die Rotationsmatrix jetzt so komisch zusammensetz weiß ich auch nich genau, ich hab mir nach dem englischen Wiki gerichtet, weil mit der Matrix im deutsch Wiki hats nich funktioniert. @Traude: Das was du in deinem Beitrag gepostet hast, hatte ich glaube auch so. Aber ich glaub bei mir war irgend ein dreher drin, oder die Quelle war falsch, weil es ja nich ging. Aber mit der Rotationsmatrix aus dem englischen Wiki gehts auch. Hinweis 1: ich weiß, hab ich auch schon so gemacht Hinweis 2: hatte ich auch schon ^^ Hinweis 3: Danke für den Tipp, aber ich werd es erstmal so lassen, weil ich keine Zeit hab um mich neu in das Thema einzuarbeiten, denn von Quaternionen höre ich heute zum 1. mal. Wenn die Zeit gekommen ist werd ich mir das aber mal angucken.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
ich hab mir grad mal die Quaternionen angesehen. Und es überall nur die Rede von Drehungen. Eine Positionsbestimmung ist wo mit den nich möglich? Da müsste man ja Rotation und Position unabhängig voneinander Interpolieren. Gibts da vlt iwo n Tutorial oder sowas dazu?
Nein, das wird immer gerne verschwiegen wie man die Dinger richtig benutzt. Also mit einem reinen Quaternion kannst du keine Translation machen. ABER, du kannst einfach einen Translations-Vektor dazu speichern.
Hier einfach mal Copy&Paste aus meinem Code. Die Methode rotate() eines Quaterions wendet das Quaternion einfach auf den Punkt an. Die Klasse Frame3 kannst du dann quasi genauso benutzen wie eine Matrix, mit dem Unterschied das du weniger Rechenoperationen benötigst und das ganze numerisch stabiler ist. Nur wenn du mehrere Punkte mit deinem Frame3 transformieren willst solltest du es erst in eine Matrix umwandeln. Ein Frame erlaubt aber nur Translation und Rotation. Eine Skalierung, Spiegelung, Scherung oder Projektion ist nicht möglich.
Code:
/*************************************************************************** * Copyright (C) 2010 by Martin Weusten * * martin dot weusten at rwth minus aachen dot de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef INCLUDE_GUARD_CML_FRAME3 #define INCLUDE_GUARD_CML_FRAME3
/** A 'Frame' is a Quaternion4 combined with a Vector3. * Using this class you can use quaternions similar as 4x4 matrices. The * quaternion does represent the rotation part, the vector is the translation. */ template<class T> class Frame3 { public: Frame3<T>() { } ///< no-initialization constructor Frame3<T>(const Vector3<T>& _p, const Quaternion4<T>& _q);
// assignment operators Frame3<T>& operator*=(const Frame3<T>& f); ///< combine two frames and assign result
// operations Matrix44<T> matrix() const; ///< convert transformation into matrix Frame3<T> inverse() const; ///< calculate inverse transformation Vector3<T> transform(const Vector3<T>& v) const; ///< transform point bool isNaN() const; ///< tests if one of the values is NaN = 'Not a Number'
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Zitat:
Nein, das wird immer gerne verschwiegen wie man die Dinger richtig benutzt.
Dafür hasse ich die Mathematiker: sie hören einem gar nicht zu. Wenn man fragt: "Was sind Quaternionen?" dann verstehen sie immer: "Wie rechnet man mit Quaternionen?" Und sie erklären einem dann laaang und breiiiit wie man das macht. Was Quaternionen bewirken, steht dann meist im Kleingedruckten.
Wie Coolcat schon sagte, kann man damit rotieren und sonst nix. Aber das können sie besser als Matrizen, denn sie sind
a) kleiner (brauchen also weniger Speicherplatz, das war auf alten Grafikkarten ein Thema: wieviele Floats gehen in ein Uniform-Array? Und da gehen eben mehr Quaternionen als Matrizen in ein Uniform-Array, was den Effekt hat, dass man weniger Schwierigkeiten hat, Skelette mit vielen Gelenken zu berechnen, allerdings muss man immer den Positionsvektor noch zusätzlich berücksichtigen).
b) sind im Gegensatz zu Matrizen in der Lage, effektiv zu interpolieren (man kann mit relativ wenig Rechenaufwand zwischen zwei Quaternionen interpolieren, Stichwort: "Lerp" = Linear Interpolation; es gibt auch "Slerp" = Spherical Linear Interpolation und auch noch einige andere)
Ich hätt natürlich auch Sourcecode - sogar in Pascal - aber Du bist ja ein Self-Made-Man.
Zuletzt geändert von Traude am Do Jun 24, 2010 20:01, insgesamt 1-mal geändert.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
Traude hat geschrieben:
Ich hätt natürlich auch Sourcecode - sogar in Pascal - aber Du bist ja ein Self-Made-Man.
meistens schon, aber wenn ich gar kein Ahnung hab guck ich mir auch gern mal Code von anderen an Wäre cool, wenn du mir den mal zukommen lassen könntest.
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Das ist mein SourceCode, denn kannst Du gerne haben; wie man mit Quaternionen rechnet, ist kein Geheimnis. Ich habe den Code nirgendwo abgeschrieben, sondern jedes einzelne nach dem mathemtischen Algo gebastelt und mit mindestens zwei (meistens C++) Implementierungen abgeglichen. Wenn ich es wichtig fand, habe ich die Quelle dazugeschrieben. Sollte also glaub ich unbedenklich sein, das zu verwenden. Solltest Du Fehler finden wäre ich natürlich dankbar für eine Rückmeldung. Übersetzt in eine Lizenz wäre das eine BSD-Lizenz.
Ich garantiere aber für nichts. Als Hinweis: Wenn ich die Dinger schon mal benutzt habe und es funktioniert hat, dann steht dabei: "Has been tested and found OK". Bei manchen steht das nicht dabei. Allerdings werden diese Funktionen manchmal von anderen Funktionen verwendet, wo der "OK" Vermerk dabei ist. Ich war also nicht immer ganz konsequent.
Auf Schnelligkeit optimiert ist der Code nicht, mehr auf *Deutlichkeit*. Aber das sollte ja ganz in Deinem Sinne sein.
Zwei wichtige Definitionen:
Code:
TQuaternion = Packed Record RealW,ImagX,ImagY,ImagZ: TFloat32; End; TVector3F = Packed Record X,Y,Z: TFloat32; End;
Meine Variablen sehen ein wenig anders aus als die Delphi-Variablen, aber sie sollten eigentlich selbsterklärend sein, siehe z.B. TFloat32. Die Funktion "Quaternion", also gleich die erste, hat noch ein Manko: man sollte sie normalisieren. Aber das ist in dem SourceCode derzeit noch nicht drin. Wenn man bei "AX,AY,AZ" eine nicht normalisierte Rotationsachse eingibt, ereignen sich seltsame Dinge.
Code:
//******************************************************************** // Q U A T E R N I O N //******************************************************************** // Has been tested and found OK Function Quaternion(Const Angle,AX,AY,AZ: TFloat32): TQuaternion; Var LocalQuat: TQuaternion; LocalVector: TVector3F; CosHalfAngle,SinHalfAngle: TFloat32; Begin CosHalfAngle:= Cos(Angle/2*PIDIV180); SinHalfAngle:= Sin(Angle/2*PIDIV180);
With Result Do Begin RealW:= CosHalfAngle; ImagX:= AX*SinHalfAngle; ImagY:= AY*SinHalfAngle; ImagZ:= AZ*SinHalfAngle; End; End; //******************************************************************** // Has been tested and found OK Function QuaternionAdd(Const Quat1,Quat2: TQuaternion): TQuaternion; Begin With Result Do Begin RealW:= Quat1.RealW + Quat2.RealW; ImagX:= Quat1.ImagX + Quat2.ImagX; ImagY:= Quat1.ImagY + Quat2.ImagY; ImagZ:= Quat1.ImagZ + Quat2.ImagZ; End; End; //******************************************************************** // Linear interpolation between two quaternions (LERP) // Has been tested and found OK Function QuaternionBlendLinear(Const Quat1,Quat2: TQuaternion; Const AFactor: TFloat32): TQuaternion; Begin Result:= QuaternionNormalize(QuaternionAdd( (QuaternionScale(Quat1,(1-AFactor))), (QuaternionScale(Quat2, AFactor)))); End; //******************************************************************** // Spherical linear interpolation between two quaternions (SLERP)
// Has been tested and found OK Function QuaternionBlendSpheric(Quat1,Quat2: TQuaternion; Const AFactor: TFloat32): TQuaternion; Var AlphaInRad,CosAlpha,SinAlpha,Scale0,Scale1: TFloat32; Begin // Calculate angle between the two quaternions CosAlpha:= QuaternionDotProduct(Quat1,Quat2); AlphaInRad:= ArcCos(CosAlpha); SinAlpha:= Sin(AlphaInRad);
// Consider negative cosinus (angles between 90 and 270 degree) If CosAlpha < 0 Then Begin CosAlpha:= Abs(CosAlpha); Quat2:= QuaternionConjugate(Quat2); End;
With Result Do Begin RealW:= Scale0*Quat1.RealW + Scale1*Quat2.RealW; ImagX:= Scale0*Quat1.ImagX + Scale1*Quat2.ImagX; ImagY:= Scale0*Quat1.ImagY + Scale1*Quat2.ImagY; ImagZ:= Scale0*Quat1.ImagZ + Scale1*Quat2.ImagZ; End; End; //******************************************************************** // Has been tested and found OK Function QuaternionConjugate(Const AQuat: TQuaternion): TQuaternion; Begin With Result Do Begin ImagX:=-ImagX; ImagY:=-ImagY; ImagZ:=-ImagZ; End; End; //******************************************************************** // Has been tested and found OK Function QuaternionDotProduct (Const Quat1,Quat2: TQuaternion): TFloat32; Begin Result:= +Quat1.RealW * Quat2.RealW +Quat1.ImagX * Quat2.ImagX +Quat1.ImagY * Quat2.ImagY +Quat1.ImagZ * Quat2.ImagZ; End; //******************************************************************** Function QuaternionInverse(Const AQuat: TQuaternion): TQuaternion; Begin Result:= QuaternionNormalize(QuaternionConjugate(AQuat)); End; //******************************************************************** // Has been tested and found OK Function QuaternionMultiply (Const ANormQuat1,ANormQuat2: TQuaternion): TQuaternion; Begin With Result Do Begin RealW:= + ANormQuat1.RealW * ANormQuat2.RealW - ANormQuat1.ImagX * ANormQuat2.ImagX - ANormQuat1.ImagY * ANormQuat2.ImagY - ANormQuat1.ImagZ * ANormQuat2.ImagZ;
ImagZ:= + ANormQuat1.RealW * ANormQuat2.ImagZ + ANormQuat1.ImagX * ANormQuat2.ImagY - ANormQuat1.ImagY * ANormQuat2.ImagX + ANormQuat1.ImagZ * ANormQuat2.RealW; End; End; //******************************************************************** Function QuaternionNormalize(Const AQuat: TQuaternion): TQuaternion; Var QuatValue: TFloat32; Begin QuatValue:= QuaternionValue(AQuat); If QuatValue <> 0 Then With Result Do Begin RealW:= AQuat.RealW / QuatValue; ImagX:= AQuat.ImagX / QuatValue; ImagY:= AQuat.ImagY / QuatValue; ImagZ:= AQuat.ImagZ / QuatValue; End Else Result:= QUATIDENTITY; End; //******************************************************************** Function QuaternionScale(Const AQuat: TQuaternion; Const AFactor: TFloat32): TQuaternion; Begin With Result Do Begin RealW:= AQuat.RealW * AFactor; ImagX:= AQuat.ImagX * AFactor; ImagY:= AQuat.ImagY * AFactor; ImagZ:= AQuat.ImagZ * AFactor; End; End; //******************************************************************** Function QuaternionValue(Const AQuat: TQuaternion): TFloat32; Begin With AQuat Do Result:= RealW*RealW + ImagX*ImagX + ImagY*ImagY + ImagZ*ImagZ; End; //******************************************************************** // Q U A T E R N I O N - Conversion //******************************************************************** // Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm Function AngleAxisToQuaternion (Const ARotation: TAngleAxis): TQuaternion; Begin With ARotation,Axis Do Result:= Quaternion(Angle,X,Y,Z); End; //******************************************************************** // Source:http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm Function QuaternionToAngleAxis(Const AQuat: TQuaternion): TAngleAxis; Var Scale: TFloat32; Begin With AQuat Do Scale:= Sqrt(ImagX*ImagX+ImagY*ImagY+ImagZ*ImagZ);
With Result Do If Scale <> 0 Then Begin Angle:= 2*ArcCos(AQuat.RealW)/PIDIV180; Axis.X:= AQuat.ImagX/Scale; Axis.Y:= AQuat.ImagY/Scale; Axis.Z:= AQuat.ImagZ/Scale; End Else Begin Angle:= 0; Axis:= ZPLUSVECTOR; End; End; //******************************************************************** // Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm // Has been tested and found OK Function QuaternionToMatrix(AQuat: TQuaternion): TMatrix4D; Begin Result:= MATIDENTITY;
AQuat:= QuaternionNormalize(AQuat); With AQuat Do Begin Result[0].X:= 1 - 2*ImagY*ImagY - 2*ImagZ*ImagZ; Result[0].Y:= 2*ImagX*ImagY + 2*RealW*ImagZ; Result[0].Z:= 2*ImagX*ImagZ - 2*RealW*ImagY; Result[0].W:= 0;
Wenn man fragt: "Was sind Quaternionen?" dann verstehen sie immer: "Wie rechnet man mit Quaternionen?"
ähm... die richtige Antwort auf "Was sind Quaternionen?" wäre doch eigentlich: "Zahlen, die aus einem realteil und drei imaginärteilen bestehen" (oder so ähnlich). Das ist (glaube ich) auch nicht viel aufschlussreicher.
Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.