LibGame v0.4.0
The LG Game Engine - Copyright (C) 2024-2026 ETMSoftware
Loading...
Searching...
No Matches
lg_scene.c File Reference

Functions

LG_Scenelg_scene_new (int id, LG_Camera *cam1, LG_Light light1, Rec2Df landscape_rec, uint16_t grid_width, const char *euler_ang_rot_order)
 
void lg_scene_free (LG_Scene *scene)
 
LG_SceneNodelg_scenenode_new_and_set (int id, LG_SceneNode *parent_node, lg_scenenode_type type, LG_Path path, LG_LoadMesh_Flags flags, vec3_t transl, LG_Quat orientation, vec3_t scaling)
 
void lg_fill_node_NTOS_from_local_matrix (LG_Node_NTOS *ntos, mat4_t *local_matrix, const char *euler_ang_rot_order, zboolean set_quat)
 
void lg_fill_node_NTOS_from_scenenode (LG_Node_NTOS *ntos, LG_SceneNode *node, const char *euler_ang_rot_order, zboolean set_quat)
 
zboolean lg_scene_generate_data_from_nodes (LG_Scene *scene, LG_SceneNode *top_node)
 
zboolean lg_scene_save_nodes_bmeshes (LG_SceneNode *top_node)
 
zboolean lg_scene_update_nodes_meshes_path_to_bmesh (LG_SceneNode *top_node)
 
int lg_mesh_update_mats_paths (LG_Mesh *mesh)
 
zboolean lg_scene_sanitize_nodes_mesh_mats (LG_Scene *scene)
 
zboolean lg_scene_sanitize_nodes_ids (LG_Scene *scene)
 
zboolean lg_scene_generate_serializable_data (LG_Scene *scene)
 
LG_SceneNodelg_scene_generate_nodes_from_data (LG_Scene *scene, LG_SceneNode *top_node, LG_LoadMesh_Flags flags)
 
zboolean lg_set_TRS_matrix_from_node_NTOS_euler (mat4_t *m_TRS, LG_Node_NTOS *ntos, const char *euler_ang_rot_order)
 
void lg_set_NTOS_array_euler_angs_from_quats (LG_Scene *scene)
 
void lg_node_NTOS_info (LG_Node_NTOS *ntos)
 
void lg_node_NTOS_array_info_to_stream (LG_Scene *scene, FILE *stream, zboolean readable)
 
char * lg_node_NTOS_info_to_string (LG_Node_NTOS *ntos)
 
char * lg_node_NTOS_array_info_to_string (LG_Scene *scene, zboolean readable)
 
zboolean lg_scene_load_data_from_assets (LG_Scene *scene, const char *relative_path, int32_t *n_node_ntos)
 
zboolean lg_scene_load_data_from_file (LG_Scene *scene, const char *full_path, int32_t *n_node_ntos)
 
zboolean lg_scene_load_data_from_txt_file (LG_Scene *scene, const char *full_path, int32_t *n_node_ntos)
 
zboolean lg_scene_save_data_to_file (LG_Scene *scene, const char *full_path)
 
zboolean lg_create_wr_scenes_dir ()
 
const char * lg_get_reversed_rot_order (const char *rot_order)
 
zboolean lg_rot_order_is_valid (const char *rot_order)
 

Detailed Description

=== Higher level scene/frame stuff ===

The starting point for scenes

SERIALIZING nodes (scene graph, including hierarchy) with LG_Node_NTOS[]

NTOS stands for (mesh file) NAME and (scene node) TOS (Transl/Orientation/Scaling)

NOTE:

  • LG_Node_NTOS x/y/z_oe -> orientation as Euler ang (as 3 doubles) - TO BE USED IN GAME LOOP UI
  • LG_Node_NTOS x/y/z/w_oq -> orientation as a quat (as 4 floats) - TO BE USED WHEN SAVING/LOADING

WARNING: .scene files save LG_Scene binary block of all serializable data

typedef struct {
int32_t id;
LG_Light light1;
Rec2Df landscape_rec;
LG_Node_NTOS nodes_ntos[NODE_NTOS_MAX_NUM];
int32_t n_node_ntos;
char euler_ang_rot_order[4];
// ...
Definition lg_light.h:26
Definition lg_scene_graph.h:111
Definition lg_gr_func.h:56
Definition lg_scene_graph.h:69

whereas .scene.txt files only save LG_Scene nodes_ntos[NODE_NTOS_MAX_NUM] and n_node_ntos

typedef struct {
// ...
LG_Node_NTOS nodes_ntos[NODE_NTOS_MAX_NUM];
int32_t n_node_ntos;
// ...

Function Documentation

◆ lg_scene_new()

LG_Scene * lg_scene_new ( int  id,
LG_Camera cam1,
LG_Light  light1,
Rec2Df  landscape_rec,
uint16_t  grid_width,
const char *  euler_ang_rot_order 
)

Create and init a new scene

Can not contain more than NODE_NTOS_MAX_NUM mesh references

LG_Node_NTOS and LG_Scene are defined in lg_scene_graph.h

// === Scene node serializable data ===
// NTOS stands for (mesh file) NAME and (scene node) TOS (Transl/Orientation/Scaling)
// Use float for LG_EulerAng
typedef union {
struct {
// Ids and Type
int32_t id; // User-defined - SHOULD BE UNIQUE -> always > 0, 0 = top node
int32_t parent_id; // Set to < 0 if node = top node
int32_t type; // Actually lg_scenenode_type (int), may be other that MESH
LG_Path name; // User-defined - usually mesh LG_Path, ie path to OBJ/FBX/BMESH file if type == MESH
// Transl.
float x_t;
float y_t;
float z_t;
// Orientation as Euler ang (as 3 floats) - TO BE USED IN GAME LOOP UI
float x_oe;
float y_oe;
float z_oe;
// Scaling
float x_s;
float y_s;
float z_s;
// Orientation as a quat (as 4 doubles) - TO BE USED WHEN SAVING/LOADING
double x_oq;
double y_oq;
double z_oq;
double w_oq;
};
struct {
int32_t id2;
int32_t parent_id2;
int32_t type2;
LG_Path name2;
float v[17];
};
// New nodes/nodes ids added to the scene should start above first_obj_node/SCENE_FIRST_OBJ_NODE_ID (id = 3)
enum {
SCENE_ROOT_NODE_ID = 0,
SCENE_GRID_NODE_ID,
SCENE_XYZ_ARROWS_NODE_ID,
SCENE_FIRST_OBJ_NODE_ID
};
typedef struct {
// All serializable data
int32_t id; // Set to -1 on error
LG_Light light1;
Rec2Df landscape_rec;
LG_Node_NTOS nodes_ntos[NODE_NTOS_MAX_NUM];
int32_t n_node_ntos;
char euler_ang_rot_order[4];
// Not serializable data
LG_Camera *cam1;
LG_SceneNode *root;
LG_SceneNode *grid;
LG_SceneNode *xyz_arrows;
LG_SceneNode *first_obj_node;
Definition lg_camera.h:22
Definition lg_goodies.h:20
Definition lg_scene_graph.h:44

Generated nodes:

  • root -> parent of grid, xyz_arrows, and first_obj_node - id = 0, type = ROOT
  • grid -> with an initialized Lines3D_VB horizontal grid - id = 1, type = GRID
  • xyz_arrows -> with an initialized Lines3D_VB xyz_arrows - id = 2, type = LINES3D
  • first_obj_node -> id = 3, type = FIRST_OBJ

New nodes ids added to the scene should start above SCENE_FIRST_OBJ_NODE_ID (id = 3)

Default grid color = 0, 255, 255, 255

Returned scene must be freed with lg_scene_free() when done

Parameters
idScene's id
cam1A pointer to a LG_Camera
light1A LG_Light
landscape_recA Rec2Df, should be centered
grid_widthGrid width, ie number of units along one row or one column, should be even - if odd, we substract one
euler_ang_rot_orderOne of "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
Returns
A Pointer to an initialized LG_Scene if OK, NULL on error - must be freed with lg_scene_free() when done

◆ lg_scene_free()

void lg_scene_free ( LG_Scene scene)

Free 'root', 'grid', 'xyz_arrows', 'first_obj_node', and all other nodes of the scene graph, then free scene itself

WARNING:

  • Be carefull not to call this func after a call to lg_scenenode_remove_and_free_all() which will free ALL nodes but the root node
  • But you can call it after a call to lg_scenenode_remove_and_free_all_equal_or_below(first_object_node)
Parameters
sceneA LG_Scene

◆ lg_scenenode_new_and_set()

LG_SceneNode * lg_scenenode_new_and_set ( int  id,
LG_SceneNode parent_node,
lg_scenenode_type  type,
LG_Path  path,
LG_LoadMesh_Flags  flags,
vec3_t  transl,
LG_Quat  orientation,
vec3_t  scaling 
)

Helper func to create and set a new LG_SceneNode instance

Create node, add node to scene graph, load node's mesh (if type == MESH), and set node's local matrix

WARNING: if type != MESH, node->name is set to lg_path(basename2(path.s), NAME_ONLY)

Helper macros for less confusion:

#define transl_v3(x, y, z) vec3(x, y, z)
#define scaling_v3(x, y, z) vec3(x, y, z)

Mesh must be freed when done with the scene

Parameters
idNode's id
parent_nodeA pointer to a scene graph node
typeOne of ROOT, FIRST_OBJ, MESH, LINES3D, MESHLINES_ARRAY, GRID, MESHLINES_GRID, LANDSCAPE_ROOT, QT_NODE, SKYBOX, LIGHT, SHADER_ONLY, UNDEFINED
pathIf type == MESH, LG_Path to mesh file, with extension OBJ or FBX or BMESH, otherwise lg_path(basename2(path.s), NAME_ONLY)
flagsApply to mesh: save_to_cache_linux, invert_z, normalize_xyz, horiz_center, vert_center, vert_bottom
translTranslation/position vec3
orientationOrientation quat
scalingScaling vec3
Returns
A pointer to a LG_SceneNode if OK, NULL on error - must be freed afterwards

◆ lg_fill_node_NTOS_from_local_matrix()

void lg_fill_node_NTOS_from_local_matrix ( LG_Node_NTOS ntos,
mat4_t local_matrix,
const char *  euler_ang_rot_order,
zboolean  set_quat 
)

Fill a LG_Node_NTOS's TOS part, ie Transl./Orientation/Scaling (only) from a local matrix

Parameters
ntosPointer to a LG_Node_NTOS
local_matrixPointer to a mat4_t
euler_ang_rot_orderOne of "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
set_quatWhether to compute quat or leave it un touched

◆ lg_fill_node_NTOS_from_scenenode()

void lg_fill_node_NTOS_from_scenenode ( LG_Node_NTOS ntos,
LG_SceneNode node,
const char *  euler_ang_rot_order,
zboolean  set_quat 
)

Fill a LG_Node_NTOS from a LG_SceneNode

Parameters
ntosPointer to a LG_Node_NTOS
nodePointer to a LG_SceneNode
euler_ang_rot_orderOne of "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
set_quatWhether to compute quat or not

◆ lg_scene_generate_data_from_nodes()

zboolean lg_scene_generate_data_from_nodes ( LG_Scene scene,
LG_SceneNode top_node 
)

Generate LG_Scene serializable data, ie scene's (LG_Node_NTOS) nodes_ntos[NODE_NTOS_MAX_NUM] from a scene graph top node (LG_SceneNode *) by traversing it and calling fill_node_ntos(node, scene) for each node, which generate TOS values from node's local matrix

Will fill an array of LG_Node_NTOS from scene nodes from (serializing hierachical nodes tree)

NOTE1: scene->euler_ang_rot_order must have been initialized first with a correct value

NOTE2: you can use lg_scene_generate_serializable_data(scene) instead of this func

Parameters
scenePointer to a LG_Scene
top_nodeThe top scene node
Returns
Return TRUE if OK (always actually)

◆ lg_scene_save_nodes_bmeshes()

zboolean lg_scene_save_nodes_bmeshes ( LG_SceneNode top_node)

Save scenenodes meshes as BMESH files - requires a valid full path

Call first internally lg_scene_update_nodes_meshes_path_to_bmesh()

Parameters
top_nodeThe top scene node
Returns
Return TRUE if OK (always actually)

◆ lg_scene_update_nodes_meshes_path_to_bmesh()

zboolean lg_scene_update_nodes_meshes_path_to_bmesh ( LG_SceneNode top_node)

Set scenenodes meshes path as BMESH files - requires a valid path

Change extension and up dir from obj/fbx to bmesh

This func is automatically called by lg_scene_save_nodes_bmeshes()

If the original path is of the form PATH1/obj/mesh1.obj or PATH1/fbx/mesh1.fbx, the new path will be of the form: PATH1/bmesh/mesh1.bmesh

Parameters
top_nodeThe top scene node
Returns
Return TRUE if OK (always actually)

◆ lg_mesh_update_mats_paths()

int lg_mesh_update_mats_paths ( LG_Mesh mesh)

Update LG_Mesh materials[] LG_Path's with runtime info from lg_get_game_env()->assets_dir and lg_get_game_env()->app_wr_dir

Parameters
meshPointer to LG_Mesh
Returns
Return 0 if OK (always actually)

◆ lg_scene_sanitize_nodes_mesh_mats()

zboolean lg_scene_sanitize_nodes_mesh_mats ( LG_Scene scene)

Update node->mesh->materials[] paths

Parameters
scenePointer to a LG_Scene
Returns
Return TRUE if OK (always actually)

◆ lg_scene_sanitize_nodes_ids()

zboolean lg_scene_sanitize_nodes_ids ( LG_Scene scene)

Update node->id's so that they are continuous, ie 4, 7, 8, 15, 20 -> 4, 5, 6, 7, 8

Parameters
scenePointer to a LG_Scene
Returns
Return TRUE if OK (always actually)

◆ lg_scene_generate_serializable_data()

zboolean lg_scene_generate_serializable_data ( LG_Scene scene)

Generate LG_Scene serializable data, ie scene's (LG_Node_NTOS) nodes_ntos[NODE_NTOS_MAX_NUM] from LG_Scene first_obj_node (LG_SceneNode *) by calling lg_scene_generate_data_from_nodes(scene, scene->first_obj_node)

Parameters
scenePointer to a LG_Scene
Returns
Return TRUE if OK , bla bla

◆ lg_scene_generate_nodes_from_data()

LG_SceneNode * lg_scene_generate_nodes_from_data ( LG_Scene scene,
LG_SceneNode top_node,
LG_LoadMesh_Flags  flags 
)

Generate scene nodes (LG_SceneNode *) from a LG_Scene serializable data and mesh files by parsing scene's (LG_Node_NTOS) nodes_ntos[NODE_NTOS_MAX_NUM]

Will create and set scene nodes from an array of LG_Node_NTOS (deserializing nodes tree)

NTOS stands for (mesh file) NAME and (scene node) TOS (Transl/Orientation/Scaling)

(could/should more accurately be ITNTOS for Ids/Type/Name/Transl/Orientation/Scaling)

Generated scene nodes id should start at or above SCENE_FIRST_OBJ_NODE_ID (id = 3) W You can then add top_node to your scene root node or first_obj_node, or whatever you fancy

Example code:

zboolean z = lg_scene_load_data_from_file(lev->scene, lg_app_wr_file("scenes/scene_1.scene"), &n_node_ntos);
if (!z || n_node_ntos == -1) {
if (question_win("'scenes/scene_1.scene' not found\nCreate, save to file, and use default one") == YES) {
INFO_ERR("No default scene file available - will create, save to file, and use a new one\n")
LG_Node_NTOS node_ntos_set1[] = {
{{4, 3, MESH, "meshes/bmesh/shark1.bmesh",
0, 40, 0, 0, 0, 0, 25, 25, 25, 0, 0, 0, 1}},
{{5, 3, MESH, "meshes/bmesh/pikachu2.bmesh",
-50, 0, 50, 0, 0, 0, 25, 25, 25, 0, 0, 0, 1}},
{{6, 3, MESH, "meshes/bmesh/tree2.bmesh",
50, 0, 50, 0, 0, 0, 25, 25, 25, 0, 0, 0, 1}},
{{7, 3, MESH, "meshes/bmesh/windmill1.bmesh",
-50, 0, -50, 0, 0, 0, 25, 25, 25, 0, 0, 0, 1}},
{{8, 3, MESH, "meshes/bmesh/cube3.bmesh",
50, 0, -50, 0, 0, 0, 12, 12, 12, 0, 0, 0, 1}},
{{9, 6, MESH, "meshes/bmesh/airplane.bmesh",
4, 1, -2, 0, 0, 0, 1.5, 1.5, 1.5, 0, 0, 0, 1}}
};
lev->scene->n_node_ntos = (int)(sizeof(node_ntos_set1) / sizeof(LG_Node_NTOS));
for (i = 0; i < lev->scene->n_node_ntos; i++) {
lev->scene->nodes_ntos[i] = node_ntos_set1[i];
}
}
}
lev->scene->first_obj_node = lg_scene_generate_nodes_from_data(lev->scene, lev->scene->first_obj_node, lev->flags1);
if (lev->scene->first_obj_node == NULL) {
error_win(LOG, "lg_scene_generate_nodes_from_data() failed");
// ...
}
const char * lg_app_wr_file(const char *relative_path)
Definition lg_dirs_stuff.c:78
zboolean lg_scene_load_data_from_file(LG_Scene *scene, const char *full_path, int32_t *n_node_ntos)
Definition lg_scene.c:1099
LG_SceneNode * lg_scene_generate_nodes_from_data(LG_Scene *scene, LG_SceneNode *top_node, LG_LoadMesh_Flags flags)
Definition lg_scene.c:645
Parameters
scenePointer to a LG_Scene
top_nodeA scene node
flagsMesh loading flags
Returns
top_node if OK, NULL on error

◆ lg_set_TRS_matrix_from_node_NTOS_euler()

zboolean lg_set_TRS_matrix_from_node_NTOS_euler ( mat4_t m_TRS,
LG_Node_NTOS ntos,
const char *  euler_ang_rot_order 
)

Set an existing TRS matrix (Transl/Rotation/Scaling) from a LG_Node_NTOS, using Euler angles (x_oe, y_oe, z_oe) for rotation

Parameters
m_TRSPointer to a mat4_t
ntosPointer to a LG_Node_NTOS
euler_ang_rot_orderOne of "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
Returns
TRUE if OK, FALSE otherwise

◆ lg_set_NTOS_array_euler_angs_from_quats()

void lg_set_NTOS_array_euler_angs_from_quats ( LG_Scene scene)

Set a scene LG_Node_NTOS array (scene->nodes_ntos[])'s Euler angles from quats

Parameters
scenePointer to a LG_Scene

◆ lg_node_NTOS_info()

void lg_node_NTOS_info ( LG_Node_NTOS ntos)

Print out LG_Node_NTOS info

Parameters
ntosPointer to a LG_Node_NTOS

◆ lg_node_NTOS_array_info_to_stream()

void lg_node_NTOS_array_info_to_stream ( LG_Scene scene,
FILE *  stream,
zboolean  readable 
)

Send LG_Scene's nodes_ntos[] info to stream (as text)

Parameters
sceneA pointer to a LG_Scene
streamStream - use STD_OUT to output to terminal
readableInfo in human-readable form

◆ lg_node_NTOS_info_to_string()

char * lg_node_NTOS_info_to_string ( LG_Node_NTOS ntos)

Get LG_Node_NTOS info as a string

Parameters
ntosPointer to a LG_Node_NTOS
Returns
LG_Node_NTOS info as a string - must be freed when done, or NULL on error

◆ lg_node_NTOS_array_info_to_string()

char * lg_node_NTOS_array_info_to_string ( LG_Scene scene,
zboolean  readable 
)

Get LG_Scene's nodes_ntos[] info as a string

Parameters
sceneA pointer to a LG_Scene
readableInfo in human-readable form
Returns
LG_Scene's nodes_ntos[] info as a string - must be freed when done, or NULL on error

◆ lg_scene_load_data_from_assets()

zboolean lg_scene_load_data_from_assets ( LG_Scene scene,
const char *  relative_path,
int32_t *  n_node_ntos 
)

Load LG_Scene serializable data from a scene file (with .scene extension) - must be in the ASSETS folder

WARNING: .scene files save LG_Scene binary block of all serializable data whereas .scene.txt files only save LG_Scene nodes_ntos[NODE_NTOS_MAX_NUM] and n_node_ntos

Parameters
scenePointer to a LG_Scene
relative_pathRelative path to scene file - must be in the ASSETS folder
n_node_ntosPointer to int32_t which will get scene->n_node_ntos, or -1 on error
Returns
TRUE if OK, FALSE otherwise

◆ lg_scene_load_data_from_file()

zboolean lg_scene_load_data_from_file ( LG_Scene scene,
const char *  full_path,
int32_t *  n_node_ntos 
)

Load LG_Scene serializable data from a scene file (with .scene extension)

WARNING: .scene files save LG_Scene binary block of all serializable data whereas .scene.txt files only save LG_Scene nodes_ntos[NODE_NTOS_MAX_NUM] and n_node_ntos

Parameters
scenePointer to a LG_Scene
full_pathFull path to scene file
n_node_ntosPointer to int32_t which will get scene->n_node_ntos, or -1 on error
Returns
TRUE if OK, FALSE otherwise

◆ lg_scene_load_data_from_txt_file()

zboolean lg_scene_load_data_from_txt_file ( LG_Scene scene,
const char *  full_path,
int32_t *  n_node_ntos 
)

Load LG_Scene serializable data from a .scene.txt file - on ANDROID must be in the ASSETS folder

WARNING: .scene files save LG_Scene binary block of all serializable data whereas .scene.txt files only save LG_Scene nodes_ntos[NODE_NTOS_MAX_NUM] and n_node_ntos

Parameters
scenePointer to a LG_Scene
full_pathFull path to scene file
n_node_ntosPointer to int32_t which will get scene->n_node_ntos, or -1 on error
Returns
TRUE if OK, FALSE otherwise

◆ lg_scene_save_data_to_file()

zboolean lg_scene_save_data_to_file ( LG_Scene scene,
const char *  full_path 
)

Save LG_Scene serializable data to a file - on ANDROID must be in the APP WRITABLE folder

Also write LG_Scene's nodes_ntos[] into 'file_name.scene.txt' and (in human-readable form) into 'file_name.scene.hr_txt'

NOTE: To use the BMESH format, you may want to run first lg_scene_save_nodes_bmeshes()

You may also run lg_scene_sanitize_nodes_ids()

You should run lg_scene_generate_data_from_nodes() or lg_scene_generate_serializable_data() before calling this function to make sure you have valid serializable data

So, actually:

lg_scene_save_nodes_bmeshes(scene.first_obj_node);
zboolean lg_scene_generate_serializable_data(LG_Scene *scene)
Definition lg_scene.c:578
zboolean lg_scene_save_data_to_file(LG_Scene *scene, const char *full_path)
Definition lg_scene.c:1319
zboolean lg_scene_sanitize_nodes_ids(LG_Scene *scene)
Definition lg_scene.c:563
zboolean lg_scene_save_nodes_bmeshes(LG_SceneNode *top_node)
Definition lg_scene.c:429

WARNING: .scene files save LG_Scene binary block of all serializable data whereas .scene.txt files only save LG_Scene nodes_ntos[NODE_NTOS_MAX_NUM] and n_node_ntos

Parameters
scenePointer a to LG_Scene
full_pathFull path to scene file - on ANDROID must be in the APP WRITABLE folder
Returns
TRUE if OK, FALSE on error

◆ lg_create_wr_scenes_dir()

zboolean lg_create_wr_scenes_dir ( )

Create the scene folder (SCENES_DIR) in the APP WRITABLE folder

Returns
TRUE if OK, FALSE on error

◆ lg_get_reversed_rot_order()

const char * lg_get_reversed_rot_order ( const char *  rot_order)

Return reversed rot order string, ie "XYZ" -> "ZYX"

Parameters
rot_orderA 3 chars long string, expected to be a valid rot sequence
Returns
The reversed string, or an empty string if rot_order is not valid

◆ lg_rot_order_is_valid()

zboolean lg_rot_order_is_valid ( const char *  rot_order)

Check if rot order string is valid, ie one of "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"

Parameters
rot_orderA 3 chars long string
Returns
TRUE if rot_order ist valid, FALSE otherwise