ssol_object.c (7371B)
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_device_c.h" 19 #include "ssol_object_c.h" 20 #include "ssol_shape_c.h" 21 22 #include <star/s3d.h> 23 24 #include <rsys/ref_count.h> 25 #include <rsys/rsys.h> 26 #include <rsys/mem_allocator.h> 27 #include <rsys/double3.h> 28 29 /******************************************************************************* 30 * Helper functions 31 ******************************************************************************/ 32 static void 33 object_release(ref_T* ref) 34 { 35 struct ssol_device* dev; 36 struct ssol_object* object = CONTAINER_OF(ref, struct ssol_object, ref); 37 ASSERT(ref); 38 dev = object->dev; 39 ASSERT(dev && dev->allocator); 40 SSOL(object_clear(object)); 41 darray_shaded_shape_release(&object->shaded_shapes); 42 htable_shaded_shape_release(&object->shaded_shapes_rt); 43 htable_shaded_shape_release(&object->shaded_shapes_samp); 44 if(object->scn_rt) S3D(scene_ref_put(object->scn_rt)); 45 if(object->scn_samp) S3D(scene_ref_put(object->scn_samp)); 46 MEM_RM(dev->allocator, object); 47 SSOL(device_ref_put(dev)); 48 } 49 50 /******************************************************************************* 51 * Exported ssol_object functions 52 ******************************************************************************/ 53 res_T 54 ssol_object_create 55 (struct ssol_device* dev, 56 struct ssol_object** out_object) 57 { 58 struct ssol_object* object = NULL; 59 res_T res = RES_OK; 60 61 if(!dev || !out_object) { 62 res = RES_BAD_ARG; 63 goto error; 64 } 65 66 object = MEM_CALLOC(dev->allocator, 1, sizeof(struct ssol_object)); 67 if(!object) { 68 res = RES_MEM_ERR; 69 goto error; 70 } 71 SSOL(device_ref_get(dev)); 72 object->dev = dev; 73 ref_init(&object->ref); 74 darray_shaded_shape_init(dev->allocator, &object->shaded_shapes); 75 htable_shaded_shape_init(dev->allocator, &object->shaded_shapes_rt); 76 htable_shaded_shape_init(dev->allocator, &object->shaded_shapes_samp); 77 78 /* Create the Star-3D RT scene to instantiate through the instance */ 79 res = s3d_scene_create(dev->s3d, &object->scn_rt); 80 if(res != RES_OK) goto error; 81 /* Create the Star-3D sampling scene to instantiated through the instance */ 82 res = s3d_scene_create(dev->s3d, &object->scn_samp); 83 if(res != RES_OK) goto error; 84 85 exit: 86 if(out_object) *out_object = object; 87 return res; 88 error: 89 if(object) { 90 SSOL(object_ref_put(object)); 91 object = NULL; 92 } 93 goto exit; 94 } 95 res_T 96 ssol_object_ref_get(struct ssol_object* object) 97 { 98 if(!object) return RES_BAD_ARG; 99 ref_get(&object->ref); 100 return RES_OK; 101 } 102 103 res_T 104 ssol_object_ref_put(struct ssol_object* object) 105 { 106 if(!object) return RES_BAD_ARG; 107 ref_put(&object->ref, object_release); 108 return RES_OK; 109 } 110 111 res_T 112 ssol_object_add_shaded_shape 113 (struct ssol_object* object, 114 struct ssol_shape* shape, 115 struct ssol_material* front, 116 struct ssol_material* back) 117 { 118 enum { 119 ATTACH_S3D_RT, ATTACH_S3D_SAMP, REGISTER_RT, REGISTER_SAMP, REGISTER_SHAPE 120 }; 121 struct shaded_shape* shaded_shape; 122 unsigned id_rt, id_samp; 123 size_t i; 124 int mask = 0; 125 res_T res = RES_OK; 126 127 if(!object || !shape || !front || !back) { 128 res = RES_BAD_ARG; 129 goto error; 130 } 131 132 S3D(shape_get_id(shape->shape_rt, &id_rt)); 133 S3D(shape_get_id(shape->shape_samp, &id_samp)); 134 if(htable_shaded_shape_find(&object->shaded_shapes_rt, &id_rt)) { 135 log_warning 136 (object->dev, "%s: the object already own the shape.\n", FUNC_NAME); 137 goto exit; 138 } 139 140 /* Add the shape RT to the RT scene of the object */ 141 res = s3d_scene_attach_shape(object->scn_rt, shape->shape_rt); 142 if(res != RES_OK) goto error; 143 mask |= BIT(ATTACH_S3D_RT); 144 145 /* Add the shape samp to the sampling scene of the object */ 146 res = s3d_scene_attach_shape(object->scn_samp, shape->shape_samp); 147 if(res != RES_OK) goto error; 148 mask |= BIT(ATTACH_S3D_SAMP); 149 150 /* Ask for a shaded shape identifier */ 151 i = darray_shaded_shape_size_get(&object->shaded_shapes); 152 res = darray_shaded_shape_resize(&object->shaded_shapes, i+1); 153 if(res != RES_OK) goto error; 154 mask |= BIT(REGISTER_SHAPE); 155 156 /* Register the RT shape identifer */ 157 res = htable_shaded_shape_set(&object->shaded_shapes_rt, &id_rt, &i); 158 if(res != RES_OK) goto error; 159 mask |= BIT(REGISTER_RT); 160 161 /* Register the samp shape identifier */ 162 res = htable_shaded_shape_set(&object->shaded_shapes_samp, &id_samp, &i); 163 if(res != RES_OK) goto error; 164 mask |= BIT(REGISTER_SAMP); 165 166 /* Setup the object shaded shape */ 167 object->scn_rt_area += shape->shape_rt_area; 168 object->scn_samp_area += shape->shape_samp_area; 169 SSOL(shape_ref_get(shape)); 170 SSOL(material_ref_get(front)); 171 SSOL(material_ref_get(back)); 172 shaded_shape = darray_shaded_shape_data_get(&object->shaded_shapes)+i; 173 shaded_shape->shape = shape; 174 shaded_shape->mtl_front = front; 175 shaded_shape->mtl_back = back; 176 177 exit: 178 return res; 179 error: 180 if(mask & BIT(ATTACH_S3D_RT)) { 181 S3D(scene_detach_shape(object->scn_rt, shape->shape_rt)); 182 } 183 if(mask & BIT(ATTACH_S3D_SAMP)) { 184 S3D(scene_detach_shape(object->scn_samp, shape->shape_samp)); 185 } 186 if(mask & BIT(REGISTER_SHAPE)) { 187 darray_shaded_shape_pop_back(&object->shaded_shapes); 188 } 189 if(mask & BIT(REGISTER_RT)) { 190 i = htable_shaded_shape_erase(&object->shaded_shapes_rt, &id_rt); 191 ASSERT(i == 1); 192 } 193 if(mask & BIT(REGISTER_SAMP)) { 194 i = htable_shaded_shape_erase(&object->shaded_shapes_samp, &id_samp); 195 ASSERT(i == 1); 196 } 197 goto exit; 198 } 199 200 res_T 201 ssol_object_clear(struct ssol_object* obj) 202 { 203 size_t i, n; 204 if(!obj) return RES_BAD_ARG; 205 206 n = darray_shaded_shape_size_get(&obj->shaded_shapes); 207 FOR_EACH(i, 0, n) { 208 struct shaded_shape* s = darray_shaded_shape_data_get(&obj->shaded_shapes)+i; 209 SSOL(shape_ref_put(s->shape)); 210 SSOL(material_ref_put(s->mtl_front)); 211 SSOL(material_ref_put(s->mtl_back)); 212 } 213 darray_shaded_shape_clear(&obj->shaded_shapes); 214 htable_shaded_shape_clear(&obj->shaded_shapes_rt); 215 htable_shaded_shape_clear(&obj->shaded_shapes_samp); 216 217 obj->scn_rt_area = 0; 218 obj->scn_samp_area = 0; 219 220 S3D(scene_clear(obj->scn_rt)); 221 S3D(scene_clear(obj->scn_samp)); 222 223 return RES_OK; 224 } 225 226 res_T 227 ssol_object_get_area(const struct ssol_object* object, double* area) 228 { 229 if(!object || !area) return RES_BAD_ARG;; 230 /* the area of the 3D surface */ 231 *area = object->scn_rt_area; 232 return RES_OK; 233 } 234 235 /******************************************************************************* 236 * Local function 237 ******************************************************************************/ 238 int 239 object_has_shape(struct ssol_object* obj, const struct ssol_shape* shape) 240 { 241 unsigned id; 242 ASSERT(obj && shape); 243 S3D(shape_get_id(shape->shape_rt, &id)); 244 return htable_shaded_shape_find(&obj->shaded_shapes_rt, &id) != NULL; 245 }