test_scpr_clip.c (8094B)
1 /* Copyright (C) 2016-2018, 2021-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 #define _POSIX_C_SOURCE 200112L 17 18 #include "scpr.h" 19 #include "test_scpr_utils.h" 20 21 #include <rsys/math.h> 22 #include <rsys/stretchy_array.h> 23 24 #include <memory.h> 25 26 static void 27 dump_obj(FILE* stream, const struct scpr_mesh* mesh) 28 { 29 size_t i, n; 30 31 CHK(stream != NULL); 32 CHK(mesh != NULL); 33 34 OK(scpr_mesh_get_vertices_count(mesh, &n)); 35 FOR_EACH(i, 0, n) { 36 double pos[2]; 37 OK(scpr_mesh_get_position(mesh, i, pos)); 38 fprintf(stream, "v %g %g 0\n", SPLIT2(pos)); 39 } 40 41 OK(scpr_mesh_get_triangles_count(mesh, &n)); 42 FOR_EACH(i, 0, n) { 43 size_t ids[3]; 44 OK(scpr_mesh_get_indices(mesh, i, ids)); 45 fprintf(stream, "f %lu %lu %lu\n", 46 (unsigned long)(ids[0] + 1), 47 (unsigned long)(ids[1] + 1), 48 (unsigned long)(ids[2] + 1)); 49 } 50 } 51 52 static void 53 test_triangle 54 (struct scpr_device* dev, 55 struct mem_allocator* allocator, 56 struct scpr_mesh* mesh) 57 { 58 const double triangle_pos1[] = { 0, 0, 0, 1, 1, 0 }; 59 double triangle_pos2[] = { 0, 0, 0, 1e20, 1e20, 0}; /* To be replaced */ 60 const size_t triangle_ids[] = { 0, 1, 2 }; 61 double** clip_pos; 62 double range[2]; 63 size_t nverts[] = { 3 }; 64 size_t ncomps = 1; 65 const double clip_pos0[] = { -1.0, 0.25, 1.0, 0.75, 1, 0.25 }; 66 struct scpr_polygon* poly; 67 struct polygon_context pctx; 68 struct mesh_context mctx; 69 size_t ntris; 70 71 /* Set out-of-range value in triangle_pos2 */ 72 SCPR(device_get_range(dev, range)); 73 triangle_pos2[3] = triangle_pos2[4] = range[1] + 1; 74 75 clip_pos = (double**)MEM_CALLOC(allocator, ncomps, sizeof(*clip_pos)); 76 *clip_pos = (double*)MEM_CALLOC(allocator, nverts[0], 2*sizeof(**clip_pos)); 77 memcpy(*clip_pos, clip_pos0, 2*nverts[0]*sizeof(**clip_pos)); 78 79 pctx.coords = clip_pos; 80 pctx.nverts = nverts; 81 pctx.ncomps = ncomps; 82 OK(scpr_polygon_create(dev, &poly)); 83 OK(scpr_polygon_setup_indexed_vertices(poly, ncomps, pget_nverts, pget_pos, &pctx)); 84 85 /* Check out-of-range */ 86 mctx.coords = triangle_pos2; 87 mctx.nverts = 3; 88 mctx.indices = triangle_ids; 89 mctx.ntris = 1; 90 BAD(scpr_mesh_setup_indexed_vertices 91 (mesh, mctx.ntris, mget_ids, 3, mget_pos, &mctx)); 92 93 mctx.coords = triangle_pos1; 94 OK(scpr_mesh_setup_indexed_vertices 95 (mesh, mctx.ntris, mget_ids, 3, mget_pos, &mctx)); 96 97 BAD(scpr_mesh_clip(NULL, SCPR_OPERATIONS_COUNT__, NULL)); 98 BAD(scpr_mesh_clip(mesh, SCPR_OPERATIONS_COUNT__, NULL)); 99 BAD(scpr_mesh_clip(NULL, SCPR_OPERATIONS_COUNT__, poly)); 100 BAD(scpr_mesh_clip(mesh, SCPR_OPERATIONS_COUNT__, poly)); 101 BAD(scpr_mesh_clip(NULL, SCPR_SUB, NULL)); 102 BAD(scpr_mesh_clip(mesh, SCPR_SUB, NULL)); 103 BAD(scpr_mesh_clip(NULL, SCPR_SUB, poly)); 104 OK(scpr_mesh_clip(mesh, SCPR_SUB, poly)); 105 106 /*dump_obj(stdout, mesh);*/ 107 108 OK(scpr_mesh_get_triangles_count(mesh, &ntris)); 109 CHK(ntris == 3); 110 111 MEM_RM(allocator, *clip_pos); 112 MEM_RM(allocator, clip_pos); 113 OK(scpr_polygon_ref_put(poly)); 114 } 115 116 static void 117 test_quad 118 (struct scpr_device* dev, 119 struct mem_allocator* allocator, 120 struct scpr_mesh* mesh) 121 { 122 const double quad_pos[] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 }; 123 const size_t quad_ids[] = { 0, 1, 3, 3, 1, 2 }; 124 double** clip_pos; 125 size_t nverts[] = { 4 }; 126 size_t ncomps = 1; 127 const double clip_pos0[] = { -0.25, 0.25, -0.25, 0.75, 1.25, 0.75, 1.25, 0.25 }; 128 struct scpr_polygon* poly; 129 struct polygon_context pctx; 130 struct mesh_context mctx; 131 132 clip_pos = (double**)MEM_CALLOC(allocator, ncomps, sizeof(*clip_pos)); 133 *clip_pos = (double*)MEM_CALLOC(allocator, nverts[0], 2*sizeof(**clip_pos)); 134 memcpy(*clip_pos, clip_pos0, 2*nverts[0]*sizeof(**clip_pos)); 135 136 pctx.coords = clip_pos; 137 pctx.nverts = nverts; 138 pctx.ncomps = ncomps; 139 OK(scpr_polygon_create(dev, &poly)); 140 OK(scpr_polygon_setup_indexed_vertices(poly, ncomps, pget_nverts, pget_pos, &pctx)); 141 142 mctx.coords = quad_pos; 143 mctx.nverts = sizeof(quad_pos)/(2*sizeof(double)); 144 mctx.indices = quad_ids; 145 mctx.ntris = sizeof(quad_ids)/(3*sizeof(size_t)); 146 OK(scpr_mesh_setup_indexed_vertices 147 (mesh, mctx.ntris, mget_ids, mctx.nverts, mget_pos, &mctx)); 148 149 OK(scpr_mesh_clip(mesh, SCPR_AND, poly)); 150 151 /*dump_obj(stdout, mesh);*/ 152 153 MEM_RM(allocator, *clip_pos); 154 MEM_RM(allocator, clip_pos); 155 OK(scpr_polygon_ref_put(poly)); 156 } 157 158 static void 159 test_disk 160 (struct scpr_device* dev, 161 struct mem_allocator* allocator, 162 struct scpr_mesh* mesh) 163 { 164 double** clip_pos; 165 size_t nverts[] = { 4 }; 166 size_t ncomps = 1; 167 const double clip_pos0[] 168 = { -1.75, -1.75, 1.75, -1.75, 1.75, 1.75, -1.75, 1.75 }; 169 const size_t ninternal_disks = 10; 170 const double radius = 2.5; 171 const double internal_disk_step = radius / (double)ninternal_disks; 172 const size_t nslices = 64; 173 struct scpr_polygon* poly; 174 struct polygon_context pctx; 175 struct mesh_context mctx; 176 double* pos = NULL; 177 size_t* ids = NULL; 178 size_t i, j; 179 180 clip_pos = (double**)MEM_CALLOC(allocator, ncomps, sizeof(*clip_pos)); 181 *clip_pos = (double*)MEM_CALLOC(allocator, nverts[0], 2*sizeof(**clip_pos)); 182 memcpy(*clip_pos, clip_pos0, 2*nverts[0]*sizeof(**clip_pos)); 183 184 FOR_EACH(i, 0, ninternal_disks) { 185 const double r = (double)(i+1)*internal_disk_step; 186 FOR_EACH(j, 0, nslices) { 187 const double theta = (double)j / (double)nslices * 2 * PI; 188 const double x = r * cos(theta); 189 const double y = r * sin(theta); 190 sa_push(pos, x); 191 sa_push(pos, y); 192 } 193 } 194 195 /* Center point */ 196 sa_push(pos, 0.0); 197 sa_push(pos, 0.0); 198 199 FOR_EACH(i, 0, ninternal_disks-1) { 200 const size_t offset = (i+1) * nslices; 201 FOR_EACH(j, 0, nslices) { 202 const size_t id0 = j + offset; 203 const size_t id1 = ((j + 1) % nslices) + offset; 204 const size_t id2 = id0 - nslices; 205 const size_t id3 = id1 - nslices; 206 207 sa_push(ids, id0); 208 sa_push(ids, id2); 209 sa_push(ids, id1); 210 211 sa_push(ids, id1); 212 sa_push(ids, id2); 213 sa_push(ids, id3); 214 } 215 } 216 217 /* Center triangles */ 218 FOR_EACH(j, 0, nslices) { 219 const size_t id0 = j; 220 const size_t id1 = (j + 1) % nslices; 221 const size_t id2 = sa_size(pos)/2 - 1; 222 223 sa_push(ids, id0); 224 sa_push(ids, id2); 225 sa_push(ids, id1); 226 } 227 228 pctx.coords = clip_pos; 229 pctx.nverts = nverts; 230 pctx.ncomps = ncomps; 231 OK(scpr_polygon_create(dev, &poly)); 232 OK(scpr_polygon_setup_indexed_vertices(poly, ncomps, pget_nverts, pget_pos, &pctx)); 233 234 mctx.coords = pos; 235 mctx.nverts = sa_size(pos)/2; 236 mctx.indices = ids; 237 mctx.ntris = sa_size(ids)/3; 238 OK(scpr_mesh_setup_indexed_vertices 239 (mesh, mctx.ntris, mget_ids, mctx.nverts, mget_pos, &mctx)); 240 241 OK(scpr_mesh_clip(mesh, SCPR_SUB, poly)); 242 243 dump_obj(stdout, mesh); 244 245 MEM_RM(allocator, *clip_pos); 246 MEM_RM(allocator, clip_pos); 247 sa_release(pos); 248 sa_release(ids); 249 OK(scpr_polygon_ref_put(poly)); 250 } 251 252 int 253 main(int argc, char** argv) 254 { 255 struct mem_allocator allocator; 256 struct scpr_device_create_args args = SCPR_DEVICE_CREATE_ARGS_DEFAULT; 257 struct scpr_device* dev; 258 struct scpr_mesh* mesh; 259 (void)argc, (void)argv; 260 261 mem_init_proxy_allocator(&allocator, &mem_default_allocator); 262 263 args.allocator = &allocator; 264 OK(scpr_device_create(&args, &dev)); 265 OK(scpr_mesh_create(dev, &mesh)); 266 267 test_triangle(dev, &allocator, mesh); 268 test_quad(dev, &allocator, mesh); 269 test_disk(dev, &allocator, mesh); 270 271 OK(scpr_mesh_ref_put(mesh)); 272 OK(scpr_device_ref_put(dev)); 273 274 check_memory_allocator(&allocator); 275 mem_shutdown_proxy_allocator(&allocator); 276 CHK(mem_allocated_size() == 0); 277 return 0; 278 } 279