GLBasic forum

Codesnippets => 3D-snippets => Topic started by: bigsofty on 2009-Oct-02

Title: 3D Camera Lib
Post by: bigsofty on 2009-Oct-02
EDIT: Use the Quaternion based camera lib (posted here as a sticky), use this only for ground objects and only then if you want to save a little speed.

A little camera lib, it runs off vectors, so you need the vector lib too, included.

You can use functions like, CameraViewVec to fire projectiles from the camera along the current camera view.

I will write a decent doc/example as soon as I get back to my main GLB computer, I'm away from home just now.

Cheers,

Ian

Camera Lib...

Code: (glbasic) [Select]
`TYPE Tcamera  cameraPosition AS Tvector  cameraTarget AS Tvector  cameraUpVector AS Tvector  radius = 1  moveDist = 1  hRadians vRadiansENDTYPEFUNCTION SetCameraPosition: camera AS Tcamera, cPosition AS Tvector, h ,v    GLOBAL cPI = 3.1415926535    camera.cameraPosition = cPosition    camera.cameraTarget = vector_zero()    camera.cameraUpVector = vector_zero()    camera.cameraUpVector.y = -1    camera.hRadians = h    camera.vRadians = v    RotateCamera(camera,0,0)ENDFUNCTIONFUNCTION RotateCamera: camera AS Tcamera, h,v    camera.hRadians = camera.hRadians + h    camera.vRadians = camera.vRadians + v    camera.cameraTarget.y = camera.cameraPosition.y + (camera.radius*SIN(camera.vRadians))    camera.cameraTarget.x = camera.cameraPosition.x + (camera.radius*COS(camera.vRadians)*COS(camera.hRadians))    camera.cameraTarget.z = camera.cameraPosition.z + (camera.radius*COS(camera.vRadians)*SIN(camera.hRadians))    camera.cameraUpVector.x = camera.cameraPosition.x-camera.cameraTarget.x    camera.cameraUpVector.y = ABS(camera.cameraPosition.y+(camera.radius*SIN(camera.vRadians+cPI/2)))    camera.cameraUpVector.z = camera.cameraPosition.z-camera.cameraTarget.zENDFUNCTIONFUNCTION SlideCamera: camera AS Tcamera, h, v    camera.cameraPosition.y = camera.cameraPosition.y + (v*camera.moveDist)    camera.cameraPosition.x = camera.cameraPosition.x + (h*camera.moveDist*COS(camera.hRadians+cPI/2))    camera.cameraPosition.z = camera.cameraPosition.z + (h*camera.moveDist*SIN(camera.hRadians+cPI/2))    RotateCamera(camera,0,0)ENDFUNCTIONFUNCTION MoveCamera: camera AS Tcamera, d    camera.cameraPosition.y = camera.cameraPosition.y + (d*camera.moveDist*(SIN(camera.vRadians)))    camera.cameraPosition.x = camera.cameraPosition.x + (d*camera.moveDist*(COS(camera.vRadians)*COS(camera.hRadians)))    camera.cameraPosition.z = camera.cameraPosition.z + (d*camera.moveDist*(COS(camera.vRadians)*SIN(camera.hRadians)))    RotateCamera(camera,0,0)ENDFUNCTIONFUNCTION CameraViewVec AS Tvector: camera AS Tcamera    LOCAL result AS Tvector    result.y = (SIN(camera.vRadians))    result.x = (COS(camera.vRadians)*COS(camera.hRadians))    result.z = (COS(camera.vRadians)*SIN(camera.hRadians))    RETURN resultENDFUNCTION`

Vector Lib...

Code: (glbasic) [Select]
`// --------------------------------- //TYPE Tvector x y z magnitudeENDTYPEFUNCTION setup_veclib://used TO normalize vectorGLOBAL vector_tol = 0.0001ENDFUNCTIONFUNCTION vector_calcMagnitude: vec AS Tvector //calc the magnitude of a vector AND stor in vector vec.magnitude=SQR(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z)ENDFUNCTIONFUNCTION vector_normalise: vec AS Tvector    LOCAL m //normalize a vector so it's length = 1 AND apply tolerance based on our constant tolerance value m=SQR(SQR(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z) ) IF m<= vector_tol THEN m=1 vec.x=vec.x/m vec.y=vec.y/m vec.z=vec.z/m IF ABS(vec.x)<vector_tol THEN vec.x=0 IF ABS(vec.y)<vector_tol THEN vec.y=0 IF ABS(vec.z)<vector_tol THEN vec.z=0ENDFUNCTIONFUNCTION vector_new AS Tvector: x,y,z,m LOCAL result AS Tvector result.x=x result.y=y result.z=z result.magnitude=m RETURN resultENDFUNCTIONFUNCTION vector_reverse: vec AS Tvector //reverse a vector vec.x=-vec.x vec.y=-vec.y vec.z=-vec.zENDFUNCTIONFUNCTION vector_add AS Tvector: vec1 AS Tvector, vec2 AS Tvector //add two vectors together AND RETURN the resulting vector LOCAL result AS Tvector result.x=vec1.x+vec2.x result.y=vec1.y+vec2.y result.z=vec1.z+vec2.z RETURN resultENDFUNCTIONFUNCTION vector_subtract AS Tvector: vec1 AS Tvector, vec2 AS Tvector //subtract vec1 from vec2 AND RETURN the resulting vector LOCAL result AS Tvector result.x=vec1.x-vec2.x result.y=vec1.y-vec2.y result.z=vec1.z-vec2.z RETURN resultENDFUNCTIONFUNCTION vector_scalarMultiply AS Tvector: vec1 AS Tvector, scale //scalar multiplication of a vector with result returned AS new vector //used TO scale a vector by 'scale' LOCAL result AS Tvector result.x=vec1.x*scale result.y=vec1.y*scale result.z=vec1.z*scale RETURN resultENDFUNCTIONFUNCTION vector_scalarDivision AS Tvector: vec1 AS Tvector, scale //scalar division of a vector with result returned AS new vector //used TO scale a vector LOCAL result AS Tvector result.x=vec1.x/scale result.y=vec1.y/scale result.z=vec1.z/scale RETURN resultENDFUNCTIONFUNCTION vector_conjugate AS Tvector: vec1 AS Tvector //conjugate operator takes the negative of each vector component //can be used when subtracting one vector from another OR FOR //reversing the direction of a vector. //applying conjugate is the same AS reversing a vector //returns a new vector LOCAL result AS Tvector result.x=-vec1.x result.y=-vec1.y result.z=-vec1.z RETURN resultENDFUNCTIONFUNCTION vector_crossProduct AS Tvector: vec1 AS Tvector, vec2 AS Tvector //takes vec1 AND vec2 AND returns the cross product vec1 X vec2 //the cross product is a vector perpendicular TO both vec1 AND vec2 //this is the normal of 2 vectors LOCAL result AS Tvector result.x=(vec1.y*vec2.z) - (vec1.z*vec2.y) result.y=(vec1.z*vec2.x) - (vec1.x*vec2.z) result.z=(vec1.x*vec2.y) - (vec1.y*vec2.x) RETURN resultENDFUNCTIONFUNCTION vector_dotProduct: vec1 AS Tvector, vec2 AS Tvector //calculate AND RETURN the dot product of 2 vectors (distance) LOCAL result result=(vec1.x*vec2.x)+(vec1.y*vec2.y)+(vec1.z*vec2.z) RETURN resultENDFUNCTIONFUNCTION vector_tripleScalarProduct: vec1 AS Tvector, vec2 AS Tvector, vec3 AS Tvector //calculate the triple scalar FUNCTION AND RETURN it LOCAL result result=           vec1.x * ( (vec2.y*vec3.z ) - (vec2.z * vec3.y) ) result=result + ( vec1.y * ( (-vec2.x*vec3.z) + (vec2.z * vec3.x) ) ) result=result + ( vec1.z * ( ( vec2.x*vec3.y) + (vec2.y * vec3.x) ) ) RETURN resultENDFUNCTIONFUNCTION vector_zero AS Tvector: //calculate the triple scalar FUNCTION AND RETURN it LOCAL result AS Tvector result.x = 0 result.y = 0 result.z = 0 result.magnitude = 0 RETURN resultENDFUNCTIONFUNCTION Vector_RotateAroundX AS Tvector: vec1 AS Tvector, angle LOCAL result AS Tvector result.x = vec1.x result.y = COS(angle) * vec1.y - SIN(angle) * vec1.z result.z = SIN(angle) * vec1.y + COS(angle) * vec1.z RETURN resultENDFUNCTIONFUNCTION Vector_RotateAroundY AS Tvector: vec1 AS Tvector, angle LOCAL result AS Tvector result.x  = COS(angle) * vec1.x + SIN(angle) * vec1.z result.y = vec1.y result.z = -SIN(angle) * vec1.x + COS(angle) * vec1.z RETURN resultENDFUNCTIONFUNCTION Vector_RotateAroundZ AS Tvector: vec1 AS Tvector, angle LOCAL result AS Tvector result.x = COS(angle) * vec1.x - SIN(angle) * vec1.y result.y = SIN(angle) * vec1.x + COS(angle) * vec1.y result.z = vec1.z RETURN resultENDFUNCTIONFUNCTION Vector_RotateAroundVec AS Tvector: vec1 AS Tvector, vec2 AS Tvector, angle LOCAL result AS Tvector, cosa, sina, ecosa cosa = COS(angle) sina = SIN(angle) ecosa = 1.0 - cosa result.x = vec1.x * (cosa + vec2.x * vec2.x * ecosa) + vec1.y * (vec2.x * vec2.y * ecosa - vec2.z * sina) + vec1.z * (vec2.x * vec2.z * ecosa + vec2.y * sina) result.y = vec1.x * (vec2.y * vec2.x * ecosa + vec2.z * sina) + vec1.y * (cosa + vec2.y * vec2.y * ecosa) + vec1.z * (vec2.y * vec2.z * ecosa - vec2.x * sina) result.z = vec1.x * (vec2.z * vec2.x * ecosa - vec2.y * sina) + vec1.y * (vec2.z * vec2.y * ecosa + vec2.x * sina) + vec1.z * (cosa + vec2.z * vec2.z * ecosa) RETURN resultENDFUNCTION`
Title: Re: 3D Camera Lib
Post by: Hemlos on 2009-Oct-02
Thanks bigsofty, this is handy.
Im looking forward to your example camera.
Curious, is this 3 or 6 degrees of freedom?
Title: Re: 3D Camera Lib
Post by: bigsofty on 2009-Oct-02

6 DOF, its quite simple to use if you have used vectors before.
Title: Re: 3D Camera Lib
Post by: Hemlos on 2009-Oct-22
I was looking at this library,
i noticed the rotation is horizontal and vertical.

It doesnt seem to "roll" around the camera z axis.

Care to describe just a little how to do 6dof?
Title: Re: 3D Camera Lib
Post by: bigsofty on 2009-Oct-23
Well, your right, I can't remember how I changed it to add Roll... this code is very old code.

I believe I used the vector lib to manipulate the up vector of the GLB camera...

So...

GLOBAL cam AS Tcamera
GLOBAL camroll_vec AS Tvector;
camroll_vec = Vector_RotateAroundX(cam.cameraUpVector, angle) // For the X axis
X_CAMERAUP camroll_vec.x, camroll_vec.y, camroll_vec.z
X_CAMERA cam.cameraPosition.x, cam.cameraPosition.y, cam.cameraPosition.z, cam.cameraTarget.x, cam.cameraTarget.y, cam.cameraTarget.z
cam.cameraUpVector = camroll_vec

...

I'm not in front of my GLB PC right now, so this is untested.

After another quick look, I am unsure if I would advise using this for a full 6Dof, as I don't see anything for Gimbal lock avoidance either... so unless you need a simple camera, I would avoid this one for now. To avoid the whole Gimbal trap, I would advise quaternions, in any case. If I find a more up to date one when I get home, I'll post it.
Title: Re: 3D Camera Lib
Post by: djtoon on 2011-Feb-15
well !!!! this lib shakes as well :(

whats the problem
Title: Re: 3D Camera Lib
Post by: Hemlos on 2012-Jun-14
Yes, this lib works, perfectly for cameras...if anyone was wondering.
Gimbal lock is only present in objects being viewed by a camera.
Theres no solution to object Gimbal Lock other than 2d overlays..

To avoid object gimbal lock, whether you use quaternion or simple opengl rotations:
1. Do this with another viewport
2 . use a quaternion camera and rotate and move it around the object in the second view port(not visible to player)
3. Take and a screenshot and overlay it in the 3d world...dont forget to apply lighting before the screenshot of the object.
You might need to do multiple screenshots, in order to overlap 2d on 3d and more 3d between cam and obj.
Its tricky, but itll work, im sure of it....its alot of work, thats why flight simulators are some of the most expensive peices of software on the market!

I have been tinkering with a few 3d projects relating to flight sims, and this is the ultimate way to rotate your cam.
I felt the urge to reitterate on this thread and library because, well, quaternions are mind boggling EVEN when you figgure them out.

@djtoon and everyone playing with this lib:
Important to know....keep the camera around the center of the 3d world. IE somewhere near world position 0,0,0
Make the rest of the world move thier XYZ when you move...and the camera only to rotate and wobble etc.
If you do it like this, then you can make your world as big as you want without getting the "shakes".
And after ALOT of testing, i found that the camera can be roated in all 6 degrees of freedom!
-Thanks Bigsofty!