solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

ssol_instance.c (7066B)


      1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2016, 2018 CNRS
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     16 
     17 #include "ssol.h"
     18 #include "ssol_c.h"
     19 #include "ssol_object_c.h"
     20 #include "ssol_shape_c.h"
     21 #include "ssol_instance_c.h"
     22 #include "ssol_device_c.h"
     23 
     24 #include <rsys/rsys.h>
     25 #include <rsys/mem_allocator.h>
     26 #include <rsys/ref_count.h>
     27 #include <rsys/double33.h>
     28 
     29 #include <string.h>
     30 
     31 /*******************************************************************************
     32  * Helper functions
     33  ******************************************************************************/
     34 static void
     35 instance_release(ref_T* ref)
     36 {
     37   struct ssol_device* dev;
     38   struct ssol_instance* instance;
     39   ASSERT(ref);
     40 
     41   instance = CONTAINER_OF(ref, struct ssol_instance, ref);
     42   dev = instance->dev;
     43   ASSERT(dev && dev->allocator);
     44 
     45   SSOL(object_ref_put(instance->object));
     46   if(instance->shape_rt) S3D(shape_ref_put(instance->shape_rt));
     47   if(instance->shape_samp) S3D(shape_ref_put(instance->shape_samp));
     48   MEM_RM(dev->allocator, instance);
     49   SSOL(device_ref_put(dev));
     50 }
     51 
     52 /*******************************************************************************
     53  * Exported ssol_instance functions
     54  ******************************************************************************/
     55 res_T
     56 ssol_object_instantiate
     57   (struct ssol_object* object,
     58    struct ssol_instance** out_instance)
     59 {
     60   struct ssol_instance* instance = NULL;
     61   struct ssol_device* dev;
     62 
     63   res_T res = RES_OK;
     64   if(!object || !out_instance) {
     65     res = RES_BAD_ARG;
     66     goto error;
     67   }
     68 
     69   dev = object->dev;
     70   ASSERT(dev && dev->allocator);
     71   instance = MEM_CALLOC(dev->allocator, 1, sizeof(struct ssol_instance));
     72   if(!instance) {
     73     res = RES_MEM_ERR;
     74     goto error;
     75   }
     76 
     77   ref_init(&instance->ref);
     78   SSOL(device_ref_get(dev));
     79   SSOL(object_ref_get(object));
     80   instance->dev = dev;
     81   instance->object = object;
     82   instance->sample = 1;
     83   d33_set_identity(instance->transform);
     84   d3_splat(instance->transform + 9, 0);
     85 
     86   /* Create the Star-3D instance to ray-trace */
     87   res = s3d_scene_instantiate(object->scn_rt, &instance->shape_rt);
     88   if(res != RES_OK) goto error;
     89   instance->shape_rt_area = object->scn_rt_area;
     90 
     91   /* Create the Star-3D instance to sample */
     92   res = s3d_scene_instantiate(object->scn_samp, &instance->shape_samp);
     93   if(res != RES_OK) goto error;
     94   instance->shape_samp_area = object->scn_samp_area;
     95 
     96 exit:
     97   if(out_instance) *out_instance = instance;
     98   return res;
     99 error:
    100   if(instance) {
    101     SSOL(instance_ref_put(instance));
    102     instance = NULL;
    103   }
    104   goto exit;
    105 }
    106 
    107 res_T
    108 ssol_instance_ref_get(struct ssol_instance* instance)
    109 {
    110   if(!instance)
    111     return RES_BAD_ARG;
    112   ref_get(&instance->ref);
    113   return RES_OK;
    114 }
    115 
    116 res_T
    117 ssol_instance_ref_put
    118   (struct ssol_instance* instance)
    119 {
    120   if(!instance)
    121     return RES_BAD_ARG;
    122   ref_put(&instance->ref, instance_release);
    123   return RES_OK;
    124 }
    125 
    126 res_T
    127 ssol_instance_set_transform
    128   (struct ssol_instance* instance, const double transform[12])
    129 {
    130   float t[12];
    131   int i;
    132   res_T res = RES_OK;
    133 
    134   if(!instance || !transform) {
    135     res =  RES_BAD_ARG;
    136     goto error;
    137   }
    138 
    139   FOR_EACH(i, 0, 12) {
    140     t[i] = (float) transform[i];
    141     instance->transform[i] = transform[i];
    142   }
    143 
    144   res = s3d_instance_set_transform(instance->shape_rt, t);
    145   if(res != RES_OK) goto error;
    146 
    147   if(instance->shape_rt != instance->shape_samp) {
    148     res = s3d_instance_set_transform(instance->shape_samp, t);
    149     if(res != RES_OK) goto error;
    150   }
    151 
    152 exit:
    153   return res;
    154 error:
    155   goto exit;
    156 }
    157 
    158 res_T
    159 ssol_instance_set_receiver
    160   (struct ssol_instance* instance,
    161    const int mask,
    162    const int per_primitive)
    163 {
    164   if(!instance) return RES_BAD_ARG;
    165   instance->receiver_mask = mask;
    166   instance->receiver_per_primitive = per_primitive;
    167   return RES_OK;
    168 }
    169 
    170 res_T
    171 ssol_instance_is_receiver
    172   (struct ssol_instance* instance, int* mask, int* per_primitive)
    173 {
    174   if(!instance || !mask || !per_primitive) return RES_BAD_ARG;
    175   *mask = instance->receiver_mask;
    176   *per_primitive = instance->receiver_per_primitive;
    177   return RES_OK;
    178 }
    179 
    180 res_T
    181 ssol_instance_sample
    182   (struct ssol_instance* instance,
    183    const int sample)
    184 {
    185   if(!instance) return RES_BAD_ARG;
    186   instance->sample = sample;
    187   return RES_OK;
    188 }
    189 
    190 res_T
    191 ssol_instance_get_id(const struct ssol_instance* instance, uint32_t* id)
    192 {
    193   unsigned u;
    194   STATIC_ASSERT
    195     (sizeof(unsigned) <= sizeof(uint32_t), Unexpected_sizeof_unsigned);
    196   if(!instance || !id) return RES_BAD_ARG;
    197   S3D(shape_get_id(instance->shape_rt, &u));
    198   *id = (uint32_t)u;
    199   return RES_OK;
    200 }
    201 
    202 res_T
    203 ssol_instance_get_area
    204   (const struct ssol_instance* instance,
    205    double* area)
    206 {
    207   if (!instance || !area) return RES_BAD_ARG;
    208   /* the area of the 3D surface */
    209   *area = instance->shape_rt_area;
    210   return RES_OK;
    211 }
    212 
    213 res_T
    214 ssol_instance_get_shaded_shapes_count
    215   (const struct ssol_instance* instance, size_t* count)
    216 {
    217   if(!instance || !count) return RES_BAD_ARG;
    218   *count = darray_shaded_shape_size_get(&instance->object->shaded_shapes);
    219   return RES_OK;
    220 }
    221 
    222 res_T
    223 ssol_instance_get_shaded_shape
    224   (const struct ssol_instance* instance,
    225    const size_t ishape,
    226    struct ssol_instantiated_shaded_shape* sshape)
    227 {
    228   const struct shaded_shape* shaded_shape;
    229 
    230   if(!instance || !sshape) return RES_BAD_ARG;
    231   if(ishape >= darray_shaded_shape_size_get(&instance->object->shaded_shapes))
    232     return RES_BAD_ARG;
    233 
    234   shaded_shape = darray_shaded_shape_cdata_get
    235     (&instance->object->shaded_shapes) + ishape;
    236   sshape->shape = shaded_shape->shape;
    237   sshape->mtl_front = shaded_shape->mtl_front;
    238   sshape->mtl_back = shaded_shape->mtl_back;
    239 
    240   d33_set(sshape->R__, instance->transform);
    241   d3_set(sshape->T__, instance->transform+9);
    242   d33_invtrans(sshape->R_invtrans__, sshape->R__);
    243   return RES_OK;
    244 }
    245 
    246 res_T
    247 ssol_instantiated_shaded_shape_get_vertex_attrib
    248   (const struct ssol_instantiated_shaded_shape* sshape,
    249    const unsigned ivert,
    250    const enum ssol_attrib_usage usage,
    251    double value[])
    252 {
    253   res_T res = RES_OK;
    254 
    255   if(!sshape || (unsigned)usage >= SSOL_ATTRIBS_COUNT__ || !value)
    256     return RES_BAD_ARG;
    257 
    258   res = shape_fetched_raw_vertex_attrib(sshape->shape, ivert, usage, value);
    259   if(res != RES_OK) return res;
    260 
    261   /* Transform the fetched attrib */
    262   switch(usage) {
    263     case SSOL_NORMAL:
    264       d33_muld3(value, sshape->R_invtrans__, value);
    265       break;
    266     case SSOL_POSITION:
    267       d33_muld3(value, sshape->R__, value);
    268       d3_add(value, sshape->T__, value);
    269       break;
    270     default: /* Do nothing */ break;
    271   }
    272   return RES_OK;
    273 }
    274