diff options
-rw-r--r-- | source/blender/editors/armature/meshlaplacian.c | 105 | ||||
-rw-r--r-- | source/blender/render/extern/include/RE_raytrace.h | 108 | ||||
-rw-r--r-- | source/blender/render/intern/include/rayobject.h | 122 | ||||
-rw-r--r-- | source/blender/render/intern/include/render_types.h | 7 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayobject.c | 276 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayobject_mesh.c | 128 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayobject_octree.c (renamed from source/blender/render/intern/source/raytrace.c) | 700 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayshade.c | 275 | ||||
-rw-r--r-- | source/blender/render/intern/source/rendercore.c | 33 |
9 files changed, 951 insertions, 803 deletions
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 8807b21e653..c3ab60ffda6 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -30,6 +30,7 @@ #include <math.h> #include <string.h> +#include <assert.h> #include "MEM_guardedalloc.h" @@ -105,7 +106,7 @@ struct LaplacianSystem { float *p; /* values from all p vectors */ float *mindist; /* minimum distance to a bone for all vertices */ - RayTree *raytree; /* ray tracing acceleration structure */ + RayObject *raytree; /* ray tracing acceleration structure */ MFace **vface; /* a face that the vertex belongs to */ } heat; @@ -394,77 +395,31 @@ float laplacian_system_get_solution(int v) #define DISTANCE_EPSILON 1e-4f /* Raytracing for vertex to bone visibility */ - -static LaplacianSystem *HeatSys = NULL; - -static void heat_ray_coords_func(RayFace *face, float **v1, float **v2, float **v3, float **v4) -{ - MFace *mface= (MFace*)face; - float (*verts)[3]= HeatSys->heat.verts; - - *v1= verts[mface->v1]; - *v2= verts[mface->v2]; - *v3= verts[mface->v3]; - *v4= (mface->v4)? verts[mface->v4]: NULL; -} - -static int heat_ray_check_func(Isect *is, int ob, RayFace *face) -{ - float *v1, *v2, *v3, *v4, nor[3]; - - /* don't intersect if the ray faces along the face normal */ - heat_ray_coords_func(face, &v1, &v2, &v3, &v4); - - if(v4) CalcNormFloat4(v1, v2, v3, v4, nor); - else CalcNormFloat(v1, v2, v3, nor); - - return (INPR(nor, is->vec) < 0); -} - static void heat_ray_tree_create(LaplacianSystem *sys) { Mesh *me = sys->heat.mesh; - RayTree *tree; MFace *mface; - float min[3], max[3]; int a; - /* create a raytrace tree from the mesh */ - INIT_MINMAX(min, max); - - for(a=0; a<me->totvert; a++) - DO_MINMAX(sys->heat.verts[a], min, max); - - tree= RE_ray_tree_create(64, me->totface, min, max, - heat_ray_coords_func, heat_ray_check_func, NULL, NULL); - - sys->heat.vface= MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); - - HeatSys= sys; + sys->heat.raytree = RayObject_mesh_create(me, me); + sys->heat.vface = MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); for(a=0, mface=me->mface; a<me->totface; a++, mface++) { - RE_ray_tree_add_face(tree, 0, mface); - sys->heat.vface[mface->v1]= mface; sys->heat.vface[mface->v2]= mface; sys->heat.vface[mface->v3]= mface; if(mface->v4) sys->heat.vface[mface->v4]= mface; } - - HeatSys= NULL; - - RE_ray_tree_done(tree); - - sys->heat.raytree= tree; } static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) { Isect isec; MFace *mface; - float dir[3]; + float end[3]; int visible; + assert( 0 ); mface= sys->heat.vface[vertex]; if(!mface) return 1; @@ -473,22 +428,24 @@ static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) memset(&isec, 0, sizeof(isec)); isec.mode= RE_RAY_SHADOW; isec.lay= -1; - isec.face_last= NULL; - isec.faceorig= mface; + isec.orig.face = mface; + isec.skip = RE_SKIP_CULLFACE; VECCOPY(isec.start, sys->heat.verts[vertex]); - PclosestVL3Dfl(isec.end, isec.start, - sys->heat.root[bone], sys->heat.tip[bone]); + PclosestVL3Dfl(end, isec.start, sys->heat.root[bone], sys->heat.tip[bone]); + + VECSUB(isec.vec, end, isec.start); + isec.labda = 1.0f; +#if 0 + TODO /* add an extra offset to the start position to avoid self intersection */ - VECSUB(dir, isec.end, isec.start); + VECCOPY(dir, isec.vec); Normalize(dir); VecMulf(dir, 1e-5); VecAddf(isec.start, isec.start, dir); - - HeatSys= sys; - visible= !RE_ray_tree_intersect(sys->heat.raytree, &isec); - HeatSys= NULL; +#endif + visible= !RayObject_raycast(sys->heat.raytree, &isec); return visible; } @@ -752,7 +709,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, /* free */ if(vertsflipped) MEM_freeN(vertsflipped); - RE_ray_tree_free(sys->heat.raytree); + RayObject_free(sys->heat.raytree); MEM_freeN(sys->heat.vface); MEM_freeN(sys->heat.mindist); @@ -1049,7 +1006,7 @@ typedef struct MeshDeformBind { int *varidx; /* raytrace */ - RayTree *raytree; + RayObject *raytree; } MeshDeformBind; /* ray intersection */ @@ -1173,7 +1130,7 @@ static void meshdeform_ray_tree_free(MeshDeformBind *mdb) static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec) { MFace *mface; - float face[4][3], co[3], uvw[3], len, nor[3]; + float face[4][3], co[3], uvw[3], len, nor[3], end[3]; int f, hit, is= 0, totface; isec->labda= 1e10; @@ -1181,6 +1138,8 @@ static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec) mface= mdb->cagedm->getFaceArray(mdb->cagedm); totface= mdb->cagedm->getNumFaces(mdb->cagedm); + VECADDFAC( end, isec->start, isec->vec, isec->labda ); + for(f=0; f<totface; f++, mface++) { VECCOPY(face[0], mdb->cagecos[mface->v1]); VECCOPY(face[1], mdb->cagecos[mface->v2]); @@ -1188,26 +1147,26 @@ static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec) if(mface->v4) { VECCOPY(face[3], mdb->cagecos[mface->v4]); - hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[1], face[2], co, uvw); + hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); if(hit) { CalcNormFloat(face[0], face[1], face[2], nor); } else { - hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[2], face[3], co, uvw); + hit= meshdeform_tri_intersect(isec->start, end, face[0], face[2], face[3], co, uvw); CalcNormFloat(face[0], face[2], face[3], nor); } } else { - hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[1], face[2], co, uvw); + hit= meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); CalcNormFloat(face[0], face[1], face[2], nor); } if(hit) { - len= VecLenf(isec->start, co)/VecLenf(isec->start, isec->end); + len= VecLenf(isec->start, co)/VecLenf(isec->start, end); if(len < isec->labda) { isec->labda= len; - isec->face= mface; + isec->hit.face = mface; isec->isect= (INPR(isec->vec, nor) <= 0.0f); is= 1; } @@ -1223,20 +1182,18 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float Isect isec; float (*cagecos)[3]; MFace *mface; - float vert[4][3], len; + float vert[4][3], len, end[3]; static float epsilon[3]= {0, 0, 0}; //1e-4, 1e-4, 1e-4}; /* setup isec */ memset(&isec, 0, sizeof(isec)); isec.mode= RE_RAY_MIRROR; /* we want the closest intersection */ isec.lay= -1; - isec.face_last= NULL; - isec.faceorig= NULL; isec.labda= 1e10f; VECADD(isec.start, co1, epsilon); - VECADD(isec.end, co2, epsilon); - VECSUB(isec.vec, isec.end, isec.start); + VECADD(end, co2, epsilon); + VECSUB(isec.vec, end, isec.start); #if 0 /*if(RE_ray_tree_intersect(mdb->raytree, &isec)) {*/ @@ -1244,7 +1201,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float if(meshdeform_intersect(mdb, &isec)) { len= isec.labda; - mface= isec.face; + mface=(MFace*)isec.hit.face; /* create MDefBoundIsect */ isect= BLI_memarena_alloc(mdb->memarena, sizeof(*isect)); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 8f429f7dd90..b274fe681b3 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): André Pinto. * * ***** END GPL LICENSE BLOCK ***** * RE_raytrace.h: ray tracing api, can be used independently from the renderer. @@ -31,84 +31,64 @@ #ifndef RE_RAYTRACE_H #define RE_RAYTRACE_H -/* ray types */ -#define RE_RAY_SHADOW 0 -#define RE_RAY_MIRROR 1 -#define RE_RAY_SHADOW_TRA 2 -/* spatial tree for raytracing acceleration */ -typedef void RayTree; -/* abstraction of face type */ -typedef void RayFace; +/* Internals about raycasting structures can be found on intern/raytree.h */ +typedef struct RayObject RayObject; +typedef struct Isect Isect; +struct DerivedMesh; +struct Mesh; -/* object numbers above this are transformed */ -#define RE_RAY_TRANSFORM_OFFS 0x8000000 +int RayObject_raycast(RayObject *r, Isect *i); +void RayObject_add (RayObject *r, RayObject *); +void RayObject_done(RayObject *r); +void RayObject_free(RayObject *r); -/* convert from pointer to index in array and back, with offset if the - * instance is transformed */ -#define RAY_OBJECT_SET(re, obi) \ - ((obi == NULL)? 0: \ - ((obi - (re)->objectinstance) + ((obi->flag & R_TRANSFORMED)? RE_RAY_TRANSFORM_OFFS: 0))) +/* RayObject constructors */ +RayObject* RayObject_octree_create(int ocres, int size); -#define RAY_OBJECT_GET(re, i) \ - ((re)->objectinstance + ((i >= RE_RAY_TRANSFORM_OFFS)? i-RE_RAY_TRANSFORM_OFFS: i)) +//RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); +RayObject* RayObject_mesh_create(struct Mesh*, void *ob); - -/* struct for intersection data */ -typedef struct Isect { - float start[3]; /* start+vec = end, in ray_tree_intersect */ +/* Ray Intersection */ +struct Isect +{ + float start[3]; float vec[3]; - float end[3]; - - float labda, u, v; /* distance to hitpoint, uv weights */ - - RayFace *face; /* face is where to intersect with */ - int ob; - RayFace *faceorig; /* start face */ - int oborig; - RayFace *face_last; /* for shadow optimize, last intersected face */ - int ob_last; - +/* float end[3]; - not used */ + + float labda, u, v; + + struct + { + void *ob; + void *face; +/* RayObject *obj; */ + } + hit, orig; + + RayObject *last_hit; /* last hit optimization */ + short isect; /* which half of quad */ short mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */ int lay; /* -1 default, set for layer lamps */ + + int skip; /* RE_SKIP_CULLFACE */ - /* only used externally */ float col[4]; /* RGBA for shadow_tra */ - - /* octree only */ - RayFace *facecontr; - int obcontr; - float ddalabda; - short faceisect; /* flag if facecontr was done or not */ - - /* custom pointer to be used in the RayCheckFunc */ + void *userdata; -} Isect; +}; -/* function callbacks for face type abstraction */ -typedef void (*RayCoordsFunc)(RayFace *face, - float **v1, float **v2, float **v3, float **v4); -typedef int (*RayCheckFunc)(Isect *is, int ob, RayFace *face); -typedef float *(*RayObjectTransformFunc)(void *userdata, int ob); +/* ray types */ +#define RE_RAY_SHADOW 0 +#define RE_RAY_MIRROR 1 +#define RE_RAY_SHADOW_TRA 2 -/* tree building and freeing */ -RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, - RayCoordsFunc coordfunc, RayCheckFunc checkfunc, - RayObjectTransformFunc transformfunc, void *userdata); -void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face); -void RE_ray_tree_done(RayTree *tree); -void RE_ray_tree_free(RayTree *tree); +/* skip options */ +#define RE_SKIP_CULLFACE 1 -/* intersection with full tree and single face */ -int RE_ray_tree_intersect(RayTree *tree, Isect *is); -int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc check); -int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, - RayCoordsFunc coordsfunc); +/* TODO use: FLT_MAX? */ +#define RE_RAYTRACE_MAXDIST 1e33 -/* retrieve the diameter of the tree structure, for setting intersection - end distance */ -float RE_ray_tree_max_size(RayTree *tree); #endif /*__RE_RAYTRACE_H__*/ - diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h new file mode 100644 index 00000000000..a1b35ac0465 --- /dev/null +++ b/source/blender/render/intern/include/rayobject.h @@ -0,0 +1,122 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef RE_RAYOBJECT_H +#define RE_RAYOBJECT_H + +#include "RE_raytrace.h" +#include <float.h> + +/* RayObject + + A ray object is everything where we can cast rays like: + * a face/triangle + * an octree + * a bvh tree + * an octree of bvh's + * a bvh of bvh's + + + All types of RayObjects can be created by implementing the + callbacks of the RayObject. + + Due to high computing time evolved with casting on faces + there is a special type of RayObject (named RayFace) + which won't use callbacks like other generic nodes. + + In order to allow a mixture of RayFace+RayObjects, + all RayObjects must be 4byte aligned, allowing us to use the + 2 least significant bits (with the mask 0x02) to define the + type of RayObject. + + This leads to 4 possible types of RayObject, but at the moment + only 2 are used: + + addr&2 - type of object + 0 RayFace + 1 RayObject (generic with API callbacks) + 2 unused + 3 unused + + 0 was choosed to RayFace because thats the one where speed will be needed. + + You actually don't need to care about this if you are only using the API + described on RE_raytrace.h + */ + +typedef struct RayFace +{ + float *v1, *v2, *v3, *v4; + + void *ob; + void *face; + +} RayFace; + +struct RayObject +{ + struct RayObjectAPI *api; + +}; + +typedef int (*RayObject_raycast_callback)(RayObject *, Isect *); +typedef void (*RayObject_add_callback)(RayObject *, RayObject *); +typedef void (*RayObject_done_callback)(RayObject *); +typedef void (*RayObject_free_callback)(RayObject *); +typedef void (*RayObject_bb_callback)(RayObject *, float *min, float *max); + +typedef struct RayObjectAPI +{ + RayObject_raycast_callback raycast; + RayObject_add_callback add; + RayObject_done_callback done; + RayObject_free_callback free; + RayObject_bb_callback bb; + +} RayObjectAPI; + +//TODO use intptr_t +#define RayObject_align(o) ((RayObject*)(((int)o)&(~3))) +#define RayObject_unalign(o) ((RayObject*)(((int)o)|1)) +#define RayObject_isFace(o) ((((int)o)&3) == 0) + +/* + * Extend min/max coords so that the rayobject is inside them + */ +void RayObject_merge_bb(RayObject *ob, float *min, float *max); + +/* + * This function differs from RayObject_raycast + * RayObject_intersect does NOT perform last-hit optimization + * So this is probably a function to call inside raytrace structures + */ +int RayObject_intersect(RayObject *r, Isect *i); + +#define ISECT_EPSILON ((float)FLT_EPSILON) + +#endif diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index ab3758781ce..4846fe8d0e4 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -53,6 +53,7 @@ struct VlakTableNode; struct GHash; struct RenderBuckets; struct ObjectInstanceRen; +struct RayObject; #define TABLEINITSIZE 1024 #define LAMPINITSIZE 256 @@ -168,7 +169,8 @@ struct Render ListBase parts; /* octree tables and variables for raytrace */ - void *raytree; + struct RayObject *raytree; + struct RayObject *rayfaces; /* TODO Temporary */ /* occlusion tree */ void *occlusiontree; @@ -491,8 +493,7 @@ typedef struct LampRen { short YF_glowtype; /* ray optim */ - VlakRen *vlr_last[BLENDER_MAX_THREADS]; - ObjectInstanceRen *obi_last[BLENDER_MAX_THREADS]; + struct RayObject *last_hit[BLENDER_MAX_THREADS]; struct MTex *mtex[MAX_MTEX]; diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c new file mode 100644 index 00000000000..ee364d3586c --- /dev/null +++ b/source/blender/render/intern/source/rayobject.c @@ -0,0 +1,276 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include "assert.h" + +#include "BKE_utildefines.h" + +#include "RE_raytrace.h" +#include "rayobject.h" + +/* ray - triangle or quad intersection */ +static int intersect_rayface(RayFace *face, Isect *is) +{ + float co1[3],co2[3],co3[3],co4[3]; + float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; + float m0, m1, m2, divdet, det1; + short ok=0; + + if(is->orig.ob == face->ob && is->orig.face == face->face) + return 0; + + /* disabled until i got real & fast cylinder checking, this code doesnt work proper for faster strands */ + // if(is->mode==RE_RAY_SHADOW && is->vlr->flag & R_STRAND) + // return intersection_strand(is); + + + VECCOPY(co1, face->v1); + VECCOPY(co2, face->v2); + + //TODO if(v4) { SWAP(float*, v3, v4); } + if(face->v4) + { + VECCOPY(co3, face->v4); + VECCOPY(co4, face->v3); + } + else + { + VECCOPY(co3, face->v3); + } + + t00= co3[0]-co1[0]; + t01= co3[1]-co1[1]; + t02= co3[2]-co1[2]; + t10= co3[0]-co2[0]; + t11= co3[1]-co2[1]; + t12= co3[2]-co2[2]; + + r0= is->vec[0]; + r1= is->vec[1]; + r2= is->vec[2]; + + x0= t12*r1-t11*r2; + x1= t10*r2-t12*r0; + x2= t11*r0-t10*r1; + + divdet= t00*x0+t01*x1+t02*x2; + + m0= is->start[0]-co3[0]; + m1= is->start[1]-co3[1]; + m2= is->start[2]-co3[2]; + det1= m0*x0+m1*x1+m2*x2; + + if(divdet!=0.0f) { + float u; + + divdet= 1.0f/divdet; + u= det1*divdet; + if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) { + float v, cros0, cros1, cros2; + + cros0= m1*t02-m2*t01; + cros1= m2*t00-m0*t02; + cros2= m0*t01-m1*t00; + v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); + + if(v<ISECT_EPSILON && (u + v) > -(1.0f+ISECT_EPSILON)) { + float labda; + labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); + + if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { + is->labda= labda; + is->u= u; is->v= v; + ok= 1; + } + } + } + } + + if(ok==0 && face->v4) { + + t20= co3[0]-co4[0]; + t21= co3[1]-co4[1]; + t22= co3[2]-co4[2]; + + divdet= t20*x0+t21*x1+t22*x2; + if(divdet!=0.0f) { + float u; + divdet= 1.0f/divdet; + u = det1*divdet; + + if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) { + float v, cros0, cros1, cros2; + cros0= m1*t22-m2*t21; + cros1= m2*t20-m0*t22; + cros2= m0*t21-m1*t20; + v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); + + if(v<ISECT_EPSILON && (u + v) >-(1.0f+ISECT_EPSILON)) { + float labda; + labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); + + if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { + ok= 2; + is->labda= labda; + is->u= u; is->v= v; + } + } + } + } + } + + if(ok) { + is->isect= ok; // wich half of the quad + +/* + TODO + if(is->mode!=RE_RAY_SHADOW) { + / * for mirror & tra-shadow: large faces can be filled in too often, this prevents + a face being detected too soon... * / + if(is->labda > is->ddalabda) { + return 0; + } + } +*/ + +#if 0 + TODO + /* when a shadow ray leaves a face, it can be little outside the edges of it, causing + intersection to be detected in its neighbour face */ + if(is->facecontr && is->faceisect); // optimizing, the tests below are not needed + else if(is->labda< .1) { + RayFace *face= is->orig.face; + float *origv1, *origv2, *origv3, *origv4; + short de= 0; + + coordsfunc(face, &origv1, &origv2, &origv3, &origv4); + + if(ob == is->orig.ob) { + if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++; + if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++; + if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++; + if(origv4) { + if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++; + } + } + if(de) { + /* so there's a shared edge or vertex, let's intersect ray with face + itself, if that's true we can safely return 1, otherwise we assume + the intersection is invalid, 0 */ + + if(is->facecontr==NULL) { + is->obcontr= is->orig.ob; + is->facecontr= face; + is->faceisect= intersection2(face, is->orig.ob, transformfunc, coordsfunc, is->userdata, + -r0, -r1, -r2, + is->start[0], is->start[1], is->start[2]); + } + + if(is->faceisect) return 1; + return 0; + } + } +#endif + + is->hit.ob = face->ob; + is->hit.face = face->face; + return 1; + } + + return 0; +} + +int RayObject_raycast(RayObject *r, Isect *i) +{ + if(i->mode==RE_RAY_SHADOW && i->last_hit && RayObject_intersect(i->last_hit, i)) + return 1; + + return RayObject_intersect(r, i); +} + +int RayObject_intersect(RayObject *r, Isect *i) +{ + assert(i->mode==RE_RAY_SHADOW); + if(RayObject_isFace(r)) + { + return intersect_rayface( (RayFace*) r, i); + } + else + { + //TODO should be done somewhere else +// float len = Normalize( i->vec ); + int hit; + i->vec[0] *= i->labda; + i->vec[1] *= i->labda; + i->vec[2] *= i->labda; + i->labda = 1.0f; //RE_RAYTRACE_MAXDIST; //len; + + r = RayObject_align( r ); + + hit = r->api->raycast( r, i ); +// i->labda /= len; + + return hit; + } +} + +void RayObject_add(RayObject *r, RayObject *o) +{ + r = RayObject_align( r ); + return r->api->add( r, o ); +} + +void RayObject_done(RayObject *r) +{ + r = RayObject_align( r ); + r->api->done( r ); +} + +void RayObject_free(RayObject *r) +{ + r = RayObject_align( r ); + r->api->free( r ); +} + +void RayObject_merge_bb(RayObject *r, float *min, float *max) +{ + if(RayObject_isFace(r)) + { + RayFace *face = (RayFace*)r; + DO_MINMAX( face->v1, min, max ); + DO_MINMAX( face->v2, min, max ); + DO_MINMAX( face->v3, min, max ); + if(face->v4) DO_MINMAX( face->v4, min, max ); + } + else + { + r = RayObject_align( r ); + r->api->bb( r, min, max ); + } +} + diff --git a/source/blender/render/intern/source/rayobject_mesh.c b/source/blender/render/intern/source/rayobject_mesh.c new file mode 100644 index 00000000000..7b8bca38172 --- /dev/null +++ b/source/blender/render/intern/source/rayobject_mesh.c @@ -0,0 +1,128 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include "rayobject.h" + +#include "MEM_guardedalloc.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "BKE_utildefines.h" + +typedef struct RayMesh +{ + RayObject rayobj; + + Mesh *mesh; + void *ob; + + RayFace *faces; + int num_faces; + +} RayMesh; + +static int RayObject_mesh_intersect(RayObject *o, Isect *isec); +static void RayObject_mesh_add(RayObject *o, RayObject *ob); +static void RayObject_mesh_done(RayObject *o); +static void RayObject_mesh_free(RayObject *o); +static void RayObject_mesh_bb(RayObject *o, float *min, float *max); + +static RayObjectAPI mesh_api = +{ + RayObject_mesh_intersect, + RayObject_mesh_add, + RayObject_mesh_done, + RayObject_mesh_free, + RayObject_mesh_bb +}; + + +static int RayObject_mesh_intersect(RayObject *o, Isect *isec) +{ + RayMesh *rm= (RayMesh*)o; + int i, hit = 0; + for(i = 0; i<rm->num_faces; i++) + if(RayObject_raycast( (RayObject*)rm->faces+i, isec )) + { + hit = 1; + if(isec->mode == RE_RAY_SHADOW) + break; + } + + return hit; +} + +static void RayObject_mesh_add(RayObject *o, RayObject *ob) +{ +} + +static void RayObject_mesh_done(RayObject *o) +{ +} + +static void RayObject_mesh_free(RayObject *o) +{ + RayMesh *rm= (RayMesh*)o; + MEM_freeN( rm->faces ); + MEM_freeN( rm ); +} + +static void RayObject_mesh_bb(RayObject *o, float *min, float *max) +{ + RayMesh *rm= (RayMesh*)o; + int i; + for(i = 0; i<rm->mesh->totvert; i++) + DO_MINMAX( rm->mesh->mvert[i].co, min, max); +} + +RayObject* RayObject_mesh_create(Mesh *mesh, void *ob) +{ + RayMesh *rm= MEM_callocN(sizeof(RayMesh), "Octree"); + int i; + RayFace *face; + MFace *mface; + + rm->rayobj.api = &mesh_api; + rm->mesh = mesh; + rm->faces = MEM_callocN(sizeof(RayFace)*mesh->totface, "octree rayobject nodes"); + rm->num_faces = mesh->totface; + + face = rm->faces; + mface = mesh->mface; + for(i=0; i<mesh->totface; i++, face++, mface++) + { + face->v1 = mesh->mvert[mface->v1].co; + face->v2 = mesh->mvert[mface->v2].co; + face->v3 = mesh->mvert[mface->v3].co; + face->v4 = mface->v4 ? mesh->mvert[mface->v4].co : NULL; + + face->ob = ob; + face->face = (void*)i; + } + + return RayObject_unalign((RayObject*) rm); +} diff --git a/source/blender/render/intern/source/raytrace.c b/source/blender/render/intern/source/rayobject_octree.c index 09d3711885a..a738898871b 100644 --- a/source/blender/render/intern/source/raytrace.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -32,6 +32,7 @@ #include <string.h> #include <stdlib.h> #include <float.h> +#include <assert.h> #include "MEM_guardedalloc.h" @@ -41,10 +42,9 @@ #include "BLI_arithb.h" -#include "RE_raytrace.h" +#include "rayobject.h" /* ********** structs *************** */ - #define BRANCH_ARRAY 1024 #define NODE_ARRAY 4096 @@ -60,13 +60,14 @@ typedef struct OcVal typedef struct Node { - struct RayFace *v[8]; - int ob[8]; + struct RayObject *v[8]; struct OcVal ov[8]; struct Node *next; } Node; typedef struct Octree { + RayObject rayobj; + struct Branch **adrbranch; struct Node **adrnode; float ocsize; /* ocsize: mult factor, max size octree */ @@ -74,19 +75,29 @@ typedef struct Octree { float min[3], max[3]; int ocres; int branchcount, nodecount; - char *ocface; /* during building only */ - RayCoordsFunc coordsfunc; - RayCheckFunc checkfunc; - RayObjectTransformFunc transformfunc; - void *userdata; -} Octree; -/* ******** globals ***************** */ + /* during building only */ + char *ocface; + + RayObject **ro_nodes; + int ro_nodes_size, ro_nodes_used; + +} Octree; -/* just for statistics */ -static int raycount; -static int accepted, rejected, coherent_ray; +static int RayObject_octree_intersect(RayObject *o, Isect *isec); +static void RayObject_octree_add(RayObject *o, RayObject *ob); +static void RayObject_octree_done(RayObject *o); +static void RayObject_octree_free(RayObject *o); +static void RayObject_octree_bb(RayObject *o, float *min, float *max); +static RayObjectAPI octree_api = +{ + RayObject_octree_intersect, + RayObject_octree_add, + RayObject_octree_done, + RayObject_octree_free, + RayObject_octree_bb +}; /* **************** ocval method ******************* */ /* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */ @@ -233,7 +244,7 @@ static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3] return 0; } -static void ocwrite(Octree *oc, int ob, RayFace *face, int quad, short x, short y, short z, float rtf[][3]) +static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short z, float rtf[][3]) { Branch *br; Node *no; @@ -283,8 +294,7 @@ static void ocwrite(Octree *oc, int ob, RayFace *face, int quad, short x, short while(no->v[a]!=NULL) a++; } - no->v[a]= face; - no->ob[a]= ob; + no->v[a]= (RayObject*)face; if(quad) calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]); @@ -374,13 +384,10 @@ static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocfa ocface[oc->ocres*ocx2+ocy2]=1; } -static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin) +static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin, short *ocmax) { - short *ocmax; int a, x, y, y1, y2; - ocmax=ocmin+3; - for(x=ocmin[c1];x<=ocmax[c1];x++) { a= oc->ocres*x; for(y=ocmin[c2];y<=ocmax[c2];y++) { @@ -399,7 +406,7 @@ static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *oc } } -void RE_ray_tree_free(RayTree *tree) +static void RayObject_octree_free(RayObject *tree) { Octree *oc= (Octree*)tree; @@ -439,65 +446,38 @@ void RE_ray_tree_free(RayTree *tree) MEM_freeN(oc); } -RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayCoordsFunc coordsfunc, RayCheckFunc checkfunc, RayObjectTransformFunc transformfunc, void *userdata) + +RayObject *RayObject_octree_create(int ocres, int size) { - Octree *oc; - float t00, t01, t02; - int c, ocres2; + Octree *oc= MEM_callocN(sizeof(Octree), "Octree"); - oc= MEM_callocN(sizeof(Octree), "Octree"); - oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); - oc->adrnode= MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes"); - - oc->coordsfunc= coordsfunc; - oc->checkfunc= checkfunc; - oc->transformfunc= transformfunc; - oc->userdata= userdata; - - /* only for debug info */ - raycount=0; - accepted= 0; - rejected= 0; - coherent_ray= 0; + oc->rayobj.api = &octree_api; - /* fill main octree struct */ - oc->ocres= ocres; - ocres2= oc->ocres*oc->ocres; + oc->ocres = ocres; - VECCOPY(oc->min, min); - VECCOPY(oc->max, max); + oc->ro_nodes = MEM_callocN(sizeof(RayObject*)*size, "octree rayobject nodes"); + oc->ro_nodes_size = size; + oc->ro_nodes_used = 0; - oc->adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree"); - /* the lookup table, per face, for which nodes to fill in */ - oc->ocface= MEM_callocN( 3*ocres2 + 8, "ocface"); - memset(oc->ocface, 0, 3*ocres2); + return RayObject_unalign((RayObject*) oc); +} - for(c=0;c<3;c++) { /* octree enlarge, still needed? */ - oc->min[c]-= 0.01f; - oc->max[c]+= 0.01f; - } - t00= oc->max[0]-oc->min[0]; - t01= oc->max[1]-oc->min[1]; - t02= oc->max[2]-oc->min[2]; - - /* this minus 0.1 is old safety... seems to be needed? */ - oc->ocfacx= (oc->ocres-0.1)/t00; - oc->ocfacy= (oc->ocres-0.1)/t01; - oc->ocfacz= (oc->ocres-0.1)/t02; - - oc->ocsize= sqrt(t00*t00+t01*t01+t02*t02); /* global, max size octree */ +static void RayObject_octree_add(RayObject *tree, RayObject *node) +{ + Octree *oc = (Octree*)tree; - return (RayTree*)oc; + assert( oc->ro_nodes_used < oc->ro_nodes_size ); + oc->ro_nodes[ oc->ro_nodes_used++ ] = node; } -void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) +static void octree_fill_rayface(Octree *oc, RayFace *face) { - Octree *oc = (Octree*)tree; - float *v1, *v2, *v3, *v4, ocfac[3], rtf[4][3]; + float ocfac[3], rtf[4][3]; float co1[3], co2[3], co3[3], co4[3]; - short rts[4][3], ocmin[6], *ocmax; + short rts[4][3]; + short ocmin[3], ocmax[3]; char *ocface= oc->ocface; // front, top, size view of face, to fill in int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2; @@ -507,28 +487,12 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) ocres2= oc->ocres*oc->ocres; - ocmax= ocmin+3; + VECCOPY(co1, face->v1); + VECCOPY(co2, face->v2); + VECCOPY(co3, face->v3); + if(face->v4) + VECCOPY(co4, face->v4); - oc->coordsfunc(face, &v1, &v2, &v3, &v4); - - VECCOPY(co1, v1); - VECCOPY(co2, v2); - VECCOPY(co3, v3); - if(v4) - VECCOPY(co4, v4); - - if(ob >= RE_RAY_TRANSFORM_OFFS) { - float (*mat)[4]= (float(*)[4])oc->transformfunc(oc->userdata, ob); - - if(mat) { - Mat4MulVecfl(mat, co1); - Mat4MulVecfl(mat, co2); - Mat4MulVecfl(mat, co3); - if(v4) - Mat4MulVecfl(mat, co4); - } - } - for(c=0;c<3;c++) { rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ; rts[0][c]= (short)rtf[0][c]; @@ -536,7 +500,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) rts[1][c]= (short)rtf[1][c]; rtf[2][c]= (co3[c]-oc->min[c])*ocfac[c] ; rts[2][c]= (short)rtf[2][c]; - if(v4) { + if(face->v4) { rtf[3][c]= (co4[c]-oc->min[c])*ocfac[c] ; rts[3][c]= (short)rtf[3][c]; } @@ -546,7 +510,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) oc1= rts[0][c]; oc2= rts[1][c]; oc3= rts[2][c]; - if(v4==NULL) { + if(face->v4==NULL) { ocmin[c]= MIN3(oc1,oc2,oc3); ocmax[c]= MAX3(oc1,oc2,oc3); } @@ -560,7 +524,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) } if(ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) { - ocwrite(oc, ob, face, (v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf); + ocwrite(oc, face, (face->v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf); } else { @@ -570,7 +534,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) d2dda(oc, 1,2,0,1,ocface+ocres2,rts,rtf); d2dda(oc, 1,2,0,2,ocface,rts,rtf); d2dda(oc, 1,2,1,2,ocface+2*ocres2,rts,rtf); - if(v4==NULL) { + if(face->v4==NULL) { d2dda(oc, 2,0,0,1,ocface+ocres2,rts,rtf); d2dda(oc, 2,0,0,2,ocface,rts,rtf); d2dda(oc, 2,0,1,2,ocface+2*ocres2,rts,rtf); @@ -584,9 +548,9 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) d2dda(oc, 3,0,1,2,ocface+2*ocres2,rts,rtf); } /* nothing todo with triangle..., just fills :) */ - filltriangle(oc, 0,1,ocface+ocres2,ocmin); - filltriangle(oc, 0,2,ocface,ocmin); - filltriangle(oc, 1,2,ocface+2*ocres2,ocmin); + filltriangle(oc, 0,1,ocface+ocres2,ocmin,ocmax); + filltriangle(oc, 0,2,ocface,ocmin,ocmax); + filltriangle(oc, 1,2,ocface+2*ocres2,ocmin,ocmax); /* init static vars here */ face_in_node(face, 0,0,0, rtf); @@ -599,7 +563,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) for(z=ocmin[2];z<=ocmax[2];z++) { if(ocface[b+z] && ocface[a+z]) { if(face_in_node(NULL, x, y, z, rtf)) - ocwrite(oc, ob, face, (v4 != NULL), x,y,z, rtf); + ocwrite(oc, face, (face->v4 != NULL), x,y,z, rtf); } } } @@ -625,433 +589,116 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) } } -void RE_ray_tree_done(RayTree *tree) -{ - Octree *oc= (Octree*)tree; - - MEM_freeN(oc->ocface); - oc->ocface= NULL; -} - -/* ************ raytracer **************** */ - -#define ISECT_EPSILON ((float)FLT_EPSILON) - -/* only for self-intersecting test with current render face (where ray left) */ -static int intersection2(RayFace *face, int ob, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc, void *userdata, float r0, float r1, float r2, float rx1, float ry1, float rz1) +static void RayObject_octree_done(RayObject *tree) { - float *v1, *v2, *v3, *v4, co1[3], co2[3], co3[3], co4[3]; - float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22; - float m0, m1, m2, divdet, det, det1; - float u1, v, u2; - - coordsfunc(face, &v1, &v2, &v3, &v4); - - /* happens for baking with non existing face */ - if(v1==NULL) - return 1; - - if(v4) { - SWAP(float*, v3, v4); - } - - VECCOPY(co1, v1); - VECCOPY(co2, v2); - VECCOPY(co3, v3); - if(v4) - VECCOPY(co4, v4); - - if(ob >= RE_RAY_TRANSFORM_OFFS) { - float (*mat)[4]= (float(*)[4])transformfunc(userdata, ob); - - if(mat) { - Mat4MulVecfl(mat, co1); - Mat4MulVecfl(mat, co2); - Mat4MulVecfl(mat, co3); - if(v4) - Mat4MulVecfl(mat, co4); - } - } + Octree *oc = (Octree*)tree; + int c; + float t00, t01, t02; + int ocres2 = oc->ocres*oc->ocres; - t00= co3[0]-co1[0]; - t01= co3[1]-co1[1]; - t02= co3[2]-co1[2]; - t10= co3[0]-co2[0]; - t11= co3[1]-co2[1]; - t12= co3[2]-co2[2]; + INIT_MINMAX(oc->min, oc->max); - x0= t11*r2-t12*r1; - x1= t12*r0-t10*r2; - x2= t10*r1-t11*r0; - - divdet= t00*x0+t01*x1+t02*x2; - - m0= rx1-co3[0]; - m1= ry1-co3[1]; - m2= rz1-co3[2]; - det1= m0*x0+m1*x1+m2*x2; - - if(divdet!=0.0f) { - u1= det1/divdet; - - if(u1<ISECT_EPSILON) { - det= t00*(m1*r2-m2*r1); - det+= t01*(m2*r0-m0*r2); - det+= t02*(m0*r1-m1*r0); - v= det/divdet; - - if(v<ISECT_EPSILON && (u1 + v) > -(1.0f+ISECT_EPSILON)) { - return 1; - } - } - } - - if(v4) { - - t20= co3[0]-co4[0]; - t21= co3[1]-co4[1]; - t22= co3[2]-co4[2]; - - divdet= t20*x0+t21*x1+t22*x2; - if(divdet!=0.0f) { - u2= det1/divdet; + /* Calculate Bounding Box */ + for(c=0; c<oc->ro_nodes_used; c++) + RayObject_merge_bb(oc->ro_nodes[c], oc->min, oc->max); - if(u2<ISECT_EPSILON) { - det= t20*(m1*r2-m2*r1); - det+= t21*(m2*r0-m0*r2); - det+= t22*(m0*r1-m1*r0); - v= det/divdet; - - if(v<ISECT_EPSILON && (u2 + v) >= -(1.0f+ISECT_EPSILON)) { - return 2; - } - } - } - } - return 0; -} - -#if 0 -/* ray - line intersection */ -/* disabled until i got real & fast cylinder checking, this code doesnt work proper -for faster strands */ - -static int intersection_strand(Isect *is) -{ - float v1[3], v2[3]; /* length of strand */ - float axis[3], rc[3], nor[3], radline, dist, len; - - /* radius strand */ - radline= 0.5f*VecLenf(is->vlr->v1->co, is->vlr->v2->co); - - VecMidf(v1, is->vlr->v1->co, is->vlr->v2->co); - VecMidf(v2, is->vlr->v3->co, is->vlr->v4->co); - - VECSUB(rc, v1, is->start); /* vector from base ray to base cylinder */ - VECSUB(axis, v2, v1); /* cylinder axis */ - - CROSS(nor, is->vec, axis); - len= VecLength(nor); - - if(len<FLT_EPSILON) - return 0; - - dist= INPR(rc, nor)/len; /* distance between ray and axis cylinder */ + /* Alloc memory */ + oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); + oc->adrnode= MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes"); - if(dist<radline && dist>-radline) { - float dot1, dot2, dot3, rlen, alen, div; - float labda; - - /* calculating the intersection point of shortest distance */ - dot1 = INPR(rc, is->vec); - dot2 = INPR(is->vec, axis); - dot3 = INPR(rc, axis); - rlen = INPR(is->vec, is->vec); - alen = INPR(axis, axis); - - div = alen * rlen - dot2 * dot2; - if (ABS(div) < FLT_EPSILON) - return 0; - - labda = (dot1*dot2 - dot3*rlen)/div; - - radline/= sqrt(alen); - - /* labda: where on axis do we have closest intersection? */ - if(labda >= -radline && labda <= 1.0f+radline) { - VlakRen *vlr= is->faceorig; - VertRen *v1= is->vlr->v1, *v2= is->vlr->v2, *v3= is->vlr->v3, *v4= is->vlr->v4; - /* but we dont do shadows from faces sharing edge */ - - if(v1==vlr->v1 || v2==vlr->v1 || v3==vlr->v1 || v4==vlr->v1) return 0; - if(v1==vlr->v2 || v2==vlr->v2 || v3==vlr->v2 || v4==vlr->v2) return 0; - if(v1==vlr->v3 || v2==vlr->v3 || v3==vlr->v3 || v4==vlr->v3) return 0; - if(vlr->v4) { - if(v1==vlr->v4 || v2==vlr->v4 || v3==vlr->v4 || v4==vlr->v4) return 0; - } - return 1; - } - } - return 0; -} -#endif - -/* ray - triangle or quad intersection */ -int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc) -{ - RayFace *face= is->face; - int ob= is->ob; - float *v1,*v2,*v3,*v4,co1[3],co2[3],co3[3],co4[3]; - float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; - float m0, m1, m2, divdet, det1; - short ok=0; - - /* disabled until i got real & fast cylinder checking, this code doesnt work proper - for faster strands */ -// if(is->mode==RE_RAY_SHADOW && is->vlr->flag & R_STRAND) -// return intersection_strand(is); + oc->adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree"); - coordsfunc(face, &v1, &v2, &v3, &v4); - - if(v4) { - SWAP(float*, v3, v4); - } + /* the lookup table, per face, for which nodes to fill in */ + oc->ocface= MEM_callocN( 3*ocres2 + 8, "ocface"); + memset(oc->ocface, 0, 3*ocres2); - VECCOPY(co1, v1); - VECCOPY(co2, v2); - VECCOPY(co3, v3); - if(v4) - VECCOPY(co4, v4); - - if(ob) { - float (*mat)[4]= (float(*)[4])transformfunc(is->userdata, ob); - - if(mat) { - Mat4MulVecfl(mat, co1); - Mat4MulVecfl(mat, co2); - Mat4MulVecfl(mat, co3); - if(v4) - Mat4MulVecfl(mat, co4); - } + for(c=0;c<3;c++) { /* octree enlarge, still needed? */ + oc->min[c]-= 0.01f; + oc->max[c]+= 0.01f; } - t00= co3[0]-co1[0]; - t01= co3[1]-co1[1]; - t02= co3[2]-co1[2]; - t10= co3[0]-co2[0]; - t11= co3[1]-co2[1]; - t12= co3[2]-co2[2]; - - r0= is->vec[0]; - r1= is->vec[1]; - r2= is->vec[2]; + t00= oc->max[0]-oc->min[0]; + t01= oc->max[1]-oc->min[1]; + t02= oc->max[2]-oc->min[2]; - x0= t12*r1-t11*r2; - x1= t10*r2-t12*r0; - x2= t11*r0-t10*r1; - - divdet= t00*x0+t01*x1+t02*x2; - - m0= is->start[0]-co3[0]; - m1= is->start[1]-co3[1]; - m2= is->start[2]-co3[2]; - det1= m0*x0+m1*x1+m2*x2; + /* this minus 0.1 is old safety... seems to be needed? */ + oc->ocfacx= (oc->ocres-0.1)/t00; + oc->ocfacy= (oc->ocres-0.1)/t01; + oc->ocfacz= (oc->ocres-0.1)/t02; - if(divdet!=0.0f) { - float u; + oc->ocsize= sqrt(t00*t00+t01*t01+t02*t02); /* global, max size octree */ - divdet= 1.0f/divdet; - u= det1*divdet; - if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) { - float v, cros0, cros1, cros2; - - cros0= m1*t02-m2*t01; - cros1= m2*t00-m0*t02; - cros2= m0*t01-m1*t00; - v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); - - if(v<ISECT_EPSILON && (u + v) > -(1.0f+ISECT_EPSILON)) { - float labda; - labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); - - if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { - is->labda= labda; - is->u= u; is->v= v; - ok= 1; - } - } - } + for(c=0; c<oc->ro_nodes_used; c++) + { + assert( RayObject_isFace(oc->ro_nodes[c]) ); + octree_fill_rayface(oc, (RayFace*)oc->ro_nodes[c]); } - if(ok==0 && v4) { - - t20= co3[0]-co4[0]; - t21= co3[1]-co4[1]; - t22= co3[2]-co4[2]; - - divdet= t20*x0+t21*x1+t22*x2; - if(divdet!=0.0f) { - float u; - divdet= 1.0f/divdet; - u = det1*divdet; - - if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) { - float v, cros0, cros1, cros2; - cros0= m1*t22-m2*t21; - cros1= m2*t20-m0*t22; - cros2= m0*t21-m1*t20; - v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); + MEM_freeN(oc->ocface); + MEM_freeN(oc->ro_nodes); - if(v<ISECT_EPSILON && (u + v) >-(1.0f+ISECT_EPSILON)) { - float labda; - labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); - - if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { - ok= 2; - is->labda= labda; - is->u= u; is->v= v; - } - } - } - } - } - - if(ok) { - is->isect= ok; // wich half of the quad - - if(is->mode!=RE_RAY_SHADOW) { - /* for mirror & tra-shadow: large faces can be filled in too often, this prevents - a face being detected too soon... */ - if(is->labda > is->ddalabda) { - return 0; - } - } - - /* when a shadow ray leaves a face, it can be little outside the edges of it, causing - intersection to be detected in its neighbour face */ - - if(is->facecontr && is->faceisect); // optimizing, the tests below are not needed - else if(is->labda< .1) { - RayFace *face= is->faceorig; - float *origv1, *origv2, *origv3, *origv4; - short de= 0; - - coordsfunc(face, &origv1, &origv2, &origv3, &origv4); - - if(ob == is->oborig) { - if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++; - if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++; - if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++; - if(origv4) { - if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++; - } - } - if(de) { - /* so there's a shared edge or vertex, let's intersect ray with face - itself, if that's true we can safely return 1, otherwise we assume - the intersection is invalid, 0 */ - - if(is->facecontr==NULL) { - is->obcontr= is->oborig; - is->facecontr= face; - is->faceisect= intersection2(face, is->oborig, transformfunc, coordsfunc, is->userdata, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]); - } - - if(is->faceisect) return 1; - return 0; - } - } - - return 1; - } + printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx ); + printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy ); + printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz ); +} - return 0; +static void RayObject_octree_bb(RayObject *tree, float *min, float *max) +{ + Octree *oc = (Octree*)tree; + DO_MINMAX(oc->min, min, max); + DO_MINMAX(oc->max, min, max); } /* check all faces in this node */ -static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc checkfunc) +static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) { - RayFace *face; - int ob; short nr=0; - OcVal *ov; /* return on any first hit */ if(is->mode==RE_RAY_SHADOW) { - - face= no->v[0]; - ob= no->ob[0]; - while(face) { - - if(!(is->faceorig == face && is->oborig == ob)) { - - if(checkfunc(is, ob, face)) { - - ov= no->ov+nr; - if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - //accepted++; - is->ob= ob; - is->face= face; - if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) { - is->ob_last= ob; - is->face_last= face; - return 1; - } - } - //else rejected++; - } - } + for(; no; no = no->next) + for(nr=0; nr<8; nr++) + { + RayObject *face = no->v[nr]; + OcVal *ov = no->ov+nr; + + if(!face) break; //TODO? return 0; - nr++; - if(nr==8) { - no= no->next; - if(no==0) return 0; - nr=0; + if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) + { + if( RayObject_intersect(face,is) ) + return 1; } - face= no->v[nr]; - ob= no->ob[nr]; } } - else { /* else mirror or glass or shadowtra, return closest face */ + else + { /* else mirror or glass or shadowtra, return closest face */ Isect isect; int found= 0; + assert(0); + is->labda= 1.0f; /* needed? */ - isect= *is; /* copy for sorting */ + isect= *is; /* copy for sorting */ - face= no->v[0]; - ob= no->ob[0]; - while(face) { - - if(!(is->faceorig == face && is->oborig == ob)) { - if(checkfunc(is, ob, face)) { - ov= no->ov+nr; - if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - //accepted++; - - isect.ob= ob; - isect.face= face; - if(RE_ray_face_intersection(&isect, oc->transformfunc, oc->coordsfunc)) { - if(isect.labda<is->labda) { - *is= isect; - found= 1; - } - - } - } - //else rejected++; - } - } + for(; no; no = no->next) + for(nr=0; nr<8; nr++) + { + RayObject *face = no->v[nr]; + OcVal *ov = no->ov+nr; - nr++; - if(nr==8) { - no= no->next; - if(no==NULL) break; - nr=0; + if(!face) return 0; + + if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) + { + + if( RayObject_raycast(face,is) ) + if(isect.labda<is->labda) { + *is= isect; + found= 1; + } } - face= no->v[nr]; - ob= no->ob[nr]; } return found; @@ -1175,21 +822,14 @@ static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, i */ -int RE_ray_tree_intersect(RayTree *tree, Isect *is) -{ - Octree *oc= (Octree*)tree; - - return RE_ray_tree_intersect_check(tree, is, oc->checkfunc); -} - /* return 1: found valid intersection */ -/* starts with is->faceorig */ -int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc) +/* starts with is->orig.face */ +static int RayObject_octree_intersect(RayObject *tree, Isect *is) { Octree *oc= (Octree*)tree; Node *no; OcVal ocval; - float vec1[3], vec2[3]; + float vec1[3], vec2[3], end[3]; float u1,u2,ox1,ox2,oy1,oy2,oz1,oz2; float labdao,labdax,ldx,labday,ldy,labdaz,ldz, ddalabda; int dx,dy,dz; @@ -1200,45 +840,51 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc if(oc->branchcount==0) return 0; /* do this before intersect calls */ +#if 0 is->facecontr= NULL; /* to check shared edge */ is->obcontr= 0; is->faceisect= is->isect= 0; /* shared edge, quad half flag */ is->userdata= oc->userdata; +#endif +#if 0 /* only for shadow! */ if(is->mode==RE_RAY_SHADOW) { - /* check with last intersected shadow face */ - if(is->face_last!=NULL && !(is->face_last==is->faceorig && is->ob_last==is->oborig)) { - if(checkfunc(is, is->ob_last, is->face_last)) { - is->ob= is->ob_last; - is->face= is->face_last; + /* TODO check with last intersected shadow face */ + if(is->last.face!=NULL && !(is->last.face==is->orig.face && is->last.ob==is->orig.ob)) { + if(checkfunc(is, is->last.ob, is->last.face)) { + is->ob= is->last.ob; + is->face= is->last.face; VECSUB(is->vec, is->end, is->start); if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) return 1; } } } +#endif - ldx= is->end[0] - is->start[0]; + VECADDFAC( end, is->start, is->vec, is->labda ); + ldx= end[0] - is->start[0]; u1= 0.0f; u2= 1.0f; - + /* clip with octree cube */ if(cliptest(-ldx, is->start[0]-oc->min[0], &u1,&u2)) { if(cliptest(ldx, oc->max[0]-is->start[0], &u1,&u2)) { - ldy= is->end[1] - is->start[1]; + ldy= end[1] - is->start[1]; if(cliptest(-ldy, is->start[1]-oc->min[1], &u1,&u2)) { if(cliptest(ldy, oc->max[1]-is->start[1], &u1,&u2)) { - ldz= is->end[2] - is->start[2]; + ldz = end[2] - is->start[2]; if(cliptest(-ldz, is->start[2]-oc->min[2], &u1,&u2)) { if(cliptest(ldz, oc->max[2]-is->start[2], &u1,&u2)) { c1=1; if(u2<1.0f) { - is->end[0]= is->start[0]+u2*ldx; - is->end[1]= is->start[1]+u2*ldy; - is->end[2]= is->start[2]+u2*ldz; + end[0]= is->start[0]+u2*ldx; + end[1]= is->start[1]+u2*ldy; + end[2]= is->start[2]+u2*ldz; } if(u1>0.0f) { + assert( 0 ); is->start[0]+=u1*ldx; is->start[1]+=u1*ldy; is->start[2]+=u1*ldz; @@ -1259,9 +905,9 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc ox1= (is->start[0]-oc->min[0])*oc->ocfacx; oy1= (is->start[1]-oc->min[1])*oc->ocfacy; oz1= (is->start[2]-oc->min[2])*oc->ocfacz; - ox2= (is->end[0]-oc->min[0])*oc->ocfacx; - oy2= (is->end[1]-oc->min[1])*oc->ocfacy; - oz2= (is->end[2]-oc->min[2])*oc->ocfacz; + ox2= (end[0]-oc->min[0])*oc->ocfacx; + oy2= (end[1]-oc->min[1])*oc->ocfacy; + oz2= (end[2]-oc->min[2])*oc->ocfacz; ocx1= (int)ox1; ocy1= (int)oy1; @@ -1269,9 +915,16 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc ocx2= (int)ox2; ocy2= (int)oy2; ocz2= (int)oz2; + +// for(ocx1=0; ocx1<oc->ocres; ocx1++) +// for(ocy1=0; ocy1<oc->ocres; ocy1++) +// for(ocz1=0; ocz1<oc->ocres; ocz1++) +// { +// no= ocread(oc, ocx1, ocy1, ocz1); +// if( testnode(oc, is, no, ocval) ) return 1; +// } - /* for intersection */ - VECSUB(is->vec, is->end, is->start); +// return 0; if(ocx1==ocx2 && ocy1==ocy2 && ocz1==ocz2) { no= ocread(oc, ocx1, ocy1, ocz1); @@ -1280,8 +933,8 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1; vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2; calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2); - is->ddalabda= 1.0f; - if( testnode(oc, is, no, ocval, checkfunc) ) return 1; +// is->ddalabda= 1.0f; + if( testnode(oc, is, no, ocval) ) return 1; } } else { @@ -1359,8 +1012,8 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc vec2[2]= oz1-ddalabda*doz; calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2); - is->ddalabda= ddalabda; - if( testnode(oc, is, no, ocval, checkfunc) ) return 1; +// is->ddalabda= ddalabda; + if( testnode(oc, is, no, ocval) ) return 1; } labdao= ddalabda; @@ -1430,13 +1083,10 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc } /* reached end, no intersections found */ - is->ob_last= 0; - is->face_last= NULL; + is->hit.ob = 0; + is->hit.face = NULL; return 0; } -float RE_ray_tree_max_size(RayTree *tree) -{ - return ((Octree*)tree)->ocsize; -} + diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index e89cf20e4b1..83165bb6b52 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -29,6 +29,7 @@ #include <string.h> #include <stdlib.h> #include <float.h> +#include <assert.h> #include "MEM_guardedalloc.h" @@ -56,6 +57,7 @@ #include "texture.h" #include "RE_raytrace.h" +#include "rayobject.h" #define RAY_TRA 1 #define RAY_TRAFLIP 2 @@ -68,6 +70,7 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#if 0 static void vlr_face_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4) { VlakRen *vlr= (VlakRen*)face; @@ -101,27 +104,28 @@ static float *vlr_get_transform(void *userdata, int i) return (obi->flag & R_TRANSFORMED)? (float*)obi->mat: NULL; } +#endif void freeraytree(Render *re) { if(re->raytree) { - RE_ray_tree_free(re->raytree); + RayObject_free(re->raytree); re->raytree= NULL; + MEM_freeN( re->rayfaces ); } } - void makeraytree(Render *re) { ObjectInstanceRen *obi; ObjectRen *obr; VlakRen *vlr= NULL; - float min[3], max[3], co1[3], co2[3], co3[3], co4[3]; double lasttime= PIL_check_seconds_timer(); int v, totv = 0, totface = 0; + RayFace *faces, *cur_face; - INIT_MINMAX(min, max); - - /* first min max raytree space */ + //TODO (for now octree only supports RayFaces so we need to create them) + // + //count faces for(obi=re->instancetable.first; obi; obi=obi->next) { obr= obi->obr; @@ -134,52 +138,32 @@ void makeraytree(Render *re) /* baking selected to active needs non-traceable too */ if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) { if((vlr->mat->mode & MA_WIRE)==0) { - VECCOPY(co1, vlr->v1->co); - VECCOPY(co2, vlr->v2->co); - VECCOPY(co3, vlr->v3->co); - - if(obi->flag & R_TRANSFORMED) { - Mat4MulVecfl(obi->mat, co1); - Mat4MulVecfl(obi->mat, co2); - Mat4MulVecfl(obi->mat, co3); - } - - DO_MINMAX(co1, min, max); - DO_MINMAX(co2, min, max); - DO_MINMAX(co3, min, max); - - if(vlr->v4) { - VECCOPY(co4, vlr->v4->co); - if(obi->flag & R_TRANSFORMED) - Mat4MulVecfl(obi->mat, co4); - DO_MINMAX(co4, min, max); - } - totface++; } } } } - - re->raytree= RE_ray_tree_create(re->r.ocres, totface, min, max, - vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); - - if(min[0] > max[0]) { /* empty raytree */ - RE_ray_tree_done(re->raytree); - return; - } - + + re->raytree = RayObject_octree_create( re->r.ocres, totface ); + + //Fill rayfaces + re->rayfaces = (RayObject*)MEM_callocN(totface*sizeof(RayFace), "render faces"); + cur_face = faces = (RayFace*)re->rayfaces; + for(obi=re->instancetable.first; obi; obi=obi->next) { obr= obi->obr; if(re->excludeob && obr->ob == re->excludeob) continue; - for(v=0; v<obr->totvlak; v++, totv++) { - if((v & 255)==0) { + for(v=0;v<obr->totvlak;v++) { + if((v & 255)==0) + { double time= PIL_check_seconds_timer(); vlr= obr->vlaknodes[v>>8].vlak; + + vlr= obr->vlaknodes[v>>8].vlak; if(re->test_break(re->tbh)) break; if(time-lasttime>1.0f) { @@ -192,23 +176,35 @@ void makeraytree(Render *re) } } else vlr++; - - if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) - if((vlr->mat->mode & MA_WIRE)==0) - RE_ray_tree_add_face(re->raytree, RAY_OBJECT_SET(re, obi), vlr); + /* baking selected to active needs non-traceable too */ + if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) { + if((vlr->mat->mode & MA_WIRE)==0) { + cur_face->v1 = vlr->v1->co; + cur_face->v2 = vlr->v2->co; + cur_face->v3 = vlr->v3->co; + cur_face->v4 = vlr->v4 ? vlr->v4->co : NULL; + + cur_face->ob = (void*)obi; + cur_face->face = vlr; + + RayObject_add( re->raytree, (RayObject*) cur_face ); + cur_face++; + } + } } } - RE_ray_tree_done(re->raytree); - + RayObject_done( re->raytree ); +//TODO vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); + re->i.infostr= NULL; re->stats_draw(re->sdh, &re->i); } static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) { - VlakRen *vlr= (VlakRen*)is->face; - ObjectInstanceRen *obi= RAY_OBJECT_GET(&R, is->ob); + ObjectInstanceRen *obi= (ObjectInstanceRen*)is->hit.ob; + VlakRen *vlr= (VlakRen*)is->hit.face; int osatex= 0; /* set up view vector */ @@ -420,29 +416,25 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo ShadeResult shr; Isect isec; float f, f1, fr, fg, fb; - float ref[3], maxsize=RE_ray_tree_max_size(R.raytree); + float ref[3]; float dist_mir = origshi->mat->dist_mir; + assert(0); + /* Warning, This is not that nice, and possibly a bit slow for every ray, however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ memset(&shi, 0, sizeof(ShadeInput)); /* end warning! - Campbell */ VECCOPY(isec.start, start); - if (dist_mir > 0.0) { - isec.end[0]= start[0]+dist_mir*vec[0]; - isec.end[1]= start[1]+dist_mir*vec[1]; - isec.end[2]= start[2]+dist_mir*vec[2]; - } else { - isec.end[0]= start[0]+maxsize*vec[0]; - isec.end[1]= start[1]+maxsize*vec[1]; - isec.end[2]= start[2]+maxsize*vec[2]; - } + VECCOPY(isec.vec, vec ); + isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; isec.mode= RE_RAY_MIRROR; - isec.faceorig= (RayFace*)vlr; - isec.oborig= RAY_OBJECT_SET(&R, obi); - if(RE_ray_tree_intersect(R.raytree, &isec)) { + isec.orig.ob = obi; + isec.orig.face = vlr; + + if(RayObject_raycast(R.raytree, &isec)) { float d= 1.0f; shi.mask= origshi->mask; @@ -1279,8 +1271,10 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) if it has col[3]>0.0f continue. so exit when alpha is full */ ShadeInput shi; ShadeResult shr; + + assert(0); - if(RE_ray_tree_intersect(R.raytree, is)) { + if(RayObject_raycast(R.raytree, is)) { float d= 1.0f; /* we got a face */ @@ -1312,8 +1306,9 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) /* adapt isect struct */ VECCOPY(is->start, shi.co); - is->oborig= RAY_OBJECT_SET(&R, shi.obi); - is->faceorig= (RayFace*)shi.vlr; + + is->orig.ob = shi.obi; + is->orig.face = shi.vlr; ray_trace_shadow_tra(is, depth-1, traflag | RAY_TRA); } @@ -1329,9 +1324,11 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) Isect isec; ShadeInput shi; ShadeResult shr_t; - float vec[3], accum[3], div= 0.0f, maxsize= RE_ray_tree_max_size(R.raytree); + float vec[3], accum[3], div= 0.0f; int a; + assert(0); + if(only_one) { return 0; } @@ -1339,8 +1336,8 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) accum[0]= accum[1]= accum[2]= 0.0f; isec.mode= RE_RAY_MIRROR; - isec.faceorig= (RayFace*)ship->vlr; - isec.oborig= RAY_OBJECT_SET(&R, ship->obi); + isec.orig.ob = ship->obi; + isec.orig.face = ship->vlr; for(a=0; a<8*8; a++) { @@ -1352,12 +1349,12 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) vec[1]-= vec[1]; vec[2]-= vec[2]; } + VECCOPY(isec.start, ship->co); - isec.end[0]= isec.start[0] + maxsize*vec[0]; - isec.end[1]= isec.start[1] + maxsize*vec[1]; - isec.end[2]= isec.start[2] + maxsize*vec[2]; - - if(RE_ray_tree_intersect(R.raytree, &isec)) { + VECCOPY(isec.vec, vec ); + isec.labda = RE_RAYTRACE_MAXDIST; + + if(RayObject_raycast(R.raytree, &isec)) { float fac; /* Warning, This is not that nice, and possibly a bit slow for every ray, @@ -1545,10 +1542,16 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) float dxyview[3], skyadded=0, div; int aocolor; - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); - isec.face_last= NULL; - isec.ob_last= 0; + assert(0); + + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; + + isec.hit.ob = 0; + isec.hit.face = 0; + + isec.last_hit = NULL; + isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; @@ -1601,13 +1604,14 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) Normalize(dir); VECCOPY(isec.start, shi->co); - isec.end[0] = shi->co[0] - maxdist*dir[0]; - isec.end[1] = shi->co[1] - maxdist*dir[1]; - isec.end[2] = shi->co[2] - maxdist*dir[2]; + isec.vec[0] = -dir[0]; + isec.vec[1] = -dir[1]; + isec.vec[2] = -dir[2]; + isec.labda = maxdist; prev = fac; - if(RE_ray_tree_intersect(R.raytree, &isec)) { + if(RayObject_raycast(R.raytree, &isec)) { if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); else fac+= 1.0f; } @@ -1672,10 +1676,16 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) float dxyview[3]; int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp; - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); - isec.face_last= NULL; - isec.ob_last= 0; + assert(0); + + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; + + isec.hit.ob = 0; + isec.hit.face = 0; + + isec.last_hit = NULL; + isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; @@ -1725,14 +1735,15 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) actual++; - /* always set start/end, RE_ray_tree_intersect clips it */ + /* always set start/vec/labda */ VECCOPY(isec.start, shi->co); - isec.end[0] = shi->co[0] - maxdist*vec[0]; - isec.end[1] = shi->co[1] - maxdist*vec[1]; - isec.end[2] = shi->co[2] - maxdist*vec[2]; + isec.vec[0] = -vec[0]; + isec.vec[1] = -vec[1]; + isec.vec[2] = -vec[2]; + isec.labda = maxdist; /* do the trace */ - if(RE_ray_tree_intersect(R.raytree, &isec)) { + if(RayObject_raycast(R.raytree, &isec)) { if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); else sh+= 1.0f; } @@ -1838,7 +1849,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * int samples=0; float samp3d[3]; - float fac=0.0f, vec[3]; + float fac=0.0f, vec[3], end[3]; float colsq[4]; float adapt_thresh = lar->adapt_thresh; int min_adapt_samples=4, max_samples = lar->ray_totsamp; @@ -1848,6 +1859,8 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * float jitco[RE_MAX_OSA][3]; int totjitco; +// assert(0); + colsq[0] = colsq[1] = colsq[2] = 0.0; if(isec->mode==RE_RAY_SHADOW_TRA) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; @@ -1879,8 +1892,9 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * while (samples < max_samples) { - isec->faceorig= (RayFace*)shi->vlr; - isec->oborig= RAY_OBJECT_SET(&R, shi->obi); + + isec->orig.ob = shi->obi; + isec->orig.face = shi->vlr; /* manually jitter the start shading co-ord per sample * based on the pre-generated OSA texture sampling offsets, @@ -1916,11 +1930,11 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * /* align samples to lamp vector */ Mat3MulVecfl(lar->mat, samp3d); } - isec->end[0]= vec[0]+samp3d[0]; - isec->end[1]= vec[1]+samp3d[1]; - isec->end[2]= vec[2]+samp3d[2]; + end[0] = vec[0]+samp3d[0]; + end[1] = vec[1]+samp3d[1]; + end[2] = vec[2]+samp3d[2]; } else { - VECCOPY(isec->end, vec); + VECCOPY(end, vec); } if(shi->strand) { @@ -1928,7 +1942,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * float jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco)); float v[3]; - VECSUB(v, co, isec->end); + VECSUB(v, co, end); Normalize(v); co[0] -= jitbias*v[0]; @@ -1937,6 +1951,11 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * } VECCOPY(isec->start, co); +// VECSUB(isec->vec, end, isec->start); + isec->vec[0] = end[0]-isec->start[0]; + isec->vec[1] = end[1]-isec->start[1]; + isec->vec[2] = end[2]-isec->start[2]; + isec->labda = 1.0f; // * Normalize(isec->vec); /* trace the ray */ if(isec->mode==RE_RAY_SHADOW_TRA) { @@ -1955,7 +1974,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * colsq[2] += isec->col[2]*isec->col[2]; } else { - if( RE_ray_tree_intersect(R.raytree, isec) ) fac+= 1.0f; + if( RayObject_raycast(R.raytree, isec) ) fac+= 1.0f; } samples++; @@ -1996,6 +2015,8 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa float fac=0.0f, div=0.0f, vec[3]; int a, j= -1, mask; + assert(0); + if(isec->mode==RE_RAY_SHADOW_TRA) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; } @@ -2022,19 +2043,18 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa } } - isec->faceorig= (RayFace*)shi->vlr; - isec->oborig= RAY_OBJECT_SET(&R, shi->obi); + isec->orig.ob = shi->obi; + isec->orig.face = shi->vlr; vec[0]= jitlamp[0]; vec[1]= jitlamp[1]; vec[2]= 0.0f; Mat3MulVecfl(lar->mat, vec); - /* set start and end, RE_ray_tree_intersect clips it */ + /* set start and vec */ VECCOPY(isec->start, shi->co); - isec->end[0]= lampco[0]+vec[0]; - isec->end[1]= lampco[1]+vec[1]; - isec->end[2]= lampco[2]+vec[2]; + VECCOPY(isec->vec, vec); + isec->labda = 1.0f; if(isec->mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ @@ -2047,7 +2067,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa shadfac[2] += isec->col[2]; shadfac[3] += isec->col[3]; } - else if( RE_ray_tree_intersect(R.raytree, isec) ) fac+= 1.0f; + else if( RayObject_raycast(R.raytree, isec) ) fac+= 1.0f; div+= 1.0f; jitlamp+= 2; @@ -2071,7 +2091,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) { Isect isec; - float lampco[3], maxsize; + float lampco[3]; /* setup isec */ if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; @@ -2084,19 +2104,16 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) /* only when not mir tracing, first hit optimm */ if(shi->depth==0) { - isec.face_last= (RayFace*)lar->vlr_last[shi->thread]; - isec.ob_last= RAY_OBJECT_SET(&R, lar->obi_last[shi->thread]); + isec.last_hit = lar->last_hit[shi->thread]; } else { - isec.face_last= NULL; - isec.ob_last= 0; + isec.last_hit = NULL; } if(lar->type==LA_SUN || lar->type==LA_HEMI) { - maxsize= RE_ray_tree_max_size(R.raytree); - lampco[0]= shi->co[0] - maxsize*lar->vec[0]; - lampco[1]= shi->co[1] - maxsize*lar->vec[1]; - lampco[2]= shi->co[2] - maxsize*lar->vec[2]; + lampco[0]= shi->co[0] - RE_RAYTRACE_MAXDIST*lar->vec[0]; + lampco[1]= shi->co[1] - RE_RAYTRACE_MAXDIST*lar->vec[1]; + lampco[2]= shi->co[2] - RE_RAYTRACE_MAXDIST*lar->vec[2]; } else { VECCOPY(lampco, lar->co); @@ -2109,13 +2126,15 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) } else { if(lar->ray_totsamp<2) { - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; + shadfac[3]= 1.0f; // 1.0=full light /* set up isec vec */ VECCOPY(isec.start, shi->co); - VECCOPY(isec.end, lampco); + VECSUB(isec.vec, lampco, isec.start); + isec.labda = 1.0f; if(isec.mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ @@ -2125,7 +2144,11 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0); QUATCOPY(shadfac, isec.col); } - else if(RE_ray_tree_intersect(R.raytree, &isec)) shadfac[3]= 0.0f; + else + { + assert(0); + if(RayObject_raycast(R.raytree, &isec)) shadfac[3]= 0.0f; + } } else { ray_shadow_jitter(shi, lar, lampco, shadfac, &isec); @@ -2134,8 +2157,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) /* for first hit optim, set last interesected shadow face */ if(shi->depth==0) { - lar->vlr_last[shi->thread]= (VlakRen*)isec.face_last; - lar->obi_last[shi->thread]= RAY_OBJECT_GET(&R, isec.ob_last); + lar->last_hit[shi->thread] = isec.last_hit; } } @@ -2145,7 +2167,9 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co) { Isect isec; - float lampco[3], maxsize; + float lampco[3]; + + assert(0); /* setup isec */ isec.mode= RE_RAY_SHADOW_TRA; @@ -2153,23 +2177,22 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; if(lar->type==LA_SUN || lar->type==LA_HEMI) { - maxsize= RE_ray_tree_max_size(R.raytree); - lampco[0]= shi->co[0] - maxsize*lar->vec[0]; - lampco[1]= shi->co[1] - maxsize*lar->vec[1]; - lampco[2]= shi->co[2] - maxsize*lar->vec[2]; + lampco[0]= shi->co[0] - RE_RAYTRACE_MAXDIST*lar->vec[0]; + lampco[1]= shi->co[1] - RE_RAYTRACE_MAXDIST*lar->vec[1]; + lampco[2]= shi->co[2] - RE_RAYTRACE_MAXDIST*lar->vec[2]; } else { VECCOPY(lampco, lar->co); } - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; /* set up isec vec */ VECCOPY(isec.start, shi->co); VECCOPY(isec.end, lampco); - if(RE_ray_tree_intersect(R.raytree, &isec)) { + if(RayObject_raycast(R.raytree, &isec)) { /* we got a face */ /* render co */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index deb6f0db743..fe1ab21a4a4 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -31,6 +31,7 @@ #include <math.h> #include <float.h> #include <string.h> +#include <assert.h> /* External modules: */ #include "MEM_guardedalloc.h" @@ -2234,6 +2235,7 @@ static void bake_displacement(void *handle, ShadeInput *shi, float dist, int x, } } +#if 0 static int bake_check_intersect(Isect *is, int ob, RayFace *face) { BakeShade *bs = (BakeShade*)is->userdata; @@ -2243,9 +2245,13 @@ static int bake_check_intersect(Isect *is, int ob, RayFace *face) return (R.objectinstance[ob].obr->ob != bs->actob); } +#endif -static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) +static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) { + //TODO + assert( 0 ); +#if 0 float maxdist; int hit; @@ -2253,15 +2259,17 @@ static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, flo if(R.r.bake_maxdist > 0.0f) maxdist= R.r.bake_maxdist; else - maxdist= RE_ray_tree_max_size(R.raytree) + R.r.bake_biasdist; + maxdist= FLT_MAX + R.r.bake_biasdist; + //TODO normalized direction? VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist); + isect->dir[0] = dir[0]*sign; + isect->dir[1] = dir[1]*sign; + isect->dir[2] = dir[2]*sign; + isect->labda = maxdist; - isect->end[0] = isect->start[0] + dir[0]*maxdist*sign; - isect->end[1] = isect->start[1] + dir[1]*maxdist*sign; - isect->end[2] = isect->start[2] + dir[2]*maxdist*sign; - - hit = RE_ray_tree_intersect_check(R.raytree, isect, bake_check_intersect); + hit = RayObject_raycast(raytree, isect); + //TODO bake_check_intersect if(hit) { hitco[0] = isect->start[0] + isect->labda*isect->vec[0]; hitco[1] = isect->start[1] + isect->labda*isect->vec[1]; @@ -2271,6 +2279,8 @@ static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, flo } return hit; +#endif + return 0; } static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) @@ -2387,8 +2397,9 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) for(sign=-1; sign<=1; sign+=2) { memset(&isec, 0, sizeof(isec)); isec.mode= RE_RAY_MIRROR; - isec.faceorig= (RayFace*)vlr; - isec.oborig= RAY_OBJECT_SET(&R, obi); + + isec.orig.ob = obi; + isec.orig.face = vlr; isec.userdata= bs; if(bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) { @@ -2412,8 +2423,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) /* if hit, we shade from the new point, otherwise from point one starting face */ if(hit) { - vlr= (VlakRen*)minisec.face; - obi= RAY_OBJECT_GET(&R, minisec.ob); + obi= (ObjectInstanceRen*)minisec.hit.ob; + vlr= (VlakRen*)minisec.hit.face; quad= (minisec.isect == 2); VECCOPY(shi->co, minco); |