3D Camera Lib

Previous topic - Next topic

bigsofty

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
vRadians
ENDTYPE


FUNCTION 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)
ENDFUNCTION


FUNCTION 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.z
ENDFUNCTION


FUNCTION 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)
ENDFUNCTION


FUNCTION 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)
ENDFUNCTION


FUNCTION 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 result
ENDFUNCTION



Vector Lib...

Code (glbasic) Select
// --------------------------------- //

TYPE Tvector
x
y
z
magnitude
ENDTYPE

FUNCTION setup_veclib:
//used TO normalize vector
GLOBAL vector_tol = 0.0001
ENDFUNCTION

FUNCTION 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)
ENDFUNCTION

FUNCTION 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=0
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION vector_reverse: vec AS Tvector
//reverse a vector
vec.x=-vec.x
vec.y=-vec.y
vec.z=-vec.z
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION

FUNCTION 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 result
ENDFUNCTION
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Hemlos

Thanks bigsofty, this is handy.
Im looking forward to your example camera.
Curious, is this 3 or 6 degrees of freedom?
Bing ChatGpt is pretty smart :O

bigsofty

Your very welcome bud.

6 DOF, its quite simple to use if you have used vectors before.
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Hemlos

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?
Please?
Bing ChatGpt is pretty smart :O

bigsofty

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.
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

djtoon

well !!!! this lib shakes as well :(

whats the problem

Hemlos

#6
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!
Bing ChatGpt is pretty smart :O