PDA

View Full Version : drawing 3d geometrical shapes using opengl , but without glu



noeska
10-01-2011, 04:17 PM
Is there an existing unit for drawing 3d geometrical shapes like cube/sphere/cylinder/cone/capsule etc?

Glu cannot be used as i want to draw the shapes using an vertex buffer objects with GL_TRIANGLES .

Also i am trying to write some function doing 3d drawing so far i am only happy with the cube and sphere code, for the cylinder i made several attempts but none of them work like i expect them. My attempt in glmodel is not working nice enough with the sphere shape in order to make a 3d capsule shape.

So thanks in advance for your help.

User137
11-01-2011, 05:52 AM
Making actual 3D games is basically impossible without a modelling program. That is why i never generate them runtime. 1) less to code, 2) faster loading times, 3) texture mapping and normals the way i like.

Anyway because i actually created my own modelling program (no longer developed cause its with Delphi), i do have some code to create different objects. This is cylinder for example, just to maybe give hints. If you want to we may try to see what your functions are doing...
Don't remember how that code made texture coordinates but there's a different function to generate normals based on smoothing groups.

function TWorld3D.MakeCylinder(radius,sy: single; sides,segs: integer): word;
var x,y,z: array[1..5] of single; x1,y1,i: integer;
segA,segY: single;
begin
result:=New3DObject;
if sides<3 then sides:=3;
if segs<1 then segs:=1;
segA:=2*PI/sides; segY:=sy/segs;
with o[result] do
for x1:=0 to sides-1 do begin
// Cylinder
for y1:=0 to segs-1 do begin
x[2]:=radius*cos(x1*segA);
z[2]:=radius*sin(x1*segA);
y[2]:=-sy/2+y1*segY;
x[3]:=radius*cos(x1*segA);
z[3]:=radius*sin(x1*segA);
y[3]:=-sy/2+(y1+1)*segY;
x[4]:=radius*cos((x1+1)*segA);
z[4]:=radius*sin((x1+1)*segA);
y[4]:=-sy/2+(y1+1)*segY;
x[1]:=radius*cos((x1+1)*segA);
z[1]:=radius*sin((x1+1)*segA);
y[1]:=-sy/2+y1*segY;
o[result].AddFace(x,y,z,4);
end;
// Top - Bottom
for y1:=0 to 1 do begin
x[1]:=radius*cos(x1*segA);
z[1]:=radius*sin(x1*segA);
x[2]:=radius*cos((x1-y1*2+1)*segA);
z[2]:=radius*sin((x1-y1*2+1)*segA);
x[3]:=0; z[3]:=0;
for i:=1 to 3 do y[i]:=-sy/2+y1*sy;
TFace(f[o[result].AddFace(x,y,z,3)]).smoothGroup:=1;
end;
end;
o[result].UpdateSize;
end;

vgo
11-01-2011, 11:06 AM
Here's some old code of mine.



unit mvRenderHelpers;
{**<
@author(Jani Alanen <http://www.projectminiverse.com>)
@created(2007-01-27)
@lastmod(2009-01-07)

Miscellaneous helper code for rendering .

History

Created:
27.01.2007 (JA)

Modified:
07.01.2009 (JA)
- Renamed to mvRenderHelpers.pas

}
interface

uses
{$IFDEF USE_SDL}
GL, GLU,
{$ELSE}
dglOpenGL,
{$ENDIF}
mvMath;

procedure DrawCube(Size: TFloat);
procedure DrawTorus(MinorRadius, MajorRadius: TFloat; NumMinor, NumMajor: TInt);
procedure DrawSphere(NumMajor, NumMinor: TInt; Radius: TFloat);
procedure DrawCylinder(NumMajor, NumMinor: TInt; Height, Radius: TFloat);
procedure DrawSkewedPyramid(Size: TFloat);
procedure DrawWireSkewedPyramid(Size: TFloat);
procedure DrawTetrahedron(Size: TFloat);
procedure DrawWireTetrahedron(Size: TFloat);
procedure DrawOctahedron(Size: TFloat);
procedure DrawWireOctahedron(Size: TFloat);

implementation

uses
mvGLUtils, mvGlobal;


procedure DrawCube(Size: TFloat);
const
// Texture coordinates from bottom left to top right
TexCoord: array [0..3] of TTexel = ((u: 0; v: 0),
(u: 1; v: 0),
(u: 1; v: 1),
(u: 0; v: 1));
// Vertices used in cube
Vertex: array [0..7] of TVertex = ((v:(-1.0, 1.0, 1.0)), // 0
(v:( 1.0, 1.0, 1.0)), // 1
(v:( 1.0,-1.0, 1.0)), // 2
(v:(-1.0,-1.0, 1.0)), // 3
(v:(-1.0, 1.0,-1.0)), // 4
(v:( 1.0, 1.0,-1.0)), // 5
(v:( 1.0,-1.0,-1.0)), // 6
(v:(-1.0,-1.0,-1.0))); // 7
// Faces of the cube
Cube: array [0..5, 0..3] of Integer = ((0, 1, 2, 3),
(1, 5, 6, 2),
(4, 5, 1, 0),
(0, 3, 7, 4),
(3, 2, 6, 7),
(5, 4, 7, 6));
// Normals for each face of the cube
// Angle of normal and face is allways 90 degrees and
// length is allways 1.0!
Normals: array [0..5] of TVertex = ((v:( 0.0, 0.0, 1.0)),
(v:( 1.0, 0.0, 0.0)),
(v:( 0.0, 1.0, 0.0)),
(v:(-1.0, 0.0, 0.0)),
(v:( 0.0,-1.0, 0.0)),
(v:( 0.0, 0.0,-1.0)));
var
i, j: Integer;
begin
{
// Start rendering quads
glBegin(GL_QUADS);
for i := 0 to 5 do
begin
// Set normal for this face
glNormal3fv(@Normals[i][0]);
for j := 0 to 3 do
begin
// Texture coordinates for this vertex in texels
glTexCoord2f(TexCoord[j, 0], TexCoord[j, 1]);
// Position for this vertex, object position NOT world position
glVertex3fv(@Vertex[Cube[i, j]][0]);
end;
glCheckForError();
end;
// End rendering quads
glEnd;
}

glBegin(GL_QUADS);

//glColor3f(1, 1, 1);
glNormal3f( 0.0, 0.0, 1.0);
glTexCoord2f(0, 0); glVertex3f( Size / 2, Size / 2, Size / 2);
glTexCoord2f(1, 0); glVertex3f(-Size / 2, Size / 2, Size / 2);
glTexCoord2f(1, 1); glVertex3f(-Size / 2,-Size / 2, Size / 2);
glTexCoord2f(0, 1); glVertex3f( Size / 2,-Size / 2, Size / 2);

//glColor3f(1, 0, 0);
glNormal3f( 0.0, 0.0,-1.0);
glTexCoord2f(0, 0); glVertex3f(-Size / 2,-Size / 2,-Size / 2);
glTexCoord2f(1, 0);glVertex3f(-Size / 2, Size / 2,-Size / 2);
glTexCoord2f(1, 1); glVertex3f( Size / 2, Size / 2,-Size / 2);
glTexCoord2f(0, 1); glVertex3f( Size / 2,-Size / 2,-Size / 2);

//glColor3f(0, 1, 0);
glNormal3f( 0.0, 1.0, 0.0);
glTexCoord2f(0, 0); glVertex3f( Size / 2, Size / 2, Size / 2);
glTexCoord2f(1, 0); glVertex3f( Size / 2, Size / 2,-Size / 2);
glTexCoord2f(1, 1); glVertex3f(-Size / 2, Size / 2,-Size / 2);
glTexCoord2f(0, 1); glVertex3f(-Size / 2, Size / 2, Size / 2);

//glColor3f(0, 0, 1);
glNormal3f( 0.0,-1.0, 0.0);
glTexCoord2f(0, 0); glVertex3f(-Size / 2,-Size / 2,-Size / 2);
glTexCoord2f(1, 0); glVertex3f( Size / 2,-Size / 2,-Size / 2);
glTexCoord2f(1, 1); glVertex3f( Size / 2,-Size / 2, Size / 2);
glTexCoord2f(0, 1); glVertex3f(-Size / 2,-Size / 2, Size / 2);

//glColor3f(0, 1, 1);
glNormal3f( 1.0, 0.0, 0.0);
glTexCoord2f(0, 0); glVertex3f( Size / 2, Size / 2, Size / 2);
glTexCoord2f(1, 0); glVertex3f( Size / 2,-Size / 2, Size / 2);
glTexCoord2f(1, 1); glVertex3f( Size / 2,-Size / 2,-Size / 2);
glTexCoord2f(0, 1); glVertex3f( Size / 2, Size / 2,-Size / 2);

//glColor3f(1, 1, 0);
glNormal3f(-1.0, 0.0, 0.0);
glTexCoord2f(0, 0); glVertex3f(-Size / 2,-Size / 2,-Size / 2);
glTexCoord2f(1, 0); glVertex3f(-Size / 2,-Size / 2, Size / 2);
glTexCoord2f(1, 1); glVertex3f(-Size / 2, Size / 2, Size / 2);
glTexCoord2f(0, 1); glVertex3f(-Size / 2, Size / 2,-Size / 2);
glEnd();

{
glVertex3f(-Size + x, Size + y, Size + z);
glVertex3f( Size + x, Size + y, Size + z);
glVertex3f( Size + x,-Size + y, Size + z);
glVertex3f(-Size + x,-Size + y, Size + z);

glVertex3f( Size + x, Size + y, Size + z);
glVertex3f( Size + x, Size + y,-Size + z);
glVertex3f( Size + x,-Size + y,-Size + z);
glVertex3f( Size + x,-Size + y, Size + z);

glVertex3f(-Size + x, Size + y,-Size + z);
glVertex3f( Size + x, Size + y,-Size + z);
glVertex3f( Size + x, Size + y,-Size + z);
glVertex3f(-Size + x, Size + y,-Size + z);

glVertex3f(-Size + x, Size + y,-Size + z);
glVertex3f(-Size + x,-Size + y, Size + z);
glVertex3f(-Size + x,-Size + y,-Size + z);
glVertex3f(-Size + x, Size + y,-Size + z);

glVertex3f(-Size + x,-Size + y, Size + z);
glVertex3f( Size + x,-Size + y, Size + z);
glVertex3f( Size + x,-Size + y,-Size + z);
glVertex3f(-Size + x,-Size + y,-Size + z);

glVertex3f( Size + x, Size,-Size + z);
glVertex3f(-Size + x, Size,-Size + z);
glVertex3f(-Size + x,-Size,-Size + z);
glVertex3f( Size + x,-Size,-Size + z);
}

//glEnd;
end;

procedure DrawTorus(MinorRadius, MajorRadius: TFloat; NumMinor, NumMajor: TInt);
var
MajorStep, MinorStep: TFloat;
i, j: Integer;
a0, a1, b: TFloat;
x0, y0, x1, y1, c, r, z: TFloat;
begin
MajorStep := 2.7 * PI / NumMajor;
MinorStep := 2.7 * PI / NumMajor;
for i := 0 to numMajor do
begin
a0 := i * MajorStep;
a1 := a0 + MajorStep;
x0 := Cos(a0);
y0 := Sin(a0);
x1 := Cos(a1);
y1 := Sin(a1);
glBegin(GL_TRIANGLE_STRIP);
for j := 0 to numMinor do
begin
b := j * MinorStep;
c := Cos(b);
r := MinorRadius * c + MajorRadius;
z := MinorRadius * Sin(b);

glNormal3f(x0 * c, y0 * c, z / MinorRadius);
glTexCoord2f(i / NumMajor, j / NumMinor);
glVertex3f(x0 * r, y0 * r, z);

glNormal3f(x1 * c, y1 * c, z / MinorRadius);
glTexCoord2f((i + 1) / NumMajor, j / NumMinor);
glVertex3f(x1 * r, y1 * r, z);
end;
glEnd();
end;
end;

procedure DrawSphere(NumMajor, NumMinor: Integer; Radius: TFloat);
var
MajorStep, MinorStep: TFloat;
i, j: Integer;
a, b, c, r0, r1: TFloat;
x, y, z0, z1: TFloat;
begin
MajorStep := (PI / NumMajor);
MinorStep := (2.0 * PI / NumMinor);

for i := 0 to NumMajor do
begin
a := i * MajorStep;
b := a + MajorStep;
r0 := radius * Sin(a);
r1 := radius * Sin(b);
z0 := radius * Cos(a);
z1 := radius * Cos(b);

glBegin(GL_TRIANGLE_STRIP);
for j := 0 to NumMinor do
begin
c := j * MinorStep;
x := Cos(c);
y := Sin(c);

glNormal3f((x * r0) / radius, (y * r0) / Radius, z0 / Radius);
glTexCoord2f(j / NumMinor, i / NumMajor);
glVertex3f(x * r0, y * r0, z0);

glNormal3f((x * r1) / Radius, (y * r1) / Radius, z1 / Radius);
glTexCoord2f(j / NumMinor, (i + 1) / NumMajor);
glVertex3f(x * r1, y * r1, z1);
end;
glEnd();
end;
end;

procedure DrawCylinder(NumMajor, NumMinor: TInt; Height, Radius: TFloat);
var MajorStep, MinorStep: TFloat;
i, j: Integer;
a, x, y, z0, z1: TFloat;
begin
MajorStep := Height / NumMajor;
MinorStep := 2.0 * PI / NumMinor;

for i := 0 to NumMajor do
begin
z0 := 0.5 * Height - i * MajorStep;
z1 := z0 - MajorStep;

glBegin(GL_TRIANGLE_STRIP);
for j := 0 to NumMinor do
begin
a := j * MinorStep;
x := Radius * Cos(a);
y := Radius * Sin(a);

glNormal3f(x / radius, y / radius, 0.0);
glTexCoord2f(j / numMinor, i / numMajor);
glVertex3f(x, y, z0);

glNormal3f(x / radius, y / radius, 0.0);
glTexCoord2f(j / numMinor, (i + 1) / numMajor);
glVertex3f(x, y, z1);
end;
glEnd();
end;
end;

procedure DrawSkewedPyramid(Size: TFloat);
begin
glBegin(GL_TRIANGLES);
// Back
glVertex3f(0, Size, -(Size / 2)); // Top
glVertex3f(Size/2, 0, -(Size / 2)); // Bottom right
glVertex3f(-Size/2, 0, -(Size / 2)); // Bottom left
//glVertex3f(0, Size, -(Size / 2));
glEnd;

// Left
glBegin(GL_TRIANGLES);
glVertex3f(0, 0, (Size / 2)); // Nose
glVertex3f(0, Size, -(Size / 2));
glVertex3f(-Size/2, 0, -(Size / 2));

//glVertex3f(0, 0, (Size / 2));
glEnd;

// Right
glBegin(GL_TRIANGLES);
glVertex3f(0, Size, -(Size / 2));
glVertex3f(0, 0, (Size / 2));
glVertex3f(Size/2, 0, -(Size / 2));
//glVertex3f(0, Size, -(Size / 2));
glEnd();

// Bottom
glBegin(GL_TRIANGLES);
glVertex3f(0, 0, (Size / 2));
glVertex3f(-Size/2, 0, -(Size / 2));
glVertex3f(Size/2, 0, -(Size / 2));
//glVertex3f(0, 0, (Size / 2));
glEnd();
end;

procedure DrawWireSkewedPyramid(Size: TFloat);
begin
glBegin(GL_LINE_STRIP);
// Back
glVertex3f(0, Size, -(Size / 2)); // Top
glVertex3f(Size/2, 0, -(Size / 2)); // Bottom right
glVertex3f(-Size/2, 0, -(Size / 2)); // Bottom left
glVertex3f(0, Size, -(Size / 2));
glEnd;

// Left
glBegin(GL_LINE_STRIP);
glVertex3f(0, 0, (Size / 2)); // Nose
glVertex3f(0, Size, -(Size / 2));
glVertex3f(-Size/2, 0, -(Size / 2));
glVertex3f(0, 0, (Size / 2));
glEnd;

// Right
glBegin(GL_LINE_STRIP);
glVertex3f(0, Size, -(Size / 2));
glVertex3f(0, 0, (Size / 2));
glVertex3f(Size/2, 0, -(Size / 2));
glVertex3f(0, Size, -(Size / 2));
glEnd();

// Bottom
glBegin(GL_LINE_STRIP);
glVertex3f(0, 0, (Size / 2));
glVertex3f(-Size/2, 0, -(Size / 2));
glVertex3f(Size/2, 0, -(Size / 2));
glVertex3f(0, 0, (Size / 2));
glEnd();
end;

procedure DrawTetrahedron(Size: TFloat);
begin
{
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(0, 2 * (Size / 2), 0);
glVertex3f(-1 * (Size / 2), 0, 1 * (Size / 2));
glVertex3f(1 * (Size / 2), 0, 1 * (Size / 2));
glVertex3f(0, 0, -1.4 * (Size / 2));
glVertex3f(0, 2 * (Size / 2), 0);
glVertex3f(-1 * (Size / 2), 0, 1 * (Size / 2));
glEnd();
}
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(0, 2 * (Size / 2) - 0.5, 0);
glVertex3f(-1 * (Size / 2), -0.5, 1 * (Size / 2));
glVertex3f(1 * (Size / 2), -0.5, 1 * (Size / 2));
glVertex3f(0, -0.5, -1.4 * (Size / 2));
glVertex3f(0, 2 * (Size / 2) - 0.5, 0);
glVertex3f(-1 * (Size / 2), -0.5, 1 * (Size / 2));
glEnd();
end;

procedure DrawWireTetrahedron(Size: TFloat);
begin
{
glBegin(GL_LINE_STRIP);
glVertex3f(0, 2 * (Size / 2), 0);
glVertex3f(-1 * (Size / 2), 0, 1 * (Size / 2));
glVertex3f(1 * (Size / 2), 0, 1 * (Size / 2));
glVertex3f(0, 2 * (Size / 2), 0);

glVertex3f(0, 2 * (Size / 2), 0);
glVertex3f(-1 * (Size / 2), 0, 1 * (Size / 2));
glVertex3f(0, 0, -1.4 * (Size / 2));
glVertex3f(0, 2 * (Size / 2), 0);

glVertex3f(0, 0, -1.4 * (Size / 2));
glVertex3f(0, 2 * (Size / 2), 0);
glVertex3f(1 * (Size / 2), 0, 1 * (Size / 2));
glVertex3f(0, 0, -1.4 * (Size / 2));

glEnd();
}
glBegin(GL_LINE_STRIP);
glVertex3f(0, 2 * (Size / 2) - 0.5, 0);
glVertex3f(-1 * (Size / 2), -0.5, 1 * (Size / 2));
glVertex3f(1 * (Size / 2), -0.5, 1 * (Size / 2));
glVertex3f(0, 2 * (Size / 2) - 0.5, 0);

glVertex3f(0, 2 * (Size / 2) - 0.5, 0);
glVertex3f(-1 * (Size / 2), -0.5, 1 * (Size / 2));
glVertex3f(0, -0.5, -1.4 * (Size / 2));
glVertex3f(0, 2 * (Size / 2) - 0.5, 0);

glVertex3f(0, -0.5, -1.4 * (Size / 2));
glVertex3f(0, 2 * (Size / 2) - 0.5, 0);
glVertex3f(1 * (Size / 2), -0.5, 1 * (Size / 2));
glVertex3f(0, -0.5, -1.4 * (Size / 2));

glEnd();
end;

procedure DrawOctahedron(Size: TFloat);
const
Vertices: array [0..5] of TVector3f = (
(v: (0.0, 0.0, 1.0/SQRT2)),
(v: ( 0.5, 0.5, 0.0)),
(v: (-0.5, 0.5, 0.0)),
(v: (-0.5,-0.5, 0.0)),
(v: (0.5,-0.5, 0.0)),
(v: (0.0, 0.0, -1.0/SQRT2))
);
begin
glScalef(Size, Size, Size);
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(@Vertices[0]);
glVertex3fv(@Vertices[1]);
glVertex3fv(@Vertices[2]);
glVertex3fv(@Vertices[3]);
glVertex3fv(@Vertices[4]);
glVertex3fv(@Vertices[1]);
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(@Vertices[5]);
glVertex3fv(@Vertices[1]);
glVertex3fv(@Vertices[4]);
glVertex3fv(@Vertices[3]);
glVertex3fv(@Vertices[2]);
glVertex3fv(@Vertices[1]);
glEnd();
end;

procedure DrawWireOctahedron(Size: TFloat);
const
Vertices: array [0..5] of TVector3f = (
(v: (0.0, 0.0, 1.0/SQRT2)),
(v: ( 0.5, 0.5, 0.0)),
(v: (-0.5, 0.5, 0.0)),
(v: (-0.5,-0.5, 0.0)),
(v: (0.5,-0.5, 0.0)),
(v: (0.0, 0.0, -1.0/SQRT2))
);
begin
glScalef(Size, Size, Size);
glBegin(GL_LINES);
glVertex3fv(@Vertices[0]);
glVertex3fv(@Vertices[1]);
glVertex3fv(@Vertices[0]);
glVertex3fv(@Vertices[2]);
glVertex3fv(@Vertices[0]);
glVertex3fv(@Vertices[3]);
glVertex3fv(@Vertices[0]);
glVertex3fv(@Vertices[4]);
glVertex3fv(@Vertices[0]);
glVertex3fv(@Vertices[1]);
glEnd();
glBegin(GL_LINES);
glVertex3fv(@Vertices[5]);
glVertex3fv(@Vertices[1]);
glVertex3fv(@Vertices[5]);
glVertex3fv(@Vertices[4]);
glVertex3fv(@Vertices[5]);
glVertex3fv(@Vertices[3]);
glVertex3fv(@Vertices[5]);
glVertex3fv(@Vertices[2]);
glVertex3fv(@Vertices[5]);
glVertex3fv(@Vertices[1]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(@Vertices[1]);
glVertex3fv(@Vertices[4]);
glVertex3fv(@Vertices[3]);
glVertex3fv(@Vertices[2]);
glVertex3fv(@Vertices[1]);
glEnd();
end;


end.

code_glitch
11-01-2011, 04:02 PM
Hey there vgo - that is some mighty good code you've got there if I may say so myself. Would you mind awfully if I included this in Prometheus and added your name to the credits? This is non-commercial use, just so you know.

michalis
11-01-2011, 07:29 PM
You can also take a look at sphere/cylinder/cone/cube -> mesh convertion in my engine. The code doesn't do direct rendering (it only converts to a mesh in TNodeIndexedFaceSet instance), and it's a little involved (I have to deal with texture coords, optional over-triangulating for Gouraud shading and such), but maybe it will be useful for some hints anyway. It's LGPL.

https://vrmlengine.svn.sourceforge.net/svnroot/vrmlengine/trunk/kambi_vrml_game_engine/src/vrml/vrmlnodes_cone_cylinder.inc
https://vrmlengine.svn.sourceforge.net/svnroot/vrmlengine/trunk/kambi_vrml_game_engine/src/vrml/vrmlnodes_box.inc
https://vrmlengine.svn.sourceforge.net/svnroot/vrmlengine/trunk/kambi_vrml_game_engine/src/vrml/vrmlnodes_sphere.inc

code_glitch
11-01-2011, 08:30 PM
looks like a 3d promethetus is a possibility in the future then. for now though, lets focus on the the three current branches of it ;)

noeska
12-01-2011, 06:39 PM
This is what i have sofar (left out all but cylinder related):



unit glShapes;

interface

// Version: MPL 1.1

uses
DglOpenGL,
glTypes;

function createPlane(halfExtend: GLfloat;var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GluInt;
function createCube(ax,ay,az: GLfloat;var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;

function createSphere(numSlices:GLuint; radius: GLfloat; var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;
function createCylinder(radius: GLFloat; height: GLFloat; var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;
function createDisk(radius: GLFloat; height: GLFloat; var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;
function createClosedCylinder(radius: GLFloat; height: GLFloat; var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;

implementation

uses math;

{------------------------------------------------------------------}
{ Function to create a plane shape }
{------------------------------------------------------------------}
function createPlane(halfExtend: GLfloat;var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GluInt;
var
numVertices: Gluint;
numIndices: Gluint;
i: GLuint;

const
xy_vertices: array[0..15] of GLFloat=
( -1.0, -1.0, 0.0, +1.0,
+1.0, -1.0, 0.0, +1.0,
-1.0, +1.0, 0.0, +1.0,
+1.0, +1.0, 0.0, +1.0);
xy_normals: array[0..11] of GLFloat=
( 0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0);
xy_texCoords: array[0..7] of GLFloat=
( 0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0);
xy_indices: array[0..5] of GLuint=
( 0, 1, 2,
1, 3, 2);

begin
numVertices := 4;
numIndices := 6;

numberVertices := numVertices;

SetLength(vertices, 4*numVertices );
for i := 0 to (4*numVertices) - 1 do
vertices[i]:=xy_vertices[i];

for i := 0 to numVertices-1 do
begin
vertices[i*4+0] := vertices[i*4+0] * halfExtend;
vertices[i*4+1] := vertices[i*4+1] * halfExtend;
end;

SetLength(normals, 3*numVertices);
for i := 0 to (3*numVertices) - 1 do
normals[i]:=xy_normals[i];

SetLength(texCoords,2*numVertices);
for i := 0 to (2*numVertices) - 1 do
texcoords[i]:=xy_texcoords[i];

SetLength(indices, numIndices);
for i := 0 to numIndices - 1 do
indices[i]:=xy_indices[i];

result := numIndices;
end;


function createCylinder(radius: GLFloat; height: GLFloat; var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;
var
i,j: GLuint;
//CirclePoints: array of TVector3;
CIRCLE_RESOLUTION : integer;
WIDTH_RESOLUTION : integer;
WIDTH : glFloat;
totalElements : integer;
MAX_VERTICIES: integer;
curidx: integer;
anglestep: GLFloat;
begin

//pff now renders somewhat ok
//TODO: add top and botom look at meshgen sources
//TODO: vary width of circle over height
//so stop using circlepoints

RADIUS := RADIUS /2; //why div 2 is that because i define with instead of radious

CIRCLE_RESOLUTION := 35;
WIDTH_RESOLUTION := 10;
WIDTH := height/2;
//setlength(CirclePoints,CIRCLE_RESOLUTION);

MAX_VERTICIES := (CIRCLE_RESOLUTION * WIDTH_RESOLUTION);
numberVertices := MAX_VERTICIES;

angleStep := (2.0 * PI) / CIRCLE_RESOLUTION;

// Circle end-caps
//for i:=0 to CIRCLE_RESOLUTION-1 do
//begin
// circlePoints[i].x := cos( degtorad( (360.0 / CIRCLE_RESOLUTION) * i ) * RADIUS);
// circlePoints[i].y := sin( degtorad( (360.0 / CIRCLE_RESOLUTION) * i ) * RADIUS);
//end;

// Vertices
setlength(vertices, high(vertices) + (CIRCLE_RESOLUTION * WIDTH_RESOLUTION * 4) );

curidx := 0;

//TODO: swap i and j to make cone? also make vertices normals in one step

for i:=0 to CIRCLE_RESOLUTION-1 do
begin
for j:=0 to WIDTH_RESOLUTION-1 do
begin


//vertices[curidx + 0] := radius * sin ( angleStep * i ) * sin ( angleStep * j );
//vertices[curidx + 0] := cos( degtorad( (360.0 / CIRCLE_RESOLUTION) * i )) * RADIUS;// + circlePoints[i].y;
vertices[curidx + 0] := cos( ( anglestep * i )) * RADIUS;// + circlePoints[i].y;

vertices[curidx + 1] := (WIDTH*j) / (WIDTH_RESOLUTION);//(WIDTH*2) / (WIDTH_RESOLUTION * j);//circlePoints[i].y;//WIDTH / (WIDTH_RESOLUTION * j);
//vertices[curidx + 2] := sin( degtorad( (360.0 / CIRCLE_RESOLUTION) * i )) * RADIUS;//WIDTH / (WIDTH_RESOLUTION * j);////circlePoints[i].y*WIDTH_RESOLUTION*j; //i * WIDTH_RESOLUTION+j;
vertices[curidx + 2] := sin( ( anglestep * i )) * RADIUS;//WIDTH / (WIDTH_RESOLUTION * j);////circlePoints[i].y*WIDTH_RESOLUTION*j; //i * WIDTH_RESOLUTION+j;

vertices[curidx + 3] := 1.0;



curidx := curidx + 4;



end;


//radius := radius - 0.1; //make an spiral ake tape dispensen when on

end;

// Indices
totalElements := CIRCLE_RESOLUTION * WIDTH_RESOLUTION * 6;
setlength(indices, high(indices) + totalElements);

curidx :=0;
for i:=0 to CIRCLE_RESOLUTION-1 do
begin
for j:=0 to WIDTH_RESOLUTION-1 do
begin
indices[curidx+0]:=(i*WIDTH_RESOLUTION + j + 1) mod MAX_VERTICIES;
indices[curidx+1]:=(i*WIDTH_RESOLUTION + j) mod MAX_VERTICIES;
indices[curidx+2]:=((i+1) * WIDTH_RESOLUTION + j) mod MAX_VERTICIES;

indices[curidx+3]:=(i*WIDTH_RESOLUTION + j + 1) mod MAX_VERTICIES;
indices[curidx+4]:=((i+1) * WIDTH_RESOLUTION + j) mod MAX_VERTICIES;
indices[curidx+5]:=((i+1) * WIDTH_RESOLUTION + j + 1) mod MAX_VERTICIES;

curidx := curidx +6;
end;
end;

// Normals
setlength(normals, high(normals) + CIRCLE_RESOLUTION * WIDTH_RESOLUTION * 3 );

curidx := 0;
for i:=0 to CIRCLE_RESOLUTION-1 do
begin
for j:=0 to WIDTH_RESOLUTION-1 do
begin
//normals[curidx+0] := (radius * sin ( angleStep * i ) * sin ( angleStep * j ))/radius;
normals[curidx + 0] := cos( ( anglestep * i ));//cos( degtorad( (360.0 / CIRCLE_RESOLUTION) * i ) );// * RADIUS) / radius;
normals[curidx + 1] := ((j*WIDTH) / WIDTH_RESOLUTION) /radius;
normals[curidx + 2] := sin( ( anglestep * i ));//sin( degtorad( (360.0 / CIRCLE_RESOLUTION) * i ) );// * RADIUS) / radius;
curidx := curidx + 3;
end;
end;

// TexCoords
setlength(texcoords, high(texcoords) + (CIRCLE_RESOLUTION * WIDTH_RESOLUTION * 2 ));
curidx := 0;
for i:=0 to CIRCLE_RESOLUTION-1 do
begin
for j:=0 to WIDTH_RESOLUTION-1 do
begin
texcoords[curidx + 0] := 0;
texcoords[curidx + 1] := 0;
curidx := curidx + 2;
end;
end;

result := totalElements;

end;

function createDisk(radius: GLFloat; height: GLFloat; var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;
var
i,j: GLuint;
CIRCLE_RESOLUTION : integer;
WIDTH_RESOLUTION : integer;
WIDTH : glFloat;
totalElements : integer;
MAX_VERTICIES: integer;
curidx: integer;
anglestep: GLFloat;
temp: integer;
begin

//stacking is wrong


RADIUS := RADIUS /2; //why div 2 is that because i define with instead of radious

CIRCLE_RESOLUTION := 35;
WIDTH_RESOLUTION := 10;
WIDTH := height/2;

//WIDTH := 0.5;


MAX_VERTICIES := (CIRCLE_RESOLUTION * WIDTH_RESOLUTION);
numberVertices := MAX_VERTICIES;

angleStep := (2.0 * PI) / CIRCLE_RESOLUTION;


// Vertices
curidx := high(vertices);
setlength(vertices, high(vertices) + (CIRCLE_RESOLUTION * 4) + (4) );

//curidx := 0;

//center point begin close
vertices[curidx + 0] := 0.0;
vertices[curidx + 1] := 1.0 * width;
vertices[curidx + 2] := 0.0;
vertices[curidx + 3] := 1.0;
curidx := curidx + 4;

j:=0;
for i:=0 to CIRCLE_RESOLUTION-1 do
begin
vertices[curidx + 0] := cos( ( anglestep * i )) * RADIUS;
vertices[curidx + 1] := 1.0 * width;
vertices[curidx + 2] := sin( ( anglestep * i )) * RADIUS;
vertices[curidx + 3] := 1.0;
curidx := curidx + 4;
end;

//Indices
totalElements := (CIRCLE_RESOLUTION * 3);

curidx := high(indices);
temp := curidx;
setlength(indices, high(indices) + totalElements);

//curidx :=0;
for i:=0 to CIRCLE_RESOLUTION-1 do
begin
Indices[(curidx)+2]:=temp;//0;
Indices[(curidx)+1]:=temp+(i+1);
if (i = CIRCLE_RESOLUTION-1) then
Indices[(curidx)+0]:=temp+1 //1
else
Indices[(curidx)+0]:=temp+(i+2);

curidx := curidx + 3;
end;

// Normals
curidx :=high(normals);
setlength(normals, high(normals) + (CIRCLE_RESOLUTION * 3) + (3) );

//curidx := 0;

normals[curidx + 0] := 0.0;
normals[curidx + 1] := 1.0;
normals[curidx + 2] := 0.0;

curidx := curidx + 3;

j:=0;
for i:=0 to CIRCLE_RESOLUTION-1 do
begin
normals[curidx + 0] := 0;
normals[curidx + 1] := 1;
normals[curidx + 2] := 0;
curidx := curidx + 3;
end;

// TexCoords
curidx := high(texcoords);
setlength(texcoords, high(texcoords) + ( CIRCLE_RESOLUTION * 2) );
//curidx := 0;
j:=0;
for i:=0 to CIRCLE_RESOLUTION-1 do
begin
texcoords[curidx + 0] := 0;
texcoords[curidx + 1] := 0;
curidx := curidx + 2;
end;

result := totalElements;

end;

function createClosedCylinder(radius: GLFloat; height: GLFloat; var vertices: GLBufferf;var normals: GLbufferf; var texCoords: GLbufferf; var indices: GLBufferi;var numberVertices: GLuint): GLuint;
var
total, numofvert: GLUint;
begin
setlength(vertices,1);
setlength(normals,1);
setlength(texCoords,1);
setlength(indices,1);

total := createCylinder(radius, height, vertices, normals, texCoords, indices,numberVertices);
numofvert := numberVertices;
total := total + createDisk(radius, height, vertices, normals, texCoords, indices,numberVertices);
numberVertices := numberVertices + numofvert;
end;

end.


Drawing an open cylinder works, drawing an disk works, but combining them give lots of unexpected results. The calling of creatdisk is broken in this example it is not intendended to be called on its own, only as part createclosedcylinder.

User137
13-01-2011, 09:55 AM
The result of function createClosedCylinder() seems to be undefined... Didn't compiler warn about it? ;)

vgo
13-01-2011, 11:10 AM
Hey there vgo - that is some mighty good code you've got there if I may say so myself. Would you mind awfully if I included this in Prometheus and added your name to the credits? This is non-commercial use, just so you know.

Sure, I'm glad the code is useful for someone. :)