Registriert: Do Jun 09, 2005 13:48 Beiträge: 117 Wohnort: Sankt Augustin
Hallo,
ich habe versucht im Forum für Einsteiger einen Hinweis für die Lösung meines Problems zu finden, wurde aber leider nicht fündig. Sollte dieses Problem (was ich ja annehme) schon von anderer Seite aufgebracht worden sein würde mich ein Hinweis auf die Lösung sehr freuen.
Ich möchte eine Rohrlandschaft aufbauen. Es hat also nichts mit Animation zu tun. Die Rohre sollen vom Benutzer beliebig auf dem Bildschirm zu platzieren sein. Ich habe also ein Eingabe- und ein Ausgabefenster. Gebe ich die Koordinaten V1: -1,-1,-10 - V2: 1,1,-10 an wird ein Zylinder von V1 bis V2 gezeichnet. In den Anfang und das Ende eines jeden Zylinders wird eine Kugel gezeichnet, so dass anschließende Zylinder keine Lücken erzeugen.
Ich habe mir also aus den Foren und von anderer Stelle die benötigten Funktionen gesucht und wende sie an.
Es klappt alles ganz prima wenn ich nur eindimensional verdrehe. Wenn ich gleichzeitig verschiebe und der Zylinder nicht mehr durch den Mittelpunkt (0,0,irgendwas) läuft, weicht die Zylinderspitze immer mehr von dem gewünschten Zielpunkt ab je mehr ich aus dem Mittelpunkt der Szene gehe.
Die Reihenfolge ist glTranslate und dann glRotate, was ja nachher umgekehrt aufgelöst wird (sollte also stimmen).
Ich erzeuge mir aus dem Vektor des gezeichneten Zylinders (entlang der Z-Achse) und dem Zielvektor (irgendwo) ein Dreieck und errichte darauf die normale. Diese normale dient dann als Drehachse für den Zylinder. Er wird um X Grad gedreht, wobei X durch das DotProduct der beiden Vektoren bestimmt wird. Ich habe die Winkelbildung überprüft und die scheint immer richtig zu sein. Der Fehler muss also entweder bei der Bildung der normale oder beim Verschieben liegen. Da der Startpunkt des Zylinders immer richtig gesetzt wird (habe ich mit einem in die Szene gezeichneten Grid überprüft), muss der Fehler also an der Bildung der normale liegen.
Ich kopiere meine Funktionen mal hier hinein. Vielleicht habe ich ja noch irgendwo einen versteckten Fehler. Ich habe versucht den kompletten Source Code als Attachment anzufügen aber das hat nicht geklappt. Bei Bedarf probiere ich es noch einmal.
Danke,
AndyH
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
function TFKanalForm.DotProduct (V1, V2: TGLArrayf3): TGLdouble;
var
len1, len2: TGLdouble;
Ergebnis: TGLdouble;
begin
Ergebnis := ScalarProduct (V1, V2);
Ergebnis := Ergebnis /
((sqr (power (V1[XAchse], 2) + power (V1[YAchse], 2) + power (V1[ZAchse], 2))) *
(sqr (power (V2[XAchse], 2) + power (V2[YAchse], 2) + power (V2[ZAchse], 2))));
end;
function TFKanalForm.CrossProduct(V1, V2: TGLArrayf3): TGLArrayf3;
var
CrossVec: TGLArrayf3;
begin
CrossVec[XAchse] := ((V1[YAchse]*V2[ZAchse]) - (V1[ZAchse]*V2[YAchse]));
CrossVec[YAchse] := ((V1[ZAchse]*V2[XAchse]) - (V1[XAchse]*V2[ZAchse]));
CrossVec[ZAchse] := ((V1[XAchse]*V2[YAchse]) - (V1[YAchse]*V2[XAchse]));
result := CrossVec;
end;
procedure TFKanalForm.CalcNormale (V2, V3: TGLArrayf3; var normale: TGLArrayf3);
var
Kreuz, V1V2, V1V3, V1: TGLArrayf3;
begin
// dritten punkt für die ebene erzeugen, auf der der
// normale vektor erzeugt werden soll
V1[XAchse] := 0.0;
V1[YAchse] := 0.0;
V1[ZAchse] := 0.0;
procedure TFKanalForm.NormalizedVektor(V1: TGLArrayf3; var normal: TGLArrayf3);
var
len: TGLfloat;
begin
CopyVektor (V1, normal);
len := Magnitude(normal);
// avoid division by zero
if len = 0.0 then len := 1.0;
normal [XAchse] := normal [XAchse] / len;
normal [YAchse] := normal [YAchse] / len;
normal [ZAchse] := normal [ZAchse] / len;
end;
function TFKanalForm.Magnitude(Vector : TGLArrayf3) : TGLfloat;
begin
{Returns the length of the Vector}
result := sqrt(power (Vector[XAchse], 2)+
power (Vector[YAchse], 2)+
power (Vector[ZAchse], 2));
end;
procedure TFKanalForm.Render;
var
i: integer;
slices, stacks: TGLint;
LPosition:TGLArrayf4; //light position
LModelAmbient:TGLArrayf4; //Umgebungslicht
SwapIt: boolean;
MyMatrix: TMatrix;
PMyMatrix: PMatrix;
XOffs, YOffs, ZOffs: TGLdouble;
begin
PMyMatrix := @MyMatrix;
if length (GrafikArray) > 0 then
begin
SwapIt := false;
slices := 360; // teilstücke des radius
stacks := 32; // teilstücke der länge
for i := 0 to ArrayLength - 1 do
begin
if GrafikArray[i].Display then
begin
glMatrixMode(GL_MODELVIEW);
SwapIt := true;
glPushMatrix; // save current matrix
glColor3f(red, green, blue);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Beton1Texture);
// anfang des zylinders auf die gewünschte position und kugel zeichnen
glLoadIdentity;
glTranslatef(GrafikArray[i].StartVektor[XAchse],
GrafikArray[i].StartVektor[YAchse],
GrafikArray[i].StartVektor[ZAchse]);
gluSphere(Sphere, GrafikArray[i].DurchmesserStart, 36, 36);
// im ende des zylinders auch eine kugel zeichnen
glLoadIdentity;
glTranslatef(GrafikArray[i].ZielVektor[XAchse],
GrafikArray[i].ZielVektor[YAchse],
GrafikArray[i].ZielVektor[ZAchse]);
gluSphere(Sphere, GrafikArray[i].DurchmesserZiel, 36, 36);
glLoadIdentity;
// zuerst verschieben und dann rotieren, da die matrixoperationen
// bei der ausführung in umgekehrter reihenfolge ausgeführt werden
// anfang des zylinders auf den startpunkt
glTranslatef(GrafikArray[i].StartVektor[XAchse],
GrafikArray[i].StartVektor[YAchse],
GrafikArray[i].StartVektor[ZAchse]);
// zylinder auf das ziel ausrichten
// Wenn du also z.B. gleichzeitig
// X um 45°, Y um 20°C und Z um 60°C drehen willst,
// dann sollte folgendes funzen :
// Code:
// glRotatef(60, 0.75,0.3333,1);
if GrafikArray[i].Angle <> 0.0 then
glRotated(GrafikArray[i].Angle,
GrafikArray[i].Normale[XAchse],
GrafikArray[i].Normale[YAchse],
GrafikArray[i].Normale[ZAchse]); // um errechneten Winkel auf der errechneten Achse drehen
// nur zur überprüfung der gesetzten werte:
glGetFloatv(GL_MODELVIEW_MATRIX, PMyMatrix);
DrawGrid;
if SwapIt then
begin
glFlush; // bearbeitung der GL-befehle beginnen
glFinish; // warten bis alle befehle ausgeführt sind
SwapBuffers(DC); // flackern verhindern
end;
end;
end;
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
glRotate dreht immer um den Koordinatenursprung. Das bedeutet, wenn du zuerst glTranslate aufrufst und dann drehst, dass das Rohr sich um "einen Punkt im Raum" dreht. Dieser Punkt ist der KOU der Szene.
OpenGL funktioniert reihenfolgenmäßig nicht wie die Mathematik dahinter. Wenn du mathematisch das
Code:
[Rot] * [Trans] * [Punkte]
machen willst, musst du die Befehle in der Reihenfolge
Code:
Translatef
Rotatef
aufrufen.
(Ist irgendwoi auch klar, da OpenGL ne Programmiersprache ist, und da die Befehle abgearbeitet werden, wenn sie aufgerufen werden. )
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Mitglieder in diesem Forum: 0 Mitglieder und 4 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.