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 00033 #include <assert.h> 00034 00035 #include "MEM_guardedalloc.h" 00036 00037 #include "BLI_math.h" 00038 #include "BLI_utildefines.h" 00039 00040 #include "rayintersection.h" 00041 #include "rayobject.h" 00042 00043 #define RE_COST_INSTANCE (1.0f) 00044 00045 static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec); 00046 static void RE_rayobject_instance_free(RayObject *o); 00047 static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max); 00048 static float RE_rayobject_instance_cost(RayObject *o); 00049 00050 static void RE_rayobject_instance_hint_bb(RayObject *UNUSED(o), RayHint *UNUSED(hint), 00051 float *UNUSED(min), float *UNUSED(max)) 00052 {} 00053 00054 static RayObjectAPI instance_api = 00055 { 00056 RE_rayobject_instance_intersect, 00057 NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob); 00058 NULL, //static void RE_rayobject_instance_done(RayObject *o); 00059 RE_rayobject_instance_free, 00060 RE_rayobject_instance_bb, 00061 RE_rayobject_instance_cost, 00062 RE_rayobject_instance_hint_bb 00063 }; 00064 00065 typedef struct InstanceRayObject 00066 { 00067 RayObject rayobj; 00068 RayObject *target; 00069 00070 void *ob; //Object represented by this instance 00071 void *target_ob; //Object represented by the inner RayObject, needed to handle self-intersection 00072 00073 float global2target[4][4]; 00074 float target2global[4][4]; 00075 00076 } InstanceRayObject; 00077 00078 00079 RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob) 00080 { 00081 InstanceRayObject *obj= (InstanceRayObject*)MEM_callocN(sizeof(InstanceRayObject), "InstanceRayObject"); 00082 assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ 00083 00084 obj->rayobj.api = &instance_api; 00085 obj->target = target; 00086 obj->ob = ob; 00087 obj->target_ob = target_ob; 00088 00089 copy_m4_m4(obj->target2global, transform); 00090 invert_m4_m4(obj->global2target, obj->target2global); 00091 00092 return RE_rayobject_unalignRayAPI((RayObject*) obj); 00093 } 00094 00095 static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec) 00096 { 00097 InstanceRayObject *obj = (InstanceRayObject*)o; 00098 float start[3], dir[3], idot_axis[3], dist; 00099 int changed = 0, i, res; 00100 00101 // TODO - this is disabling self intersection on instances 00102 if(isec->orig.ob == obj->ob && obj->ob) 00103 { 00104 changed = 1; 00105 isec->orig.ob = obj->target_ob; 00106 } 00107 00108 // backup old values 00109 copy_v3_v3(start, isec->start); 00110 copy_v3_v3(dir, isec->dir); 00111 copy_v3_v3(idot_axis, isec->idot_axis); 00112 dist = isec->dist; 00113 00114 // transform to target coordinates system 00115 mul_m4_v3(obj->global2target, isec->start); 00116 mul_mat3_m4_v3(obj->global2target, isec->dir); 00117 isec->dist *= normalize_v3(isec->dir); 00118 00119 // update idot_axis and bv_index 00120 for(i=0; i<3; i++) 00121 { 00122 isec->idot_axis[i] = 1.0f / isec->dir[i]; 00123 00124 isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; 00125 isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; 00126 00127 isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; 00128 isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; 00129 } 00130 00131 // raycast 00132 res = RE_rayobject_intersect(obj->target, isec); 00133 00134 // map dist into original coordinate space 00135 if(res == 0) 00136 { 00137 isec->dist = dist; 00138 } 00139 else 00140 { 00141 // note we don't just multiply dist, because of possible 00142 // non-uniform scaling in the transform matrix 00143 float vec[3]; 00144 00145 mul_v3_v3fl(vec, isec->dir, isec->dist); 00146 mul_mat3_m4_v3(obj->target2global, vec); 00147 00148 isec->dist = len_v3(vec); 00149 isec->hit.ob = obj->ob; 00150 00151 #ifdef RT_USE_LAST_HIT 00152 // TODO support for last hit optimization in instances that can jump 00153 // directly to the last hit face. 00154 // For now it jumps directly to the last-hit instance root node. 00155 isec->last_hit = RE_rayobject_unalignRayAPI((RayObject*) obj); 00156 #endif 00157 } 00158 00159 // restore values 00160 copy_v3_v3(isec->start, start); 00161 copy_v3_v3(isec->dir, dir); 00162 copy_v3_v3(isec->idot_axis, idot_axis); 00163 00164 if(changed) 00165 isec->orig.ob = obj->ob; 00166 00167 // restore bv_index 00168 for(i=0; i<3; i++) 00169 { 00170 isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; 00171 isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; 00172 00173 isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; 00174 isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; 00175 } 00176 00177 return res; 00178 } 00179 00180 static void RE_rayobject_instance_free(RayObject *o) 00181 { 00182 InstanceRayObject *obj = (InstanceRayObject*)o; 00183 MEM_freeN(obj); 00184 } 00185 00186 static float RE_rayobject_instance_cost(RayObject *o) 00187 { 00188 InstanceRayObject *obj = (InstanceRayObject*)o; 00189 return RE_rayobject_cost(obj->target) + RE_COST_INSTANCE; 00190 } 00191 00192 static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max) 00193 { 00194 //TODO: 00195 // *better bb.. calculated without rotations of bb 00196 // *maybe cache that better-fitted-BB at the InstanceRayObject 00197 InstanceRayObject *obj = (InstanceRayObject*)o; 00198 00199 float m[3], M[3], t[3]; 00200 int i, j; 00201 INIT_MINMAX(m, M); 00202 RE_rayobject_merge_bb(obj->target, m, M); 00203 00204 //There must be a faster way than rotating all the 8 vertexs of the BB 00205 for(i=0; i<8; i++) 00206 { 00207 for(j=0; j<3; j++) t[j] = i&(1<<j) ? M[j] : m[j]; 00208 mul_m4_v3(obj->target2global, t); 00209 DO_MINMAX(t, min, max); 00210 } 00211 } 00212