LibGame  v0.4.0
The LG Game Engine - Copyright (C) 2024-2025 ETMSoftware
lg_mesh.h
1 /*
2  * LibGame - Copyright (C) Emmanuel Thomas-Maurin 2011-2025
3  * All rights reserved
4  */
5 
6 #ifndef LG_MESH_H
7 #define LG_MESH_H
8 
9 #define LG_MESH_NAME_MAX_LEN (64 - 1)
10 #define MAT_NAME_MAX_LEN (64 - 1)
11 #define N_MAX_MAT_PER_OBJ 64 /* Or N_MAX_MAT_PER_MTL ? */
12 #define N_MAX_USEMTL_PER_OBJ 256 /* 4096 ? */
13 
14 #define LG_FLOAT_EPSILON (1e-6) /* 1e-6 or 1e-8 ? */
15 
16 #define MAX_FILE_EXT_LEN 64 /* Extension length must not exceed that */
17 
18 #define MESH_VBO_EXT "vbo"
19 #define MESH_IBO_EXT "ibo"
20 #define MESH_INFO_EXT "info"
21 #define BINARY_MESH_EXT "bmesh"
22 
23 #define LG_BMESH_HEADER_SIZE 65536 /* 64 KiB - make sure it's < sizeof(LG_Mesh) */
24 
25 #define MAX_U32BIT_VALUE 4294967296
26 
27 #define CHECK_PATH(_z_) INFO_OUT("DEBUG: [%s %d]: %s() -> %s\n", basename2(__FILE__), __LINE__, __func__, _z_)
28 
29 /* Why 50 Mib ?
30 #define LG_OBJ_FILE_MAXSIZE ((size_t)50 * (size_t)(1024 * 1024))*/
31 
32 #define LG_MESH_IS_RH 1
33 #define LG_MESH_IS_LH 2
34 
35 /* Mesh original format, ie from OBJ/FBX file or whatever */
36 typedef enum {
37  LG_MESH_OBJ,
38  LG_MESH_FBX,
39  LG_MESH_TERRAIN,
40  LG_MESH_OTHER
41 } lg_mesh_type;
42 
43 typedef struct {
44  char name[MAT_NAME_MAX_LEN + 1];
45  uint32_t indice; /* Material face indice in VBO (uint32_t with GL_OES_element_index_uint extension) */
46  LG_Texture *texture;
47  char tex_path[LG_TEX_PATH_MAX_LEN + 1]; /* Used by lg_mesh_reload_mats() */
48 } LG_Material;
49 
50 /* Axis-aligned bounding box */
51 typedef union {
52  struct {
53  float min_x;
54  float max_x;
55  float min_y;
56  float max_y;
57  float min_z;
58  float max_z;
59  };
60  #if 0
61  /* LG_BBox_v2 ? */
62  struct {
63  vec3_t center;
64  float extents;
65  };
66  /* LG_BBox_v3 ? */
67  struct {
68  vec3_t min;
69  vec3_t max;
70  };
71  #endif
72 } LG_BBox;
73 
74 /*
75  * === Triangle mesh ===
76  *
77  * We want the same type sizes in binary files on all suppored platforms
78  * (ie Linux and Android so far) to avoid portability issues, so we now
79  * use fixed-size types (uint32_t, int32_t, ...) a lot for vertices structs
80  * and buffer objects.
81  *
82  * In OBJ file:
83  * - 'mtllib' -> obj_file.mtl
84  * - 'usemtl' -> material name
85  *
86  * In MTL file:
87  * - 'newmtl' -> material name
88  * - 'map_K*' -> texture path
89  */
90 typedef struct {
91  int32_t type; /* lg_mesh_type = mesh original format, ie from OBJ/FBX file or whatever */
92  char name[LG_MESH_NAME_MAX_LEN + 1]; /* OBJ/FBX basename */
93  zboolean skinned;
94  /* Generated VBO and IBO */
95  union {
96  Vertex_uv_n *vbo_data; /* VBO (with interleaved vertex data) - sizeof(Vertex_uv_n) = 24 */
97  Vertex_uvn_iw *vbo_data_iw; /* VBO (with interleaved vertex data) - sizeof(Vertex_uvn_iw) = 36 */
98  /*Vertex_rgba_n *vbo_data_rgba_n; // -> TO ASSIGN COLORS TO ELEVATIONS - sizeof(Vertex_rgba_n) = 24 */
99  };
100  uint32_t *ibo_data; /* IBO (indices start at 0) - sizeof(uint32_t) = 4 */
101  uint32_t vbo_size; /* previously size_t */
102  uint32_t ibo_size; /* previously size_t */
103  /* Read from OBJ file */
104  int32_t n_v; /* Num of coords vertices */
105  int32_t n_vt; /* Num of texture coords */
106  int32_t n_vn; /* Num of normals */
107  int32_t n_f; /* Num of faces */
108  /* Materials */
109  char mtl_file[LG_MESH_NAME_MAX_LEN + 1]; /* The MTL file path */
110  int32_t n_mat; /* Num of materials (with textures) in MTL file */
111  int32_t n_usemtl; /* Num of usemtl tags in OBJ file */
112  LG_Material materials[N_MAX_USEMTL_PER_OBJ]; /* Materials referenced by usemtl tags */
113  LG_BBox bbox;
114  LG_Cuboid b_cuboid; /* Bounding cuboid */
115  Lines3D_VB b_cuboid_l3d_vb; /* Lines3D_VB from bounding box cuboid */
116  zboolean xyz_normalized;
117  double normalize_k;
118  zboolean horiz_centered; /* Horizontally centered -> x, z*/
119  zboolean vert_centered; /* Vertically centered -> y */
120  zboolean vert_bottom; /* Vertically at bottom -> y - set mesh origin at bottom, override do_vert_center */
121 } LG_Mesh;
122 
123 /* Mesh loading flags */
124 typedef struct {
125  zboolean force_reload_obj; /* Force (re)loading and (re)parsing of the OBJ file */
126  zboolean invert_z; /* Invert z spatial coord - should be set to TRUE if mesh uses RH coords sys, FALSE if mesh uses LH coords sys */
127  zboolean normalize_xyz;
128  zboolean horiz_center;
129  zboolean vert_center; /* Center mesh vertically, if vert_bottom is not set */
130  zboolean vert_bottom; /* Set mesh origin vertically at bottom, override vert_center */
132 
133 /* Helper #define's */
134 #define FORCE_RELOAD_OBJ TRUE
135 #define INVERT_Z TRUE
136 #define NORMALIZE_XYZ TRUE
137 #define HORIZ_CENTER TRUE
138 #define VERT_CENTER TRUE
139 #define VERT_BOTTOM TRUE
140 
141 /*
142  * BINARY MESH (.bmesh) file format
143  * ================================
144  * - Header = Serializable_LG_Mesh
145  * -> header_size = lg_align_up_to_next_4_bytes_boundary((void *)sizeof(Serializable_LG_Mesh))
146  * - VBO data block - aligned to 4 bytes boundaries
147  * -> starting at header_size
148  * - IBO data block - aligned to 4 bytes boundaries
149  * -> starting at header_size + lg_align_up_to_next_4_bytes_boundary((void *)(uint64_t)mesh->vbo_size)
150  */
151 
152 /*
153  * === Structs for serialization ===
154  * We convert pointers to two uint32_t values:
155  * Vertex_uv_n *vbo_data
156  * ->
157  * uint32_t vbo_data_big;
158  * uint32_t vbo_data_little;
159  *
160  */
161 
162 typedef struct {
163  char name[MAT_NAME_MAX_LEN + 1];
164  uint32_t indice;
165  uint32_t texture_big; /* Pointer value as 2 uint32_t */
166  uint32_t texture_little;
167  char tex_path[LG_TEX_PATH_MAX_LEN + 1];
169 
170 typedef struct {
171  int32_t type;
172  char name[LG_MESH_NAME_MAX_LEN + 1];
173  zboolean skinned;
174  uint32_t vbo_data_big; /* Pointer value as 2 uint32_t */
175  uint32_t vbo_data_little;
176  uint32_t ibo_data_big; /* Pointer value as 2 uint32_t */
177  uint32_t ibo_data_little;
178  uint32_t vbo_size;
179  uint32_t ibo_size;
180  int32_t n_v;
181  int32_t n_vt;
182  int32_t n_vn;
183  int32_t n_f;
184  char mtl_file[LG_MESH_NAME_MAX_LEN + 1];
185  int32_t n_mat;
186  int32_t n_usemtl;
187  Serializable_LG_Material materials[N_MAX_USEMTL_PER_OBJ];
188  LG_BBox bbox;
189  LG_Cuboid b_cuboid;
190  Lines3D_VB b_cuboid_l3d_vb;
191  zboolean xyz_normalized;
192  double normalize_k;
193  zboolean horiz_centered;
194  zboolean vert_centered;
195  zboolean vert_bottom;
197 
198 LG_Mesh *lg_mesh_load(const char *, LG_LoadMesh_Flags);
199 
200 LG_Mesh *lg_mesh_new_from_objfile(const char *, zboolean, zboolean, zboolean, zboolean, zboolean);
201 
202 LG_Mesh *lg_mesh_new_from_fbxfile(const char *, zboolean, zboolean, zboolean, zboolean, zboolean);
203 
204 void lg_mesh_free(LG_Mesh *);
205 
206 int lg_bmesh_save_to_file(const char *, LG_Mesh *);
207 
208 int lg_bmesh_load_from_file(const char *, LG_Mesh **);
209 
211 
213 
215 
217 
219 
220 LG_LoadMesh_Flags lg_loadmesh_flags(zboolean, zboolean, zboolean, zboolean, zboolean, zboolean);
221 
222 void lg_mesh_info(LG_Mesh *);
223 
224 char *lg_replace_file_extension(const char *, const char *);
225 
226 int lg_vbo_save_to_file(const char *, LG_Mesh *);
227 
228 int lg_vbo_load_from_file(const char *, LG_Mesh **);
229 
230 #endif /* LG_MESH_H */
LG_Mesh
Definition: lg_mesh.h:90
lg_bmesh_load_from_file
int lg_bmesh_load_from_file(const char *path, LG_Mesh **mesh)
Definition: lg_mesh.c:321
LG_LoadMesh_Flags
Definition: lg_mesh.h:124
LG_Cuboid
Definition: lg_3d_primitives.h:64
Serializable_LG_Material
Definition: lg_mesh.h:162
lg_mesh_new_from_objfile
LG_Mesh * lg_mesh_new_from_objfile(const char *file_name, zboolean invert_z, zboolean normalize_xyz, zboolean horiz_center, zboolean vert_center, zboolean vert_bottom)
Definition: lg_mesh.c:182
lg_bmesh_save_to_file
int lg_bmesh_save_to_file(const char *path, LG_Mesh *mesh)
Definition: lg_mesh.c:262
lg_serialize_LG_Material_64_to_32
void lg_serialize_LG_Material_64_to_32(Serializable_LG_Material *s_mat, LG_Material *mat)
Definition: lg_mesh.c:431
lg_vbo_load_from_file
int lg_vbo_load_from_file(const char *path, LG_Mesh **mesh)
Definition: lg_mesh.c:749
Vertex_uv_n
Definition: lg_vertex.h:46
lg_replace_file_extension
char * lg_replace_file_extension(const char *path, const char *new_ext)
Definition: lg_mesh.c:670
Lines3D_VB
Definition: lg_3d_primitives.h:53
lg_mesh_load
LG_Mesh * lg_mesh_load(const char *file_name, LG_LoadMesh_Flags flags)
Definition: lg_mesh.c:82
lg_unserialize_LG_Material_32_to_64
void lg_unserialize_LG_Material_32_to_64(LG_Material *mat, Serializable_LG_Material *s_mat)
Definition: lg_mesh.c:446
lg_mesh_free
void lg_mesh_free(LG_Mesh *mesh)
Definition: lg_mesh.c:223
vec3_t
Definition: math_3d.h:123
lg_mesh_new_from_fbxfile
LG_Mesh * lg_mesh_new_from_fbxfile(const char *file_name, zboolean invert_z, zboolean normalize_xyz, zboolean horiz_center, zboolean vert_center, zboolean vert_bottom)
Definition: lg_mesh.c:213
LG_Material
Definition: lg_mesh.h:43
lg_loadmesh_flags
LG_LoadMesh_Flags lg_loadmesh_flags(zboolean force_reload_obj, zboolean invert_z, zboolean normalize_xyz, zboolean horiz_center, zboolean vert_center, zboolean vert_bottom)
Definition: lg_mesh.c:556
lg_mesh_reload_mats
int lg_mesh_reload_mats(LG_Mesh *mesh)
Definition: lg_mesh.c:410
lg_unserialize_LG_Mesh_32_to_64
void lg_unserialize_LG_Mesh_32_to_64(LG_Mesh *mesh, Serializable_LG_Mesh *s_mesh)
Definition: lg_mesh.c:502
lg_mesh_info
void lg_mesh_info(LG_Mesh *mesh)
Definition: lg_mesh.c:572
Serializable_LG_Mesh
Definition: lg_mesh.h:170
LG_Texture
Definition: lg_textures.h:45
lg_vbo_save_to_file
int lg_vbo_save_to_file(const char *path, LG_Mesh *mesh)
Definition: lg_mesh.c:707
lg_serialize_LG_Mesh_64_to_32
void lg_serialize_LG_Mesh_64_to_32(Serializable_LG_Mesh *s_mesh, LG_Mesh *mesh)
Definition: lg_mesh.c:460
Vertex_uvn_iw
Definition: lg_vertex.h:62
LG_BBox
Definition: lg_mesh.h:51