test_s3d_accel_struct_conf.c (7776B)
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 21 #include <rsys/clock_time.h> 22 #include <rsys/math.h> 23 #include <string.h> 24 25 /******************************************************************************* 26 * Mesh functions and data structure 27 ******************************************************************************/ 28 struct mesh { 29 double* pos; 30 size_t* ids; 31 size_t nverts; 32 size_t ntris; 33 struct mem_allocator* allocator; 34 }; 35 36 static void 37 mesh_init_sphere 38 (struct mesh* sphere, 39 struct mem_allocator* allocator, 40 const size_t nthetas) 41 { 42 const size_t nphis = (size_t)(((double)nthetas + 0.5) * 0.5); 43 const double step_theta = 2*PI / (double)nthetas; 44 const double step_phi = PI / (double)nphis; 45 size_t itheta, iphi; 46 size_t i; 47 48 CHK(sphere && allocator && nthetas); 49 memset(sphere, 0, sizeof(*sphere)); 50 51 sphere->nverts = nthetas * (nphis-1)/*#contour verts*/ + 2 /*polar verts*/; 52 sphere->ntris = 2*nthetas * (nphis-2)/*#contour tris*/ + 2*nthetas/*#polar tris*/; 53 sphere->allocator = allocator; 54 55 sphere->pos = MEM_CALLOC(allocator, sphere->nverts, sizeof(double[3])); 56 CHK(sphere->pos); 57 sphere->ids = MEM_CALLOC(allocator, sphere->ntris, sizeof(size_t[3])); 58 CHK(sphere->ids); 59 60 /* Build the contour vertices */ 61 i = 0; 62 FOR_EACH(itheta, 0, nthetas) { 63 const double theta = -PI + (double)itheta * step_theta; 64 const double cos_theta = cos(theta); 65 const double sin_theta = sin(theta); 66 FOR_EACH(iphi, 0, nphis-1) { 67 const double phi = -PI*0.5 + (double)(iphi + 1) * step_phi; 68 const double cos_phi = cos(phi); 69 const double sin_phi = sin(phi); 70 sphere->pos[i++] = cos_phi * cos_theta; 71 sphere->pos[i++] = cos_phi * sin_theta; 72 sphere->pos[i++] = sin_phi; 73 } 74 } 75 /* polar vertices */ 76 sphere->pos[i++] = 0.0; sphere->pos[i++] = 0.0; sphere->pos[i++] =-1.0; 77 sphere->pos[i++] = 0.0; sphere->pos[i++] = 0.0; sphere->pos[i++] = 1.0; 78 CHK(i == sphere->nverts*3); 79 80 /* Define the indices of the contour primitives */ 81 i = 0; 82 FOR_EACH(itheta, 0, nthetas) { 83 const size_t itheta0 = itheta * (nphis - 1); 84 const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1); 85 FOR_EACH(iphi, 0, nphis-2) { 86 const size_t iphi0 = iphi + 0; 87 const size_t iphi1 = iphi + 1; 88 sphere->ids[i++] = itheta0 + iphi0; /* First triangle */ 89 sphere->ids[i++] = itheta0 + iphi1; 90 sphere->ids[i++] = itheta1 + iphi0; 91 sphere->ids[i++] = itheta1 + iphi0; /* Second triangle */ 92 sphere->ids[i++] = itheta0 + iphi1; 93 sphere->ids[i++] = itheta1 + iphi1; 94 } 95 } 96 /* Define the indices of the polar primitives */ 97 FOR_EACH(itheta, 0, nthetas) { 98 const size_t itheta0 = itheta * (nphis - 1); 99 const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1); 100 sphere->ids[i++] = nthetas * (nphis - 1); 101 sphere->ids[i++] = itheta0; 102 sphere->ids[i++] = itheta1; 103 sphere->ids[i++] = nthetas * (nphis - 1) + 1; 104 sphere->ids[i++] = itheta1 + (nphis - 2); 105 sphere->ids[i++] = itheta0 + (nphis - 2); 106 } 107 CHK(i == sphere->ntris*3); 108 } 109 110 static void 111 mesh_release(struct mesh* mesh) 112 { 113 CHK(mesh); 114 MEM_RM(mesh->allocator, mesh->pos); 115 MEM_RM(mesh->allocator, mesh->ids); 116 } 117 118 static INLINE void 119 mesh_dump(const struct mesh* mesh, FILE* stream) 120 { 121 size_t i; 122 CHK(mesh && stream); 123 FOR_EACH(i, 0, mesh->nverts) { 124 fprintf(stream, "v %g %g %g\n", 125 mesh->pos[i*3+0], 126 mesh->pos[i*3+1], 127 mesh->pos[i*3+2]); 128 } 129 FOR_EACH(i, 0, mesh->ntris) { 130 fprintf(stream, "f %lu %lu %lu\n", 131 (unsigned long)mesh->ids[i*3+0]+1, 132 (unsigned long)mesh->ids[i*3+1]+1, 133 (unsigned long)mesh->ids[i*3+2]+1); 134 } 135 } 136 137 static void 138 mesh_get_pos(const unsigned ivert, float pos[3], void* ctx) 139 { 140 const struct mesh* mesh = ctx; 141 CHK(pos && ctx && ivert < mesh->nverts); 142 pos[0] = (float)mesh->pos[ivert*3+0]; 143 pos[1] = (float)mesh->pos[ivert*3+1]; 144 pos[2] = (float)mesh->pos[ivert*3+2]; 145 } 146 147 static void 148 mesh_get_tri(const unsigned itri, unsigned ids[3], void* ctx) 149 { 150 const struct mesh* mesh = ctx; 151 CHK(ids && ctx && itri < mesh->ntris); 152 ids[0] = (unsigned)mesh->ids[itri*3+0]; 153 ids[1] = (unsigned)mesh->ids[itri*3+1]; 154 ids[2] = (unsigned)mesh->ids[itri*3+2]; 155 } 156 157 /******************************************************************************* 158 * Helper functions 159 ******************************************************************************/ 160 static void 161 time_scene_view_creation 162 (struct s3d_scene* scn, 163 const struct s3d_accel_struct_conf* cfg, 164 const char* string) 165 { 166 char dump[128]; 167 struct time t0, t1; 168 struct s3d_scene_view* view; 169 CHK(scn); 170 171 time_current(&t0); 172 CHK(s3d_scene_view_create2(scn, S3D_TRACE, cfg, &view) == RES_OK); 173 time_sub(&t0, time_current(&t1), &t0); 174 time_dump(&t0, TIME_ALL, NULL, dump, sizeof(dump)); 175 printf("%s: %s\n", string, dump); 176 CHK(s3d_scene_view_ref_put(view) == RES_OK); 177 } 178 179 /******************************************************************************* 180 * Main test function 181 ******************************************************************************/ 182 int 183 main(int argc, char** argv) 184 { 185 struct mem_allocator allocator; 186 struct mesh sphere; 187 struct s3d_device* dev; 188 struct s3d_shape* shape; 189 struct s3d_scene* scn; 190 struct s3d_scene_view* view; 191 struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL; 192 struct s3d_accel_struct_conf cfg = S3D_ACCEL_STRUCT_CONF_DEFAULT; 193 (void)argc, (void)argv; 194 195 mem_init_proxy_allocator(&allocator, &mem_default_allocator); 196 197 mesh_init_sphere(&sphere, &allocator, 256); 198 /*mesh_dump(&sphere, stdout);*/ 199 200 CHK(s3d_device_create(NULL, &allocator, 1, &dev) == RES_OK); 201 CHK(s3d_scene_create(dev, &scn) == RES_OK); 202 CHK(s3d_shape_create_mesh(dev, &shape) == RES_OK); 203 CHK(s3d_scene_attach_shape(scn, shape) == RES_OK); 204 205 vdata.usage = S3D_POSITION; 206 vdata.type = S3D_FLOAT3; 207 vdata.get = mesh_get_pos; 208 CHK(s3d_mesh_setup_indexed_vertices(shape, (unsigned)sphere.ntris, mesh_get_tri, 209 (unsigned)sphere.nverts, &vdata, 1, &sphere) == RES_OK); 210 211 CHK(s3d_scene_view_create2(NULL, S3D_TRACE, NULL, &view) == RES_BAD_ARG); 212 CHK(s3d_scene_view_create2(scn, S3D_TRACE, NULL, NULL) == RES_BAD_ARG); 213 214 time_scene_view_creation(scn, NULL, "All default"); 215 216 cfg.quality = S3D_ACCEL_STRUCT_QUALITY_LOW; 217 cfg.mask = S3D_ACCEL_STRUCT_FLAG_ROBUST | S3D_ACCEL_STRUCT_FLAG_DYNAMIC; 218 time_scene_view_creation(scn, &cfg, "Low quality, robust & dynamic"); 219 220 cfg.quality = S3D_ACCEL_STRUCT_QUALITY_MEDIUM; 221 cfg.mask = S3D_ACCEL_STRUCT_FLAG_COMPACT; 222 time_scene_view_creation(scn, &cfg, "Medium quality, compact"); 223 224 cfg.quality = S3D_ACCEL_STRUCT_QUALITY_HIGH; 225 cfg.mask = S3D_ACCEL_STRUCT_FLAG_ROBUST | S3D_ACCEL_STRUCT_FLAG_COMPACT; 226 time_scene_view_creation(scn, &cfg, "High quality, compact & robust"); 227 228 CHK(s3d_shape_ref_put(shape) == RES_OK); 229 CHK(s3d_scene_ref_put(scn) == RES_OK); 230 CHK(s3d_device_ref_put(dev) == RES_OK); 231 232 mesh_release(&sphere); 233 234 check_memory_allocator(&allocator); 235 mem_shutdown_proxy_allocator(&allocator); 236 CHK(mem_allocated_size() == 0); 237 return 0; 238 } 239