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. Den kompletten Source Code habe ich als Attachment angefügt. Da sind allerdings einige Versuche drin, die nicht unbedingt sehenswert sind...
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;
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.