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