commit ac2e2edc450ebfa639408b5a889365359eaac1fc
parent 95df8e8e0a17bd4c4196056d2911e076f64ef3fd
Author: Egor Achkasov <eaachkasov@edu.hse.ru>
Date: Tue, 25 Mar 2025 22:22:35 +0100
Implement Sionna xml reader; Add material string->material_index map; Minor refactor
Diffstat:
| M | compute_paths.c | | | 5 | +++-- |
| A | inc/common.h | | | 16 | ++++++++++++++++ |
| A | inc/materials.h | | | 152 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | inc/scene.h | | | 121 | +++---------------------------------------------------------------------------- |
| M | scene_fromSionna.c | | | 424 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
5 files changed, 411 insertions(+), 307 deletions(-)
diff --git a/compute_paths.c b/compute_paths.c
@@ -1,5 +1,6 @@
-#include "compute_paths.h" /* for compute_paths */
-#include "scene.h" /* for HRT_Scene, HRT_mesh, HRT_Material */
+#include "inc/compute_paths.h" /* for compute_paths */
+#include "inc/scene.h" /* for HRT_Scene, HRT_mesh, HRT_Material */
+#include "inc/materials.h" /* for g_hrt_materials */
#include <stddef.h> /* for size_t */
#include <stdlib.h> /* for exit, malloc, free */
diff --git a/inc/common.h b/inc/common.h
@@ -0,0 +1,16 @@
+#define IN
+#define OUT
+
+#define FREE_POINTERS(...) \
+ do { \
+ void *ptrs[] = {__VA_ARGS__};\
+ for (size_t i = 0; i < sizeof(ptrs) / sizeof(ptrs[0]); i++) \
+ free(ptrs[i]); \
+ } while (0)
+
+#define PERROR_CLEANUP_EXIT(msg, rc, ...) \
+ do { \
+ perror(msg); \
+ FREE_POINTERS(__VA_ARGS__); \
+ exit(rc); \
+ } while (0)
diff --git a/inc/materials.h b/inc/materials.h
@@ -0,0 +1,152 @@
+#ifndef MATERIALS_H
+#define MATERIALS_H
+
+#include "scene.h" /* for HRT_Material */
+
+#include <stdint.h> /* for uint32_t */
+#include <string.h> /* for strncmp */
+
+/* number of defined materials */
+#define NUM_G_MATERIALS 17
+HRT_Material g_hrt_materials[NUM_G_MATERIALS] = {
+ /* 0 */
+ {3, "air",
+ 1.f, 0.f, 0.f, 0.001f,
+ 0.1f, 0.5f, 0.3f, 0.2f,
+ 2, 2},
+ /* 1 */
+ {8, "concrete",
+ 5.24f, 0.f, 0.0462f, 0.7822f,
+ 0.5f, 0.33f, 0.34f, 0.33f,
+ 4, 4},
+ /* 2 */
+ {5, "brick",
+ 3.91f, 0.f, 0.0238f, 0.16f,
+ 0.4f, 0.4f, 0.3f, 0.3f,
+ 3, 3},
+ /* 3 */
+ {12, "plasterboard",
+ 2.73f, 0.f, 0.0085f, 0.9395f,
+ 0.3f, 0.4f, 0.4f, 0.2f,
+ 3, 3},
+ /* 4 */
+ {4, "wood",
+ 1.99f, 0.f, 0.0047f, 1.0718f,
+ 0.2f, 0.5f, 0.3f, 0.2f,
+ 2, 2},
+ /* 5 */
+ {5, "glass",
+ 6.31f, 0.f, 0.0036f, 1.3394f,
+ 0.3f, 0.4f, 0.4f, 0.2f,
+ 3, 3},
+ /* 6 */
+ {5, "glass",
+ 5.79f, 0.f, 0.0004f, 1.658f,
+ 0.3f, 0.4f, 0.4f, 0.2f,
+ 3, 3},
+ /* 7 */
+ {13, "ceiling board",
+ 1.48f, 0.f, 0.0011f, 1.0750f,
+ 0.2f, 0.5f, 0.3f, 0.2f,
+ 2, 2},
+ /* 8 */
+ {13, "ceiling board",
+ 1.52f, 0.f, 0.0029f, 1.029f,
+ 0.2f, 0.5f, 0.3f, 0.2f,
+ 2, 2},
+ /* 9 */
+ {9, "chipboard",
+ 2.58f, 0.f, 0.0217f, 0.7800f,
+ 0.4f, 0.4f, 0.3f, 0.3f,
+ 3, 3},
+ /* 10 */
+ {7, "plywood",
+ 2.71f, 0.f, 0.33f, 0.f,
+ 0.3f, 0.5f, 0.3f, 0.2f,
+ 3, 3},
+ /* 11 */
+ {6, "marble",
+ 7.074f, 0.f, 0.0055f,
+ 0.9262f, 0.3f, 0.4f, 0.4f, 0.2f,
+ 3, 3},
+ /* 12 */
+ {10, "floorboard",
+ 3.66f, 0.f, 0.0044f, 1.3515f,
+ 0.3f, 0.4f, 0.4f, 0.2f,
+ 3, 3},
+ /* 13 */
+ {5, "metal",
+ 1.f, 0.f, 10000000.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 1, 1},
+ /* 14 */
+ {15, "very dry ground",
+ 3.f, 0.f, 0.00015f, 2.52f,
+ 0.4f, 0.3f, 0.4f, 0.3f,
+ 4, 4},
+ /* 15 */
+ {17, "medium dry ground",
+ 15.f, -0.1f, 0.035f, 1.63f,
+ 0.5f, 0.33f, 0.34f, 0.33f,
+ 4, 4},
+ /* 16 */
+ {10, "wet ground",
+ 30.f, -0.4f, 0.15f, 1.30f,
+ 0.5f, 0.33f, 0.34f, 0.33f,
+ 4, 4}
+};
+typedef enum {
+ MATERIAL_AIR = 0,
+ MATERIAL_CONCRETE = 1,
+ MATERIAL_BRICK = 2,
+ MATERIAL_PLASTERBOARD = 3,
+ MATERIAL_WOOD = 4,
+ MATERIAL_GLASS1 = 5,
+ MATERIAL_GLASS2 = 6,
+ MATERIAL_CEILING_BOARD1 = 7,
+ MATERIAL_CEILING_BOARD2 = 8,
+ MATERIAL_CHIPBOARD = 9,
+ MATERIAL_PLYWOOD = 10,
+ MATERIAL_MARBLE = 11,
+ MATERIAL_FLOORBOARD = 12,
+ MATERIAL_METAL = 13,
+ MATERIAL_VERY_DRY_GROUND = 14,
+ MATERIAL_MEDIUM_DRY_GROUND = 15,
+ MATERIAL_WET_GROUND = 16
+} MaterialIndex;
+
+/* Map material name strings to material indices */
+typedef struct {
+ /* Material name. Null-terminated string. Lower case. */
+ const char *name;
+ MaterialIndex index;
+} MaterialMap;
+
+MaterialMap material_map[] = {
+ {"air", MATERIAL_AIR},
+ {"concrete", MATERIAL_CONCRETE},
+ {"brick", MATERIAL_BRICK},
+ {"plasterboard", MATERIAL_PLASTERBOARD},
+ {"wood", MATERIAL_WOOD},
+ {"glass1", MATERIAL_GLASS1},
+ {"glass2", MATERIAL_GLASS2},
+ {"ceiling_board1", MATERIAL_CEILING_BOARD1},
+ {"ceiling_board2", MATERIAL_CEILING_BOARD2},
+ {"chipboard", MATERIAL_CHIPBOARD},
+ {"plywood", MATERIAL_PLYWOOD},
+ {"marble", MATERIAL_MARBLE},
+ {"floorboard", MATERIAL_FLOORBOARD},
+ {"metal", MATERIAL_METAL},
+ {"very_dry_ground", MATERIAL_VERY_DRY_GROUND},
+ {"medium_dry_ground", MATERIAL_MEDIUM_DRY_GROUND},
+ {"wet_ground", MATERIAL_WET_GROUND}
+};
+
+MaterialIndex get_material_index(const char *name) {
+ for (uint32_t i = 0; i < NUM_G_MATERIALS; ++i)
+ if (strcmp(material_map[i].name, name) == 0)
+ return material_map[i].index;
+ return MATERIAL_AIR; /* Invalid material. Default to air */
+}
+
+#endif /* MATERIALS_H */
diff --git a/inc/scene.h b/inc/scene.h
@@ -1,8 +1,7 @@
-#include <stdint.h> /* for uint32_t */
+#ifndef SCENE_H
+#define SCENE_H
-/*******************************************************************/
-/* Scene */
-/*******************************************************************/
+#include <stdint.h> /* for uint32_t */
typedef struct {
/* Number of vertices */
@@ -24,10 +23,6 @@ typedef struct {
HRT_Mesh *meshes;
} HRT_Scene;
-/*******************************************************************/
-/* Materials */
-/*******************************************************************/
-
typedef struct {
/* Number of characters in the name */
uint32_t name_sz;
@@ -62,112 +57,4 @@ typedef struct {
uint8_t s3_alpha;
} HRT_Material;
-/* number of defined materials */
-#define NUM_G_MATERIALS 17
-HRT_Material g_hrt_materials[NUM_G_MATERIALS] = {
- /* 0 */
- {3, "air",
- 1.f, 0.f, 0.f, 0.001f,
- 0.1f, 0.5f, 0.3f, 0.2f,
- 2, 2},
- /* 1 */
- {8, "concrete",
- 5.24f, 0.f, 0.0462f, 0.7822f,
- 0.5f, 0.33f, 0.34f, 0.33f,
- 4, 4},
- /* 2 */
- {5, "brick",
- 3.91f, 0.f, 0.0238f, 0.16f,
- 0.4f, 0.4f, 0.3f, 0.3f,
- 3, 3},
- /* 3 */
- {12, "plasterboard",
- 2.73f, 0.f, 0.0085f, 0.9395f,
- 0.3f, 0.4f, 0.4f, 0.2f,
- 3, 3},
- /* 4 */
- {4, "wood",
- 1.99f, 0.f, 0.0047f, 1.0718f,
- 0.2f, 0.5f, 0.3f, 0.2f,
- 2, 2},
- /* 5 */
- {5, "glass",
- 6.31f, 0.f, 0.0036f, 1.3394f,
- 0.3f, 0.4f, 0.4f, 0.2f,
- 3, 3},
- /* 6 */
- {5, "glass",
- 5.79f, 0.f, 0.0004f, 1.658f,
- 0.3f, 0.4f, 0.4f, 0.2f,
- 3, 3},
- /* 7 */
- {13, "ceiling board",
- 1.48f, 0.f, 0.0011f, 1.0750f,
- 0.2f, 0.5f, 0.3f, 0.2f,
- 2, 2},
- /* 8 */
- {13, "ceiling board",
- 1.52f, 0.f, 0.0029f, 1.029f,
- 0.2f, 0.5f, 0.3f, 0.2f,
- 2, 2},
- /* 9 */
- {9, "chipboard",
- 2.58f, 0.f, 0.0217f, 0.7800f,
- 0.4f, 0.4f, 0.3f, 0.3f,
- 3, 3},
- /* 10 */
- {7, "plywood",
- 2.71f, 0.f, 0.33f, 0.f,
- 0.3f, 0.5f, 0.3f, 0.2f,
- 3, 3},
- /* 11 */
- {6, "marble",
- 7.074f, 0.f, 0.0055f,
- 0.9262f, 0.3f, 0.4f, 0.4f, 0.2f,
- 3, 3},
- /* 12 */
- {10, "floorboard",
- 3.66f, 0.f, 0.0044f, 1.3515f,
- 0.3f, 0.4f, 0.4f, 0.2f,
- 3, 3},
- /* 13 */
- {5, "metal",
- 1.f, 0.f, 10000000.f, 0.f,
- 0.f, 0.f, 1.f, 0.f,
- 1, 1},
- /* 14 */
- {15, "very dry ground",
- 3.f, 0.f, 0.00015f, 2.52f,
- 0.4f, 0.3f, 0.4f, 0.3f,
- 4, 4},
- /* 15 */
- {17, "medium dry ground",
- 15.f, -0.1f, 0.035f, 1.63f,
- 0.5f, 0.33f, 0.34f, 0.33f,
- 4, 4},
- /* 16 */
- {10, "wet ground",
- 30.f, -0.4f, 0.15f, 1.30f,
- 0.5f, 0.33f, 0.34f, 0.33f,
- 4, 4}
-};
-typedef enum {
- MATERIAL_AIR = 0,
- MATERIAL_CONCRETE = 1,
- MATERIAL_BRICK = 2,
- MATERIAL_PLASTERBOARD = 3,
- MATERIAL_WOOD = 4,
- MATERIAL_GLASS1 = 5,
- MATERIAL_GLASS2 = 6,
- MATERIAL_CEILING_BOARD1 = 7,
- MATERIAL_CEILING_BOARD2 = 8,
- MATERIAL_CHIPBOARD = 9,
- MATERIAL_PLYWOOD = 10,
- MATERIAL_MARBLE = 11,
- MATERIAL_FLOORBOARD = 12,
- MATERIAL_METAL = 13,
- MATERIAL_VERY_DRY_GROUND = 14,
- MATERIAL_MEDIUM_DRY_GROUND = 15,
- MATERIAL_WET_GROUND = 16
-} MaterialIndex;
-
+#endif /* SCENE_H */
diff --git a/scene_fromSionna.c b/scene_fromSionna.c
@@ -1,13 +1,13 @@
/* vim: set tabstop=2:softtabstop=2:shiftwidth=2:noexpandtab */
-#include "scene.h" /* for HRT_Scene, HRT_Mesh, HRT_Material */
+#include "inc/common.h" /* for IN, OUT, PERROR_CLEANUP_EXIT */
+#include "inc/scene.h" /* for HRT_Scene, HRT_Mesh, HRT_Material */
+#include "inc/materials.h" /* for g_hrt_materials, MATERIAL_CONCRETE */
#include <stdio.h> /* for FILE, fopen, fclose, fseek, fgets, sscanf, printf */
#include <stdlib.h> /* for malloc */
#include <stdint.h> /* for uint8_t, uint32_t */
#include <string.h> /* for strncmp, strrchr, strcmp */
-#include <dirent.h> /* for opendir, readdir, closedir, DT_REG */
-
/**
* Hardcoded scenes
@@ -101,10 +101,8 @@ const char* scene_simpleReflector_filename = "simple_reflector.xml";
*/
HRT_Mesh readPly(const char* filepath) {
FILE* f = fopen(filepath, "rb");
- if (f == NULL) {
- perror("Error: cannot open file");
- exit(8);
- }
+ if (f == NULL)
+ PERROR_CLEANUP_EXIT("Error: cannot open file", 8);
char buf[256];
HRT_Mesh mesh = {
@@ -121,27 +119,20 @@ HRT_Mesh readPly(const char* filepath) {
if (!strncmp(buf, "end_header", 10))
break;
if (!strncmp(buf, "element vertex ", 15)) {
- if (sscanf(buf, "element vertex %u", &mesh.num_vertices) != 1) {
- perror("Error: cannot read number of vertices");
- exit(8);
- }
+ if (sscanf(buf, "element vertex %u", &mesh.num_vertices) != 1)
+ PERROR_CLEANUP_EXIT("Error: cannot read number of vertices", 8);
}
else if (!strncmp(buf, "element face ", 13))
- if (sscanf(buf, "element face %u", &mesh.num_triangles) != 1) {
- perror("Error: cannot read number of triangles");
- exit(8);
- }
+ if (sscanf(buf, "element face %u", &mesh.num_triangles) != 1)
+ PERROR_CLEANUP_EXIT("Error: cannot read number of triangles", 8);
}
/* check if vertex and face elements are found */
- if (mesh.num_vertices == 0 || mesh.num_triangles == 0) {
- perror("Error: PLY element vertex or element face not found");
- exit(8);
+ if (mesh.num_vertices == 0 || mesh.num_triangles == 0)
+ PERROR_CLEANUP_EXIT("Error: PLY element vertex or element face not found", 8);
/* check if the numbers are not too big */
- } else if (mesh.num_vertices > 1000000 || mesh.num_triangles > 1000000) {
- perror("Error: PLY element vertex or element face too big");
- exit(8);
- }
+ else if (mesh.num_vertices > 1000000 || mesh.num_triangles > 1000000)
+ PERROR_CLEANUP_EXIT("Error: PLY element vertex or element face too big", 8);
/* allocate memory for vertices and faces */
mesh.vs = (float*)malloc(3 * mesh.num_vertices * sizeof(float));
@@ -149,42 +140,26 @@ HRT_Mesh readPly(const char* filepath) {
/* read vertices */
for (uint32_t i = 0; i != mesh.num_vertices * 3; i += 3) {
- if (fread(&mesh.vs[i], sizeof(float), 3, f) != 3) {
- perror("Error: cannot read vertex");
- goto free_and_error;
- }
+ if (fread(&mesh.vs[i], sizeof(float), 3, f) != 3)
+ PERROR_CLEANUP_EXIT("Error: cannot read vertex", 8, mesh.vs, mesh.is);
/* skip s and t */
- if (fseek(f, 8, SEEK_CUR) != 0) {
- perror("Error: cannot skip s and t");
- goto free_and_error;
- }
+ if (fseek(f, 8, SEEK_CUR) != 0)
+ PERROR_CLEANUP_EXIT("Error: cannot skip s and t", 8, mesh.vs, mesh.is);
}
/* read faces */
for (uint32_t i = 0; i != mesh.num_triangles * 3; i += 3) {
uint8_t n;
- if (fread(&n, sizeof(uint8_t), 1, f) != 1) {
- perror("Error: cannot read number of vertices in face");
- goto free_and_error;
- }
- if (n != 3) {
- perror("Error: face is not a triangle");
- goto free_and_error;
- }
- if (fread(&mesh.is[i], sizeof(uint32_t), 3, f) != 3) {
- perror("Error: cannot read face");
- goto free_and_error;
- }
+ if (fread(&n, sizeof(uint8_t), 1, f) != 1)
+ PERROR_CLEANUP_EXIT("Error: cannot read number of vertices in face", 8, mesh.vs, mesh.is);
+ if (n != 3)
+ PERROR_CLEANUP_EXIT("Error: face is not a triangle", 8, mesh.vs, mesh.is);
+ if (fread(&mesh.is[i], sizeof(uint32_t), 3, f) != 3)
+ PERROR_CLEANUP_EXIT("Error: cannot read face", 8, mesh.vs, mesh.is);
}
fclose(f);
return mesh;
-
-free_and_error:
- free(mesh.vs);
- free(mesh.is);
- fclose(f);
- exit(8);
}
/** Read a scene config CSV file.
@@ -203,79 +178,191 @@ free_and_error:
* \param velocity Output array of velocities. Size [num_meshes * 3]
*/
void readCsv(
- const char* filepath,
- uint32_t* num_meshes,
- char** mesh_filenames,
- uint32_t* material_indicies,
- float* velocity
+ IN const char* filepath,
+ OUT uint32_t* csv_num_meshes,
+ OUT char** csv_mesh_filenames,
+ OUT uint32_t* csv_material_indicies,
+ OUT float* csv_velocities
)
{
FILE* f = fopen(filepath, "r");
- if (f == NULL) {
- perror("Error: cannot open file");
- exit(8);
- }
+ if (!f)
+ PERROR_CLEANUP_EXIT("Error: cannot open file", 8);
/* Check header */
char buf[256];
- if (fgets(buf, 256, f) == NULL) {
- perror("Error: cannot read header");
- exit(8);
- }
- if (strncmp(buf, "name,material_index,velocity_x,velocity_y,velocity_z\n", 48)) {
- perror("Error: invalid header");
- exit(8);
- }
+ if (!fgets(buf, 256, f))
+ PERROR_CLEANUP_EXIT("Error: cannot read header", 8);
+ if (strncmp(buf, "name,material_index,velocity_x,velocity_y,velocity_z\n", 48))
+ PERROR_CLEANUP_EXIT("Error: invalid header", 8);
/* Count number of lines */
- *num_meshes = 0;
+ *csv_num_meshes = 0;
while (fgets(buf, 256, f))
- ++(*num_meshes);
+ ++(*csv_num_meshes);
+ if (*csv_num_meshes == 0) {
+ fclose(f);
+ return;
+ }
/* Return to the beginning of the file */
rewind(f);
/* Skip header */
- if (fgets(buf, 256, f) == NULL) {
- perror("Error: cannot read header");
- exit(8);
- }
+ if (!fgets(buf, 256, f))
+ PERROR_CLEANUP_EXIT("Error: cannot read header", 8);
/* Allocate memory for the arrays */
- mesh_filenames = (char**)malloc(*num_meshes * sizeof(char*));
- material_indicies = (uint32_t*)malloc(*num_meshes * sizeof(uint32_t));
- velocity = (float*)malloc(*num_meshes * 3 * sizeof(float));
+ csv_mesh_filenames = (char**)malloc(*csv_num_meshes * sizeof(char*));
+ csv_material_indicies = (uint32_t*)malloc(*csv_num_meshes * sizeof(uint32_t));
+ csv_velocities = (float*)malloc(*csv_num_meshes * 3 * sizeof(float));
/* Read lines */
- for (uint32_t i = 0; i != *num_meshes; ++i) {
+ for (uint32_t i = 0; i != *csv_num_meshes; ++i) {
/* Read line */
- if (fgets(buf, 256, f) == NULL) {
- perror("Error: cannot read line");
- exit(8);
- }
+ if (!fgets(buf, 256, f))
+ PERROR_CLEANUP_EXIT("Error: cannot read line", 8);
/* Parse line */
char name[50];
int rc = sscanf(
buf,
"%49[^,],%u,%f,%f,%f\n",
name,
- &material_indicies[i],
- &velocity[i * 3],
- &velocity[i * 3 + 1],
- &velocity[i * 3 + 2]
+ &csv_material_indicies[i],
+ &csv_velocities[i * 3],
+ &csv_velocities[i * 3 + 1],
+ &csv_velocities[i * 3 + 2]
);
- if (rc != 4) {
- perror("Error: cannot parse line");
- exit(8);
- }
+ if (rc != 4)
+ PERROR_CLEANUP_EXIT("Error: cannot parse line", 8);
/* Copy name */
- mesh_filenames[i] = (char*)malloc(strlen(name) + 1);
- if (mesh_filenames[i] == NULL) {
- perror("Error: cannot allocate memory for mesh filename");
- exit(8);
- }
- strcpy(mesh_filenames[i], name);
+ csv_mesh_filenames[i] = (char*)malloc(strlen(name) + 1);
+ if (!csv_mesh_filenames[i])
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for mesh filename", 8);
+ strcpy(csv_mesh_filenames[i], name);
}
}
+/** Read a Sionna scene XML file.
+ *
+ * Extracts each shape's name, file path and material.
+ *
+ * \param filepath Path to the XML file
+ * \param xml_num_meshes Output number of meshes in the XML file
+ * \param xml_mesh_filepaths Output array of mesh file paths (null-terminated strings)
+ * \param xml_mesh_names Output array of mesh names (null-terminated strings)
+ * \param xml_mesh_materials Output array of mesh materials (null-terminated strings)
+ */
+void readXml(
+ IN const char* filepath,
+ OUT uint32_t* xml_num_meshes,
+ OUT char*** xml_mesh_filepaths,
+ OUT char*** xml_mesh_names,
+ OUT char*** xml_mesh_materials
+)
+{
+ FILE* f = fopen(filepath, "r");
+ if (f == NULL)
+ PERROR_CLEANUP_EXIT("Error: cannot open the xml file", 8);
+
+ fseek(f, 0, SEEK_END);
+ long fsize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ char* buf = (char*)malloc(fsize + 1);
+ if (!buf)
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for the xml file", 8);
+ if (fread(buf, 1, fsize, f) != fsize)
+ PERROR_CLEANUP_EXIT("Error: cannot read the xml file", 8, buf);
+ buf[fsize] = '\0';
+
+ /* Count the amount of "<shape" entries */
+ char** shape_positions = NULL;
+ *xml_num_meshes = 0;
+ char* pos = buf, *end;
+ while ((pos = strstr(pos, "<shape")) != NULL) {
+ ++*xml_num_meshes;
+ shape_positions = (char**)realloc(shape_positions, *xml_num_meshes * sizeof(char*));
+ if (!shape_positions)
+ PERROR_CLEANUP_EXIT("Error: cannot reallocate memory for shape positions", 8, buf);
+ shape_positions[*xml_num_meshes - 1] = pos;
+ pos += 6;
+ }
+ if (*xml_num_meshes == 0)
+ PERROR_CLEANUP_EXIT("Error: no shapes found in the xml file", 8, buf);
+ if (!shape_positions)
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for shape positions", 8, buf);
+
+ /* Allocate memory for the mesh data */
+ *xml_mesh_filepaths = (char**)malloc(*xml_num_meshes * sizeof(char*));
+ *xml_mesh_names = (char**)malloc(*xml_num_meshes * sizeof(char*));
+ *xml_mesh_materials = (char**)malloc(*xml_num_meshes * sizeof(char*));
+ if (!*xml_mesh_filepaths || !*xml_mesh_names || !*xml_mesh_materials)
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for mesh data", 8, buf);
+
+ /* For each "<shape" entry, extract the name, file path and material */
+ char *e_name, *e_filepath, *e_material;
+ for (uint32_t i = 0; i != *xml_num_meshes; ++i) {
+ pos = shape_positions[i] + 6;
+
+ /* Find mesh name */
+ if ((pos = strstr(pos, "name=\"")) == NULL)
+ PERROR_CLEANUP_EXIT("Error: cannot find mesh name", 8,
+ buf, shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ pos += 6;
+ end = strchr(pos, '\"');
+ if (!end)
+ PERROR_CLEANUP_EXIT("Error: cannot find mesh name end", 8,
+ buf, shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ e_name = (char*)malloc(end - pos + 1);
+ if (!e_name)
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for mesh name", 8,
+ buf, shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ strncpy(e_name, pos, end - pos);
+ e_name[end - pos] = '\0';
+
+ /* Find mesh file path */
+ if (!(pos = strstr(pos, "<string name=\"filename\"")))
+ PERROR_CLEANUP_EXIT("Error: cannot find mesh file path", 8, buf, e_name,
+ shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ if (!(pos = strstr(pos, "value=\"")))
+ PERROR_CLEANUP_EXIT("Error: cannot find mesh file path value", 8, buf, e_name,
+ shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ pos += 7;
+ end = strchr(pos, '\"');
+ if (!end)
+ PERROR_CLEANUP_EXIT("Error: cannot find mesh file path end", 8, buf, e_name,
+ shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ e_filepath = (char*)malloc(end - pos + 1);
+ if (!e_filepath)
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for mesh file path", 8, buf, e_name,
+ shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ strncpy(e_filepath, pos, end - pos);
+ e_filepath[end - pos] = '\0';
+
+ /* Find mesh material */
+ if (!(pos = strstr(pos, "id=\"mat-itu_")))
+ PERROR_CLEANUP_EXIT("Error: cannot find mesh material", 8, buf, e_name, e_filepath,
+ shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ pos += 12;
+ end = strchr(pos, '\"');
+ if (!end)
+ PERROR_CLEANUP_EXIT("Error: cannot find mesh material end", 8, buf, e_name, e_filepath,
+ shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ e_material = (char*)malloc(end - pos + 1);
+ if (!e_material)
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for mesh material", 8, buf, e_name, e_filepath,
+ shape_positions, *xml_mesh_filepaths, *xml_mesh_names, *xml_mesh_materials);
+ strncpy(e_material, pos, end - pos);
+ e_material[end - pos] = '\0';
+
+ /* Save mesh data */
+ (*xml_mesh_filepaths)[i] = e_filepath;
+ (*xml_mesh_names)[i] = e_name;
+ (*xml_mesh_materials)[i] = e_material;
+ }
+
+ free(shape_positions);
+ free(buf);
+}
/* Read a Sionna .xml scene. Assumes meshes are in a "meshes" directory.
*
@@ -285,17 +372,26 @@ void readCsv(
void readScene(const char* filepath, HRT_Scene* scene) {
/* Check if filepath ends with ".xml" */
size_t filepath_len = strlen(filepath);
- if (filepath_len > 4 && strcmp(filepath + filepath_len - 4, ".xml") != 0) {
- perror("Error: scene file must end with .xml");
- exit(8);
- }
+ if (filepath_len > 4 && strcmp(filepath + filepath_len - 4, ".xml") != 0)
+ PERROR_CLEANUP_EXIT("Error: scene file must end with .xml", 8);
+
+ /* Read the xml file */
+ uint32_t xml_num_meshes;
+ char** xml_mesh_filepaths;
+ char** xml_mesh_names;
+ char** xml_mesh_materials;
+ readXml(
+ filepath,
+ &xml_num_meshes,
+ &xml_mesh_filepaths,
+ &xml_mesh_names,
+ &xml_mesh_materials
+ );
/* Read the scene config CSV file */
char* csv_path = (char*)malloc(filepath_len + 1);
- if (!csv_path) {
- perror("Error: failed to allocate csv_path");
- exit(8);
- }
+ if (!csv_path)
+ PERROR_CLEANUP_EXIT("Error: cannot allocate memory for csv_path", 8);
strcpy(csv_path, filepath);
strcpy(csv_path + filepath_len - 4, ".csv");
uint32_t csv_num_meshes;
@@ -309,92 +405,47 @@ void readScene(const char* filepath, HRT_Scene* scene) {
csv_material_indicies,
csv_velocity
);
-
- /* Get the meshes directory path */
- const char* last_slash = strrchr(filepath, '/');
- size_t base_len = (last_slash ? (last_slash - filepath + 1) : 0);
- char* dir_path = (char*)malloc(base_len + strlen("meshes/") + 1);
- if (!dir_path) {
- perror("Error: failed to allocate dir_path");
- exit(8);
- }
- if (base_len > 0) {
- strncpy(dir_path, filepath, base_len);
- dir_path[base_len] = '\0';
- } else
- dir_path[0] = '\0'; /* No directory, start empty */
- strcat(dir_path, "meshes/");
-
- /* Scan the directory for .ply files */
- DIR* dir = opendir(dir_path);
- if (!dir) {
- perror("Failed to open meshes directory");
- free(dir_path);
- exit(8);
- }
-
- /* Count the number of .ply files */
- uint32_t ply_count = 0;
- struct dirent* entry;
- while ((entry = readdir(dir))) {
- if (entry->d_type != DT_REG) continue;
- size_t name_len = strlen(entry->d_name);
- if (name_len > 4 && strncmp(entry->d_name + name_len - 4, ".ply", 4) == 0)
- ply_count++;
- }
-
- /* Allocate memory for the meshes array */
- scene->num_meshes = ply_count;
- scene->meshes = (HRT_Mesh*)malloc(ply_count * sizeof(HRT_Mesh));
- if (!scene->meshes && ply_count > 0) {
- perror("Error: failed to allocate meshes array");
- free(dir_path);
- closedir(dir);
- exit(8);
- }
-
- /* Read each .ply file */
- rewinddir(dir); // Reset directory pointer
- uint32_t mesh_idx = 0;
- while ((entry = readdir(dir)) && mesh_idx < ply_count) {
- /* Continue if not a regular file or not a .ply file */
- size_t name_len = strlen(entry->d_name);
- if ((entry->d_type != DT_REG)
- || (name_len <= 4 || strcmp(entry->d_name + name_len - 4, ".ply")))
- continue;
-
- /* Construct full filepath for the .ply file */
- char* ply_path = (char*)malloc(strlen(dir_path) + name_len + 1);
- if (!ply_path) {
- perror("Error: failed to allocate ply_path");
- free(dir_path);
- closedir(dir);
- free(scene->meshes);
- exit(8);
- }
- strcpy(ply_path, dir_path);
- strcat(ply_path, entry->d_name);
-
- /* Read mesh */
- scene->meshes[mesh_idx] = readPly(ply_path);
-
- /* Get material index and velocity from the CSV file */
- for (uint32_t i = 0; i != csv_num_meshes; ++i)
- if (strcmp(entry->d_name, csv_mesh_filenames[i]) == 0) {
- scene->meshes[mesh_idx].material_index = csv_material_indicies[i];
- scene->meshes[mesh_idx].velocity[0] = csv_velocity[i * 3];
- scene->meshes[mesh_idx].velocity[1] = csv_velocity[i * 3 + 1];
- scene->meshes[mesh_idx].velocity[2] = csv_velocity[i * 3 + 2];
+ free(csv_path);
+
+ /* Read the meshes */
+
+ /* Get the scene directory path */
+ size_t scene_dir_len = strrchr(filepath, '/') - filepath + 1;
+ /* if filepath is "/path/to/scene.xml", scene_dir is "/path/to/" */
+ char* scene_dir = (char*)malloc(scene_dir_len + 7);
+ if (!scene_dir)
+ PERROR_CLEANUP_EXIT("Error: failed to allocate scene_dir", 8);
+ strncpy(scene_dir, filepath, scene_dir_len);
+
+ /* For each ply file from the xml file */
+ scene->num_meshes = xml_num_meshes;
+ scene->meshes = (HRT_Mesh*)malloc(xml_num_meshes * sizeof(HRT_Mesh));
+ if (!scene->meshes && xml_num_meshes > 0)
+ PERROR_CLEANUP_EXIT("Error: failed to allocate meshes array", 8);
+ for (uint32_t i = 0; i != xml_num_meshes; ++i) {
+ /* Get the mesh file path */
+ size_t mesh_filepath_len = scene_dir_len + strlen(xml_mesh_filepaths[i]);
+ char* mesh_filepath = (char*)malloc(mesh_filepath_len);
+ mesh_filepath[0] = '\0';
+ strncat(mesh_filepath, scene_dir, scene_dir_len);
+ strncat(mesh_filepath + scene_dir_len, xml_mesh_filepaths[i], mesh_filepath_len - scene_dir_len);
+ /* Read the mesh */
+ scene->meshes[i] = readPly(mesh_filepath);
+ free(mesh_filepath);
+ /* Set the material index from the material name from xml */
+ scene->meshes[i].material_index = get_material_index(xml_mesh_materials[i]);
+ /* Set the material index and velocity from CSV if present */
+ for (uint32_t j = 0; j != csv_num_meshes; ++j)
+ if (strcmp(xml_mesh_names[i], csv_mesh_filenames[j]) == 0) {
+ scene->meshes[i].material_index = csv_material_indicies[j];
+ scene->meshes[i].velocity[0] = csv_velocity[j * 3];
+ scene->meshes[i].velocity[1] = csv_velocity[j * 3 + 1];
+ scene->meshes[i].velocity[2] = csv_velocity[j * 3 + 2];
break;
}
-
- ++mesh_idx;
- free(ply_path);
}
- // Cleanup
- closedir(dir);
- free(dir_path);
+ free(scene_dir);
}
@@ -428,10 +479,8 @@ int main(int argc, char *argv[]) {
}
FILE *fp = fopen("scene.hrt", "wb");
- if (fp == NULL) {
- perror("Error: cannot open file");
- return 1;
- }
+ if (!fp)
+ PERROR_CLEANUP_EXIT("Error: cannot open file", 8);
/* MAGIC */
fwrite("HRT", 1, 3, fp);
@@ -450,6 +499,5 @@ int main(int argc, char *argv[]) {
}
fclose(fp);
-
return 0;
}