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