OpenGL Camera almost done

BlitzMax Forums/BlitzMax OpenGL Programming/OpenGL Camera almost done

Finally got a decent camera ported over. The only real problem I'm having is the orientation. I set the initial camera y position to 5 and it puts it at -5 in the world.

Can you guys check this out and see why the Y axis is inverted. Btw, the vector.bmx is below in it's own codebox.

The problem may lie here:
cam.ViewDir.Set(0.0, 0.0, 1.0)
cam.UpVector.Set(0.0, 1.0, 0.0)
cam.RightVector.Set(1.0, 0.0, 0.0)

The z component of ViewDir was originally set to -1 and that made positioning the camera on the z axis be in reverse. Soon as I get the bugs worked out I'll put this in the archives.

Controls: Arrow Keys to move and strafe - Mouse to look around.

Camera.bmx
'Advanced Camera
'converted by Chroma from a site I can't remember atm cuz my brain is fried now...

Global width = 1024
Global height = 768

GLGraphics(width,height,32,85,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER)
'glClear(GL_COLOR_BUFFER_BIT)
'glLoadIdentity();

Include "vector.bmx"

Const PIdiv180:Double = (Pi/180.0)

ReShape(width,height)


CenterX = GraphicsWidth()/2
CenterY = GraphicsHeight()/2


'Init Camera
Global cam:Camera = Camera.Create()
	cam.Position.Set(0.0, 0.0, 0.0)
	cam.ViewDir.Set(0.0, 0.0, -1.0)
	cam.UpVector.Set(0.0, 1.0, 0.0)
	cam.RightVector.Set(1.0, 0.0, 0.0)
	cam.RotatedX = 0.0
	cam.RotatedY = 0.0
	cam.RotatedZ = 0.0

MoveMouse CenterX,CenterY

cam.position.set(0,5,20)

'Main Loop
While Not KeyHit(KEY_ESCAPE)
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity();

'Keyboard Controls
If KeyDown(KEY_UP) Then cam.moveforward(-0.1)
If KeyDown(KEY_DOWN) Then cam.moveforward(0.1)
If KeyDown(KEY_LEFT) Then cam.straferight(-0.1)
If KeyDown(KEY_RIGHT) Then cam.straferight(0.1)

'Mouselook Controls
cam.rotatex( -(MouseY()-CenterY) * 3.0 )
cam.rotatey( -(MouseX()-CenterX) * 3.0 )
cam.rotatez(cam.RotatedZ)



'Render Camera
cam.render()

'Render the DisplayList
Display()

'Reset Mouse
MoveMouse CenterX,CenterY

Flip
Wend

'Draw Some Cool Stuff To Look At
Function Display()
	glTranslatef(0.0,-0.5,-6.0)

	glScalef(3.0,1.0,3.0)
	
	 size! = 2.0
	 LinesX = 30
	 LinesZ = 30

	halfsize! = size / 2.0
	glColor3f(1.0,1.0,1.0)
	glPushMatrix()
		glTranslatef(0.0,-halfsize ,0.0)
		DrawNet(size,LinesX,LinesZ)
		glTranslatef(0.0,size,0.0)
		DrawNet(size,LinesX,LinesZ)
	glPopMatrix()
	glColor3f(0.0,0.0,1.0)
	glPushMatrix()
		glTranslatef(-halfsize,0.0,0.0);
		glRotatef(90.0,0.0,0.0,halfsize)
		DrawNet(size,LinesX,LinesZ)
		glTranslatef(0.0,-size,0.0)
		DrawNet(size,LinesX,LinesZ)
	glPopMatrix()
	glColor3f(1.0,0.0,0.0)
	glPushMatrix()
		glTranslatef(0.0,0.0,-halfsize)	
		glRotatef(90.0,halfsize,0.0,0.0)
		DrawNet(size,LinesX,LinesZ)
		glTranslatef(0.0,size,0.0)
		DrawNet(size,LinesX,LinesZ)
	glPopMatrix()
	glFlush()
EndFunction


Function DrawNet(size:Float, LinesX:Int, LinesZ:Int)
	glBegin(GL_LINES)
	For xc = 0 To LinesX-1 
	
		glVertex3f(	-size / 2.0 + xc / Float(LinesX-1)*size,0.0,size / 2.0)
		glVertex3f(	-size / 2.0 + xc / Float(LinesX-1)*size,0.0,size / -2.0)
	Next
	For zc = 0 To LinesX-1
	
		glVertex3f(	size / 2.0,0.0,-size / 2.0 + zc / Float(LinesZ-1)*size)
		glVertex3f(	size / -2.0,0.0,-size / 2.0 + zc / Float(LinesZ-1)*size);
	Next
		glEnd()
End Function


Function ReShape(x:Int, y:Int)
	If y = 0 And x = 0 Return
	glMatrixMode(GL_PROJECTION)  
	glLoadIdentity()
	gluPerspective(45.0,x/y,0.5,2000.0)
	glMatrixMode(GL_MODELVIEW)
	glViewport(0,0,x,y)
End Function


Type Camera
	Field Position:Vector
	Field ViewDir:Vector
	Field UpVector:Vector
	Field RightVector:Vector
	Field RotatedX:Float
	Field RotatedY:Float
	Field RotatedZ:Float
	
	Function Create:Camera( xpos:Float=0, ypos:Float=0, zpos:Float=0 )
		Local c:Camera = New Camera
		c.Position:Vector = Vector.Create(xpos,ypos,zpos)
		c.ViewDir:Vector = Vector.Create()
		c.UpVector:Vector = Vector.Create()
		c.RightVector:Vector = Vector.Create()
		Return c
	End Function

	Method Render()
		Local ViewPoint:Vector = New Vector
		ViewPoint.Add( Position, ViewDir ) 
		gluLookAt( Position.x,Position.y,Position.z,ViewPoint.x,ViewPoint.y,ViewPoint.z,UpVector.x,UpVector.y,UpVector.z)
	End Method
	
	
'	Method Rotate(p:Float,y:Float,r:Float)
'	End Method
	
'	Method Turn(pr:Float,yr:Float,rr:Float)
'	End Method
	
'	Method Move(xd:Float,yd:Float,zd:Float)
'	End Method

'	Method Point(entity:Int)
'	End Method
	
'	Method AlignTo(x:Float,y:Float,z:Float)
'	End Method

'	Method Zoom(zm:Float)
'	End Method

	Method RotateX( Angle:Float )
		self.RotatedX :+ Angle
		Local temp1:Vector = Vector.Create( ViewDir.x, ViewDir.y, ViewDir.z )
		Local temp2:Vector = Vector.Create( UpVector.x, UpVector.y, UpVector.z )
		Local temp3:Vector = Vector.Create()
		temp1.MulScalar( Cos(Angle * PIdiv180) )
		temp2.MulScalar( Sin(Angle * PIdiv180) )
		temp3.Add(temp1,temp2)
		temp3.Normalize()
		self.ViewDir.Set( temp3.x, temp3.y, temp3.z )
		UpVector.CrossProduct(ViewDir,RightVector)
		UpVector.MulScalar(-1)
	End Method
	
	Method RotateY( Angle:Float )
		self.RotatedY :+ Angle
		Local temp4:Vector = Vector.Create( ViewDir.x, ViewDir.y, ViewDir.z )
		Local temp5:Vector = Vector.Create( RightVector.x, RightVector.y, RightVector.z )
		Local temp6:Vector = Vector.Create()
		temp4.MulScalar( Cos(Angle * PIdiv180) )
		temp5.MulScalar( Sin(Angle * PIdiv180) )
		temp6.Sub(temp4,temp5)
		temp6.Normalize()
		self.ViewDir.Set( temp6.x, temp6.y, temp6.z )
		RightVector.CrossProduct(ViewDir,UpVector)
	End Method

	Method RotateZ( Angle:Float )
		self.RotatedZ :+ Angle
		Local temp7:Vector = Vector.Create( RightVector.x, RightVector.y, RightVector.z )
		Local temp8:Vector = Vector.Create( UpVector.x, UpVector.y, UpVector.z )
		Local temp9:Vector = Vector.Create()
		temp7.MulScalar( Cos(Angle * PIdiv180) )
		temp8.MulScalar( Sin(Angle * PIdiv180) )
		temp9.Add(temp7,temp8)
		temp9.Normalize()
		RightVector.set( temp9.x, temp9.y, temp9.z )
		UpVector.CrossProduct(ViewDir, RightVector)
		UpVector.MulScalar(-1)
	End Method

	Method MoveForward( Distance:Float )
		Local temp:Vector = Vector.Create(ViewDir.x,ViewDir.y,ViewDir.z)
		temp.MulScalar(-Distance)
		Position.Add( Position, temp )
	End Method

	Method StrafeRight( Distance:Float )
		Local temp:Vector = Vector.Create(RightVector.x,RightVector.y,RightVector.z)
		temp.MulScalar(Distance)
		Position.Add( Position, temp )
	End Method

	Method MoveUpward( Distance:Float )
		Position.Add( Position, UpVector.MulScalar(Distance) )
	End Method

End Type


Vector.bmx
'// Vector Math Library v2.0
'// BlitzMAX Edition
'// by Chroma


Type Vector
	Field x:Float
	Field y:Float
	Field z:Float
	
	Const Tol:Float = 0.001
	
	Function Create:Vector( x:Float = 0, y:Float = 0, z:Float = 0 )
		Local v:Vector = New Vector
		v.x = x
		v.y = y
		v.z = z
		Return v
	End Function
	
	Method Set( x:Float = 0, y:Float = 0, z:Float = 0 )
		self.x = x
		self.y = y
		self.z = z
	End Method
	
	Method Add( v1:Vector, v2:Vector )
		self.x = v1.x + v2.x
		self.y = v1.y + v2.y
		self.z = v1.z + v2.z
	End Method
	
	Method Sub( v1:Vector, v2:Vector )
		self.x = v1.x - v2.x
		self.y = v1.y - v2.y
		self.z = v1.z - v2.z
	End Method
	
	Method Mul( v1:Vector, v2:Vector )
		self.x = v1.x * v2.x
		self.y = v1.y * v2.y
		self.z = v1.z * v2.z
	End Method
	
	Method Div( v1:Vector, v2:Vector )
		self.x = v1.x / v2.x
		self.y = v1.y / v2.y
		self.z = v1.z / v2.z
	End Method
	
	Method AddScalar( s:Float )
		self.x :+ s
		self.y :+ s
		self.z :+ s
	End Method
	
	Method SubScalar( s:Float )
		self.x :- s
		self.y :- s
		self.z :- s
	End Method
	
	Method MulScalar( s:Float )
		self.x :* s
		self.y :* s
		self.z :* s
	End Method
	
	Method DivScalar( s:Float )
		self.x :/ s
		self.y :/ s
		self.z :/ s
	End Method
		
	Method Magnitude:Float()
		Return Sqr(self.x * self.x + self.y * self.y + self.z * self.z)
	End Method

	Method Normalize()
		Local mag:Float = self.Magnitude()
		If mag = 0.0 Then self.Set(0.0,0.0,0.0);Return
		self.x :/ mag
		self.y :/ mag
		self.z :/ mag
		'If ( Abs( self.x ) < Tol ) self.x = 0.0
		'If ( Abs( self.y ) < Tol ) self.y = 0.0
		'If ( Abs( self.z ) < Tol ) self.z = 0.0
	End Method
	
	Method CrossProduct( v1:Vector, v2:Vector)
		self.x =  v1.y * v2.z  -  v1.z * v2.y 
		self.y = -v1.x * v2.z  +  v1.z * v2.x 
		self.z =  v1.x * v2.y  -  v1.y * v2.x
	EndMethod
	
	Method DotProduct:Float(v:Vector)
		Return self.x * v.x + self.y * v.y + self.z * v.z
	EndMethod

	Method AddTimeStep( v:Vector, time_step:Float )
		self.x :+ v.x * time_step
		self.y :+ v.y * time_step
		self.z :+ v.z * time_step
	End Method
	
	Method Show( xpos:Int, ypos:Int, label:String )
		DrawText label+"_X: "+self.x, xpos, ypos
		DrawText label+"_Y: "+self.y, xpos, ypos + 20
		DrawText label+"_Z: "+self.z, xpos, ypos + 40
	End Method
	
'	Method QuatToVec(q:Quat)
'		self.x = q.x
'		self.y = q.y
'		self.z = q.z
'	End Method

End Type

'// Degrees To Radians Conversion
Function DegreesToRadians:Float(deg:Float)
	Return deg * Pi / 180.0
End Function

'// Radians To Degrees Conversion
Function RadiansToDegrees:Float(rad:Float)
	Return rad * 180.0 / Pi
End Function