test_senc3d_utils.h (8328B)
1 /* Copyright (C) 2018-2020, 2023, 2024 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef TEST_UTILS_H 17 #define TEST_UTILS_H 18 19 #include <rsys/rsys.h> 20 #include <rsys/mem_allocator.h> 21 #include <rsys/double3.h> 22 23 #include <stdio.h> 24 25 #include <star/senc3d.h> 26 27 #define OK(Expr) CHK((Expr) == RES_OK) 28 #define BA(Expr) CHK((Expr) == RES_BAD_ARG) 29 #define BO(Expr) CHK((Expr) == RES_BAD_OP) 30 31 /****************************************************************************** 32 * Geometry 33 *****************************************************************************/ 34 /* Distorded cube */ 35 static const double box_vertices[8/*#vertices*/*3/*#coords per vertex*/] = { 36 0.1, 0.0, 0.0, 37 1.0, 0.0, 0.0, 38 0.0, 1.0, 0.0, 39 1.0, 1.0, 0.0, 40 0.0, 0.0, 1.1, 41 1.0, 0.0, 1.0, 42 0.0, 1.0, 1.0, 43 1.0, 1.1, 1.0 44 }; 45 /* Need a true cube for some tests */ 46 static const double cube_vertices[8/*#vertices*/ * 3/*#coords per vertex*/] = { 47 0.0, 0.0, 0.0, 48 1.0, 0.0, 0.0, 49 0.0, 1.0, 0.0, 50 1.0, 1.0, 0.0, 51 0.0, 0.0, 1.0, 52 1.0, 0.0, 1.0, 53 0.0, 1.0, 1.0, 54 1.0, 1.0, 1.0 55 }; 56 static const unsigned nvertices = sizeof(box_vertices) / (3*sizeof(double)); 57 STATIC_ASSERT(sizeof(box_vertices) == sizeof(cube_vertices), 58 The_2_geometries_must_have_the_same_number_of_vertices); 59 60 /* The following array lists the indices toward the 3D vertices of each 61 * triangle. 62 * ,2---,3 ,2----3 63 * ,' | ,'/| ,'/| \ | 64 * 6----7' / | 6' / | \ | Y 65 * |', | / ,1 | / ,0---,1 | 66 * | ',|/,' |/,' | ,' o--X 67 * 4----5' 4----5' / 68 * Front, right Back, left and Z 69 * and Top faces bottom faces */ 70 static const unsigned 71 box_indices[12/*#triangles*/*3/*#indices per triangle*/] = { 72 0, 2, 1, 1, 2, 3, /* Front face */ 73 0, 4, 2, 2, 4, 6, /* Left face*/ 74 4, 5, 6, 6, 5, 7, /* Back face */ 75 3, 7, 1, 1, 7, 5, /* Right face */ 76 2, 6, 3, 3, 6, 7, /* Top face */ 77 0, 1, 4, 4, 1, 5 /* Bottom face */ 78 }; 79 static const unsigned 80 ntriangles = sizeof(box_indices) / (3 * sizeof(*box_indices)); 81 82 struct context { 83 const double* positions; 84 const unsigned* indices; 85 const unsigned* front_media; 86 const unsigned* back_media; 87 const unsigned* properties; 88 void* custom; 89 double offset[3]; 90 double scale; 91 char reverse_vrtx, reverse_med; 92 }; 93 #define CONTEXT_NULL__ {\ 94 NULL, NULL, NULL, NULL, NULL, NULL, {0,0,0}, 1, 0, 0\ 95 } 96 97 static const unsigned medium0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 98 static const unsigned medium1[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 99 static const unsigned medium2[12] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; 100 static const unsigned medium1_3[12] = { 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 }; 101 static const unsigned medium1_back0[12] = { 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }; 102 static const unsigned medium1_front0[12] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 103 104 static INLINE void 105 get_indices(const unsigned itri, unsigned ids[3], void* context) 106 { 107 const struct context* ctx = context; 108 ASSERT(ids && ctx); 109 ids[0] = ctx->indices[itri * 3 + 0]; 110 ids[ctx->reverse_vrtx ? 2 : 1] = ctx->indices[itri * 3 + 1]; 111 ids[ctx->reverse_vrtx ? 1 : 2] = ctx->indices[itri * 3 + 2]; 112 } 113 114 static INLINE void 115 get_position(const unsigned ivert, double pos[3], void* context) 116 { 117 const struct context* ctx = context; 118 ASSERT(pos && ctx && ctx->scale != 0); 119 pos[0] = ctx->positions[ivert * 3 + 0] * ctx->scale + ctx->offset[0]; 120 pos[1] = ctx->positions[ivert * 3 + 1] * ctx->scale + ctx->offset[1]; 121 pos[2] = ctx->positions[ivert * 3 + 2] * ctx->scale + ctx->offset[2]; 122 } 123 124 static INLINE void 125 get_media(const unsigned itri, unsigned medium[2], void* context) 126 { 127 const struct context* ctx = context; 128 ASSERT(medium && ctx); 129 medium[ctx->reverse_med ? 1 : 0] = ctx->front_media[itri]; 130 medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[itri]; 131 } 132 133 static INLINE void 134 get_media_from_properties(const unsigned itri, unsigned medium[2], void* context) 135 { 136 const struct context* ctx = context; 137 ASSERT(medium && ctx); 138 medium[ctx->reverse_med ? 1 : 0] = ctx->properties[3 * itri + 0]; 139 medium[ctx->reverse_med ? 0 : 1] = ctx->properties[3 * itri + 1]; 140 } 141 142 /****************************************************************************** 143 * Miscellaneous 144 *****************************************************************************/ 145 static INLINE void 146 dump_global 147 (struct senc3d_scene* scn, 148 const char* name) 149 { 150 FILE* stream; 151 unsigned triangles_count, vertices_count, i; 152 153 ASSERT(scn && name); 154 155 OK(senc3d_scene_get_vertices_count(scn, &vertices_count)); 156 OK(senc3d_scene_get_triangles_count(scn, &triangles_count)); 157 158 stream = fopen(name, "w"); 159 CHK(stream); 160 FOR_EACH(i, 0, vertices_count) { 161 double tmp[3]; 162 OK(senc3d_scene_get_vertex(scn, i, tmp)); 163 fprintf(stream, "v %g %g %g\n", SPLIT3(tmp)); 164 } 165 FOR_EACH(i, 0, triangles_count) { 166 unsigned indices[3]; 167 OK(senc3d_scene_get_triangle(scn, i, indices)); 168 fprintf(stream, "f %u %u %u\n", 169 1 + indices[0], 1 + indices[1], 1 + indices[2]); 170 } 171 fclose(stream); 172 } 173 174 static INLINE void 175 dump_enclosure 176 (struct senc3d_scene* scn, 177 const unsigned enc, 178 const char* name) 179 { 180 struct senc3d_enclosure* enclosure; 181 struct senc3d_enclosure_header header; 182 FILE* stream; 183 unsigned count, i; 184 185 ASSERT(scn && name); 186 187 SENC3D(scene_get_enclosure_count(scn, &count)); 188 ASSERT(enc < count); 189 OK(senc3d_scene_get_enclosure(scn, enc, &enclosure)); 190 OK(senc3d_enclosure_get_header(enclosure, &header)); 191 192 stream = fopen(name, "w"); 193 CHK(stream); 194 FOR_EACH(i, 0, header.vertices_count) { 195 double tmp[3]; 196 OK(senc3d_enclosure_get_vertex(enclosure, i, tmp)); 197 fprintf(stream, "v %g %g %g\n", SPLIT3(tmp)); 198 } 199 FOR_EACH(i, 0, header.primitives_count) { 200 unsigned indices[3]; 201 OK(senc3d_enclosure_get_triangle(enclosure, i, indices)); 202 fprintf(stream, "f %u %u %u\n", 203 1+indices[0], 1+indices[1], 1+indices[2]); 204 } 205 OK(senc3d_enclosure_ref_put(enclosure)); 206 fclose(stream); 207 } 208 209 static INLINE void 210 check_memory_allocator(struct mem_allocator* allocator) 211 { 212 if(MEM_ALLOCATED_SIZE(allocator)) { 213 char dump[1024]; 214 MEM_DUMP(allocator, dump, sizeof(dump)); 215 fprintf(stderr, "%s\n", dump); 216 FATAL("Memory leaks.\n"); 217 } 218 } 219 220 /****************************************************************************** 221 * Check functions 222 *****************************************************************************/ 223 /* Compare the itri-th triangle of enclosure with a triangle described by trg2 & vertices2 */ 224 static INLINE void 225 cmp_trg 226 (const unsigned itri, 227 const struct senc3d_enclosure* enclosure, 228 const unsigned trg2[3], 229 const double* vertices2, 230 int* trg_eq, 231 int* trg_reversed) 232 { 233 unsigned trg1[3]; 234 double t1[3][3]; 235 double t2[3][3]; 236 unsigned trg1_eq[3] = { 3, 3, 3 }; 237 unsigned i, j, fst_vrtx = 3; 238 239 ASSERT(enclosure && trg2 && vertices2 && trg_eq && trg_reversed); 240 241 OK(senc3d_enclosure_get_triangle(enclosure, itri, trg1)); 242 FOR_EACH(i, 0, 3) { 243 OK(senc3d_enclosure_get_vertex(enclosure, trg1[i], t1[i])); 244 d3_set(t2[i], vertices2 + (3 * trg2[i])); 245 } 246 FOR_EACH(i, 0, 3) { 247 FOR_EACH(j, 0, 3) { 248 if(d3_eq(t1[i], t2[j])) { 249 trg1_eq[i] = j; 250 if(i == 0) fst_vrtx = j; 251 break; 252 } 253 } 254 } 255 FOR_EACH(i, 0, 3) { 256 if(trg1_eq[i] == 3) { 257 *trg_eq = 0; 258 return; 259 } 260 if(trg1_eq[i] == trg1_eq[(i + 1) % 3] 261 || trg1_eq[i] == trg1_eq[(i + 2) % 3]) { 262 *trg_eq = 0; 263 return; 264 } 265 } 266 /* Same 3 vertices */ 267 ASSERT(fst_vrtx != 3); 268 *trg_eq = 1; 269 270 *trg_reversed = (trg1_eq[1] != (fst_vrtx + 1) % 3); 271 ASSERT(*trg_reversed != (trg1_eq[1] != (fst_vrtx + 2) % 3)); 272 } 273 274 #endif /* TEST_UTILS_H */