Registriert: Do Feb 21, 2008 22:10 Beiträge: 89 Wohnort: Boppard
Hi,
Ich wollte mich mal erkundigen, was ihr so nutzt zum Rendern von standard Primitiven. (Sphere, Cylinder, Capsule, Cone und was sonst noch so dazu gehört)
Ich perönlich habe eine Unit geschrieben, die manche Objekte (bisher nur Sphere) mit glu rendert, aber für jeden Auflösungswert eines solchen Objektes eine Display-List anlegt um ein gleiches Objekt beim nächsten mal direkt rendern zu können (außer bei ner Box).
Momenan bereitet mir aber eine Sache große schwirigkeiten und zwar das rendern einer Capsule.
Als ausweichslösung rendere ich momentan zwei Spheres + einen Cylinder, was aber aufgrund der Texturkoordinaten und den überflüssigen Polygonen unakzeptabel ist.
Hat vielleicht jemand hier in der Community einen Code zum rendern einer Capsule und würde den mal zur Verfügung stellen?
Denn trotz einer Suche im Netz bin ich bisher auf nichts brauchbares gestoßen.
PS: Auch andere Posts bezüglich dem rendern der standard Primitiven sind erwüncht
Ich erstelle derartige Dinge gar nicht "im Code", sondern nutze ein einfaches Modellingtool wie Wings3D dafür. Die sind total simpel zu laden (wenn man z.B. nach rwx exportiert) und man kann sogar noch mehr machen als eine Capsule.
LG Ziz
_________________ Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut. Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’. Und du schaust mich an und fragst ob ich das kann. Und ich denk, ich werd' mich ändern irgendwann. _________________Farin Urlaub - Bewegungslos
Registriert: Sa Aug 18, 2007 18:47 Beiträge: 694 Wohnort: Köln
Programmiersprache: Java
Ich finde, generell ist bei einer Capsule die Texturierung nicht einfach. Wie würdest du die Koordinaten denn verteilen? Obere halbe Kugel von 0.0 - 0.25, Zylinder in der Mitte 0.25 - 0.75 und unter halbe Kugel 0.75 - 1.0 ? Oder relativ zur Größe? Soll heissen: Wenn die Capsule länger wird, skaliert die Textur über das komplette Objekt?
_________________ Es werde Licht. glEnable(GL_LIGHTING); Und es ward Licht.
Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
Außerdem ist ein Mesh bei einer Capsule nicht so einfach möglich, wenn sich die höhre des mittelstücks ändern soll.
Doch, das ist recht einfach, wenn deine Capsule aus drei Teilen besteht. Boden und Deckel werden normal gerendert, das Mittelstück wird zur Laufzeit auf die entsprechende Höhe skaliert. Siehe glScale.
Zitat:
z.B. während der ausführung des Programms die Auflösungzu ändern.
Warum willst du den während der Ausführung die Geometrie-Auflösung anpassen? Reicht es nicht z.B. einfach drei verschiedene Detailstufen zu haben die du dafür aber extern in einem Programm (Wings3D, Blender, ...) erzeugst?
Das mit den verschiedenen "Auflösungen" ist ein beliebtes Mittel zur Performanceverbesserung. Nennt sich "Level of Detail". Wie Coolcat gesagt hat, erstellt man 3 oder mehr verschiedene Detailstufen für verschiedene Entfernungen und zwischen den Entfernungen gibt es kurze Momente, wo man beide Detailstufen zeichnet und langsam von der einen zur anderen überblendet (in Abhängigkeit von der Entfernung).
Blender ist sehr mächtig, das kann bestimmt auch aus einem High Poly Modell verschiedene Modells mit geringerem LOD erzeugen. Aber da müsste ich den Erzählstaffelstab weitergeben.
_________________ Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut. Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’. Und du schaust mich an und fragst ob ich das kann. Und ich denk, ich werd' mich ändern irgendwann. _________________Farin Urlaub - Bewegungslos
Registriert: Do Feb 21, 2008 22:10 Beiträge: 89 Wohnort: Boppard
Ja aber mir geht es eben nun mal um Codeschnipsel!
Wenn ich zum beispiel nur eine kleine Demoapp schreiben will möchte ich nicht gleich nen ganzen Model-Loader da rein hauen nur um ne Capsule zu rendern.
Und das mit glScale bei einer Capsule ist ggenau das was NICHT funktioniert.
Wenn man die skaliert sind die Endkappen nicht mehr Kugeln sondern Ellipsen!
Man müsste in dem Fall das Model aufteilen und wieder getrennt rendern was nicht gerade optimal ist -.-
Momentan arbeite ich an einem Code, der eine Capsule rendern kann. Die Endkappen sind schon nur noch halbe Spheres, die ich mit ner eigenen Funktion DrawPartialSphere zeichne.
Nur die Texturcoordinaten sind wie damadmax schon bemerkt hat ein kleines Problem. Ich denke auch das die aufteilung in [0..0.25] - [0.25..0.75] - [0.75..1] am besten ist, da man wenn man so etwas mit Textur rendert bestimmt möchte das ein bestimmter Teil der Textur genau an der Kante zu der Sphere liegt.
Eine andere interessante Variante wäre aber bestimmt auch die Möglichkeit 2 Texturen zu verwenden - für die Spheres und den Mittelteil.
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
Also wenn du zwei Texturen willst, kannst du auch das Mittelteil skalieren (so wie Coolcat beschrieben hat). Du brauchst für das Mittelteil dann ja ohnehin einen extra Rendercall. Es sei denn du verwendest Multitexturing, wobei die Mitte 100% Texture0 und die Halbkugeln 100% Texture1 haben.
Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:35, insgesamt 1-mal geändert.
Wenn Shader eine Option sind kannst du die Capsule auch im Vertexshader skalieren. Sagen wir die Capsule ist entlang der Z-Achse ausgerichtet und die Halbkugeln setzen bei z=-1 bzw. z=1 an. Dann ist so ein Shader ganz simpel:
Registriert: Do Feb 21, 2008 22:10 Beiträge: 89 Wohnort: Boppard
Sagt mal versteht hier niemand den Sinn dieses Threads???????
Es geht um ZEICHENFUNKTIONEN!
Der Sinn liegt darin, dass man so etwas auch in einer Demoapp nutzen kann, ohne gleich Shader, Modelle und sonst welchen Kram zu verwenden Gerade für Anfänger soll dies mal eine Möglichkeit sein schnell und ohne viel Aufwand Primitives zu zeichnen, ohne solche Sachen wie glut zu verwenden.
Ich habe mittlerweile aus einem Code den ich mal gefunden hatte eine optimierte Variante zum Zeichnen einer Sphere erstellt. Einen Hinweis dabei noch: Alle Zeichenfunktionen die ich anlege sind darauf ausgelegt, Objekte mit der Größe 2*2*2 zu Zeichnen, sodass ein vorher ausgeführtes glScale die Radien zu den Seitenlängen des gezeichneten Objektes enthält.
Hier mal die Sphere:
Code:
Procedure DrawSphere(n : Byte); Const Two_PI = PI * 2; Half_PI = PI / 2; Var i, j : Integer; sin1, cos1 : Extended; sin2, cos2 : Extended; vect : TVector3f; SinCosData : Array of Extended; Begin If (n < 4) Then Begin glBegin(GL_POINTS); glVertex3f(0, 0, 0); glEnd; exit; End;
//Precalculate sinus and cosinus values for the object SetLength(SinCosData, (n+1)*2); for i := 0 to n do SinCos(i * Two_PI / n, SinCosData[i*2], SinCosData[i*2+1]);
For j := 0 To n div 2 Do Begin SinCos(j * Two_PI / n - Half_PI, Sin1, Cos1); SinCos((j + 1) * Two_PI / n - Half_PI, Sin2, Cos2);
glBegin(GL_QUAD_STRIP); For i := n Downto 0 Do Begin vect.x := Cos2 * SinCosData[i*2+1]; vect.y := Sin2; vect.z := Cos2 * SinCosData[i*2];
glTexCoord2f(1 - i / n, 1 - 2 * (j + 1) / n); glNormal3fv(@vect); glVertex3fv(@vect);
glTexCoord2f(1 - i / n, 1 - 2 * j / n); glNormal3fv(@vect); glVertex3fv(@vect); End; glEnd; End; End;
Eine Partial-Sphere (wird bei der Capsule benötigt):
Code:
Procedure DrawPartialSphere(n : Byte; FromFactor: Single=0; ToFactor: Single=1); Const Two_PI = PI * 2; Half_PI = PI / 2; Var i, j : Integer; sin1, cos1 : Extended; sin2, cos2 : Extended; vect : TVector3f; SinCosData : Array of Extended; Begin If (n < 4) Then Begin glBegin(GL_POINTS); glVertex3f(0, 0, 0); glEnd; exit; End;
ToFactor := Min(1, ToFactor); FromFactor := Max(0, FromFactor); If FromFactor > ToFactor then exit;
FromFactor := arcsin(FromFactor*2-1) / PI + 0.5; ToFactor := arcsin(ToFactor*2-1) / PI + 0.5;
//Precalculate sinus and cosinus values for the cylinder SetLength(SinCosData, (n+1)*2); for i := 0 to n do SinCos(i * Two_PI / n, SinCosData[i*2], SinCosData[i*2+1]);
For j := round(n div 2 * FromFactor) To round(n div 2 * ToFactor) Do Begin SinCos(j * Two_PI / n - Half_PI, Sin1, Cos1); SinCos((j + 1) * Two_PI / n - Half_PI, Sin2, Cos2);
glBegin(GL_QUAD_STRIP); For i := n Downto 0 Do Begin vect.x := Cos2 * SinCosData[i*2+1]; vect.y := Sin2; vect.z := Cos2 * SinCosData[i*2];
glTexCoord2f(1 - i / n, 1 - 2 * (j + 1) / n); glNormal3fv(@vect); glVertex3fv(@vect);
glTexCoord2f(1 - i / n, 1 - 2 * j / n); glNormal3fv(@vect); glVertex3fv(@vect); End; glEnd; End; End;
Und ein Cylinder:
Code:
Procedure DrawCylinder(n : Byte); Const Two_PI = PI * 2; Half_PI = PI / 2; Var i : Integer; vect : TVector3f; SinCosData : Array of Extended; Begin If n < 4 then exit; If n = 4 then DrawCube;
glEnable(GL_NORMALIZE);
//Precalculate sinus and cosinus values for the object SetLength(SinCosData, (n+1)*2); for i := 0 to n do SinCos(i/n * Two_PI, SinCosData[i*2], SinCosData[i*2+1]);
glBegin(GL_QUAD_STRIP); for i := 0 to n do begin vect.x := SinCosData[i*2]; vect.z := SinCosData[i*2+1]; vect.y := 1;
Registriert: Do Feb 21, 2008 22:10 Beiträge: 89 Wohnort: Boppard
Coolcat hat geschrieben:
Warum willst du den während der Ausführung die Geometrie-Auflösung anpassen? Reicht es nicht z.B. einfach drei verschiedene Detailstufen zu haben die du dafür aber extern in einem Programm (Wings3D, Blender, ...) erzeugst?
Es geht nicht darum von EINEM Objekt die Auflösung zu ändern, sondern verschiedene objekte mit unterschiedlichen Auflösungen zu rendern.
So würde ich z.B. für eine Skysphere eine andere Auflösung nehmen als für eine große Kugel die irgendwo durch das Level rollt. Bei einer Skysphere sieht man eh kaum Kanten, jedoch merkt man solche bei einer Kugel von außen im Level direkt.
EDIT: Im Code von meinem vorherigen post war ein Fehler - den habe ich korrigiert
Registriert: Do Feb 21, 2008 22:10 Beiträge: 89 Wohnort: Boppard
Ahhh genau das wars was ich gesucht habe!!
Der code zum Zeichnen einer Sphere hatte ich von dort.
Nur habe ich den um einiges verbessert, da in meiner Version Unmengen von überflüggigen SinCos-Aufrufen wegfallen durch einen kleinen Cache.
Außerdem habe ich den Code direkt so geschrieben, das die Größe der Objekte ausschließlich über glScale bestimmt wird, da meist vor dem Zeichnen des Objektes ein glPushMatrix und ein glTranslate stehen. Dadurch ist es dann natürlich performanter die Größe des Objektes mit glScale zu bestimmen statt mehrfach Multiplikationen im Code durchzuführen.
Ich bin nun dabei für den Zylinder einen Wiki-Artikel zu schreiben. Die anderen im Wiki fehlenden Primitive werde ich dann bei Gelegenheit ergänzen
Registriert: Do Feb 21, 2008 22:10 Beiträge: 89 Wohnort: Boppard
Inzwischen habe ich auch einen gut funktionierend Code zum Rendern einer Capsule:
Code:
Procedure slDrawCapsule(n : Byte; rad, height : Single); Const Two_PI = PI * 2; Half_PI = PI / 2; Var i, j : Integer; sin1, cos1 : Extended; sin2, cos2 : Extended; UV : TVector2f; vect : TVector3f; SinCosData : Array of Extended; Begin glPushMatrix; glScalef(rad, rad, rad); height := height / rad; rad := 1;
If height - 2 > 0 then begin glEnable(GL_NORMALIZE);
//Precalculate sinus and cosinus values for the cylinder SetLength(SinCosData, (n+1)*2); for i := 0 to n do SinCos(i/n * Two_PI, SinCosData[i*2], SinCosData[i*2+1]);
//Draw Cylinder glBegin(GL_QUAD_STRIP); for i := 0 to n do begin vect.x := SinCosData[i*2]; vect.z := SinCosData[i*2+1]; vect.y := height*0.5 - 1;
//Draw lower half-sphere glTranslatef(0, -height * 0.5 + 1, 0); For j := 0 To n div 4 Do Begin SinCos(j * Two_PI / n - Half_PI, Sin1, Cos1); SinCos((j + 1) * Two_PI / n - Half_PI, Sin2, Cos2);
glBegin(GL_QUAD_STRIP); For i := n Downto 0 Do Begin vect.x := Cos2 * SinCosData[i*2+1]; vect.y := Sin2; vect.z := Cos2 * SinCosData[i*2];
//Draw upper half-sphere glTranslatef(0, height - 1 * 2, 0); For j := n div 4 To n div 2 Do Begin SinCos(j * Two_PI / n - Half_PI, Sin1, Cos1); SinCos((j + 1) * Two_PI / n - Half_PI, Sin2, Cos2);
glBegin(GL_QUAD_STRIP); For i := n Downto 0 Do Begin vect.x := Cos2 * SinCosData[i*2+1]; vect.y := Sin2; vect.z := Cos2 * SinCosData[i*2];
Die Textur wird dabei so gestreckt, das die untere Halbkugel im Bereich [0..0,25], der Mittelteil [0,25..0,75] und die obere Halbkugel im Bereich [0,75..1] der Textur liegt.
Bei Gelegenheit werde ich dann diesen Code im Wiki posten.
Mitglieder in diesem Forum: 0 Mitglieder und 2 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.