Simple primative library.

Miscellaneous Forums/Blitz Showcase/Simple primative library.

Hello, I've created a simple primative library for OpenGL users. It is done in blitz but you could convert it as needed. It would be best to call the command inside of an opengl list. This way the overhead is minimized in drawing them. I spell poory. I would greatly appreciate credit if you use this as a base for custom primatives.



Happy coding.

It features:
draw_tube(Hdivisions:Float, vdivisions:Float, Height:Float, radius:Float, capped:Byte)

draw_cone(Hdivisions:Float, Height:Float, radius:Float, capped:Byte)

draw_sphere(Hdivisions:Float, vdivisions:Float, radius:Float)

draw_hemisphere(Hdivisions:Float, vdivisions:Float, radius:Float, capped:Byte)

draw_torus(Hdivisions:Float, vdivisions:Float, radius:Float, radius2:Float)

here is the demo with the code:
Strict
GLGraphics 480, 480
glEnable GL_DEPTH_TEST
glEnable GL_LIGHTING
glEnable GL_LIGHT0
glShadeModel(GL_SMOOTH) 
glMatrixMode GL_PROJECTION
glLoadIdentity
glClearColor(.25, .25, .25, 1) 

glFrustum - 0.1, 0.1, - 0.1, 0.1, 0.1, 10000.0

glMatrixMode GL_MODELVIEW
glLoadIdentity
Global xrot:Float
Global yrot:Float

Type surface_normal
Field x:Float, y:Float, z:Float
 
EndType ' something to hold data for surface normal
Function create_surface_normal:surface_normal(p1x:Float, p1y:Float, p1z:Float, p2x:Float, p2y:Float, p2z:Float, p3x:Float, p3y:Float, p3z:Float, bool_side = 0) 
		Local nx:Float = ((p3y - p2y) * (p2z - p1z)) - ((p3z - p2z) * (p2y - p1y)) 
		Local ny:Float = ((p3z - p2z) * (p2x - p1x)) - ((p3x - p2x) * (p2z - p1z)) 
		Local nz:Float = ((p3x - p2x) * (p2y - p1y)) - ((p3y - p2y) * (p2x - p1x)) 
		Local N:Float = Sqr((nx * nx) + (ny * ny) + (nz * nz)) 
			
			If bool_side = 1
				N = n * -1.0
			EndIf
			
		Local a:Float = (1.0 / N) * nx
		Local b:Float = (1.0 / N) * ny
		Local c:Float = (1.0 / N) * nz
		Local v:surface_normal = New surface_normal
		
		v.x = a
		v.y = b
		v.z = c
		Return v
endfunction 
Function radius_inscribed:Float(nsides:Float, side_length:Float) 
	Local half_angle#=360.0/(nsides*2.0)
	Local half_side#=side_length/2.0
	Return half_side/Tan(half_angle)
End Function
Function radius_circumscribed#(nsides#,side_length#)
	Local half_angle#=360.0/(nsides*2.0)
	Local half_side#=side_length/2.0
	Return half_side/Sin(half_angle)
End Function

Function draw_cell(numsides:Float, thickness:Float) 
	Local sub:Float = 360.0 / numsides
	Local radius:Float = radius_circumscribed(numsides, 32.0) 
	Local radius2:Float = radius - 2.0
	Local topz:Float = -thickness / 2.0
	Local n:surface_normal = New surface_normal
	
	'top face
	glBegin(GL_TRIANGLE_FAN) 
	n = create_surface_normal(0.0, 0.0, topz, Cos(0 * sub) * radius2, Sin(0 * sub) * radius2, topz, Cos((1) * sub) * radius2, Sin((1) * sub) * radius2, topz, 0) 
	glNormal3f(n.x, n.y, n.z) 
	glVertex3f(0.0, 0.0, topz) 
	For Local i = 0 To numsides
		glVertex3f(Cos(I * sub) * radius2, Sin(i * sub) * radius2, topz) 
	Next
	glEnd
	
	'bottom face
	n = create_surface_normal(0.0, 0.0, topz, Cos(0 * -sub) * radius2, Sin(0 * -sub) * radius2, - topz, Cos((1) * -sub) * radius2, Sin((1) * -sub) * radius2, - topz, 0) 
	
	glBegin(GL_TRIANGLE_FAN) 
	glNormal3f(n.x, n.y, n.z) 
	glVertex3f(0.0, 0.0, - topz) 
	For Local j = 0 To numsides
		glVertex3f(Cos(j * -sub) * radius2, Sin(j * -sub) * radius2, - topz) 
	Next
	glEnd
	
	'middle belt
	glBegin(GL_QUADS) 
	glNormal3f(0.0, 0.0, - topz) 

	For Local k = 0 To numsides - 1
	n = create_surface_normal(Cos(k * -sub) * radius, Sin(k * -sub) * radius, - topz / 2.0, Cos((k - 1) * -sub) * radius, Sin((k - 1) * -sub) * radius, - topz / 2.0, Cos((k - 1) * -sub) * radius, Sin((k - 1) * -sub) * radius, topz / 2.0, 0) 
	glNormal3f(n.x, n.y, n.z) 
		glVertex3f(Cos(k * -sub) * radius, Sin(k * -sub) * radius, - topz / 2.0) 
		glVertex3f(Cos((k - 1) * -sub) * radius, Sin((k - 1) * -sub) * radius, - topz / 2.0) 
		glVertex3f(Cos((k - 1) * -sub) * radius, Sin((k - 1) * -sub) * radius, topz / 2.0) 
		glVertex3f(Cos(k * -sub) * radius, Sin(k * -sub) * radius, topz / 2.0) 
		 
	Next
	glEnd
	
	glBegin(GL_QUADS) 
	glNormal3f(0.0, 0.0, - topz) 
	
	' bridge belt to top
	For Local l = 0 To numsides - 1
	n = create_surface_normal(Cos(l * -sub) * radius2, Sin(l * -sub) * radius2, - topz, Cos((l - 1) * -sub) * radius2, Sin((l - 1) * -sub) * radius2, - topz, Cos((l - 1) * -sub) * radius, Sin((l - 1) * -sub) * radius, - topz / 2.0, 0) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(Cos(l * -sub) * radius2, Sin(l * -sub) * radius2, - topz) 
		glVertex3f(Cos((l - 1) * -sub) * radius2, Sin((l - 1) * -sub) * radius2, - topz) 
		glVertex3f(Cos((l - 1) * -sub) * radius, Sin((l - 1) * -sub) * radius, - topz / 2.0) 
		glVertex3f(Cos(l * -sub) * radius, Sin(l * -sub) * radius, - topz / 2.0) 
		 
	Next
	glEnd
	
	' bridge belt to bottom
	glBegin(GL_QUADS) 
	For Local m = 0 To numsides - 1
	n = create_surface_normal(Cos(m * sub) * radius2, Sin(m * sub) * radius2, topz, Cos((m - 1) * sub) * radius2, Sin((m - 1) * sub) * radius2, topz, Cos((m - 1) * sub) * radius, Sin((m - 1) * sub) * radius, topz / 2.0, 0) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(Cos(m * sub) * radius2, Sin(m * sub) * radius2, topz) 
		glVertex3f(Cos((m - 1) * sub) * radius2, Sin((m - 1) * sub) * radius2, topz) 
		glVertex3f(Cos((m - 1) * sub) * radius, Sin((m - 1) * sub) * radius, topz / 2.0) 
		glVertex3f(Cos(m * sub) * radius, Sin(m * sub) * radius, topz / 2.0) 
		 
	Next
	glEnd
End Function
Function draw_tube(Hdivisions:Float, vdivisions:Float, Height:Float, radius:Float, capped:Byte) 
	'use a double for loop
	Local belt_height:Float = Height / vdivisions
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal = New surface_normal
	
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To vdivisions - 1
		n = create_surface_normal(Cos(sub * x) * radius, - half_height + (Y * belt_height), Sin(sub * x) * radius, Cos(sub * (x + 1)) * radius, - half_height + (Y * belt_height), Sin(sub * (x + 1)) * radius, Cos(sub * (x + 1)) * radius, - half_height + ((Y + 1) * belt_height), Sin(sub * (x + 1)) * radius, 0) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(Cos(sub * x) * radius, - half_height + (Y * belt_height), Sin(sub * x) * radius) 
		glVertex3f(Cos(sub * (x + 1)) * radius, - half_height + (Y * belt_height), Sin(sub * (x + 1)) * radius) 
		glVertex3f(Cos(sub * (x + 1)) * radius, - half_height + ((Y + 1) * belt_height), Sin(sub * (x + 1)) * radius)
		glVertex3f(Cos(sub * x) * radius, - half_height + ((Y + 1) * belt_height), Sin(sub * x) * radius) 
		Next
	Next
	' draw the top and bottom
	If capped = 1
		glBegin(GL_TRIANGLES) 
		
		glNormal3f(0, - 1.0, 0) 
		For Local x:Float = 0 To hdivisions - 1 
			glVertex3f(0, - half_height, 0) 
			glVertex3f(Cos(sub * x) * radius, - half_height, Sin(sub * x) * radius) 
			glVertex3f(Cos(sub * (x - 1)) * radius, - half_height, Sin(sub * (x - 1)) * radius) 
			
		Next
		glEnd
		
		glBegin(GL_TRIANGLES) 
		
		glNormal3f(0, 1.0, 0) 
		For Local x:Float = 0 To hdivisions - 1 
			glVertex3f(0, half_height, 0) 
			glVertex3f(Cos(sub * x) * radius, half_height, Sin(sub * x) * radius) 
			glVertex3f(Cos(sub * (x - 1)) * radius, half_height, Sin(sub * (x - 1)) * radius) 
			
		Next
		glEnd
	End If
	glEnd
End Function
Function draw_cone(Hdivisions:Float, Height:Float, radius:Float, capped:Byte) 
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal = New surface_normal
	
	glBegin(GL_TRIANGLES) 
	For Local x:Float = 0 To hdivisions - 1
		n = create_surface_normal(0, - half_height, 0, Cos(sub * (x + 1)) * radius, half_height, Sin(sub * (x + 1)) * radius, Cos(sub * x) * radius, half_height, Sin(sub * x) * radius) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(0, - half_height, 0) 

		glVertex3f(Cos(sub * (x + 1)) * radius, half_height, Sin(sub * (x + 1)) * radius) 
		glVertex3f(Cos(sub * x) * radius, half_height, Sin(sub * x) * radius) 
	Next
	' draw the top and bottom
	If capped = 1
		glBegin(GL_TRIANGLES) 
		
		glNormal3f(0, 1.0, 0) 
		For Local x:Float = 0 To hdivisions - 1 
			glVertex3f(0, half_height, 0) 
			glVertex3f(Cos(sub * x) * radius, half_height, Sin(sub * x) * radius) 
			glVertex3f(Cos(sub * (x - 1)) * radius, half_height, Sin(sub * (x - 1)) * radius) 
			
		Next
		glEnd
	End If
	glEnd
End Function
Function draw_sphere(Hdivisions:Float, vdivisions:Float, radius:Float) 
	'use a double for loop
	Local Height:Float = radius * 2.0
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal
	Local XZ_sub:Float = 180 / vdivisions
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To vdivisions - 1
		'find the first y value radius
		Local r:Float = Sin(y * xz_sub) * radius
		' find second y value radius
		Local r2:Float = Sin((y + 1) * xz_sub) * radius
		n = create_surface_normal(Cos(sub * x) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * x) * r2, Cos(sub * (x + 1)) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r2, Cos(sub * (x + 1)) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r) 
		glNormal3f(n.x, n.y, n.z)
		
		 
		 
		glVertex3f(Cos(sub * x) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * x) * r2) 
		glVertex3f(Cos(sub * (x + 1)) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r2) 
		glVertex3f(Cos(sub * (x + 1)) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r) 
		glVertex3f(Cos(sub * x) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * x) * r) 
		 
		Next
	Next
	glEnd
End Function
Function draw_hemisphere(Hdivisions:Float, vdivisions:Float, radius:Float, capped:Byte) 
'use a double for loop
	vdivisions:*2.0
	Local Height:Float = radius * 2.0
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal
	Local XZ_sub:Float = 180 / vdivisions
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To (vdivisions / 2.0) - 1
		'find the first y value radius
		Local r:Float = Sin(y * xz_sub) * radius
		' find second y value radius
		Local r2:Float = Sin((y + 1) * xz_sub) * radius
		n = create_surface_normal(Cos(sub * x) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * x) * r2, Cos(sub * (x + 1)) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r2, Cos(sub * (x + 1)) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r) 
		glNormal3f(n.x, n.y, n.z)
		
		 
		 
		glVertex3f(Cos(sub * x) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * x) * r2) 
		glVertex3f(Cos(sub * (x + 1)) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r2) 
		glVertex3f(Cos(sub * (x + 1)) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r) 
		glVertex3f(Cos(sub * x) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * x) * r) 
		 
		Next
	Next
	glEnd
	
	If capped = 1
		glBegin(GL_TRIANGLES) 
		
		glNormal3f(0, - 1.0, 0) 
		For Local x:Float = 0 To hdivisions - 1 
			glVertex3f(0, 0, 0) 
			glVertex3f(Cos(sub * x) * radius, 0, Sin(sub * x) * radius) 
			glVertex3f(Cos(sub * (x - 1)) * radius, 0, Sin(sub * (x - 1)) * radius) 
			
		Next
		glEnd
	EndIf
	
EndFunction
Function draw_torus(Hdivisions:Float, vdivisions:Float, radius:Float, radius2:Float) 
	vdivisions:/2.0
	Local Height:Float = radius * 2.0
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal
	Local XZ_sub:Float = 180 / vdivisions
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To (vdivisions * 2.0) - 1
		'find the first y value radius
		Local r:Float = radius2 + Sin(y * xz_sub) * radius
		' find second y value radius
		Local r2:Float = radius2 + Sin((y + 1) * xz_sub) * radius
		n = create_surface_normal(Cos(sub * x) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * x) * r2, Cos(sub * (x + 1)) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r2, Cos(sub * (x + 1)) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r) 
		glNormal3f(n.x, n.y, n.z)
		
		 
		 
		glVertex3f(Cos(sub * x) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * x) * r2) 
		glVertex3f(Cos(sub * (x + 1)) * r2, Cos((y + 1) * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r2) 
		glVertex3f(Cos(sub * (x + 1)) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * (x + 1)) * r) 
		glVertex3f(Cos(sub * x) * r, Cos(y * (180 / vdivisions)) * radius, Sin(sub * x) * r) 
		 
		Next
	Next
	glEnd
End Function
' test the library here
While Not KeyHit( KEY_ESCAPE )

	glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT		'Clear The Screen And The Depth Buffer

	
	glLoadIdentity() 
	glTranslatef 40, - 40, - 100.0
	glRotatef xrot, 0.0, 1.0, 0.0
	glRotatef yrot, 1.0, 0.0, 0.0
	draw_torus(12, 12, 8, 16) 
	glLoadIdentity() 
	glTranslatef 40, 40, - 100.0
	glRotatef xrot, 0.0, 1.0, 0.0
	glRotatef yrot, 1.0, 0.0, 0.0
	draw_hemisphere(12, 12, 32, 1) 
	glLoadIdentity() 
	glTranslatef - 40, - 40, - 100.0
	glRotatef xrot, 0.0, 1.0, 0.0
	glRotatef yrot, 1.0, 0.0, 0.0
	draw_tube(12, 1, 32, 32, 1) 
	glLoadIdentity() 
	glTranslatef - 40, 40, - 100.0
	glRotatef xrot, 0.0, 1.0, 0.0
	glRotatef yrot, 1.0, 0.0, 0.0
	draw_cone(12, 32, 32, 1) 
	glLoadIdentity() 
	glTranslatef 0, 0, - 100.0
	glRotatef xrot, 0.0, 1.0, 0.0
	glRotatef yrot, 1.0, 0.0, 0.0
	draw_sphere(12, 12, 16) 
	xrot:+(KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT)) * 2
	yrot:+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN)) * 2
	Flip

Wend


Although I'm not really a OGL person, thanks for sharing mate, that's solid work.

I was waiting for somebody to make something like this, tho "draw" seems to me like the wrong word to use in a command like this, use "CreateTube(ubercode, ubercode, ubercode)" :D

Hmmm I see some improvements that can be made in optimization. Mostly redundant value calculations. Please pardon the crudeness of the code it is all done from scratch. I guess I may work on optimizations. I'm glad somebody can use this I was worried from the lack of posts. I've been learning OpenGL for some time now and was upset that there wasn't commands to draw simple primitives. Tori become rings you can fly through. Spheres become bouncing balls. Tubes and cones become abstract houses. Primatives can be very fun to use and give your game that 80's feeling. I still need to figure out how to implement Goraud shading. two posts have inspired me further.

OK, the library is now faster since I'm avoiding redundant calculations.

Compile and try please.

Strict

Type surface_normal
Field x:Float, y:Float, z:Float
 
EndType ' something to hold data for surface normal

Type material
	Field ambient:Float[]=[0.0, 0.0, 0.0, 1.0]
	Field diffuse:Float[]=[0.7, 0.7, 0.7, 1.0]
	Field specular:Float[]=[1.0, 1.0, 1.0, 1.0]
	Field emission:Float[]=[0.0, 0.0, 0.0, 1.0]
	Field shininess:Float[]=[50.0]
	Field face_side:Int = GL_FRONT
	
	Method set_material() 
		glMaterialfv(face_side, GL_AMBIENT, ambient) 
		glMaterialfv(face_side, GL_DIFFUSE, diffuse) 
		glMaterialfv(face_side, GL_SPECULAR, specular) 
		glMaterialfv(face_side, GL_EMISSION, emission) 
		glMaterialfv(face_side, GL_SHININESS, shininess) 
	End Method
End Type ' holds material properties

Function create_surface_normal:surface_normal(p1x:Float, p1y:Float, p1z:Float, p2x:Float, p2y:Float, p2z:Float, p3x:Float, p3y:Float, p3z:Float, bool_side = 0) 
		Local nx:Float = ((p3y - p2y) * (p2z - p1z)) - ((p3z - p2z) * (p2y - p1y)) 
		Local ny:Float = ((p3z - p2z) * (p2x - p1x)) - ((p3x - p2x) * (p2z - p1z)) 
		Local nz:Float = ((p3x - p2x) * (p2y - p1y)) - ((p3y - p2y) * (p2x - p1x)) 
		Local N:Float = Sqr((nx * nx) + (ny * ny) + (nz * nz)) 
			
		If bool_side = 1 ' reverse direction if called for
			N = n * -1.0
		EndIf
		Local percent:Float = 1.0 / N
		Local a:Float = (percent) * nx
		Local b:Float = (percent) * ny
		Local c:Float = (percent) * nz
		Local v:surface_normal = New surface_normal
		
		v.x = a
		v.y = b
		v.z = c
		Return v
EndFunction

Function radius_inscribed:Float(nsides:Float, side_length:Float) 
	Local half_angle#=360.0/(nsides*2.0)
	Local half_side#=side_length/2.0
	Return half_side/Tan(half_angle)
End Function

Function radius_circumscribed#(nsides#,side_length#)
	Local half_angle#=360.0/(nsides*2.0)
	Local half_side#=side_length/2.0
	Return half_side/Sin(half_angle)
End Function

Function draw_cell(numsides:Float, thickness:Float) 
	Local sub:Float = 360.0 / numsides
	Local radius:Float = radius_circumscribed(numsides, 32.0) 
	Local radius2:Float = radius - 2.0
	Local topz:Float = -thickness / 2.0
	Local n:surface_normal = New surface_normal
	
	'top face
	glBegin(GL_TRIANGLE_FAN) 
	glNormal3f(0,0,-1) 
	glVertex3f(0.0, 0.0, topz) 
	For Local i = 0 To numsides
		Local angle:Float = i * sub
		glVertex3f(Cos(angle) * radius2, Sin(angle) * radius2, topz) 
	Next
	glEnd
	
	'bottom face 

	glBegin(GL_TRIANGLE_FAN) 
	glNormal3f(0, 0, 1) 
	glVertex3f(0.0, 0.0, - topz) 
	For Local i = 0 To numsides
		Local angle:Float = i * -sub
		glVertex3f(Cos(angle) * radius2, Sin(angle) * radius2, - topz) 
	Next
	glEnd
	
	'middle belt
	glBegin(GL_QUADS) 
	For Local k = 0 To numsides - 1
	' set up verticies so they don't need to be recalculated
	Local angle1:Float = k * -sub
	Local angle2:Float = (k - 1) * -sub
	Local a:Float = Cos(angle1) * radius
	Local b:Float = Sin(angle1) * radius
	Local c:Float = topz / 2.0
	Local d:Float = Cos(angle2) * radius
	Local e:Float = Sin(angle2) * radius
	n = create_surface_normal(a, b, c, d, e, - c, d, e, c, 0) 
	glNormal3f(n.x, n.y, n.z) 
		glVertex3f(a, b, - c) 
		glVertex3f(d, e, - c) 
		glVertex3f(d, e, c) 
		glVertex3f(a, b, c) 
		 
	Next
	glEnd
	
	glBegin(GL_QUADS) 
	' bridge belt to top
	For Local l = 0 To numsides - 1
	' calculate verticies only once
	Local t:Float = -topz / 2.0
	Local angle1:Float = l * -sub
	Local angle2:Float = (l - 1) * -sub
	Local a:Float = Cos(angle1) * radius2
	Local b:Float = Sin(angle1) * radius2
	Local c:Float = Cos(angle2) * radius2
	Local d:Float = Sin(angle2) * radius2
	Local e:Float = Cos(angle2) * radius
	Local f:Float = Sin(angle2) * radius
	n = create_surface_normal(a, b, - topz, c, d, - topz, e, f, t, 0) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(a, b, - topz) 
		glVertex3f(c, d, - topz) 
		glVertex3f(e, f, t) 
		glVertex3f(Cos(angle1) * radius, Sin(angle1) * radius, t) 
		 
	Next
	glEnd
	
	' bridge belt to bottom
	glBegin(GL_QUADS) 
	For Local m = 0 To numsides - 1
	Local t = topz / 2.0
	Local angle1:Float = m * sub
	Local angle2:Float = (m - 1) * sub
	Local a:Float = Cos(angle1) * radius2
	Local b:Float = Sin(angle1) * radius2
	Local c:Float = Cos(angle2) * radius2
	Local d:Float = Sin(angle2) * radius2
	Local e:Float = Cos(angle2) * radius
	Local f:Float = Sin(angle2) * radius
	n = create_surface_normal(a, b, topz, c, d, topz, e, f, t,0) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(a, b, topz) 
		glVertex3f(c, d, topz) 
		glVertex3f(e, f, t) 
		glVertex3f(Cos(m * sub) * radius, Sin(m * sub) * radius, t) 
		 
	Next
	glEnd
End Function

Function draw_tube(Hdivisions:Float, vdivisions:Float, Height:Float, radius:Float, capped:Byte) 
	'use a double for loop
	Local belt_height:Float = Height / vdivisions
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal = New surface_normal
	
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To vdivisions - 1
		Local s:Float = sub * x
		Local s2:Float = sub * (x + 1) 
		Local yb:Float = Y * belt_height
		Local yb2:Float = (Y + 1) * belt_height
		Local a:Float = Cos(s) * radius
		Local b:Float = -half_height + (yb) 
		Local c:Float = Sin(s) * radius
		Local d:Float = Cos(s2) * radius
		Local e:Float = Sin(s2) * radius
		Local f:Float = -half_height + (yb2) 
		n = create_surface_normal(a, b, c, d, b, e, d, f, e, 0) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(a, b, c) 
		glVertex3f(d, b, e) 
		glVertex3f(d, f, e) 
		glVertex3f(a, f, c) 
		Next
	Next
	glEnd
	' draw the top and bottom
	If capped = 1
		glBegin(GL_TRIANGLE_FAN) 
		glNormal3f(0, - 1.0, 0) 
		glVertex3f(0, - half_height, 0) 
		For Local x:Float = 0 To hdivisions - 1
			Local angle1:Float = sub * x
			Local angle2:Float = sub * (x - 1) 
			 
			glVertex3f(Cos(angle1) * radius, - half_height, Sin(angle1) * radius) 
			glVertex3f(Cos(angle2) * radius, - half_height, Sin(angle2) * radius) 
			
		Next
		glEnd
		
		glBegin(GL_TRIANGLE_FAN) 
		glNormal3f(0, 1.0, 0) 
		glVertex3f(0, half_height, 0) 
		For Local x:Float = 0 To hdivisions - 1
			Local angle1:Float = sub * x
			Local angle2:Float = sub * (x - 1) 
			 
			glVertex3f(Cos(angle1) * radius, half_height, Sin(angle1) * radius) 
			glVertex3f(Cos(angle2) * radius, half_height, Sin(angle2) * radius) 
			
		Next
		glEnd
	End If
	
End Function

Function draw_cone(Hdivisions:Float, Height:Float, radius:Float, capped:Byte) 
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal = New surface_normal
	
	glBegin(GL_TRIANGLES) 
	
	For Local x:Float = 0 To hdivisions - 1
		Local angle1:Float = sub * x
		Local angle2:Float = sub * (x + 1) 
		Local a:Float = Cos(angle2) * radius
		Local b:Float = Sin(angle2) * radius
		Local c:Float = Cos(angle1) * radius
		Local d:Float = Sin(angle1) * radius
		n = create_surface_normal(0, - half_height, 0, a, half_height, b, c, half_height, d) 
		glNormal3f(n.x, n.y, n.z) 
		glVertex3f(0, - half_height, 0) 

		glVertex3f(a, half_height, b) 
		glVertex3f(c, half_height, d) 
	Next
	glEnd
	' draw the top and bottom
	If capped = 1
		glBegin(GL_TRIANGLE_FAN) 
		
		glNormal3f(0, 1.0, 0) 
		glVertex3f(0, half_height, 0) 
		For Local x:Float = 0 To hdivisions - 1
			Local angle1:Float = sub * x
			Local angle2:Float = sub * (x - 1) 
			 
			glVertex3f(Cos(angle1) * radius, half_height, Sin(angle1) * radius) 
			glVertex3f(Cos(angle2) * radius, half_height, Sin(angle2) * radius) 
			
		Next
		glEnd
	End If
	
End Function

Function draw_sphere(Hdivisions:Float, vdivisions:Float, radius:Float) 
	'use a double for loop
	Local Height:Float = radius * 2.0
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal
	Local XZ_sub:Float = 180 / vdivisions
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To vdivisions - 1
			'find the first y value radius
			Local r:Float = Sin(y * xz_sub) * radius
			' find second y value radius
			Local r2:Float = Sin((y + 1) * xz_sub) * radius
			Local angle1:Float = sub * x
			Local angle2:Float = sub * (x + 1) 
			Local angle3:Float = (y + 1) * xz_sub
			Local angle4:Float = y * xz_sub
			Local a:Float = Cos(angle1) * r2
			Local b:Float = Cos(angle3) * radius
			Local c:Float = Sin(angle1) * r2
			Local d:Float = Cos(angle2) * r2
			Local e:Float = Sin(angle2) * r2
			Local f:Float = Cos(angle2) * r
			Local g:Float = Cos(angle4) * radius
			Local h:Float = Sin(angle2) * r
			n = create_surface_normal(a, b, c, d, b, e, f, g, h) 
			glNormal3f(n.x, n.y, n.z) 
			
			' test normals
			glVertex3f(a, b, c)  
			glVertex3f(d, b, e)  
			glVertex3f(f, g, h) 
			glVertex3f(Cos(angle1) * r, g, Sin(angle1) * r) 
		Next
	Next
	glEnd
End Function

Function draw_hemisphere(Hdivisions:Float, vdivisions:Float, radius:Float, capped:Byte) 
'use a double for loop
	vdivisions:*2.0
	Local Height:Float = radius * 2.0
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal
	Local XZ_sub:Float = 180 / vdivisions
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To (vdivisions / 2.0) - 1
			Local angle:Float = 180 / vdivisions
			Local angle1:Float = sub * x
			Local angle2:Float = (y + 1) * angle
			Local angle3:Float = sub * (x + 1) 
			Local angle4:Float = y * angle
			'find the first y value radius
			Local r:Float = Sin(y * xz_sub) * radius
			' find second y value radius
			Local r2:Float = Sin((y + 1) * xz_sub) * radius
			Local a:Float = Cos(angle1) * r2
			Local b:Float = Cos(angle2) * radius
			Local c:Float = Sin(angle1) * r2
			Local d:Float = Cos(angle3) * r2
			Local e:Float = Sin(angle3) * r2
			Local f:Float = Cos(angle3) * r
			Local g:Float = Cos(angle4) * radius
			Local h:Float = Sin(angle3) * r
			n = create_surface_normal(a, b, c, d, b, e, f, g, h) 
			glNormal3f(n.x, n.y, n.z) 
			glVertex3f(a, b, c) 
			glVertex3f(d, b, e) 
			glVertex3f(f, g, h) 
			glVertex3f(Cos(angle1) * r, g, Sin(angle1) * r) 
		Next
	Next
	glEnd
	
	If capped = 1
		glBegin(GL_TRIANGLE_FAN) 
		
		glNormal3f(0, - 1.0, 0) 
		glVertex3f(0, 0, 0) 
		For Local x:Float = 0 To hdivisions - 1 
			Local angle1:Float = sub * x
			Local angle2 = sub * (x - 1) 
			glVertex3f(Cos(angle1) * radius, 0, Sin(angle1) * radius) 
			glVertex3f(Cos(angle2) * radius, 0, Sin(angle2) * radius) 
			
		Next
		glEnd
	EndIf
	
EndFunction

Function draw_torus(Hdivisions:Float, vdivisions:Float, radius:Float, radius2:Float) 
	vdivisions:/2.0
	Local Height:Float = radius * 2.0
	Local half_height:Float = Height / 2.0
	Local sub:Float = 360 / hdivisions
	Local n:surface_normal
	Local XZ_sub:Float = 180 / vdivisions
	glBegin(GL_QUADS) 
	For Local x:Float = 0 To hdivisions - 1
		For Local y:Float = 0 To (vdivisions * 2.0) - 1
		
		Local angle:Float = y * xz_sub
		Local angle2:Float = (y + 1) * xz_sub
		Local angle3:Float = sub * x
		Local angle4:Float = sub * (x + 1) 
		'find the first y value radius
		Local r:Float = radius2 + Sin(angle) * radius
		' find second y value radius
		Local r2:Float = radius2 + Sin(angle2) * radius
		Local a:Float = Cos(angle3) * r2
		Local b:Float = Cos(angle2) * radius
		Local c:Float = Sin(angle3) * r2
		Local d:Float = Cos(angle4) * r2
		Local e:Float = Cos(angle2) * radius
		Local f:Float = Sin(angle4) * r2
		Local g:Float = Cos(angle4) * r
		Local h:Float = Cos(angle) * radius
		Local i:Float = Sin(angle4) * r
		n = create_surface_normal(a, b, c, d, e, f, g, h, i) 
		glNormal3f(n.x, n.y, n.z)
		
		 
		 
		glVertex3f(a, b, c) 
		glVertex3f(d, e, f) 
		glVertex3f(g, h, i) 
		glVertex3f(Cos(angle3) * r, Cos(angle) * radius, Sin(angle3) * r) 
		 
		Next
	Next
	glEnd
End Function

' test the library here--------------------------------------------------------------------

GLGraphics 640, 480
glViewport((640 - 480) / 2.0, 0, 480, 480) 
glEnable GL_DEPTH_TEST ' remove unseen faces
glEnable GL_LIGHTING ' let our little light shine
glEnable GL_LIGHT0 'let light 0 turn on
glShadeModel(GL_SMOOTH)    'smooth shading is not supported yet
glMatrixMode GL_PROJECTION ' enable perspective
glLoadIdentity
glClearColor(.25, .25, .25, 1)   ' neutral gray Clear color

glFrustum - 0.1, 0.1, - 0.1, 0.1, 0.1, 10000.0

glMatrixMode GL_MODELVIEW

' make some material properties



glLoadIdentity
Global xrot:Float
Global yrot:Float

Local p:material = New material ' demonstrate the material object ;)
p.ambient =[0.0, 0.0, 1.0, 1.0]
p.diffuse =[1.0, 0.0, 0.0, 1.0]
p.specular =[1.0, 1.0, 1.0, 1.0]
p.emission =[0.0, 0.0, 0.0, 1.0]
p.shininess =[128.0]
p.set_material()  ' Set the material as the Current

Global shape:Float = 2 ' what shape is drawn
While Not KeyHit( KEY_ESCAPE )
	glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT		'Clear The Screen and The Depth Buffer
	glDisable(GL_LIGHTING)  ' disable lighting For drawing
	GLDrawText("Ryan Burnside's Primatives Demo", 0, 0) 
	GLDrawText("Arrows Move shapes, B advances through shapes", 0, 12) 
	GLDrawText("Ryan Burnside 2007", 0, 24)  
	glEnable(GL_LIGHTING) 
	glLoadIdentity() 
	glTranslatef 0, 0, - 80.0
	glRotatef xrot, 0.0, 1.0, 0.0
	glRotatef yrot, 1.0, 0.0, 0.0
	Select shape
	Case 0
	draw_tube(4, 1, 32, 32, 1) 
	Case 1
	draw_tube(36, 1, 32, 32, 1) 
	Case 2
	draw_hemisphere(36, 16, 32,1) 
	Case 3
	draw_torus(36, 32, 8, 32) 
	Case 4
	draw_cone(36, 32, 32, 1) 
	Case 5
	draw_sphere(36, 36, 32) 
	Case 6
	draw_cell(6, 8) 
	endselect
	xrot:+(KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT)) * 2
	yrot:+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN)) * 2
	If KeyHit(KEY_B) 
		shape:+1
		If shape > 6
			shape = 0
		End If
	End If
	Flip

Wend


I don't know how many people are still following but soon you will have some hightmaps added.

a pic:


What is the max of tris and vertices for a surface, eg. for such a heightmap?

There isn't one currently. The parameters are a simple array of points ( which you could derive from a grayscale image file), and a grid width and height and a variable. Each square has two triangles that make it. I'm trying to get smooth shading working by adding a per vertex surface normal.

basically the function just takes a 2d array with z values and a grid width and grid height variable. This is my first foray into OpenGL procedural work but I think it's looking pretty reasonable. I'm not out to shaft Max3D but as a freeware developer I just can't afford the price.

Well I was refering to the 16 bit max seen in directx, so there we've got a 64k vertices maximum, at least in DX7. Esp. in terrains / heightmaps this usually isn't enough.

Basically it takes a .png and uses grayscale to determine the height of each vertex out of a user defined maximum height. The image pixel count is the vertex count as each pixel is a vertex. I'm still trying to get Goraud shading done, but I will include a file with the new features and what not. I have also included a readme with my general thoughts and goals for this. I've been having a heck of a time with Goraud per vertex normals. Feel free to add them if you can, otherwise expect somewhat of a wait as I feebly try to learn them.

a pic


The file:
http://www.mediafire.com/?dukedpgku3g

Of course I know how heghtmaps work. My question is: can you use a heightmap with more than 65535 pixels ( > 256*256)?

For the gouraud shading - you probably should try some simple code samples, eg. an implenetation in an other basic language, eg. QB, like these:

http://www.ocf.berkeley.edu/~horie/gourad2.zip
http://www.ocf.berkeley.edu/~horie/3dpoly.bas
http://www.ocf.berkeley.edu/~horie/gshade2.bas
(from toshi: http://www.ocf.berkeley.edu/~horie/project.html )

Although - I'm not sure if you really need to soft(as in software)-shade it, shouldn't you let OGL do the job using the hardware?