Code:
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.
Bookmarks