test_suniq.c (10436B)
1 /* Copyright (C) 2025 |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 Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #include "suniq.h" 17 18 #include <rsys/double3.h> 19 #include <rsys/mem_allocator.h> 20 21 /* Box lower limits in X, Y and Z */ 22 #define LX 0.0 23 #define LY 1.0 24 #define LZ 2.0 25 26 /* Box upper limits in X, Y and Z */ 27 #define UX 1.0 28 #define UY 5.1 29 #define UZ 10.314 30 31 /* List of box triangles */ 32 static const struct suniq_triangle box[] = { 33 {{{UX, UY, LZ}, {UX, LY, LZ}, {LX, LY, LZ}}}, 34 {{{UX, UY, LZ}, {LX, LY, LZ}, {LX, UY, LZ}}}, 35 {{{LX, UY, LZ}, {LX, LY, LZ}, {LX, LY, UZ}}}, 36 {{{LX, UY, LZ}, {LX, LY, UZ}, {LX, UY, UZ}}}, 37 {{{LX, UY, UZ}, {LX, LY, UZ}, {UX, UY, UZ}}}, 38 {{{UX, UY, UZ}, {LX, LY, UZ}, {UX, LY, UZ}}}, 39 {{{UX, LY, UZ}, {UX, LY, LZ}, {UX, UY, LZ}}}, 40 {{{UX, LY, UZ}, {UX, UY, LZ}, {UX, UY, UZ}}}, 41 {{{UX, UY, UZ}, {LX, UY, LZ}, {LX, UY, UZ}}}, 42 {{{UX, UY, UZ}, {UX, UY, LZ}, {LX, UY, LZ}}}, 43 {{{UX, LY, UZ}, {LX, LY, LZ}, {UX, LY, LZ}}}, 44 {{{UX, LY, UZ}, {LX, LY, UZ}, {LX, LY, LZ}}} 45 }; 46 static const size_t box_ntris = sizeof(box)/sizeof(struct suniq_triangle); 47 48 /******************************************************************************* 49 * Helper functions 50 ******************************************************************************/ 51 static void 52 check_creation(void) 53 { 54 struct mem_allocator allocator; 55 struct suniq* suniq = NULL; 56 57 /* Check creation API */ 58 CHK(suniq_create(NULL, NULL) == RES_BAD_ARG); 59 CHK(suniq_create(&allocator, NULL) == RES_BAD_ARG); 60 CHK(suniq_create(NULL/*optional*/, &suniq) == RES_OK); 61 62 /* Check ref count API */ 63 CHK(suniq_ref_get(NULL) == RES_BAD_ARG); 64 CHK(suniq_ref_get(suniq) == RES_OK); 65 CHK(suniq_ref_put(NULL) == RES_BAD_ARG); 66 CHK(suniq_ref_put(suniq) == RES_OK); 67 CHK(suniq_ref_put(suniq) == RES_OK); 68 69 CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); 70 71 /* Check the use of a user-defined allocator */ 72 CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); 73 CHK(suniq_create(&allocator, &suniq) == RES_OK); 74 CHK(MEM_ALLOCATED_SIZE(&allocator) > 0); 75 CHK(suniq_ref_put(suniq) == RES_OK); 76 CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); 77 78 mem_shutdown_proxy_allocator(&allocator); 79 } 80 81 static void 82 check_registration_1_triangle(void) 83 { 84 struct suniq_triangle tri = SUNIQ_TRIANGLE_NULL; 85 struct suniq* suniq = NULL; 86 size_t id = 0; 87 88 CHK(suniq_create(NULL, &suniq) == RES_OK); 89 90 /* Check triangle registration API */ 91 CHK(suniq_register_triangle(NULL, &box[0], &id) == RES_BAD_ARG); 92 CHK(suniq_register_triangle(suniq, NULL, &id) == RES_BAD_ARG); 93 CHK(suniq_register_triangle(suniq, &box[0], NULL/*optional*/) == RES_OK); 94 95 /* Register the same triangle again */ 96 CHK(suniq_register_triangle(suniq, &box[0], &id) == RES_OK); 97 CHK(id == 0); 98 99 /* Turn over the 1st triangle in the box and check that it is still registered 100 * as the 1st triangle */ 101 d3_set(tri.vertices[0], box[0].vertices[1]); 102 d3_set(tri.vertices[1], box[0].vertices[0]); 103 d3_set(tri.vertices[2], box[0].vertices[2]); 104 CHK(suniq_register_triangle(suniq, &tri, &id) == RES_OK); 105 CHK(id == 0); 106 107 /* Check triangle accessor API */ 108 CHK(suniq_get_triangle(NULL, id, &tri) == RES_BAD_ARG); 109 CHK(suniq_get_triangle(suniq, 1, &tri) == RES_BAD_ARG); 110 CHK(suniq_get_triangle(suniq, id, NULL) == RES_BAD_ARG); 111 CHK(suniq_get_triangle(suniq, id, &tri) == RES_OK); 112 113 /* Check that the 1st tri is saved as it was committed for the 1st time */ 114 CHK(d3_eq(tri.vertices[0], box[0].vertices[0])); 115 CHK(d3_eq(tri.vertices[1], box[0].vertices[1])); 116 CHK(d3_eq(tri.vertices[2], box[0].vertices[2])); 117 118 /* Check the clear API */ 119 CHK(suniq_clear(NULL) == RES_BAD_ARG); 120 CHK(suniq_clear(suniq) == RES_OK); 121 CHK(suniq_get_triangle(suniq, 0, &tri) == RES_BAD_ARG); /* No more triangle */ 122 123 /* Turn over the 1st triangle in the box and register it */ 124 d3_set(tri.vertices[0], box[0].vertices[1]); 125 d3_set(tri.vertices[1], box[0].vertices[0]); 126 d3_set(tri.vertices[2], box[0].vertices[2]); 127 CHK(suniq_register_triangle(suniq, &box[0], &id) == RES_OK); 128 CHK(id == 0); 129 130 CHK(suniq_ref_put(suniq) == RES_OK); 131 } 132 133 static void 134 check_registration_box(void) 135 { 136 struct suniq_triangle tri = SUNIQ_TRIANGLE_NULL; 137 struct suniq* suniq = NULL; 138 size_t id = 0; 139 size_t i = 0; 140 141 CHK(suniq_create(NULL, &suniq) == RES_OK); 142 143 /* Check the registration of the triangles in the box, where every 4th 144 * triangle is inverted */ 145 FOR_EACH(i, 0, box_ntris) { 146 147 if(i%4 != 0) { 148 CHK(suniq_register_triangle(suniq, &box[i], &id) == RES_OK); 149 } else { 150 d3_set(tri.vertices[0], box[i].vertices[2]); 151 d3_set(tri.vertices[1], box[i].vertices[1]); 152 d3_set(tri.vertices[2], box[i].vertices[0]); 153 CHK(suniq_register_triangle(suniq, &tri, &id) == RES_OK); 154 } 155 156 CHK(id == i); 157 } 158 159 /* Try to register all triangles again */ 160 FOR_EACH(i, 0, box_ntris) { 161 CHK(suniq_register_triangle(suniq, &box[i], &id) == RES_OK); 162 } 163 164 /* Check that triangles are saved as they were first registered */ 165 FOR_EACH(i, 0, box_ntris) { 166 CHK(suniq_get_triangle(suniq, i, &tri) == RES_OK); 167 168 if(i%4 != 0) { 169 CHK(d3_eq(tri.vertices[0], box[i].vertices[0])); 170 CHK(d3_eq(tri.vertices[1], box[i].vertices[1])); 171 CHK(d3_eq(tri.vertices[2], box[i].vertices[2])); 172 } else { 173 /* Every 4th triangle is inverted */ 174 CHK(d3_eq(tri.vertices[0], box[i].vertices[2])); 175 CHK(d3_eq(tri.vertices[1], box[i].vertices[1])); 176 CHK(d3_eq(tri.vertices[2], box[i].vertices[0])); 177 } 178 } 179 180 CHK(suniq_clear(suniq) == RES_OK); 181 182 /* Check that once cleared, everything is reset. So this time, all registered 183 * triangles are returned, except all 4 triangles. This is exactly the 184 * opposite of the previous situation */ 185 FOR_EACH(i, 0, box_ntris) { 186 if(i%4 == 0) { 187 CHK(suniq_register_triangle(suniq, &box[i], &id) == RES_OK); 188 189 CHK(suniq_get_triangle(suniq, i, &tri) == RES_OK); 190 CHK(d3_eq(tri.vertices[0], box[i].vertices[0])); 191 CHK(d3_eq(tri.vertices[1], box[i].vertices[1])); 192 CHK(d3_eq(tri.vertices[2], box[i].vertices[2])); 193 194 } else { 195 d3_set(tri.vertices[0], box[i].vertices[2]); 196 d3_set(tri.vertices[1], box[i].vertices[1]); 197 d3_set(tri.vertices[2], box[i].vertices[0]); 198 CHK(suniq_register_triangle(suniq, &tri, &id) == RES_OK); 199 200 CHK(suniq_get_triangle(suniq, i, &tri) == RES_OK); 201 CHK(d3_eq(tri.vertices[0], box[i].vertices[2])); 202 CHK(d3_eq(tri.vertices[1], box[i].vertices[1])); 203 CHK(d3_eq(tri.vertices[2], box[i].vertices[0])); 204 } 205 } 206 207 CHK(suniq_ref_put(suniq) == RES_OK); 208 } 209 210 static void 211 check_descriptor(void) 212 { 213 struct suniq_desc desc = SUNIQ_DESC_NULL; 214 struct suniq* suniq = NULL; 215 size_t idx[3] = {0,0,0}; 216 double vtx[3] = {0,0,0}; 217 size_t i = 0; 218 219 CHK(suniq_create(NULL, &suniq) == RES_OK); 220 221 FOR_EACH(i, 0, box_ntris) { 222 CHK(suniq_register_triangle(suniq, &box[i], NULL) == RES_OK); 223 } 224 225 /* Check descriptor API */ 226 CHK(suniq_get_desc(NULL, &desc) == RES_BAD_ARG); 227 CHK(suniq_get_desc(suniq, NULL) == RES_BAD_ARG); 228 CHK(suniq_get_desc(suniq, &desc) == RES_OK); 229 230 /* Check the number of triangles and vertices indicated by the descriptor. 231 * Note that the number of vertices cannot be known. It depends on how the 232 * indexed mesh is constructed by the library. In any case, it cannot be less 233 * than the number of vertices in the cube */ 234 CHK(desc.ntriangles == box_ntris); 235 CHK(desc.nvertices >= 8); 236 237 /* Check vertex API */ 238 CHK(suniq_desc_get_vertex(NULL, 0, vtx) == RES_BAD_ARG); 239 CHK(suniq_desc_get_vertex(&desc, desc.nvertices, vtx) == RES_BAD_ARG); 240 CHK(suniq_desc_get_vertex(&desc, 0, NULL) == RES_BAD_ARG); 241 CHK(suniq_desc_get_vertex(&desc, 0, vtx) == RES_OK); 242 243 /* Check triange indices API */ 244 CHK(suniq_desc_get_triangle_indices(NULL, 0, idx) == RES_BAD_ARG); 245 CHK(suniq_desc_get_triangle_indices(&desc, desc.ntriangles, idx) == RES_BAD_ARG); 246 CHK(suniq_desc_get_triangle_indices(&desc, 0, NULL) == RES_BAD_ARG); 247 CHK(suniq_desc_get_triangle_indices(&desc, 0, idx) == RES_OK); 248 249 /* Check descriptor data */ 250 FOR_EACH(i, 0, desc.ntriangles) { 251 const size_t* indices; 252 const double *vertex0, *vertex1, *vertex2; 253 254 indices = desc.indices + i*3/*#indices per triangle */; 255 vertex0 = desc.positions + indices[0] * 3/*#coords per vertex*/; 256 vertex1 = desc.positions + indices[1] * 3/*#coords per vertex*/; 257 vertex2 = desc.positions + indices[2] * 3/*#coords per vertex*/; 258 259 CHK(d3_eq(vertex0, box[i].vertices[0])); 260 CHK(d3_eq(vertex1, box[i].vertices[1])); 261 CHK(d3_eq(vertex2, box[i].vertices[2])); 262 263 CHK(suniq_desc_get_triangle_indices(&desc, i, idx) == RES_OK); 264 CHK(idx[0] == indices[0]); 265 CHK(idx[1] == indices[1]); 266 CHK(idx[2] == indices[2]); 267 268 CHK(suniq_desc_get_vertex(&desc, idx[0], vtx) == RES_OK); 269 CHK(d3_eq(vtx, box[i].vertices[0])); 270 CHK(suniq_desc_get_vertex(&desc, idx[1], vtx) == RES_OK); 271 CHK(d3_eq(vtx, box[i].vertices[1])); 272 CHK(suniq_desc_get_vertex(&desc, idx[2], vtx) == RES_OK); 273 CHK(d3_eq(vtx, box[i].vertices[2])); 274 } 275 276 CHK(suniq_clear(suniq) == RES_OK); 277 278 /* Check the descriptor once the registering is empty */ 279 CHK(suniq_get_desc(suniq, &desc) == RES_OK); 280 CHK(desc.nvertices == 0); 281 CHK(desc.ntriangles == 0); 282 283 /* Check that no more triangles/vertexes can be recovered */ 284 CHK(suniq_desc_get_triangle_indices(&desc, 0, idx) == RES_BAD_ARG); 285 CHK(suniq_desc_get_vertex(&desc, 0, vtx) == RES_BAD_ARG); 286 287 CHK(suniq_ref_put(suniq) == RES_OK); 288 } 289 290 /******************************************************************************* 291 * The test 292 ******************************************************************************/ 293 int 294 main(void) 295 { 296 check_creation(); 297 check_registration_1_triangle(); 298 check_registration_box(); 299 check_descriptor(); 300 301 CHK(mem_allocated_size() == 0); 302 return 0; 303 }