Author Topic: *finished* an OpenGL primative library. One small problem with spheres.  (Read 5527 times)

0 Members and 1 Guest are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Ok working on a library to draw primatives for my game.

I've been having alot of fun unraveling the code. Anyway, the problem is drawing my spheres. They seem to ignore one belt of light normal commands. This may be a general coding problem or a blitzmax problem.

Here is a pic of my retarted sphere. Notice the black top material with no apparent light normal.

current code:
Code: [Select]
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
' 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_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_tube(4, 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)
xrot:+(KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT)) * 2
yrot:+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN)) * 2
Flip

Wend

and a picture
« Last Edit: September 29, 2007 by Pixel_Outlaw »
Challenge Trophies Won:

Offline Voltage

  • Professor
  • Pentium
  • *****
  • Posts: 857
  • Karma: 53
    • View Profile
Looks right to me... with your current lighting settings....


You can adjust your lighting settings with something like...

Freebasic Code (sorry)

Code: [Select]
  Dim Shared LightAmbient(0 to 3) As Single => {0.2, 0.2, 0.2 ,1.0}   '' Ambient Light is 20% white
  Dim Shared LightDiffuse(0 to 3) As Single => {1.0, 1.0, 1.0, 1.0}   '' Diffuse Light is white
  Dim Shared LightPosition(0 to 3) As Single => {0.0, 1.7, 1.0, 0.0}  '' Position is somewhat in front of screen

 glLightfv(GL_LIGHT0, GL_AMBIENT, @LightAmbient(0))
 glLightfv(GL_LIGHT0, GL_DIFFUSE, @LightDiffuse(0))
 glLightfv(GL_LIGHT0, GL_POSITION, @LightPosition(0))

Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile


I fixed the faces. It turnes out that I was winding the faces wrong in conjunction with my surface_normal object.


I'm now working on a draw_torus command. I did it once before but it took about 5 days of 1 hour trial coding. Ofcourse, the old draw_sphere command took 4 days. I like to think I'm a better coder and thinker than I used to be last year.

Queston: Is it better to just used fixed points and gl_rotate around the axis of revolotion when creating lathed shapes like spheres,tubes,cones and tori? I havn't yet tried this method, are there any downfalls before I waste time trying them?
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
I think I understand what you're meaning but you can't use glrotate inside glbegin..glend.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
 :goodpost:

Ah ok then. I thought I could just create a profile and revolve it around an axis. I guess I'll starting watching more "Trig Gone Wild" videos. I feel like I've commited a sin(). Sorry I have a fever and it seemed funny.
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Hehe just finshed the library. The torus command turned out to be a simple edit of the draw_sphere command.

anyway free source and a pic. Procedurally generating solids is very fun for me.

The code is in blitzmax but one could convert to other languages. Everything looks to be solid and bug free. It would be best to use these commands in a list if you plan to draw alot of primatives because I'm sure my code is not optimized. it could have been done in terms of point arrays but extra commands are not a huge deal if you use lists as said.

Code: [Select]
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
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Nice one Pixel_Outlaw, looks a little odd it your pic where the shaded faces match the background (or maybe I just need a new monitor)

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Very nice!  Having a 'revolve edge around axis' primitive would be an interesting addition.  And, as you say, computing all the source vertices for every object each time is very time consuming when you only need to do it once and store the results away for later.
Karma for posting your source!

Jim
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Thanks guys. I just noticed that I have the shading set to smooth which is nonsense since it only has edge normals not vertex normals. And the shapes aren't missing faces the background is just bleeding into the faces of the same color.  ;)
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Yep, it just seemed a bit strange when I first looked at the image. Good work though.

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
There are a couple of things that I especially like about your postings Pixel, First of all you ask a question but you don't give up looking for a solution yourself once you posted the question and secondly you come back and show everyone how you are getting on and how you're tackling the problem.

That's worth some Karma from me too :) And the torus looks great!
Shockwave ^ Codigos
Challenge Trophies Won: