test_s3d_primitive.c (11393B)
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_cbox.h" 20 #include "test_s3d_utils.h" 21 22 #include <rsys/float2.h> 23 #include <rsys/float3.h> 24 #include <rsys/math.h> 25 26 static const float plane_verts[] = { 27 0.f, 0.f, 0.f, 28 1.f, 0.f, 0.f, 29 1.f, 1.f, 0.f, 30 0.f, 1.f, 0.f 31 }; 32 static const unsigned plane_nverts = sizeof(plane_verts) / (sizeof(float)*3); 33 34 static const unsigned plane_ids[] = { 0, 1, 2, 2, 3, 0 }; 35 static const unsigned plane_ntris = sizeof(plane_ids) / (sizeof(unsigned)*3); 36 37 static void 38 plane_get_ids(const unsigned itri, unsigned ids[3], void* data) 39 { 40 const unsigned id = itri * 3; 41 (void)data; 42 CHK(ids != NULL); 43 CHK(itri < plane_ntris); 44 ids[0] = plane_ids[id + 0]; 45 ids[1] = plane_ids[id + 1]; 46 ids[2] = plane_ids[id + 2]; 47 } 48 49 static void 50 plane_get_pos(const unsigned ivert, float pos[3], void* data) 51 { 52 const unsigned i = ivert*3; 53 (void)data; 54 CHK(pos != NULL); 55 CHK(ivert < plane_nverts); 56 pos[0] = plane_verts[i + 0]; 57 pos[1] = plane_verts[i + 1]; 58 pos[2] = plane_verts[i + 2]; 59 } 60 61 static void 62 plane_get_uv(const unsigned ivert, float uv[2], void* data) 63 { 64 const unsigned i = ivert*3; 65 (void)data; 66 CHK(uv != NULL); 67 CHK(ivert < plane_nverts); 68 uv[0] = -plane_verts[i + 0]; 69 uv[1] = -plane_verts[i + 1]; 70 } 71 72 int 73 main(int argc, char** argv) 74 { 75 struct mem_allocator allocator; 76 struct s3d_device* dev; 77 struct s3d_scene* scn; 78 struct s3d_scene_view* scnview; 79 struct s3d_shape* walls; 80 struct s3d_shape* plane; 81 struct s3d_attrib attr; 82 struct s3d_primitive prim = S3D_PRIMITIVE_NULL; 83 struct s3d_vertex_data attribs[2]; 84 struct cbox_desc desc; 85 size_t nprims; 86 size_t i; 87 float transform[12]; 88 float vec[3]; 89 float uv[2]; 90 float area; 91 unsigned ntris, nverts; 92 unsigned walls_id; 93 char b; 94 (void)argc, (void)argv; 95 96 mem_init_proxy_allocator(&allocator, &mem_default_allocator); 97 98 CHK(s3d_device_create(NULL, &allocator, 1, &dev) == RES_OK); 99 CHK(s3d_scene_create(dev, &scn) == RES_OK); 100 CHK(s3d_shape_create_mesh(dev, &walls) == RES_OK); 101 CHK(s3d_shape_create_mesh(dev, &plane) == RES_OK); 102 CHK(s3d_shape_get_id(walls, &walls_id) == RES_OK); 103 CHK(s3d_scene_attach_shape(scn, walls) == RES_OK); 104 105 attribs[1].usage = S3D_ATTRIB_0; 106 attribs[1].type = S3D_FLOAT2; 107 attribs[1].get = plane_get_uv; 108 109 attribs[0].usage = S3D_POSITION; 110 attribs[0].type = S3D_FLOAT3; 111 attribs[0].get = cbox_get_position; 112 113 ntris = cbox_walls_ntris; 114 nverts = cbox_walls_nverts; 115 desc.vertices = cbox_walls; 116 desc.indices = cbox_walls_ids; 117 CHK(s3d_mesh_setup_indexed_vertices 118 (walls, ntris, cbox_get_ids, nverts, attribs, 1, &desc) == RES_OK); 119 120 attribs[0].get = plane_get_pos; 121 CHK(s3d_mesh_setup_indexed_vertices 122 (plane, plane_ntris, plane_get_ids, plane_nverts, attribs, 2, NULL) == RES_OK); 123 124 CHK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview) == RES_OK); 125 CHK(s3d_scene_view_sample(scnview, 0, 0, 0, &prim, uv) == RES_OK); 126 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 127 128 CHK(s3d_primitive_get_attrib(NULL, S3D_ATTRIBS_COUNT__, NULL, NULL) == RES_BAD_ARG); 129 CHK(s3d_primitive_get_attrib(&prim, S3D_ATTRIBS_COUNT__, NULL, NULL) == RES_BAD_ARG); 130 CHK(s3d_primitive_get_attrib(NULL, S3D_ATTRIBS_COUNT__, uv, NULL) == RES_BAD_ARG); 131 CHK(s3d_primitive_get_attrib(&prim, S3D_ATTRIBS_COUNT__, uv, NULL) == RES_BAD_ARG); 132 CHK(s3d_primitive_get_attrib(NULL, S3D_ATTRIBS_COUNT__, NULL, &attr) == RES_BAD_ARG); 133 CHK(s3d_primitive_get_attrib(&prim, S3D_ATTRIBS_COUNT__, NULL, &attr) == RES_BAD_ARG); 134 CHK(s3d_primitive_get_attrib(NULL, S3D_ATTRIBS_COUNT__, uv, &attr) == RES_BAD_ARG); 135 CHK(s3d_primitive_get_attrib(&prim, S3D_ATTRIBS_COUNT__, uv, &attr) == RES_BAD_ARG); 136 137 CHK(s3d_primitive_get_attrib(NULL, S3D_POSITION, NULL, NULL) == RES_BAD_ARG); 138 CHK(s3d_primitive_get_attrib(&prim, S3D_POSITION, NULL, NULL) == RES_BAD_ARG); 139 CHK(s3d_primitive_get_attrib(NULL, S3D_POSITION, uv, NULL) == RES_BAD_ARG); 140 CHK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, NULL) == RES_BAD_ARG); 141 CHK(s3d_primitive_get_attrib(NULL, S3D_POSITION, NULL, &attr) == RES_BAD_ARG); 142 CHK(s3d_primitive_get_attrib(&prim, S3D_POSITION, NULL, &attr) == RES_BAD_ARG); 143 CHK(s3d_primitive_get_attrib(NULL, S3D_POSITION, uv, &attr) == RES_BAD_ARG); 144 CHK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr) == RES_OK); 145 CHK(attr.type == S3D_FLOAT3); 146 CHK(attr.usage == S3D_POSITION); 147 CHK(s3d_primitive_get_attrib(&prim, S3D_GEOMETRY_NORMAL, uv, &attr) == RES_OK); 148 CHK(attr.type == S3D_FLOAT3); 149 CHK(attr.usage == S3D_GEOMETRY_NORMAL); 150 CHK(s3d_primitive_get_attrib(&prim, S3D_ATTRIB_0, uv, &attr) == RES_BAD_ARG); 151 CHK(s3d_primitive_get_attrib(&S3D_PRIMITIVE_NULL, S3D_POSITION, uv, &attr) == RES_BAD_ARG); 152 153 CHK(s3d_primitive_has_attrib(NULL, S3D_ATTRIBS_COUNT__, NULL) == RES_BAD_ARG); 154 CHK(s3d_primitive_has_attrib(&prim, S3D_ATTRIBS_COUNT__, NULL) == RES_BAD_ARG); 155 CHK(s3d_primitive_has_attrib(NULL, S3D_POSITION, NULL) == RES_BAD_ARG); 156 CHK(s3d_primitive_has_attrib(&prim, S3D_POSITION, NULL) == RES_BAD_ARG); 157 CHK(s3d_primitive_has_attrib(NULL, S3D_ATTRIBS_COUNT__, &b) == RES_BAD_ARG); 158 CHK(s3d_primitive_has_attrib(&prim, S3D_ATTRIBS_COUNT__, &b) == RES_BAD_ARG); 159 CHK(s3d_primitive_has_attrib(NULL, S3D_POSITION, &b) == RES_BAD_ARG); 160 CHK(s3d_primitive_has_attrib(&prim, S3D_POSITION, &b) == RES_OK); 161 CHK(b == 1); 162 CHK(s3d_primitive_has_attrib(&prim, S3D_GEOMETRY_NORMAL, &b) == RES_OK); 163 CHK(b == 1); 164 CHK(s3d_primitive_has_attrib(&prim, S3D_ATTRIB_0, &b) == RES_OK); 165 CHK(b == 0); 166 167 CHK(s3d_primitive_get_transform(NULL, NULL) == RES_BAD_ARG); 168 CHK(s3d_primitive_get_transform(&prim, NULL) == RES_BAD_ARG); 169 CHK(s3d_primitive_get_transform(NULL, transform) == RES_BAD_ARG); 170 CHK(s3d_primitive_get_transform(&prim, transform) == RES_OK); 171 CHK(f3_eq(transform + 0, f3(vec, 1.f, 0.f, 0.f)) == 1); 172 CHK(f3_eq(transform + 3, f3(vec, 0.f, 1.f, 0.f)) == 1); 173 CHK(f3_eq(transform + 6, f3(vec, 0.f, 0.f, 1.f)) == 1); 174 CHK(f3_eq(transform + 9, f3(vec, 0.f, 0.f, 0.f)) == 1); 175 176 CHK(s3d_scene_clear(scn) == RES_OK); 177 CHK(s3d_scene_attach_shape(scn, plane) == RES_OK); 178 179 CHK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview) == RES_OK); 180 CHK(s3d_scene_view_primitives_count(scnview, &nprims) == RES_OK); 181 CHK(nprims == 2); 182 CHK(s3d_scene_view_get_primitive(scnview, 0, &prim) == RES_OK); 183 CHK(S3D_PRIMITIVE_EQ(&prim, &S3D_PRIMITIVE_NULL) == 0); 184 CHK(s3d_scene_view_ref_put(scnview) == RES_OK); 185 186 CHK(s3d_primitive_has_attrib(&prim, S3D_ATTRIB_0, &b) == RES_OK); 187 CHK(b == 1); 188 CHK(s3d_primitive_has_attrib(&prim, S3D_ATTRIB_1, &b) == RES_OK); 189 CHK(b == 0); 190 191 CHK(s3d_primitive_compute_area(NULL, NULL) == RES_BAD_ARG); 192 CHK(s3d_primitive_compute_area(&prim, NULL) == RES_BAD_ARG); 193 CHK(s3d_primitive_compute_area(NULL, &area) == RES_BAD_ARG); 194 CHK(s3d_primitive_compute_area(&prim, &area) == RES_OK); 195 CHK(eq_epsf(area, 0.5f, 1.e-6f) == 1); 196 197 CHK(s3d_primitive_sample(NULL, 1.f, 1.f, NULL) == RES_BAD_ARG); 198 CHK(s3d_primitive_sample(&prim, 1.f, 1.f, NULL) == RES_BAD_ARG); 199 CHK(s3d_primitive_sample(NULL, 0.f, 1.f, NULL) == RES_BAD_ARG); 200 CHK(s3d_primitive_sample(&prim, 0.f, 1.f, NULL) == RES_BAD_ARG); 201 CHK(s3d_primitive_sample(NULL, 1.f, 0.f, NULL) == RES_BAD_ARG); 202 CHK(s3d_primitive_sample(&prim, 1.f, 0.f, NULL) == RES_BAD_ARG); 203 CHK(s3d_primitive_sample(NULL, 0.f, 0.f, NULL) == RES_BAD_ARG); 204 CHK(s3d_primitive_sample(&prim, 0.f, 0.f, NULL) == RES_BAD_ARG); 205 CHK(s3d_primitive_sample(NULL, 1.f, 1.f, uv) == RES_BAD_ARG); 206 CHK(s3d_primitive_sample(&prim, 1.f, 1.f, uv) == RES_BAD_ARG); 207 CHK(s3d_primitive_sample(NULL, 0.f, 1.f, uv) == RES_BAD_ARG); 208 CHK(s3d_primitive_sample(&prim, 0.f, 1.f, uv) == RES_BAD_ARG); 209 CHK(s3d_primitive_sample(NULL, 1.f, 0.f, uv) == RES_BAD_ARG); 210 CHK(s3d_primitive_sample(&prim, 1.f, 0.f, uv) == RES_BAD_ARG); 211 CHK(s3d_primitive_sample(NULL, 0.f, 0.f, uv) == RES_BAD_ARG); 212 CHK(s3d_primitive_sample(&prim, 0.f, 0.f, uv) == RES_OK); 213 214 FOR_EACH(i, 0, 4096) { 215 CHK(s3d_primitive_sample 216 (&prim, rand_canonic(), rand_canonic(), uv) == RES_OK); 217 CHK(uv[0] >= 0.f); 218 CHK(uv[0] <= 1.f); 219 CHK(uv[1] >= 0.f); 220 CHK(uv[1] <= 1.f); 221 } 222 223 #define GET_VERTEX_ATTR s3d_triangle_get_vertex_attrib 224 CHK(GET_VERTEX_ATTR(NULL, 3, S3D_GEOMETRY_NORMAL, NULL) == RES_BAD_ARG); 225 CHK(GET_VERTEX_ATTR(&prim, 3, S3D_GEOMETRY_NORMAL, NULL) == RES_BAD_ARG); 226 CHK(GET_VERTEX_ATTR(NULL, 0, S3D_GEOMETRY_NORMAL, NULL) == RES_BAD_ARG); 227 CHK(GET_VERTEX_ATTR(&prim, 0, S3D_GEOMETRY_NORMAL, NULL) == RES_BAD_ARG); 228 CHK(GET_VERTEX_ATTR(NULL, 3, S3D_POSITION, NULL) == RES_BAD_ARG); 229 CHK(GET_VERTEX_ATTR(&prim, 3, S3D_POSITION, NULL) == RES_BAD_ARG); 230 CHK(GET_VERTEX_ATTR(NULL, 0, S3D_POSITION, NULL) == RES_BAD_ARG); 231 CHK(GET_VERTEX_ATTR(&prim, 0, S3D_POSITION, NULL) == RES_BAD_ARG); 232 CHK(GET_VERTEX_ATTR(NULL, 3, S3D_GEOMETRY_NORMAL, &attr) == RES_BAD_ARG); 233 CHK(GET_VERTEX_ATTR(&prim, 3, S3D_GEOMETRY_NORMAL, &attr) == RES_BAD_ARG); 234 CHK(GET_VERTEX_ATTR(NULL, 0, S3D_GEOMETRY_NORMAL, &attr) == RES_BAD_ARG); 235 CHK(GET_VERTEX_ATTR(&prim, 0, S3D_GEOMETRY_NORMAL, &attr) == RES_BAD_ARG); 236 CHK(GET_VERTEX_ATTR(NULL, 3, S3D_POSITION, &attr) == RES_BAD_ARG); 237 CHK(GET_VERTEX_ATTR(&prim, 3, S3D_POSITION, &attr) == RES_BAD_ARG); 238 CHK(GET_VERTEX_ATTR(NULL, 0, S3D_POSITION, &attr) == RES_BAD_ARG); 239 240 CHK(GET_VERTEX_ATTR(&prim, 0, S3D_POSITION, &attr) == RES_OK); 241 CHK(attr.type == S3D_FLOAT3); 242 CHK(f3_eq_eps(attr.value, plane_verts + plane_ids[0]*3, 1.e-6f) == 1); 243 CHK(GET_VERTEX_ATTR(&prim, 1, S3D_POSITION, &attr) == RES_OK); 244 CHK(attr.type == S3D_FLOAT3); 245 CHK(f3_eq_eps(attr.value, plane_verts + plane_ids[1]*3, 1.e-6f) == 1); 246 CHK(GET_VERTEX_ATTR(&prim, 2, S3D_POSITION, &attr) == RES_OK); 247 CHK(attr.type == S3D_FLOAT3); 248 CHK(f3_eq_eps(attr.value, plane_verts + plane_ids[2]*3, 1.e-6f) == 1); 249 250 CHK(GET_VERTEX_ATTR(&prim, 0, S3D_ATTRIB_0, &attr) == RES_OK); 251 CHK(attr.type == S3D_FLOAT2); 252 f2_minus(uv, plane_verts + plane_ids[0]*3); 253 CHK(f2_eq_eps(attr.value, uv, 1.e-6f) == 1); 254 CHK(GET_VERTEX_ATTR(&prim, 1, S3D_ATTRIB_0, &attr) == RES_OK); 255 CHK(attr.type == S3D_FLOAT2); 256 f2_minus(uv, plane_verts + plane_ids[1]*3); 257 CHK(f2_eq_eps(attr.value, uv, 1.e-6f) == 1); 258 CHK(GET_VERTEX_ATTR(&prim, 2, S3D_ATTRIB_0, &attr) == RES_OK); 259 CHK(attr.type == S3D_FLOAT2); 260 f2_minus(uv, plane_verts + plane_ids[2]*3); 261 CHK(f2_eq_eps(attr.value, uv, 1.e-6f) == 1); 262 #undef GET_VERTEX_ATTR 263 264 CHK(s3d_device_ref_put(dev) == RES_OK); 265 CHK(s3d_scene_ref_put(scn) == RES_OK); 266 CHK(s3d_shape_ref_put(walls) == RES_OK); 267 CHK(s3d_shape_ref_put(plane) == RES_OK); 268 269 check_memory_allocator(&allocator); 270 mem_shutdown_proxy_allocator(&allocator); 271 CHK(mem_allocated_size() == 0); 272 return 0; 273 } 274