star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.com/star-3d.git
Log | Files | Refs | README | LICENSE

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