Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2009 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): André Pinto. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00032 #include <assert.h> 00033 00034 #include "MEM_guardedalloc.h" 00035 00036 #include "BLI_kdopbvh.h" 00037 #include "BLI_math.h" 00038 #include "BLI_utildefines.h" 00039 00040 #include "rayintersection.h" 00041 #include "rayobject.h" 00042 00043 static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec); 00044 static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob); 00045 static void RE_rayobject_blibvh_done(RayObject *o); 00046 static void RE_rayobject_blibvh_free(RayObject *o); 00047 static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max); 00048 00049 static float RE_rayobject_blibvh_cost(RayObject *UNUSED(o)) 00050 { 00051 //TODO calculate the expected cost to raycast on this structure 00052 return 1.0; 00053 } 00054 00055 static void RE_rayobject_blibvh_hint_bb(RayObject *UNUSED(o), RayHint *UNUSED(hint), 00056 float *UNUSED(min), float *UNUSED(max)) 00057 { 00058 return; 00059 } 00060 00061 static RayObjectAPI bvh_api = 00062 { 00063 RE_rayobject_blibvh_intersect, 00064 RE_rayobject_blibvh_add, 00065 RE_rayobject_blibvh_done, 00066 RE_rayobject_blibvh_free, 00067 RE_rayobject_blibvh_bb, 00068 RE_rayobject_blibvh_cost, 00069 RE_rayobject_blibvh_hint_bb 00070 }; 00071 00072 typedef struct BVHObject 00073 { 00074 RayObject rayobj; 00075 RayObject **leafs, **next_leaf; 00076 BVHTree *bvh; 00077 float bb[2][3]; 00078 } BVHObject; 00079 00080 RayObject *RE_rayobject_blibvh_create(int size) 00081 { 00082 BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject"); 00083 assert(RE_rayobject_isAligned(obj)); /* RayObject API assumes real data to be 4-byte aligned */ 00084 00085 obj->rayobj.api = &bvh_api; 00086 obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); 00087 obj->next_leaf = obj->leafs = (RayObject**)MEM_callocN(size*sizeof(RayObject*), "BVHObject leafs"); 00088 00089 INIT_MINMAX(obj->bb[0], obj->bb[1]); 00090 return RE_rayobject_unalignRayAPI((RayObject*) obj); 00091 } 00092 00093 struct BVHCallbackUserData 00094 { 00095 Isect *isec; 00096 RayObject **leafs; 00097 }; 00098 00099 static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) 00100 { 00101 struct BVHCallbackUserData *data = (struct BVHCallbackUserData*)userdata; 00102 Isect *isec = data->isec; 00103 RayObject *face = data->leafs[index]; 00104 00105 if(RE_rayobject_intersect(face,isec)) 00106 { 00107 hit->index = index; 00108 00109 if(isec->mode == RE_RAY_SHADOW) 00110 hit->dist = 0; 00111 else 00112 hit->dist = isec->dist; 00113 } 00114 } 00115 00116 static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec) 00117 { 00118 BVHObject *obj = (BVHObject*)o; 00119 BVHTreeRayHit hit; 00120 float dir[3]; 00121 struct BVHCallbackUserData data; 00122 data.isec = isec; 00123 data.leafs = obj->leafs; 00124 00125 copy_v3_v3(dir, isec->dir); 00126 00127 hit.index = 0; 00128 hit.dist = isec->dist; 00129 00130 return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, (void*)&data); 00131 } 00132 00133 static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob) 00134 { 00135 BVHObject *obj = (BVHObject*)o; 00136 float min_max[6]; 00137 INIT_MINMAX(min_max, min_max+3); 00138 RE_rayobject_merge_bb(ob, min_max, min_max+3); 00139 00140 DO_MIN(min_max , obj->bb[0]); 00141 DO_MAX(min_max+3, obj->bb[1]); 00142 00143 BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2); 00144 *(obj->next_leaf++) = ob; 00145 } 00146 00147 static void RE_rayobject_blibvh_done(RayObject *o) 00148 { 00149 BVHObject *obj = (BVHObject*)o; 00150 BLI_bvhtree_balance(obj->bvh); 00151 } 00152 00153 static void RE_rayobject_blibvh_free(RayObject *o) 00154 { 00155 BVHObject *obj = (BVHObject*)o; 00156 00157 if(obj->bvh) 00158 BLI_bvhtree_free(obj->bvh); 00159 00160 if(obj->leafs) 00161 MEM_freeN(obj->leafs); 00162 00163 MEM_freeN(obj); 00164 } 00165 00166 static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max) 00167 { 00168 BVHObject *obj = (BVHObject*)o; 00169 DO_MIN(obj->bb[0], min); 00170 DO_MAX(obj->bb[1], max); 00171 } 00172