Kugel: Unterschied zwischen den Versionen
Aus DGL Wiki
Flash (Diskussion | Beiträge) K (→Variante 1) |
(→Variante 1) |
||
Zeile 61: | Zeile 61: | ||
end; | end; | ||
end;</pascal> | end;</pascal> | ||
+ | |||
+ | |||
+ | |||
+ | ==Variante 2== | ||
+ | Der nachfolgende Code selbst geschrieben (MatReno) | ||
+ | |||
+ | TVector2f : Array [0..1] of Single; | ||
+ | |||
+ | TVector3f : Array [0..2] of Single; | ||
+ | |||
+ | <pascal> | ||
+ | Procedure DrawSphereObject(radius: Single; n: word; typ: byte; inverted: boolean; voffset: TVector3f; toffset, tscale: TVector2f); | ||
+ | Var alpha : TVector2f; // i*beta around x axis | ||
+ | SinAlpha: TVector2f; // sin(alpha) | ||
+ | CosAlpha: TVector2f; // cos(alpha) | ||
+ | beta : Single; // DegToRad(360° / n) | ||
+ | delta : Single; // j*beta around z axis | ||
+ | SinDelta: Single; // sin(delta) | ||
+ | CosDelta: Single; // cos(delta) | ||
+ | h, q : word; // half, quarter | ||
+ | v : TVector3f; // vector for normal and vertex | ||
+ | border : TVector4i; // for-loop borders | ||
+ | i, j : Integer; | ||
+ | k : Byte; | ||
+ | Begin | ||
+ | radius := abs(radius); | ||
+ | |||
+ | If (n < 4) Or (Odd(n)) Or (radius = 0) Then Exit; | ||
+ | |||
+ | h := n div 2; | ||
+ | q := n div 4; | ||
+ | If (Odd(h)) Then inc(q); | ||
+ | |||
+ | Case typ of | ||
+ | 0: border := ToVector4i( -h, h-1, -q, q); // sphere | ||
+ | 1: border := ToVector4i( -h, h-1, -q, 0); // hemisphere x- | ||
+ | 2: border := ToVector4i( -h, h-1, 0, q); // hemisphere x+ | ||
+ | 3: border := ToVector4i(-h-q, -h+q-1, -q, q); // hemisphere y- | ||
+ | 4: border := ToVector4i( -q, q-1, -q, q); // hemisphere y+ | ||
+ | 5: border := ToVector4i( -h, -1, -q, q); // hemisphere z- | ||
+ | 6: border := ToVector4i( 0, h-1, -q, q); // hemisphere z+ | ||
+ | else Exit; | ||
+ | End; | ||
+ | |||
+ | beta := 2*PI / n; | ||
+ | |||
+ | For i:=border[0] to border[1] do Begin | ||
+ | alpha := ToVector2f(i*beta, (i+1)*beta); | ||
+ | |||
+ | SinAlpha := ToVector2f(sin(alpha[0]), sin(alpha[1])); | ||
+ | CosAlpha := ToVector2f(cos(alpha[0]), cos(alpha[1])); | ||
+ | |||
+ | glBegin(GL_TRIANGLE_STRIP); | ||
+ | For j:=border[2] to border[3] do Begin | ||
+ | delta := j*beta; | ||
+ | |||
+ | SinDelta := sin(delta); | ||
+ | CosDelta := cos(delta); | ||
+ | |||
+ | If (inverted) Then | ||
+ | For k:=1 downto 0 do Begin | ||
+ | v := ToVector3f(-SinDelta, -CosAlpha[k]*CosDelta, -SinAlpha[k]*CosDelta); | ||
+ | glNormal3fv(@v); | ||
+ | v := VectorAdd(VectorMult(v, -radius), voffset); | ||
+ | glTexCoord2f((j/n + 0.25)*tscale[0] + toffset[0], ((i+k)/n)*tscale[1] + toffset[1]); | ||
+ | glvertex3fv(@v); | ||
+ | End; | ||
+ | |||
+ | If (not inverted) Then | ||
+ | For k:=0 to 1 do Begin | ||
+ | v := ToVector3f(SinDelta, CosAlpha[k]*CosDelta, SinAlpha[k]*CosDelta); | ||
+ | glNormal3fv(@v); | ||
+ | v := VectorAdd(VectorMult(v, radius), voffset); | ||
+ | glTexCoord2f((j/n + 0.25)*tscale[0] + toffset[0], ((i+k)/n)*tscale[1] + toffset[1]); | ||
+ | glvertex3fv(@v); | ||
+ | End | ||
+ | End; | ||
+ | glEnd; | ||
+ | End; | ||
+ | End; | ||
+ | </pascal> | ||
+ | |||
+ | Um eine Kugel zu rendern muss man folgendes aufrufen: | ||
+ | <pascal> | ||
+ | DrawSphereObject(radius, n, 0, false, NULL_VECTOR_3f, NULL_VECTOR_2f, ToVector2f(2*tscale[0], tscale[1])); | ||
+ | </pascal> | ||
+ | |||
[[Kategorie:Technik_oder_Algorithmus]] [[Kategorie:Anleitung]] | [[Kategorie:Technik_oder_Algorithmus]] [[Kategorie:Anleitung]] |
Version vom 14. Februar 2007, 11:26 Uhr
Variante 1
Der nachfolgende Code ist ein Port von http://astronomy.swin.edu.au/~pbourke/opengl/sphere/.
Neben den Vertexpositionen werden die Normalen und Texturkoordinaten berechnet.
TVector3f ist ein einfaches Feld mit 3 Floats. (array[0..2] of float) |
procedure CreateSphere(c: TVector3f; r: Single; n: Integer); const TWOPI = PI*2; PID2 = PI/2; var i,j: Integer; theta1,theta2,theta3: Single; e,p:TVector3f; begin if (r < 0) then r := -r; if (n < 0) then n := -n; if (n < 4) or (r <= 0) then begin glBegin(GL_POINTS); glVertex3f(c[0],c[1],c[2]); glEnd; exit; end; for j:=0 to n div 2 do begin theta1 := j * TWOPI / n - PID2; theta2 := (j + 1) * TWOPI / n - PID2; glBegin(GL_QUAD_STRIP); for i:=0 to n do begin theta3 := i * TWOPI / n; e[0] := cos(theta2) * cos(theta3); e[1] := sin(theta2); e[2] := cos(theta2) * sin(theta3); p[0] := c[0] + r * e[0]; p[1] := c[1] + r * e[1]; p[2] := c[2] + r * e[2]; glNormal3f(e[0],e[1],e[2]); glTexCoord2f(i/n,2*(j+1)/n); glVertex3f(p[0],p[1],p[2]); e[0] := cos(theta1) * cos(theta3); e[1] := sin(theta1); e[2] := cos(theta1) * sin(theta3); p[0] := c[0] + r * e[0]; p[1] := c[1] + r * e[1]; p[2] := c[2] + r * e[2]; glNormal3f(e[0],e[1],e[2]); glTexCoord2f(i/n,2*j/n); glVertex3f(p[0],p[1],p[2]); end; glEnd; end; end;
Variante 2
Der nachfolgende Code selbst geschrieben (MatReno)
TVector2f : Array [0..1] of Single;
TVector3f : Array [0..2] of Single;
Procedure DrawSphereObject(radius: Single; n: word; typ: byte; inverted: boolean; voffset: TVector3f; toffset, tscale: TVector2f); Var alpha : TVector2f; // i*beta around x axis SinAlpha: TVector2f; // sin(alpha) CosAlpha: TVector2f; // cos(alpha) beta : Single; // DegToRad(360° / n) delta : Single; // j*beta around z axis SinDelta: Single; // sin(delta) CosDelta: Single; // cos(delta) h, q : word; // half, quarter v : TVector3f; // vector for normal and vertex border : TVector4i; // for-loop borders i, j : Integer; k : Byte; Begin radius := abs(radius); If (n < 4) Or (Odd(n)) Or (radius = 0) Then Exit; h := n div 2; q := n div 4; If (Odd(h)) Then inc(q); Case typ of 0: border := ToVector4i( -h, h-1, -q, q); // sphere 1: border := ToVector4i( -h, h-1, -q, 0); // hemisphere x- 2: border := ToVector4i( -h, h-1, 0, q); // hemisphere x+ 3: border := ToVector4i(-h-q, -h+q-1, -q, q); // hemisphere y- 4: border := ToVector4i( -q, q-1, -q, q); // hemisphere y+ 5: border := ToVector4i( -h, -1, -q, q); // hemisphere z- 6: border := ToVector4i( 0, h-1, -q, q); // hemisphere z+ else Exit; End; beta := 2*PI / n; For i:=border[0] to border[1] do Begin alpha := ToVector2f(i*beta, (i+1)*beta); SinAlpha := ToVector2f(sin(alpha[0]), sin(alpha[1])); CosAlpha := ToVector2f(cos(alpha[0]), cos(alpha[1])); glBegin(GL_TRIANGLE_STRIP); For j:=border[2] to border[3] do Begin delta := j*beta; SinDelta := sin(delta); CosDelta := cos(delta); If (inverted) Then For k:=1 downto 0 do Begin v := ToVector3f(-SinDelta, -CosAlpha[k]*CosDelta, -SinAlpha[k]*CosDelta); glNormal3fv(@v); v := VectorAdd(VectorMult(v, -radius), voffset); glTexCoord2f((j/n + 0.25)*tscale[0] + toffset[0], ((i+k)/n)*tscale[1] + toffset[1]); glvertex3fv(@v); End; If (not inverted) Then For k:=0 to 1 do Begin v := ToVector3f(SinDelta, CosAlpha[k]*CosDelta, SinAlpha[k]*CosDelta); glNormal3fv(@v); v := VectorAdd(VectorMult(v, radius), voffset); glTexCoord2f((j/n + 0.25)*tscale[0] + toffset[0], ((i+k)/n)*tscale[1] + toffset[1]); glvertex3fv(@v); End End; glEnd; End; End;
Um eine Kugel zu rendern muss man folgendes aufrufen:
DrawSphereObject(radius, n, 0, false, NULL_VECTOR_3f, NULL_VECTOR_2f, ToVector2f(2*tscale[0], tscale[1]));