test_s3d_scene.c (13231B)
1 /* Copyright (C) 2015-2023, 2026 |Méso|Star> (contact@meso-star.com) 2 * 3 * This file is part of Star-3D. 4 * 5 * Star-3D is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * Star-3D is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with Star-3D. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include "s3d.h" 19 #include "test_s3d_utils.h" 20 #include "test_s3d_cbox.h" 21 22 #include <rsys/math.h> 23 24 static const float cube_verts[] = { 25 5.f, 5.f, 5.f, 26 6.f, 5.f, 5.f, 27 5.f, 6.f, 5.f, 28 6.f, 6.f, 5.f, 29 5.f, 5.f, 6.f, 30 6.f, 5.f, 6.f, 31 5.f, 6.f, 6.f, 32 6.f, 6.f, 6.f 33 }; 34 static const unsigned cube_nverts = sizeof(cube_verts) / (sizeof(float)*3); 35 36 /* Front faces are CW. The normals point into the cube */ 37 static const unsigned cube_ids[] = { 38 0, 2, 1, 1, 2, 3, /* Front */ 39 0, 4, 2, 2, 4, 6, /* Left */ 40 4, 5, 6, 6, 5, 7, /* Back */ 41 3, 7, 1, 1, 7, 5, /* Right */ 42 2, 6, 3, 3, 6, 7, /* Top */ 43 0, 1, 4, 4, 1, 5 /* Bottom */ 44 }; 45 static const unsigned cube_ntris = sizeof(cube_ids) / (sizeof(unsigned)*3); 46 47 static void 48 cube_get_ids(const unsigned itri, unsigned ids[3], void* data) 49 { 50 const unsigned id = itri * 3; 51 CHK(data == NULL); 52 CHK(ids != NULL); 53 CHK(itri < cube_ntris); 54 ids[0] = cube_ids[id + 0]; 55 ids[1] = cube_ids[id + 1]; 56 ids[2] = cube_ids[id + 2]; 57 } 58 59 static void 60 cube_get_pos(const unsigned ivert, float pos[3], void* data) 61 { 62 const unsigned i = ivert*3; 63 CHK(data == NULL); 64 CHK(pos != NULL); 65 CHK(ivert < cube_nverts); 66 pos[0] = cube_verts[i + 0]; 67 pos[1] = cube_verts[i + 1]; 68 pos[2] = cube_verts[i + 2]; 69 } 70 71 int 72 main(int argc, char** argv) 73 { 74 struct mem_allocator allocator; 75 struct s3d_primitive prims[10]; 76 struct s3d_device* dev, *dev2; 77 struct s3d_scene* scn; 78 struct s3d_scene* scn2; 79 struct s3d_scene* scn3; 80 struct s3d_scene_view* scnview; 81 struct s3d_scene_view* scnview2; 82 struct s3d_scene_view* scnview3; 83 struct s3d_vertex_data attribs; 84 struct s3d_shape* shapes[4]; 85 const size_t nshapes = sizeof(shapes)/sizeof(struct s3d_shape*); 86 void* data = (void*)&cbox_walls_desc; 87 size_t i, n; 88 size_t nprims; 89 float area, volume, lower[3], upper[3]; 90 unsigned id; 91 int mask; 92 (void)argc, (void)argv; 93 94 mem_init_proxy_allocator(&allocator, &mem_default_allocator); 95 96 CHK(s3d_device_create(NULL, &allocator, 1, &dev) == RES_OK); 97 FOR_EACH(i, 0, nshapes) 98 CHK(s3d_shape_create_mesh(dev, shapes + i) == RES_OK); 99 100 CHK(s3d_scene_create(NULL, NULL) == RES_BAD_ARG); 101 CHK(s3d_scene_create(dev, NULL) == RES_BAD_ARG); 102 CHK(s3d_scene_create(NULL, &scn) == RES_BAD_ARG); 103 CHK(s3d_scene_create(dev, &scn) == RES_OK); 104 CHK(s3d_scene_create(dev, &scn2) == RES_OK); 105 CHK(s3d_scene_create(dev, &scn3) == RES_OK); 106 107 CHK(s3d_scene_get_shapes_count(NULL, NULL) == RES_BAD_ARG); 108 CHK(s3d_scene_get_shapes_count(scn, NULL) == RES_BAD_ARG); 109 CHK(s3d_scene_get_shapes_count(NULL, &n) == RES_BAD_ARG); 110 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 111 CHK(n == 0); 112 113 CHK(s3d_scene_attach_shape(NULL, NULL) == RES_BAD_ARG); 114 CHK(s3d_scene_attach_shape(scn, NULL) == RES_BAD_ARG); 115 CHK(s3d_scene_attach_shape(NULL, shapes[0]) == RES_BAD_ARG); 116 CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK); 117 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 118 CHK(n == 1); 119 CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK); 120 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 121 CHK(n == 1); 122 123 CHK(s3d_scene_detach_shape(NULL, NULL) == RES_BAD_ARG); 124 CHK(s3d_scene_detach_shape(scn, NULL) == RES_BAD_ARG); 125 CHK(s3d_scene_detach_shape(NULL, shapes[0]) == RES_BAD_ARG); 126 CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK); 127 CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_BAD_ARG); 128 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 129 CHK(n == 0); 130 131 FOR_EACH(i, 1, nshapes) { 132 CHK(s3d_scene_attach_shape(scn, shapes[i]) == RES_OK); 133 CHK(s3d_shape_ref_put(shapes[i]) == RES_OK); 134 } 135 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 136 CHK(n == nshapes - 1); 137 138 CHK(s3d_scene_instantiate(NULL, NULL) == RES_BAD_ARG); 139 CHK(s3d_scene_instantiate(scn, NULL) == RES_BAD_ARG); 140 CHK(s3d_scene_instantiate(NULL, shapes + 1) == RES_BAD_ARG); 141 CHK(s3d_scene_instantiate(scn, shapes + 1) == RES_OK); 142 143 CHK(s3d_shape_get_id(NULL, NULL) == RES_BAD_ARG); 144 CHK(s3d_shape_get_id(shapes[1], NULL) == RES_BAD_ARG); 145 CHK(s3d_shape_get_id(NULL, &id) == RES_BAD_ARG); 146 CHK(s3d_shape_get_id(shapes[1], &id) == RES_OK); 147 CHK(id != S3D_INVALID_ID); 148 149 CHK(s3d_scene_clear(NULL) == RES_BAD_ARG); 150 CHK(s3d_scene_clear(scn) == RES_OK); 151 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 152 CHK(n == 0); 153 CHK(s3d_scene_clear(scn) == RES_OK); 154 CHK(s3d_scene_instantiate(scn, shapes + 2) == RES_OK); 155 CHK(s3d_scene_attach_shape(scn, shapes[2]) == RES_BAD_ARG); 156 157 CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK); 158 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 159 CHK(n == 1); 160 161 CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK); 162 CHK(s3d_scene_view_get_mask(scnview, &mask) == RES_OK); 163 CHK(mask == S3D_TRACE); 164 165 CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK); 166 CHK(s3d_scene_clear(scn) == RES_OK); 167 168 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 169 170 CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK); 171 CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK); 172 CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK); 173 CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK); 174 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 175 176 CHK(s3d_scene_attach_shape(scn2, shapes[1]) == RES_OK); 177 CHK(s3d_scene_attach_shape(scn2, shapes[2]) == RES_OK); 178 CHK(s3d_scene_attach_shape(scn3, shapes[1]) == RES_OK); 179 180 CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK); 181 CHK(n == 1); 182 CHK(s3d_scene_get_shapes_count(scn2, &n) == RES_OK); 183 CHK(n == 2); 184 CHK(s3d_scene_get_shapes_count(scn3, &n) == RES_OK); 185 CHK(n == 1); 186 187 CHK(s3d_scene_view_create(scn2, S3D_SAMPLE|S3D_TRACE, &scnview2) == RES_OK); 188 CHK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview) == RES_OK); 189 CHK(s3d_scene_view_create(scn3, S3D_SAMPLE, &scnview3) == RES_OK); 190 CHK(s3d_scene_view_ref_put(scnview3) == RES_OK); 191 192 CHK(s3d_scene_view_compute_area(NULL, NULL) == RES_BAD_ARG); 193 CHK(s3d_scene_view_compute_area(scnview2, NULL) == RES_BAD_ARG); 194 CHK(s3d_scene_view_compute_area(NULL, &area) == RES_BAD_ARG); 195 CHK(s3d_scene_view_compute_area(scnview2, &area) == RES_OK); 196 CHK(area == 0.f); 197 198 CHK(s3d_scene_view_compute_volume(NULL, NULL) == RES_BAD_ARG); 199 CHK(s3d_scene_view_compute_volume(scnview2, NULL) == RES_BAD_ARG); 200 CHK(s3d_scene_view_compute_volume(NULL, &volume) == RES_BAD_ARG); 201 CHK(s3d_scene_view_compute_volume(scnview2, &volume) == RES_OK); 202 CHK(volume == 0.f); 203 204 CHK(s3d_scene_view_primitives_count(NULL, NULL) == RES_BAD_ARG); 205 CHK(s3d_scene_view_primitives_count(scnview2, NULL) == RES_BAD_ARG); 206 CHK(s3d_scene_view_primitives_count(NULL, &nprims) == RES_BAD_ARG); 207 CHK(s3d_scene_view_primitives_count(scnview2, &nprims) == RES_OK); 208 CHK(nprims == 0); 209 210 CHK(s3d_scene_view_get_aabb(NULL, NULL, NULL) == RES_BAD_ARG); 211 CHK(s3d_scene_view_get_aabb(scnview2, NULL, NULL) == RES_BAD_ARG); 212 CHK(s3d_scene_view_get_aabb(NULL, lower, NULL) == RES_BAD_ARG); 213 CHK(s3d_scene_view_get_aabb(scnview2, lower, NULL) == RES_BAD_ARG); 214 CHK(s3d_scene_view_get_aabb(NULL, NULL, upper) == RES_BAD_ARG); 215 CHK(s3d_scene_view_get_aabb(scnview2, NULL, upper) == RES_BAD_ARG); 216 CHK(s3d_scene_view_get_aabb(NULL, lower, upper) == RES_BAD_ARG); 217 CHK(s3d_scene_view_get_aabb(scnview2, lower, upper) == RES_OK); 218 CHK(lower[0] > upper[0]); 219 CHK(lower[1] > upper[1]); 220 CHK(lower[2] > upper[2]); 221 222 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 223 CHK(s3d_scene_view_ref_put(scnview2) == RES_OK); 224 225 CHK(s3d_scene_instantiate(scn2, shapes + 3) == RES_OK); 226 CHK(s3d_scene_attach_shape(scn3, shapes[3]) == RES_OK); 227 CHK(s3d_scene_get_shapes_count(scn3, &n) == RES_OK); 228 CHK(n == 2); 229 CHK(s3d_scene_view_create(scn3, S3D_SAMPLE|S3D_TRACE, &scnview3) == RES_BAD_ARG); 230 231 CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK); 232 233 CHK(s3d_shape_ref_put(shapes[0]) == RES_OK); 234 CHK(s3d_shape_ref_put(shapes[1]) == RES_OK); 235 CHK(s3d_shape_ref_put(shapes[2]) == RES_OK); 236 CHK(s3d_shape_ref_put(shapes[3]) == RES_OK); 237 238 CHK(s3d_scene_ref_get(NULL) == RES_BAD_ARG); 239 CHK(s3d_scene_ref_get(scn) == RES_OK); 240 CHK(s3d_scene_ref_put(NULL) == RES_BAD_ARG); 241 CHK(s3d_scene_ref_put(scn) == RES_OK); 242 CHK(s3d_scene_ref_put(scn) == RES_OK); 243 CHK(s3d_scene_ref_put(scn2) == RES_OK); 244 CHK(s3d_scene_ref_put(scn3) == RES_OK); 245 246 CHK(s3d_scene_create(dev, &scn) == RES_OK); 247 CHK(s3d_scene_create(dev, &scn2) == RES_OK); 248 249 attribs.type = S3D_FLOAT3; 250 attribs.usage = S3D_POSITION; 251 attribs.get = cbox_get_position; 252 CHK(s3d_shape_create_mesh(dev, shapes + 0) == RES_OK); 253 CHK(s3d_mesh_setup_indexed_vertices(shapes[0], cbox_walls_ntris, 254 cbox_get_ids, cbox_walls_nverts, &attribs, 1, data) == RES_OK); 255 CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK); 256 257 CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK); 258 CHK(s3d_scene_view_compute_area(scnview, &area) == RES_OK); 259 CHK(eq_epsf(area, 1532296.f, 1.e-6f) == 1); 260 CHK(s3d_scene_view_primitives_count(scnview, &nprims) == RES_OK); 261 CHK(nprims == 10); 262 CHK(s3d_scene_view_get_aabb(scnview, lower, upper) == RES_OK); 263 CHK(eq_epsf(lower[0], 0.f, 1.e-6f) == 1); 264 CHK(eq_epsf(lower[1], 0.f, 1.e-6f) == 1); 265 CHK(eq_epsf(lower[2], 0.f, 1.e-6f) == 1); 266 CHK(eq_epsf(upper[0], 552.f, 1.e-6f) == 1); 267 CHK(eq_epsf(upper[1], 559.f, 1.e-6f) == 1); 268 CHK(eq_epsf(upper[2], 548.f, 1.e-6f) == 1); 269 270 CHK(s3d_scene_instantiate(scn, shapes + 1) == RES_OK); 271 CHK(s3d_scene_attach_shape(scn2, shapes[1]) == RES_OK); 272 273 CHK(s3d_scene_view_create(scn2, S3D_GET_PRIMITIVE, &scnview2) == RES_OK); 274 CHK(s3d_scene_view_compute_area(scnview2, &area) == RES_OK); 275 CHK(eq_epsf(area, 1532296.f, 1.e-6f) == 1); 276 CHK(s3d_scene_view_primitives_count(scnview2, &nprims) == RES_OK); 277 CHK(nprims == 10); 278 CHK(s3d_scene_view_get_aabb(scnview2, lower, upper) == RES_OK); 279 CHK(eq_epsf(lower[0], 0.f, 1.e-6f) == 1); 280 CHK(eq_epsf(lower[1], 0.f, 1.e-6f) == 1); 281 CHK(eq_epsf(lower[2], 0.f, 1.e-6f) == 1); 282 CHK(eq_epsf(upper[0], 552.f, 1.e-6f) == 1); 283 CHK(eq_epsf(upper[1], 559.f, 1.e-6f) == 1); 284 CHK(eq_epsf(upper[2], 548.f, 1.e-6f) == 1); 285 286 CHK(s3d_scene_view_compute_area(scnview, &area) == RES_OK); 287 CHK(eq_epsf(area, 1532296.f, 1.e-6f) == 1); 288 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 289 290 CHK(s3d_scene_view_get_primitive(NULL, 11, NULL) == RES_BAD_ARG); 291 CHK(s3d_scene_view_get_primitive(scnview2, 11, NULL) == RES_BAD_ARG); 292 CHK(s3d_scene_view_get_primitive(NULL, 0, NULL) == RES_BAD_ARG); 293 CHK(s3d_scene_view_get_primitive(scnview2, 0, NULL) == RES_BAD_ARG); 294 CHK(s3d_scene_view_get_primitive(NULL, 11, prims + 0) == RES_BAD_ARG); 295 CHK(s3d_scene_view_get_primitive(scnview2, 11, prims + 0) == RES_BAD_ARG); 296 CHK(s3d_scene_view_get_primitive(NULL, 0, prims + 0) == RES_BAD_ARG); 297 298 FOR_EACH(i, 0, nprims) { 299 size_t j; 300 CHK(s3d_scene_view_get_primitive(scnview2, (unsigned)i, prims + i) == RES_OK); 301 CHK(S3D_PRIMITIVE_EQ(prims + i, &S3D_PRIMITIVE_NULL) == 0); 302 CHK(prims[i].scene_prim_id == i); 303 FOR_EACH(j, 0, i) 304 CHK(S3D_PRIMITIVE_EQ(prims + i, prims + j) == 0); 305 } 306 CHK(s3d_scene_view_ref_put(scnview2) == RES_OK); 307 308 attribs.type = S3D_FLOAT3; 309 attribs.usage = S3D_POSITION; 310 attribs.get = cube_get_pos; 311 CHK(s3d_mesh_setup_indexed_vertices 312 (shapes[0], cube_ntris, cube_get_ids, cube_nverts, &attribs, 1, NULL) == RES_OK); 313 314 CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK); 315 CHK(s3d_scene_view_compute_area(scnview, &area) == RES_OK); 316 CHK(eq_epsf(area, 6.f, 1.e-6f) == 1); 317 CHK(s3d_scene_view_compute_volume(scnview, &volume) == RES_OK); 318 CHK(eq_epsf(volume, 1.f, 1.e-6f) == 1); 319 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 320 321 CHK(s3d_shape_flip_surface(shapes[0]) == RES_OK); 322 CHK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview) == RES_OK); 323 CHK(s3d_scene_view_compute_volume(scnview, &volume) == RES_OK); 324 CHK(eq_epsf(volume, -1.f, 1.e-6f) == 1); 325 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 326 327 CHK(s3d_scene_get_device(NULL, NULL) == RES_BAD_ARG); 328 CHK(s3d_scene_get_device(scn, NULL) == RES_BAD_ARG); 329 CHK(s3d_scene_get_device(NULL, &dev2) == RES_BAD_ARG); 330 CHK(s3d_scene_get_device(scn, &dev2) == RES_OK); 331 CHK(dev2 == dev); 332 CHK(s3d_scene_get_device(scn2, &dev2) == RES_OK); 333 CHK(dev2 == dev); 334 335 CHK(s3d_scene_ref_put(scn) == RES_OK); 336 CHK(s3d_scene_ref_put(scn2) == RES_OK); 337 CHK(s3d_shape_ref_put(shapes[0]) == RES_OK); 338 CHK(s3d_shape_ref_put(shapes[1]) == RES_OK); 339 340 CHK(s3d_device_ref_put(dev) == RES_OK);; 341 342 check_memory_allocator(&allocator); 343 mem_shutdown_proxy_allocator(&allocator); 344 CHK(mem_allocated_size() == 0); 345 return 0; 346 } 347