![]() |
LibGame
v0.4.0
The LG Game Engine - Copyright (C) 2024-2025 ETMSoftware
|
=== SO FAR, USES RH COORDS SYS FOR MATRIX OPS ===
=== Need to write LH versions for these funcs:
Because OpenGL coords sys is RH but the Z dir is visually counter-intuitive IMO
See:
Renamed funcs in math_3d.h:
Renamed funcs in lg_camera.c/h:
Camera initial position in world coords is always at center ie (0.0, 0.0, 0.0)
NOTE about cam->orientation and cam->target:
Aircraft/flight simulator camera and user input:
With OpenGL right hand coords sys:
So:
LibGame uses column-major order matrices LibGame try to/will use LH 3D coords sys as often as possible (!= OpenGL) (To avoid endless confusion, always mention coords sys or anything relevant)
You can use a global, always available, always default-values-initialized, camera:
LG_Camera *lg_get_camera_one()
if needed, or you can use as many cameras as you want
When multiplying matrices before rendering, the right order is:
cam->proj_m * cam->view_m * node->world_matrix
or
cam->view_proj_m * node->world_matrix
MVP stands for Model-View-Proj but it should be WVP for World-View-Proj and you multiply matrices in the reversed order, ie P * V * M or P * V * W.
| LG_Camera lg_camera | ( | ) |
Return a new camera, initialized with default values:
LG_CAMERA_ORIGIN LG_CAMERA_TARGET LG_CAMERA_UP LG_V_FOV LG_Z_NEAR LG_Z_FAR
| int lg_camera_init | ( | LG_Camera * | cam | ) |
Init the camera, with default values:
LG_CAMERA_ORIGIN LG_CAMERA_TARGET LG_CAMERA_UP LG_V_FOV LG_Z_NEAR LG_Z_FAR
To change z_near value, use lg_camera_override_znear()
To change z_far value, use lg_camera_override_zfar()
What matters is the ratio (not the difference) between these values
| cam | Pointer to a LG_Camera |
| int lg_camera_set_all | ( | LG_Camera * | cam, |
| vec3_t | position, | ||
| vec3_t | target, | ||
| vec3_t | up, | ||
| float | v_fov, | ||
| float | z_near, | ||
| float | z_far | ||
| ) |
Set all camera params
| cam | Pointer to a LG_Camera |
| position | Position in world space |
| target | Look at target |
| up | The 'up' vector - will get normalized |
| v_fov | Vertical field of view, in degrees |
| z_near | Distance to the near clipping plane along -z |
| z_far | Distance to the far clipping plane along -z |
| int lg_camera_reset | ( | LG_Camera * | cam | ) |
'Reset' the camera, ie init the cam again, with default values
| cam | Pointer to a LG_Camera |
Compute and return the view matrix from the camera data
WARNING: Doesn't update cam->view_m
| cam | Pointer to a LG_Camera |
Compute and return the projection matrix from the camera data
WARNING: Doesn't update cam->proj_m
| cam | Pointer to a LG_Camera |
Compute and return the view projection matrix from the camera data
WARNING: Doesn't update cam->view_proj_m
| cam | Pointer to a LG_Camera |
| void lg_update_all_cam_m | ( | LG_Camera * | cam | ) |
(Re)compute and update all cam->view_m/proj_m/view_proj_m
This is usually done automatically (if necessary) when moving/rotating the camera or changing other camera settings
| cam | Pointer to a LG_Camera |
Move the camera (FORWARD if transl.x = 0, transl.y = 0, transl.z != 0)
Compute new 'from' and 'to" vectors for the look_at matrix, the 'up' vector remains unchanged by the translation
Doesn't change cam orientation
Update cam->view_m and cam->view_proj_m
| cam | Pointer to a LG_Camera |
| transl | Translation vector |
Rotate the camera so that it looks at target
| cam | Pointer to a LG_Camera |
| target | What the cam will look at |
=== EXPERIMENTAL - NOT WORKING SO FAR, DON'T USE ===
Rotate gradually the camera so that it will end up looking at target
| cam | Pointer to a LG_Camera |
| target | What the cam will look at |
| rot_k | Partial rotation k, in range [0.0, 1.0] |
| int lg_camera_rotate_by_eu | ( | LG_Camera * | cam, |
| LG_EulerAng | ang, | ||
| const char * | rot_order | ||
| ) |
Rotate the camera by Euler angles
Getting camera orientation from LG_EulerAng in UI is the easiest/prefered way
Update cam->target, cam->up, cam->view_m, and cam->view_proj_m
| cam | Pointer to a LG_Camera |
| ang | The Euler angles |
| rot_order | The rotations order - one of "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY" |
Rotate the camera with a quaternion
Update cam->target, cam->up, cam->view_m, and cam->view_proj_m
| cam | Pointer to a LG_Camera |
| q | The quaternion |
| int lg_camera_set_rot_by_eu | ( | LG_Camera * | cam, |
| LG_EulerAng | ang, | ||
| const char * | rot_order | ||
| ) |
Set camera rotation by Euler angles
Update cam->target, cam->up, cam->view_m, and cam->view_proj_m
| cam | Pointer to a LG_Camera |
| ang | The Euler angles |
| rot_order | The rotations order - one of "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY" |
Set camera rotation by a quaternion
Update cam->target, cam->up, cam->view_m, and cam->view_proj_m
| cam | Pointer to a LG_Camera |
| q | The quaternion |
Rotate and move ('orbit') the camera around a target, always looking at it
Orbit radius = original distance between camera and target
| cam | Pointer to a LG_Camera |
| target | Center of orbit |
| yaw | Rotation angle around the Y axis, in radians |
| pitch | Rotation angle around the X axis, in radians |
| void lg_camera_get_frustum | ( | LG_Camera * | cam, |
| LG_Frustum * | frustum | ||
| ) |
Get camera frustum, using the Gribb & Hartmann algorithm:
'Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix'
Gil Gribb ggribb@ravensoft.com
Klaus Hartmann k_hartmann@osnabrueck.netsurf.de
| cam | Pointer to a LG_Camera |
| frustum | Pointer to a LG_Frustum |
| zboolean is_in_frustum | ( | vec3_t * | v, |
| LG_Frustum * | frustum | ||
| ) |
Test if pos vector is inside frustum
A pos vector is inside a frustum if the dot product with all side planes is always > 0
| v | Pointer to a vec3_t pos vector |
| frustum | Pointer to a LG_Frustum |
| zboolean lg_cuboid_is_in_frustum | ( | LG_Cuboid * | cuboid, |
| LG_Frustum * | frustum, | ||
| zboolean | fully | ||
| ) |
Test if cuboid is inside frustum (fully or partially)
| cuboid | Pointer to a LG_Cuboid |
| frustum | Pointer to a LG_Frustum |
| fully | TRUE to test if all vertices are inside, FALSE to test if at least one is inside |
| zboolean lg_mesh_is_in_frustum | ( | LG_Mesh * | mesh, |
| LG_Frustum * | frustum, | ||
| zboolean | fully | ||
| ) |
Test if mesh is inside frustum (fully or partially)
| mesh | Pointer to a LG_Mesh |
| frustum | Pointer to a LG_Frustum |
| fully | TRUE to test if all vertices are inside, FALSE to test if at least one is inside |
| void lg_camera_override_znear | ( | LG_Camera * | cam, |
| float | z_near | ||
| ) |
Set cam->z_near value to z_near (default is LG_Z_NEAR, defined in lg_camera.h)
Update cam->proj_m and cam->view_proj_m
| cam | Pointer to a LG_Camera |
| z_near | New cam->z_near value |
| void lg_camera_override_zfar | ( | LG_Camera * | cam, |
| float | z_far | ||
| ) |
Set cam->z_far value to z_far (default is LG_Z_FAR, defined in lg_camera.h)
Update cam->proj_m and cam->view_proj_m
| cam | Pointer to a LG_Camera |
| z_far | New cam->z_far value |
| int lg_plane_normalize | ( | LG_Plane * | p | ) |
Normalize plane
| p | A pointer to a LG_Plane |
| void lg_camera_info | ( | LG_Camera * | cam | ) |
| void lg_frustum_info | ( | LG_Frustum * | frustum | ) |
Print out LG_Frustum info
| frustum | Pointer to a LG_Frustum |