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