Post by GuppyB on Jul 20, 2005 15:01:12 GMT -5
Thought I would start a series of demos that cover some basic physics and might be helpful to the community. I decided to start with gravity as in the constant vertical acceleration that you would need to calculate in any kind of 1st or 3rd person levelled shooter. This is essentially a bouncing 3D box and is well documented to teach the beginner. I even faked a shadow underneath the box that came out reasonably well.
All of the texture files are included in the Basic4Gl download and installation so you shouldn't have any problems with them, but if you do, change the names to images that you have on your computer and it should work just fine.
Demo 2 will cover Force = Mass * Acceleration and include some collisions stuff.
enjoy,
...G
All of the texture files are included in the Basic4Gl download and installation so you shouldn't have any problems with them, but if you do, change the names to images that you have on your computer and it should work just fine.
Demo 2 will cover Force = Mass * Acceleration and include some collisions stuff.
enjoy,
...G
' PHYSICS DEMO 1 - GRAVITY
' by Guppy B
'
' This program demonstrates the basic equations for gravity
' through the example of a falling and bouncing box
dim oldtick, dtime#, newtick ' time measurements
dim Xpos#, Ypos#, Zpos# ' xyz positions of box
dim Xvel#, Yvel#, Zvel# ' xyz velocity of box
dim gravity# ' gravity (acceleration)
dim shadow#(18,18), vertexshade#(2)(2), xshad,zshad ' box ground shadow variables
dim i,j,k,l 'loop variables
dim texture(3) ' texture variable
' load textures
texture(0) = LoadMipmapTexture ("Textures/wall01.jpg")
if texture(0) = 0 then print "Failed to load texture": end: endif
texture(1) = LoadMipmapTexture ("Data/Crate.bmp")
if texture(1) = 0 then print "Failed to load texture": end: endif
texture(2) = LoadMipmapTexture ("Textures/floor01.jpg")
if texture(2) = 0 then print "Failed to load texture": end: endif
' set-up OpenGl by enabling textures and back face culling
glEnable (GL_TEXTURE_2D)
glEnable (GL_CULL_FACE)
' set initial states for the variables
Gosub ResetVariables
'get the intial time
oldtick = tickcount()
' ************* Main Loop ********************
while true
' Clear Buffers and reset starting location
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
' set location for the cube and draw the cube
glTranslatef(Xpos#,Ypos#,Zpos#)
gosub drawCube
' reset the starting location
glLoadIdentity()
' set location for ground and draw the ground
glTranslatef(0.0,-4.0,-10.0)
gosub drawGround
gosub drawWalls
' draw to screen
SwapBuffers ()
' IMPORTANT: In order to maintain consistent speed of objects
' across any speed computer system, you need to calculate movement based on the relative time
' elapsed from the last time that you SwapBuffers()
' the equation below calculates the change in time or "delta" time from tickcount()
' which returns a progressively increasing value in milliseconds from the computers clock
' finally we set oldtick = newtick which will be the base time for the next pass around
newtick = tickcount()
dtime# = (newtick - oldtick) * 0.001
oldtick = newtick
' CALCULATING GRAVITY
' For our purposes Gravity is calculated as a constant vertical acceleration and
' in this example using the earth's gravity of 9.81 m/s^2, using what we know about
' acceleration which is equal to the change of velocity divided by the change in time
' or A(gravity) = velocity(initial) - velocity(end) / delta time. Using algebra we calculate end velocity as:
yvel# = yvel# + (gravity# * dtime#)
' similarly position or distance is calculated using rate(velocity) = distance / time or
Ypos# = Ypos# + (yvel# * dtime#)
' calulate x and z position in the same way
Xpos# = Xpos# + (Xvel# * dtime#)
Zpos# = Zpos# + (Zvel# * dtime#)
' since our ground is at -4.0 on y axis, and the height of our box is 2 we can
' check to see if it hits the ground by comparing the position (which is based on the center
' of the box or 1) from the ground, meaning that if the position crosses -3.0 it has hit
' the ground, we then bounce it by reversing the velocity and calculating the bounced position.
' note: to be totally realistic you'd want to calculate how much energy is absorbed by the ground
if Ypos# <= -3.0 then Yvel# = Yvel# * -1.0 : Ypos# = Ypos# + (abs(Ypos#) - 3.0): endif
' similarly bounce the box off the boundaries by reversing the velocities for the x and z axis
if Xpos# < -7.0 or Xpos# > 7.0 then Xvel# = Xvel# * -1.0: endif
if Zpos# < -17.0 or Zpos# > -3.0 then Zvel# = Zvel# * -1.0: endif
' FAKE SHADOW.... this is sets up a little fake shadow for the floor, essentially what I did was to
' divide the floor into a 16x16 grid of quads. Then I darken the quad relative to
' the position of the box x & z and the distance y from the floor
'reset shadow value
for i = 1 to 16
for j = 1 to 16
shadow#(i,j) = 1.0
next
next
'calcualte x & z position in array for shadow
xshad = int((Xpos#+0.5)+8.0)
zshad = int((Zpos#+0.5)+18.0)
' make sure that we don't go below zero or array will error
if xshad < 0 then xshad = 0: endif
if zshad < 0 then xshad = 0: endif
' add shadow to those squares that are below
for i = xshad to xshad+1
for j = zshad to zshad+1
shadow#(i,j) = 0.2 + ((Ypos#+3.0)*0.166)
next
next
wend
' ************* Draw the Box *******************
drawCube:
glBindTexture(GL_TEXTURE_2D, texture(1))
glBegin(GL_QUADS)
glColor3f(0.7,0.7,0.7) 'These glColor3f statements just add a little shading to box for realism
' Front face
glTexCoord2f(0.0, 0.0): glVertex3f(-1.0, -1.0, 1.0)
glTexCoord2f(1.0, 0.0): glVertex3f( 1.0, -1.0, 1.0)
glTexCoord2f(1.0, 1.0): glVertex3f( 1.0, 1.0, 1.0)
glTexCoord2f(0.0, 1.0): glVertex3f(-1.0, 1.0, 1.0)
' Back face
glTexCoord2f(1.0, 0.0): glVertex3f(-1.0, -1.0, -1.0)
glTexCoord2f(1.0, 1.0): glVertex3f(-1.0, 1.0, -1.0)
glTexCoord2f(0.0, 1.0): glVertex3f( 1.0, 1.0, -1.0)
glTexCoord2f(0.0, 0.0): glVertex3f( 1.0, -1.0, -1.0)
' Top face
glColor3f(1.0,1.0,1.0)
glTexCoord2f(0.0, 1.0): glVertex3f(-1.0, 1.0, -1.0)
glTexCoord2f(0.0, 0.0): glVertex3f(-1.0, 1.0, 1.0)
glTexCoord2f(1.0, 0.0): glVertex3f( 1.0, 1.0, 1.0)
glTexCoord2f(1.0, 1.0): glVertex3f( 1.0, 1.0, -1.0)
' Bottom face
glColor3f(0.3,0.3,0.3)
glTexCoord2f(1.0, 1.0): glVertex3f(-1.0, -1.0, -1.0)
glTexCoord2f(0.0, 1.0): glVertex3f( 1.0, -1.0, -1.0)
glTexCoord2f(0.0, 0.0): glVertex3f( 1.0, -1.0, 1.0)
glTexCoord2f(1.0, 0.0): glVertex3f(-1.0, -1.0, 1.0)
' Right face
glColor3f(0.7,0.7,0.7)
glTexCoord2f(1.0, 0.0): glVertex3f( 1.0, -1.0, -1.0)
glTexCoord2f(1.0, 1.0): glVertex3f( 1.0, 1.0, -1.0)
glTexCoord2f(0.0, 1.0): glVertex3f( 1.0, 1.0, 1.0)
glTexCoord2f(0.0, 0.0): glVertex3f( 1.0, -1.0, 1.0)
' Left face
glTexCoord2f(0.0, 0.0): glVertex3f(-1.0, -1.0, -1.0)
glTexCoord2f(1.0, 0.0): glVertex3f(-1.0, -1.0, 1.0)
glTexCoord2f(1.0, 1.0): glVertex3f(-1.0, 1.0, 1.0)
glTexCoord2f(0.0, 1.0): glVertex3f(-1.0, 1.0, -1.0)
glEnd()
return
' **************** Draw the Ground ***************
drawGround:
glBindTexture(GL_TEXTURE_2D, texture(2))
' ground is setup as a 16x16 grid
for i = 1 to 16
for j = 1 to 16
gosub doVertexShade
glBegin(GL_QUADS)
glColor3f(vertexshade#(0,0),vertexshade#(0,0),vertexshade#(0,0)):glTexCoord2f(0.0, 1.0): glVertex3f(i-9.0, 0.0, j-9.0)
glColor3f(vertexshade#(0,1),vertexshade#(0,1),vertexshade#(0,1)):glTexCoord2f(0.0, 0.0): glVertex3f(i-9.0, 0.0, j-8.0)
glColor3f(vertexshade#(1,1),vertexshade#(1,1),vertexshade#(1,1)):glTexCoord2f(1.0, 0.0): glVertex3f(i-8.0, 0.0, j-8.0)
glColor3f(vertexshade#(1,0),vertexshade#(1,0),vertexshade#(1,0)):glTexCoord2f(1.0, 1.0): glVertex3f( i-8.0, 0.0, j-9.0)
glEnd()
next
next
return
' ****************** Draw the Walls **********************
drawWalls:
glBindTexture(GL_TEXTURE_2D, texture(0))
glBegin(GL_QUADS)
' back wall
glColor3f(0.0,0.0,0.0)
glTexCoord2f(0.0, 0.0): glVertex3f(-8.0, -4.0, -8.0)
glTexCoord2f(4.0, 0.0): glVertex3f( 8.0, -4.0, -8.0)
glColor3f(1.0,1.0,1.0)
glTexCoord2f(4.0, 4.0): glVertex3f( 8.0, 12.0, -8.0)
glTexCoord2f(0.0, 4.0): glVertex3f(-8.0, 12.0, -8.0)
' left wall
glColor3f(0.7,0.7,0.7)
glTexCoord2f(4.0, 0.0): glVertex3f( -8.0, -4.0, -8.0)
glTexCoord2f(4.0, 4.0): glVertex3f( -8.0, 12.0, -8.0)
glTexCoord2f(0.0, 4.0): glVertex3f( -8.0, 12.0, 8.0)
glTexCoord2f(0.0, 0.0): glVertex3f( -8.0, -4.0, 8.0)
' right wall
glTexCoord2f(0.0, 0.0): glVertex3f(8.0, -4.0, -8.0)
glTexCoord2f(4.0, 0.0): glVertex3f(8.0, -4.0, 8.0)
glTexCoord2f(4.0, 4.0): glVertex3f(8.0, 12.0, 8.0)
glTexCoord2f(0.0, 4.0): glVertex3f(8.0, 12.0, -8.0)
glend()
return
' ************* Vertex Shading for Floor ***********************
' This section essentially averages the shadow value of each of the four squares around
' that vertex, which provides a softer shadow than if you normally just shaded the entire square
doVertexShade:
vertexshade#(0,0) = (shadow#(i-1,j-1) + shadow#(i,j-1) + shadow#(i-1,j) + shadow#(i,j)) / 4.0
vertexshade#(1,0) = (shadow#(i,j-1) + shadow#(i+1,j-1) + shadow#(i,j) + shadow#(i+1,j)) / 4.0
vertexshade#(0,1) = (shadow#(i-1,j) + shadow#(i,j) + shadow#(i-1,j+1) + shadow#(i,j+1)) / 4.0
vertexshade#(1,1) = (shadow#(i,j) + shadow#(i+1,j) + shadow#(i,j+1) + shadow#(i+1,j+1)) / 4.0
return
' ************** Starting Values ***********************
ResetVariables:
' starting position of box
xPos# = 0.0
Ypos# = 3.0
Zpos# = -10.0
' starting velocities
Xvel# = -1.22
Yvel# = 0.0
Zvel# = -3.11
' gravity which is set to Earths at 9.81 m/s^2
gravity# = -9.81
return