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 TEX_FILENAME_MAX_LEN (128 - 1) /* = LG_TEX_PATH_MAX_LEN */
12 #define N_MAX_MAT_PER_OBJ 64 /* Or N_MAX_MAT_PER_MTL ? */
13 #define N_MAX_USEMTL_PER_OBJ 256 /* 4096 ? */
14 
15 #define BINARY_MESH_EXT "bmesh"
16 #define LG_BMESH_HEADER_SIZE 65536 /* 64 KiB - make sure it's < sizeof(LG_Mesh) */
17 
18 #define LG_FLOAT_EPSILON (1e-6) /* 1e-6 or 1e-8 ? */
19 #define MAX_U32BIT_VALUE 4294967296
20 
21 #define CHECK_PATH(_z_) INFO_OUT("DEBUG: [%s %d]: %s() -> %s\n", basename2(__FILE__), __LINE__, __func__, _z_)
22 
23 /* Why 50 Mib ?
24 #define LG_OBJ_FILE_MAXSIZE ((size_t)50 * (size_t)(1024 * 1024))*/
25 
26 #define LG_MESH_IS_RH 1
27 #define LG_MESH_IS_LH 2
28 
29 /* Mesh original format, ie from OBJ/FBX file or whatever */
30 typedef enum {
31  LG_MESH_OBJ,
32  LG_MESH_FBX,
33  LG_MESH_TERRAIN,
34  LG_MESH_OTHER
35 } lg_mesh_type;
36 
37 typedef struct {
38  char name[MAT_NAME_MAX_LEN + 1];
39  uint32_t indice; /* Material face indice in VBO (uint32_t with GL_OES_element_index_uint extension) */
40  LG_Texture *texture;
41  char tex_filename[TEX_FILENAME_MAX_LEN + 1]; /* Relative path to image file inside the TEXTURES folder (in assets) accessible with lg_tex(path) */
42 } LG_Material;
43 
44 /* Axis-aligned bounding box */
45 typedef union {
46  struct {
47  float min_x;
48  float max_x;
49  float min_y;
50  float max_y;
51  float min_z;
52  float max_z;
53  };
54  #if 0
55  /* LG_BBox_v2 ? */
56  struct {
57  vec3_t center;
58  float extents;
59  };
60  /* LG_BBox_v3 ? */
61  struct {
62  vec3_t min;
63  vec3_t max;
64  };
65  #endif
66 } LG_BBox;
67 
68 /*
69  * === Triangle mesh ===
70  *
71  * We want the same type sizes in binary files on all suppored platforms
72  * (ie Linux and Android so far) to avoid portability issues, so we now
73  * use fixed-size types (uint32_t, int32_t, ...) a lot for vertices structs
74  * and buffer objects.
75  *
76  * In OBJ file:
77  * - 'mtllib' -> obj_file.mtl
78  * - 'usemtl' -> material name
79  *
80  * In MTL file:
81  * - 'newmtl' -> material name
82  * - 'map_K*' -> texture path
83  */
84 typedef struct {
85  int32_t type; /* lg_mesh_type = mesh original format, ie from OBJ/FBX file or whatever */
86  char name[LG_MESH_NAME_MAX_LEN + 1]; /* Should be relative path of the MESH file (OBJ/FBX/BMESH) */
87  zboolean skinned;
88  /* Generated VBO and IBO */
89  union {
90  Vertex_uv_n *vbo_data; /* VBO (with interleaved vertex data) - sizeof(Vertex_uv_n) = 24 */
91  Vertex_uvn_iw *vbo_data_iw; /* VBO (with interleaved vertex data) - sizeof(Vertex_uvn_iw) = 36 */
92  //Vertex_rgba_n *vbo_data_rgba_n; /* -> TO ASSIGN COLORS TO ELEVATIONS - sizeof(Vertex_rgba_n) = 24 */
93  };
94  uint32_t *ibo_data; /* IBO (indices start at 0) - sizeof(uint32_t) = 4 */
95  uint32_t vbo_size; /* previously size_t */
96  uint32_t ibo_size; /* previously size_t */
97  /* Read from OBJ file */
98  int32_t n_v; /* Num of coords vertices */
99  int32_t n_vt; /* Num of texture coords */
100  int32_t n_vn; /* Num of normals */
101  int32_t n_f; /* Num of faces */
102  /* Materials */
103  char mtl_file[LG_MESH_NAME_MAX_LEN + 1]; /* The MTL file path */
104  int32_t n_mat; /* Num of materials (with textures) in MTL file */
105  int32_t n_usemtl; /* Num of usemtl tags in OBJ file */
106  LG_Material materials[N_MAX_USEMTL_PER_OBJ]; /* Materials referenced by usemtl tags */
107  LG_BBox bbox;
108  LG_Cuboid b_cuboid; /* Bounding cuboid */
109  Lines3D_VB b_cuboid_l3d_vb; /* Lines3D_VB from bounding box cuboid */
110  zboolean xyz_normalized;
111  double normalize_k;
112  zboolean horiz_centered; /* Horizontally centered -> x, z*/
113  zboolean vert_centered; /* Vertically centered -> y */
114  zboolean vert_bottom; /* Vertically at bottom -> y - set mesh origin at bottom, override do_vert_center */
115 } LG_Mesh;
116 
117 /* Mesh loading flags */
118 typedef struct {
119  zboolean save_to_assets; /* Save to assets as BMESH, otherwise to cache - on Android, should always be set to FALSE as you can't write to assets */
120  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 */
121  zboolean normalize_xyz;
122  zboolean horiz_center;
123  zboolean vert_center; /* Center mesh vertically, if vert_bottom is not set */
124  zboolean vert_bottom; /* Set mesh origin vertically at bottom, override vert_center */
126 
127 /* Helper #define's */
128 #define SAVE_TO_ASSETS TRUE
129 #define INVERT_Z TRUE
130 #define NORMALIZE_XYZ TRUE
131 #define HORIZ_CENTER TRUE
132 #define VERT_CENTER TRUE
133 #define VERT_BOTTOM TRUE
134 
135 /*
136  * BINARY MESH (.bmesh) file format
137  * ================================
138  * - Header = Serializable_LG_Mesh
139  * -> header_size = lg_align_up_to_next_4_bytes_boundary((void *)sizeof(Serializable_LG_Mesh))
140  * - VBO data block - aligned to 4 bytes boundaries
141  * -> starting at header_size
142  * - IBO data block - aligned to 4 bytes boundaries
143  * -> starting at header_size + lg_align_up_to_next_4_bytes_boundary((void *)(uint64_t)mesh->vbo_size)
144  */
145 
146 /*
147  * === Structs for serialization ===
148  * We convert pointers to two uint32_t values:
149  * Vertex_uv_n *vbo_data
150  * ->
151  * uint32_t vbo_data_big;
152  * uint32_t vbo_data_little;
153  *
154  */
155 
156 typedef struct {
157  char name[MAT_NAME_MAX_LEN + 1];
158  uint32_t indice;
159  uint32_t texture_big; /* Pointer value as 2 uint32_t */
160  uint32_t texture_little;
161  char tex_filename[TEX_FILENAME_MAX_LEN + 1];
163 
164 typedef struct {
165  int32_t type;
166  char name[LG_MESH_NAME_MAX_LEN + 1];
167  zboolean skinned;
168  uint32_t vbo_data_big; /* Pointer value as 2 uint32_t */
169  uint32_t vbo_data_little;
170  uint32_t ibo_data_big; /* Pointer value as 2 uint32_t */
171  uint32_t ibo_data_little;
172  uint32_t vbo_size;
173  uint32_t ibo_size;
174  int32_t n_v;
175  int32_t n_vt;
176  int32_t n_vn;
177  int32_t n_f;
178  char mtl_file[LG_MESH_NAME_MAX_LEN + 1];
179  int32_t n_mat;
180  int32_t n_usemtl;
181  Serializable_LG_Material materials[N_MAX_USEMTL_PER_OBJ];
182  LG_BBox bbox;
183  LG_Cuboid b_cuboid;
184  Lines3D_VB b_cuboid_l3d_vb;
185  zboolean xyz_normalized;
186  double normalize_k;
187  zboolean horiz_centered;
188  zboolean vert_centered;
189  zboolean vert_bottom;
191 
192 LG_Mesh *lg_mesh_load(const char *, LG_LoadMesh_Flags);
193 
194 LG_Mesh *lg_mesh_load_easy(const char *, zboolean, LG_LoadMesh_Flags);
195 
196 LG_Mesh *lg_mesh_new_from_objfile(const char *, zboolean, zboolean, zboolean, zboolean, zboolean);
197 
198 LG_Mesh *lg_mesh_new_from_fbxfile(const char *, zboolean, zboolean, zboolean, zboolean, zboolean);
199 
200 void lg_mesh_free(LG_Mesh *);
201 
202 int lg_bmesh_save_to_file(const char *, LG_Mesh *);
203 
204 int lg_bmesh_load_from_file(const char *, LG_Mesh **);
205 
207 
209 
211 
213 
215 
216 LG_LoadMesh_Flags lg_loadmesh_flags(zboolean, zboolean, zboolean, zboolean, zboolean, zboolean);
217 
218 void lg_mesh_info(LG_Mesh *);
219 
220 char *lg_replace_file_extension(const char *, const char *);
221 
222 #endif /* LG_MESH_H */
LG_Mesh
Definition: lg_mesh.h:84
LG_LoadMesh_Flags
Definition: lg_mesh.h:118
LG_Cuboid
Definition: lg_3d_primitives.h:67
Serializable_LG_Material
Definition: lg_mesh.h:156
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:456
lg_bmesh_save_to_file
int lg_bmesh_save_to_file(const char *full_path, LG_Mesh *mesh)
Definition: lg_mesh.c:291
Vertex_uv_n
Definition: lg_vertex.h:46
lg_mesh_new_from_fbxfile
LG_Mesh * lg_mesh_new_from_fbxfile(const char *relative_path, zboolean invert_z, zboolean normalize_xyz, zboolean horiz_center, zboolean vert_center, zboolean vert_bottom)
Definition: lg_mesh.c:242
lg_loadmesh_flags
LG_LoadMesh_Flags lg_loadmesh_flags(zboolean save_to_assets, zboolean invert_z, zboolean normalize_xyz, zboolean horiz_center, zboolean vert_center, zboolean vert_bottom)
Definition: lg_mesh.c:589
lg_replace_file_extension
char * lg_replace_file_extension(const char *path, const char *new_ext)
Definition: lg_mesh.c:703
Lines3D_VB
Definition: lg_3d_primitives.h:53
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:471
lg_bmesh_load_from_file
int lg_bmesh_load_from_file(const char *full_path, LG_Mesh **mesh)
Definition: lg_mesh.c:348
lg_mesh_free
void lg_mesh_free(LG_Mesh *mesh)
Definition: lg_mesh.c:252
vec3_t
Definition: math_3d.h:123
LG_Material
Definition: lg_mesh.h:37
lg_mesh_reload_mats
int lg_mesh_reload_mats(LG_Mesh *mesh)
Definition: lg_mesh.c:435
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:531
lg_mesh_new_from_objfile
LG_Mesh * lg_mesh_new_from_objfile(const char *relative_path, zboolean invert_z, zboolean normalize_xyz, zboolean horiz_center, zboolean vert_center, zboolean vert_bottom)
Definition: lg_mesh.c:214
lg_mesh_info
void lg_mesh_info(LG_Mesh *mesh)
Definition: lg_mesh.c:605
Serializable_LG_Mesh
Definition: lg_mesh.h:164
LG_Texture
Definition: lg_textures.h:45
lg_mesh_load_easy
LG_Mesh * lg_mesh_load_easy(const char *relative_path, zboolean force_reload_objs, LG_LoadMesh_Flags flags1)
Definition: lg_mesh.c:154
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:485
Vertex_uvn_iw
Definition: lg_vertex.h:62
LG_BBox
Definition: lg_mesh.h:45
lg_mesh_load
LG_Mesh * lg_mesh_load(const char *relative_path, LG_LoadMesh_Flags flags)
Definition: lg_mesh.c:72