Raytrace modifications from the Render Branch.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 5 Feb 2011 13:41:29 +0000 (13:41 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 5 Feb 2011 13:41:29 +0000 (13:41 +0000)
These should not have any effect on render results, except in some cases with
you have overlapping faces, where the noise seems to be slightly reduced.

There are some performance improvements, for simple scenes I wouldn't expect
more than 5-10% to be cut off the render time, for sintel scenes we got about
50% on average, that's with millions of polygons on intel quad cores. This
because memory access / cache misses were the main bottleneck for those scenes,
and the optimizations improve that.

Interal changes:

* Remove RE_raytrace.h, raytracer is now only used by render engine again.
* Split non-public parts rayobject.h into rayobject_internal.h, hopefully
 makes it clearer how the API is used.
* Added rayintersection.h to contain some of the stuff from RE_raytrace.h
* Change Isect.vec/labda to Isect.dir/dist, previously vec was sometimes
  normalized and sometimes not, confusing... now dir is always normalized
  and dist contains the distance.
* Change VECCOPY and similar to BLI_math functions.
* Force inlining of auxiliary functions for ray-triangle/quad intersection,
  helps a few percentages.
* Reorganize svbvh code so all the traversal functions are in one file
* Don't do test for root so that push_childs can be inlined
* Make shadow a template parameter so it doesn't need to be runtime checked
* Optimization in raytree building, was computing bounding boxes more often
  than necessary.
* Leave out logf() factor in SAH, makes tree build quicker with no
  noticeable influence on raytracing on performance?
* Set max childs to 4, simplifies traversal code a bit, but also seems
  to help slightly in general.
* Store child pointers and child bb just as fixed arrays of size 4 in nodes,
  nearly all nodes have this many children, so overall it actually reduces
  memory usage a bit and avoids a pointer indirection.

32 files changed:
source/blender/blenkernel/intern/scene.c
source/blender/render/CMakeLists.txt
source/blender/render/extern/include/RE_raytrace.h [deleted file]
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/raycounter.h
source/blender/render/intern/include/rayintersection.h [new file with mode: 0644]
source/blender/render/intern/include/rayobject.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/rendercore.h
source/blender/render/intern/include/volumetric.h
source/blender/render/intern/raytrace/bvh.h
source/blender/render/intern/raytrace/rayobject.cpp
source/blender/render/intern/raytrace/rayobject_blibvh.cpp [moved from source/blender/render/intern/source/rayobject_blibvh.c with 91% similarity]
source/blender/render/intern/raytrace/rayobject_empty.cpp [new file with mode: 0644]
source/blender/render/intern/raytrace/rayobject_hint.h
source/blender/render/intern/raytrace/rayobject_instance.cpp [moved from source/blender/render/intern/source/rayobject_instance.c with 79% similarity]
source/blender/render/intern/raytrace/rayobject_internal.h [new file with mode: 0644]
source/blender/render/intern/raytrace/rayobject_octree.cpp [moved from source/blender/render/intern/source/rayobject_octree.c with 95% similarity]
source/blender/render/intern/raytrace/rayobject_qbvh.cpp
source/blender/render/intern/raytrace/rayobject_raycounter.cpp [moved from source/blender/render/intern/source/rayobject_raycounter.c with 97% similarity]
source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
source/blender/render/intern/raytrace/rayobject_svbvh.cpp
source/blender/render/intern/raytrace/rayobject_vbvh.cpp
source/blender/render/intern/raytrace/reorganize.h
source/blender/render/intern/raytrace/svbvh.h
source/blender/render/intern/raytrace/vbvh.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/renderdatabase.c
source/blender/render/intern/source/volume_precache.c
source/blender/render/intern/source/volumetric.c

index 94eed530ad6d162036dafd4d6458fd68ce840f4a..853e9e108d67c2e29110a1477ca58764e347480a 100644 (file)
@@ -374,6 +374,7 @@ Scene *add_scene(const char *name)
        sce->r.fg_stamp[3]= 1.0f;
        sce->r.bg_stamp[0]= sce->r.bg_stamp[1]= sce->r.bg_stamp[2]= 0.0f;
        sce->r.bg_stamp[3]= 0.25f;
+       sce->r.raytrace_options = R_RAYTRACE_USE_INSTANCES;
 
        sce->r.seq_prev_type= OB_SOLID;
        sce->r.seq_rend_type= OB_SOLID;
index 58aad270583c760bf5b090229875fb2cc7253510..ee99e3af3b9e54918b69895eb0442e2ced5bb489 100644 (file)
@@ -43,9 +43,14 @@ set(INC
 
 set(SRC
        intern/raytrace/rayobject.cpp
+       intern/raytrace/rayobject_empty.cpp
+       intern/raytrace/rayobject_octree.cpp
+       intern/raytrace/rayobject_raycounter.cpp
+       intern/raytrace/rayobject_svbvh.cpp
+       intern/raytrace/rayobject_blibvh.cpp
+       intern/raytrace/rayobject_instance.cpp
        intern/raytrace/rayobject_qbvh.cpp
        intern/raytrace/rayobject_rtbuild.cpp
-       intern/raytrace/rayobject_svbvh.cpp
        intern/raytrace/rayobject_vbvh.cpp
        intern/source/convertblender.c
        intern/source/envmap.c
@@ -57,10 +62,6 @@ set(SRC
        intern/source/pixelblending.c
        intern/source/pixelshading.c
        intern/source/pointdensity.c
-       intern/source/rayobject_blibvh.c
-       intern/source/rayobject_instance.c
-       intern/source/rayobject_octree.c
-       intern/source/rayobject_raycounter.c
        intern/source/rayshade.c
        intern/source/rendercore.c
        intern/source/render_texture.c
@@ -77,7 +78,6 @@ set(SRC
        intern/source/zbuf.c
 
        extern/include/RE_pipeline.h
-       extern/include/RE_raytrace.h
        extern/include/RE_render_ext.h
        extern/include/RE_shader_ext.h
        intern/include/envmap.h
@@ -89,6 +89,8 @@ set(SRC
        intern/include/pointdensity.h
        intern/include/raycounter.h
        intern/include/rayobject.h
+       intern/include/rayintersection.h
+       intern/include/raycounter.h
        intern/include/render_types.h
        intern/include/rendercore.h
        intern/include/renderdatabase.h
diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h
deleted file mode 100644 (file)
index cf463c0..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2007 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): André Pinto.
- *
- * ***** END GPL LICENSE BLOCK *****
- * RE_raytrace.h: ray tracing api, can be used independently from the renderer. 
- */
-
-#ifndef RE_RAYTRACE_H
-#define RE_RAYTRACE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// #define RE_RAYCOUNTER                       /* enable counters per ray, usefull for measuring raytrace structures performance */
-
-#define RE_RAY_LCTS_MAX_SIZE   256
-#define RT_USE_LAST_HIT                        /* last shadow hit is reused before raycasting on whole tree */
-//#define RT_USE_HINT                  /* last hit object is reused before raycasting on whole tree */
-
-#ifdef RE_RAYCOUNTER
-
-typedef struct RayCounter RayCounter;
-struct RayCounter
-{
-
-       struct
-       {
-               unsigned long long test, hit;
-               
-       } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit;
-};
-#endif
-
-/* Internals about raycasting structures can be found on intern/raytree.h */
-typedef struct RayObject RayObject;
-typedef struct Isect Isect;
-typedef struct RayHint RayHint;
-typedef struct RayTraceHint RayTraceHint;
-
-struct DerivedMesh;
-struct Mesh;
-struct VlakRen;
-struct ObjectInstanceRen;
-
-int  RE_rayobject_raycast(RayObject *r, Isect *i);
-void RE_rayobject_add    (RayObject *r, RayObject *);
-void RE_rayobject_done(RayObject *r);
-void RE_rayobject_free(RayObject *r);
-
-/* Extend min/max coords so that the rayobject is inside them */
-void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max);
-
-/* initializes an hint for optiming raycast where it is know that a ray will pass by the given BB often the origin point */
-void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max);
-
-/* initializes an hint for optiming raycast where it is know that a ray will be contained inside the given cone*/
-/* void RE_rayobject_hint_cone(RayObject *r, RayHint *hint, float *); */
-
-/* RayObject constructors */
-RayObject* RE_rayobject_octree_create(int ocres, int size);
-RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob);
-RayObject* RE_rayobject_empty_create(void);
-
-RayObject* RE_rayobject_blibvh_create(int size);       /* BLI_kdopbvh.c   */
-RayObject* RE_rayobject_vbvh_create(int size);         /* raytrace/rayobject_vbvh.c */
-RayObject* RE_rayobject_svbvh_create(int size);                /* raytrace/rayobject_svbvh.c */
-RayObject* RE_rayobject_qbvh_create(int size);         /* raytrace/rayobject_qbvh.c */
-
-
-/*
- * This ray object represents a triangle or a quad face.
- * All data needed to realize intersection is "localy" available.
- */
-typedef struct RayFace
-{
-       float v1[4], v2[4], v3[4], v4[3];
-       int quad;
-       void *ob;
-       void *face;
-       
-} RayFace;
-
-#define RE_rayface_isQuad(a) ((a)->quad)
-
-RayObject* RE_rayface_from_vlak(RayFace *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr);
-RayObject* RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *co1, float *co2, float *co3, float *co4);
-
-
-/*
- * This ray object represents faces directly from a given VlakRen structure.
- * Thus allowing to save memory, but making code triangle intersection dependant on render structures
- */
-typedef struct VlakPrimitive
-{
-       struct ObjectInstanceRen *ob;
-       struct VlakRen *face;
-} VlakPrimitive;
-
-RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr);
-
-
-
-/*
- * Raytrace hints
- */
-typedef struct LCTSHint LCTSHint;
-struct LCTSHint
-{
-       int size;
-       RayObject *stack[RE_RAY_LCTS_MAX_SIZE];
-};
-
-struct RayHint
-{
-       union
-       {
-               LCTSHint lcts;
-       } data;
-};
-
-
-/* Ray Intersection */
-struct Isect
-{
-       float start[3];
-       float vec[3];
-       float labda;
-
-       /* length of vec, configured by RE_rayobject_raycast */
-       int   bv_index[6];
-       float idot_axis[3];
-       float dist;
-
-/*     float end[3];                    - not used */
-
-       float u, v;
-       
-       struct
-       {
-               void *ob;
-               void *face;
-       }
-       hit, orig;
-       
-       RayObject *last_hit;    /* last hit optimization */
-
-#ifdef RT_USE_HINT
-       RayTraceHint *hint, *hit_hint;
-#endif
-       
-       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 */
-       int check;
-
-       float col[4];                   /* RGBA for shadow_tra */
-
-       void *userdata;
-       
-       RayHint *hint;
-       
-#ifdef RE_RAYCOUNTER
-       RayCounter *raycounter;
-#endif
-};
-
-/* ray types */
-#define RE_RAY_SHADOW 0
-#define RE_RAY_MIRROR 1
-#define RE_RAY_SHADOW_TRA 2
-
-/* skip options */
-#define RE_SKIP_CULLFACE                               (1 << 0)
-/* if using this flag then *face should be a pointer to a VlakRen */
-#define RE_SKIP_VLR_NEIGHBOUR                  (1 << 1)
-
-/* check options */
-#define RE_CHECK_VLR_NONE                              0
-#define RE_CHECK_VLR_RENDER                            1
-#define RE_CHECK_VLR_NON_SOLID_MATERIAL        2
-#define RE_CHECK_VLR_BAKE                              3
-
-/* TODO use: FLT_MAX? */
-#define RE_RAYTRACE_MAXDIST    1e33
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /*__RE_RAYTRACE_H__*/
index 26e34a741f756ecb6da59e168d7d713b29dcdbd9..2b451810e37bd5e237b73b3971f47349f50d0763 100644 (file)
@@ -30,7 +30,6 @@
 #ifndef RE_SHADER_EXT_H
 #define RE_SHADER_EXT_H
 
-#include "RE_raytrace.h" /* For RE_RAYCOUNTER */
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 /* this include is for shading and texture exports            */
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
index 5377a1147afb4ca2f2991bce9330ce5f78444f44..1a9b91c17a8f733b7390b1e7ad623b4c0bb98c98 100644 (file)
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #ifndef RE_RAYCOUNTER_H
 #define RE_RAYCOUNTER_H
 
-#include "RE_raytrace.h"
+//#define RE_RAYCOUNTER                        /* enable counters per ray, usefull for measuring raytrace structures performance */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #ifdef RE_RAYCOUNTER
 
-/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */
-#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).raycounter)
+/* ray counter functions */
+
+typedef struct RayCounter {
+       struct {
+               unsigned long long test, hit;
+       } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit;
+} RayCounter;
+
+#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).shading.raycounter)
 void RE_RC_INFO (RayCounter *rc);
 void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp);
 #define RE_RC_COUNT(var) (var)++
@@ -44,12 +55,17 @@ extern RayCounter re_rc_counter[];
 
 #else
 
-#      define RE_RC_INIT(isec,shi)
-#      define RE_RC_INFO(rc)
-#      define RE_RC_MERGE(dest,src)
-#      define  RE_RC_COUNT(var)
+/* ray counter stubs */
+
+#define RE_RC_INIT(isec,shi)
+#define RE_RC_INFO(rc)
+#define RE_RC_MERGE(dest,src)
+#define        RE_RC_COUNT(var)
                
 #endif
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff --git a/source/blender/render/intern/include/rayintersection.h b/source/blender/render/intern/include/rayintersection.h
new file mode 100644 (file)
index 0000000..5a8b989
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * $Id: rayintersection.h 29491 2010-06-16 18:57:23Z blendix $
+ *
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * RE_raytrace.h: ray tracing api, can be used independently from the renderer. 
+ */
+
+#ifndef __RENDER_RAYINTERSECTION_H__
+#define __RENDER_RAYINTERSECTION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct RayObject;
+
+/* Ray Hints */
+
+#define RE_RAY_LCTS_MAX_SIZE   256
+#define RT_USE_LAST_HIT                        /* last shadow hit is reused before raycasting on whole tree */
+//#define RT_USE_HINT                  /* last hit object is reused before raycasting on whole tree */
+
+typedef struct LCTSHint {
+       int size;
+       struct RayObject *stack[RE_RAY_LCTS_MAX_SIZE];
+} LCTSHint;
+
+typedef struct RayHint {
+       union { LCTSHint lcts; } data;
+} RayHint;
+
+/* Ray Intersection */
+
+typedef struct Isect {
+       /* ray start, direction (normalized vector), and max distance. on hit,
+          the distance is modified to be the distance to the hit point. */
+       float start[3];
+       float dir[3];
+       float dist;
+
+       /* precomputed values to accelerate bounding box intersection */
+       int bv_index[6];
+       float idot_axis[3];
+
+       /* intersection options */
+       int mode;                               /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */
+       int lay;                                /* -1 default, set for layer lamps */
+       int skip;                               /* skip flags */
+       int check;                              /* check flags */
+       void *userdata;                 /* used by bake check */
+
+       /* hit information */
+       float u, v;
+       int isect;                              /* which half of quad */
+       
+       struct {
+               void *ob;
+               void *face;
+       } hit, orig;
+       
+       /* last hit optimization */
+       struct RayObject *last_hit;
+
+       /* hints */
+#ifdef RT_USE_HINT
+       RayTraceHint *hint, *hit_hint;
+#endif
+       RayHint *hint;
+       
+       /* ray counter */
+#ifdef RE_RAYCOUNTER
+       RayCounter *raycounter;
+#endif
+} Isect;
+
+/* ray types */
+#define RE_RAY_SHADOW 0
+#define RE_RAY_MIRROR 1
+#define RE_RAY_SHADOW_TRA 2
+
+/* skip options */
+#define RE_SKIP_CULLFACE                (1 << 0)
+/* if using this flag then *face should be a pointer to a VlakRen */
+#define RE_SKIP_VLR_NEIGHBOUR           (1 << 1)
+
+/* check options */
+#define RE_CHECK_VLR_NONE               0
+#define RE_CHECK_VLR_RENDER             1
+#define RE_CHECK_VLR_NON_SOLID_MATERIAL 2
+#define RE_CHECK_VLR_BAKE               3
+
+/* arbitrary, but can't use e.g. FLT_MAX because of precision issues */
+#define RE_RAYTRACE_MAXDIST    1e15f
+#define RE_RAYTRACE_EPSILON 0.0f
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RENDER_RAYINTERSECTION_H__ */
+
index e16ec83fb617b7d32abade685b99f8bd80f2ac7a..61b7a23cf54d1e31f2c960064a192d18c788c57e 100644 (file)
@@ -26,6 +26,7 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #ifndef RE_RAYOBJECT_H
 #define RE_RAYOBJECT_H
 
 extern "C" {
 #endif
 
-#include "RE_raytrace.h"
-#include "render_types.h"
-#include <stdio.h>
-#include <float.h>
-
+struct Isect;
+struct ObjectInstanceRen;
+struct RayHint;
+struct VlakRen;
 
 /* 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 0x03) to define the
-       type of RayObject.
-       
-       This leads to 4 possible types of RayObject:
-
-        addr&3  - type of object
-                0              Self (reserved for each structure)
-               1       RayFace (tri/quad primitive)
-               2               RayObject (generic with API callbacks)
-               3               VlakPrimitive
-                               (vlak primitive - to be used when we have a vlak describing the data
-                                eg.: on render code)
-
-       0 means it's reserved and has it own meaning inside each ray acceleration structure
-       (this way each structure can use the allign offset to determine if a node represents a
-        RayObject primitive, which can be used to save memory)
-
-       You actually don't need to care about this if you are only using the API
-       described on RE_raytrace.h
- */
 
-/* used to align a given ray object */
-#define RE_rayobject_align(o)                          ((RayObject*)(((intptr_t)o)&(~3)))
-
-/* used to unalign a given ray object */
-#define RE_rayobject_unalignRayFace(o)         ((RayObject*)(((intptr_t)o)|1))
-#define RE_rayobject_unalignRayAPI(o)          ((RayObject*)(((intptr_t)o)|2))
-#define RE_rayobject_unalignVlakPrimitive(o)   ((RayObject*)(((intptr_t)o)|3))
-
-/* used to test the type of ray object */
-#define RE_rayobject_isAligned(o)      ((((intptr_t)o)&3) == 0)
-#define RE_rayobject_isRayFace(o)      ((((intptr_t)o)&3) == 1)
-#define RE_rayobject_isRayAPI(o)       ((((intptr_t)o)&3) == 2)
-#define RE_rayobject_isVlakPrimitive(o)        ((((intptr_t)o)&3) == 3)
-
-
-
-/*
- * This class is intended as a place holder for control, configuration of the rayobject like:
- *     - stop building (TODO maybe when porting build to threads this could be implemented with some thread_cancel function)
- *  - max number of threads and threads callback to use during build
- *     ...
- */    
-typedef int  (*RE_rayobjectcontrol_test_break_callback)(void *data);
-typedef struct RayObjectControl RayObjectControl;
-struct RayObjectControl
-{
-       void *data;
-       RE_rayobjectcontrol_test_break_callback test_break;     
-};
-
-/*
- * This rayobject represents a generic object. With it's own callbacks for raytrace operations.
- * It's suitable to implement things like LOD.
- */
-struct RayObject
-{
-       struct RayObjectAPI *api;
-
-       struct RayObjectControl control;
-};
+   Can be a face/triangle, bvh tree, object instance, etc. This is the
+   public API used by the renderer, see rayobject_internal.h for the
+   internal implementation details. */
 
+typedef struct RayObject RayObject;
 
+/* Intersection, see rayintersection.h */
 
+int RE_rayobject_raycast(RayObject *r, struct Isect *i);
 
-typedef int  (*RE_rayobject_raycast_callback)(RayObject *, Isect *);
-typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject);
-typedef void (*RE_rayobject_done_callback)(RayObject *);
-typedef void (*RE_rayobject_free_callback)(RayObject *);
-typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max);
-typedef float (*RE_rayobject_cost_callback)(RayObject *);
-typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, RayHint *, float *, float *);
+/* Acceleration Structures */
 
-typedef struct RayObjectAPI
-{
-       RE_rayobject_raycast_callback   raycast;
-       RE_rayobject_add_callback               add;
-       RE_rayobject_done_callback              done;
-       RE_rayobject_free_callback              free;
-       RE_rayobject_merge_bb_callback  bb;
-       RE_rayobject_cost_callback              cost;
-       RE_rayobject_hint_bb_callback   hint_bb;
-       
-} RayObjectAPI;
+RayObject* RE_rayobject_octree_create(int ocres, int size);
+RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob);
+RayObject* RE_rayobject_empty_create();
 
+RayObject* RE_rayobject_blibvh_create(int size);       /* BLI_kdopbvh.c   */
+RayObject* RE_rayobject_vbvh_create(int size);         /* raytrace/rayobject_vbvh.c */
+RayObject* RE_rayobject_svbvh_create(int size);                /* raytrace/rayobject_svbvh.c */
+RayObject* RE_rayobject_qbvh_create(int size);         /* raytrace/rayobject_qbvh.c */
 
-/*
- * This function differs from RE_rayobject_raycast
- * RE_rayobject_intersect does NOT perform last-hit optimization
- * So this is probably a function to call inside raytrace structures
- */
-int RE_rayobject_intersect(RayObject *r, Isect *i);
+/* Building */
 
-/*
- * Returns distance ray must travel to hit the given bounding box
- * BB should be in format [2][3]
- */
-/* float RE_rayobject_bb_intersect(const Isect *i, const float *bb); */
-int RE_rayobject_bb_intersect_test(const Isect *i, const float *bb); /* same as bb_intersect but doens't calculates distance */
+void RE_rayobject_add(RayObject *r, RayObject *);
+void RE_rayobject_done(RayObject *r);
+void RE_rayobject_free(RayObject *r);
 
-/*
- * Returns the expected cost of raycast on this node, primitives have a cost of 1
- */
-float RE_rayobject_cost(RayObject *r);
+void RE_rayobject_set_control(RayObject *r, void *data, int (*test_break)(void *data));
 
+/* RayObject representing faces, all data is locally available instead
+   of referring to some external data structure, for possibly faster
+   intersection tests. */
 
-/*
- * Returns true if for some reason a heavy processing function should stop
- * (eg.: user asked to stop during a tree a build)
- */
-int RE_rayobjectcontrol_test_break(RayObjectControl *c);
+typedef struct RayFace {
+       float v1[4], v2[4], v3[4], v4[3];
+       int quad;
+       void *ob;
+       void *face;
+} RayFace;
 
+#define RE_rayface_isQuad(a) ((a)->quad)
 
-#define ISECT_EPSILON ((float)FLT_EPSILON)
+RayObject* RE_rayface_from_vlak(RayFace *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr);
 
+/* RayObject representing faces directly from a given VlakRen structure. Thus
+   allowing to save memory, but making code triangle intersection dependant on
+   render structures. */
 
+typedef struct VlakPrimitive {
+       struct ObjectInstanceRen *ob;
+       struct VlakRen *face;
+} VlakPrimitive;
 
-#if !defined(_WIN32) && !defined(_WIN64)
+RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr);
 
-#include <sys/time.h>
-#include <time.h>
+/* Bounding Box */
 
-#define BENCH(a,name)  \
-       {                       \
-               double _t1, _t2;                                \
-               struct timeval _tstart, _tend;  \
-               clock_t _clock_init = clock();  \
-               gettimeofday ( &_tstart, NULL); \
-               (a);                                                    \
-               gettimeofday ( &_tend, NULL);   \
-               _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 );    \
-               _t2 = ( double )   _tend.tv_sec + ( double )   _tend.tv_usec/ ( 1000*1000 );    \
-               printf("BENCH:%s: %fs (real) %fs (cpu)\n", #name, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\
-       }
-#else
+/* extend min/max coords so that the rayobject is inside them */
+void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max);
 
-#define BENCH(a,name)  (a)
+/* initializes an hint for optiming raycast where it is know that a ray will pass by the given BB often the origin point */
+void RE_rayobject_hint_bb(RayObject *r, struct RayHint *hint, float *min, float *max);
 
-#endif
+/* initializes an hint for optiming raycast where it is know that a ray will be contained inside the given cone*/
+/* void RE_rayobject_hint_cone(RayObject *r, struct RayHint *hint, float *); */
 
+/* Internals */
 
+#include "../raytrace/rayobject_internal.h"
 
 #ifdef __cplusplus
 }
 #endif
 
-
 #endif
+
index 84fa7e931b256f0ba0188892938f5cdfe8e9a683..a599b1306fbc51981a472a797dc8ede890c86664 100644 (file)
@@ -607,6 +607,7 @@ typedef struct LampRen {
 #define R_DIVIDE_24            32      
 /* vertex normals are tangent or view-corrected vector, for hair strands */
 #define R_TANGENT              64              
+#define R_TRACEBLE             128
 
 /* strandbuffer->flag */
 #define R_STRAND_BSPLINE       1
index e9e30f64fdd34e81da5ddb5a73a59b36dc913ce3..3b0929bbe270b2d71b30291e09f99303851e0d89 100644 (file)
@@ -48,6 +48,7 @@ struct RenderPart;
 struct RenderLayer;
 struct ObjectRen;
 struct ListBase;
+struct RayObject;
 
 /* ------------------------------------------------------------------------- */
 
@@ -95,7 +96,7 @@ int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct Rend
 
 extern void freeraytree(Render *re);
 extern void makeraytree(Render *re);
-RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi);
+struct RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi);
 
 extern void ray_shadow(ShadeInput *, LampRen *, float *);
 extern void ray_trace(ShadeInput *, ShadeResult *);
index 37b1bd7ca292113f7d8f5b92ce911960b9612f83..827aaf3672c9af9d79b5cfeedf6ae75dfb44e7a8 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+struct Isect;
+struct ShadeInput;
+struct ShadeResult;
+
 float vol_get_density(struct ShadeInput *shi, float *co);
 void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co_);
 
index c31d1213b99203fd9e84d7d6591f4303243182e9..dd23967297aa84ddb7f5a4dd840bb42809bb7772 100644 (file)
  *
  * ***** END GPL LICENSE BLOCK *****
  */
-#include "rayobject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
 #include "raycounter.h"
-#include "rayobject_rtbuild.h"
+#include "rayintersection.h"
+#include "rayobject.h"
 #include "rayobject_hint.h"
-
-#include "BLI_utildefines.h"
+#include "rayobject_rtbuild.h"
 
 #include <assert.h>
 
 #ifdef __SSE__
 inline int test_bb_group4(__m128 *bb_group, const Isect *isec)
 {
-       
        const __m128 tmin0 = _mm_setzero_ps();
-       const __m128 tmax0 = _mm_load1_ps(&isec->labda);
-
-       const __m128 tmin1 = _mm_max_ps(tmin0, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[0]], _mm_load1_ps(&isec->start[0]) ), _mm_load1_ps(&isec->idot_axis[0])) );
-       const __m128 tmax1 = _mm_min_ps(tmax0, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[1]], _mm_load1_ps(&isec->start[0]) ), _mm_load1_ps(&isec->idot_axis[0])) );
-       const __m128 tmin2 = _mm_max_ps(tmin1, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[2]], _mm_load1_ps(&isec->start[1]) ), _mm_load1_ps(&isec->idot_axis[1])) );
-       const __m128 tmax2 = _mm_min_ps(tmax1, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[3]], _mm_load1_ps(&isec->start[1]) ), _mm_load1_ps(&isec->idot_axis[1])) );
-       const __m128 tmin3 = _mm_max_ps(tmin2, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[4]], _mm_load1_ps(&isec->start[2]) ), _mm_load1_ps(&isec->idot_axis[2])) );
-       const __m128 tmax3 = _mm_min_ps(tmax2, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[5]], _mm_load1_ps(&isec->start[2]) ), _mm_load1_ps(&isec->idot_axis[2])) );
+       const __m128 tmax0 = _mm_set_ps1(isec->dist);
+
+       float start[3], idot_axis[3];
+       copy_v3_v3(start, isec->start);
+       copy_v3_v3(idot_axis, isec->idot_axis);
+
+       const __m128 tmin1 = _mm_max_ps(tmin0, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[0]], _mm_set_ps1(start[0]) ), _mm_set_ps1(idot_axis[0])) );
+       const __m128 tmax1 = _mm_min_ps(tmax0, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[1]], _mm_set_ps1(start[0]) ), _mm_set_ps1(idot_axis[0])) );
+       const __m128 tmin2 = _mm_max_ps(tmin1, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[2]], _mm_set_ps1(start[1]) ), _mm_set_ps1(idot_axis[1])) );
+       const __m128 tmax2 = _mm_min_ps(tmax1, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[3]], _mm_set_ps1(start[1]) ), _mm_set_ps1(idot_axis[1])) );
+       const __m128 tmin3 = _mm_max_ps(tmin2, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[4]], _mm_set_ps1(start[2]) ), _mm_set_ps1(idot_axis[2])) );
+       const __m128 tmax3 = _mm_min_ps(tmax2, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[5]], _mm_set_ps1(start[2]) ), _mm_set_ps1(idot_axis[2])) );
        
        return _mm_movemask_ps(_mm_cmpge_ps(tmax3, tmin3));
 }
 #endif
 
+/*
+ * Determines the distance that the ray must travel to hit the bounding volume of the given node
+ * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe
+ *  [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9]
+ */
+static int rayobject_bb_intersect_test(const Isect *isec, const float *_bb)
+{
+       const float *bb = _bb;
+       
+       float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0];
+       float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0];
+       float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1];
+       float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1];
+       float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2];
+       float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2];
+
+       RE_RC_COUNT(isec->raycounter->bb.test);
+       
+       if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0;
+       if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0;
+       if(t1x > isec->dist || t1y > isec->dist || t1z > isec->dist) return 0;
+       RE_RC_COUNT(isec->raycounter->bb.hit);  
+
+       return 1;
+}
 
 /* bvh tree generics */
 template<class Tree> static int bvh_intersect(Tree *obj, Isect *isec);
@@ -108,7 +140,7 @@ static float bvh_cost(Tree *obj)
 /* bvh tree nodes generics */
 template<class Node> static inline int bvh_node_hit_test(Node *node, Isect *isec)
 {
-       return RE_rayobject_bb_intersect_test(isec, (const float*)node->bb);
+       return rayobject_bb_intersect_test(isec, (const float*)node->bb);
 }
 
 
@@ -133,7 +165,7 @@ static inline void bvh_node_merge_bb(Node *node, float *min, float *max)
  */
 template<class Node> static inline void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos);
 
-template<class Node,int MAX_STACK_SIZE,bool TEST_ROOT>
+template<class Node,int MAX_STACK_SIZE,bool TEST_ROOT,bool SHADOW>
 static int bvh_node_stack_raycast(Node *root, Isect *isec)
 {
        Node *stack[MAX_STACK_SIZE];
@@ -158,7 +190,7 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec)
                else
                {
                        hit |= RE_rayobject_intersect( (RayObject*)node, isec);
-                       if(hit && isec->mode == RE_RAY_SHADOW) return hit;
+                       if(SHADOW && hit) return hit;
                }
        }
        return hit;
index c267b89fc2caeaa6510a1da9ebead9254cb473a4..dd4932f0bd948303b90c79fb11677afc8ff84cdc 100644 (file)
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): Andr Pinto.
+ * Contributor(s): André Pinto.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #include <assert.h>
 
+#include "MEM_guardedalloc.h"
+
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
 
-
-
 #include "DNA_material_types.h"
 
-#include "RE_raytrace.h"
-
-#include "render_types.h"
+#include "rayintersection.h"
 #include "rayobject.h"
 #include "raycounter.h"
+#include "render_types.h"
 
-/*
- * Determines the distance that the ray must travel to hit the bounding volume of the given node
- * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe
- *  [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9]
- */
-int RE_rayobject_bb_intersect_test(const Isect *isec, const float *_bb)
-{
-       const float *bb = _bb;
-       
-       float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0];
-       float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0];
-       float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1];
-       float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1];
-       float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2];
-       float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2];
-
-       RE_RC_COUNT(isec->raycounter->bb.test);
-       
-       if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0;
-       if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0;
-       if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return 0;
-       RE_RC_COUNT(isec->raycounter->bb.hit);  
-
-       return 1;
-}
+/* RayFace
 
+   note we force always inline here, because compiler refuses to otherwise
+   because function is too long. Since this is code that is called billions
+   of times we really do want to inline. */
 
-/* only for self-intersecting test with current render face (where ray left) */
-static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, float ry1, float rz1)
+MALWAYS_INLINE RayObject* rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4)
 {
-       float 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;
+       rayface->ob = ob;
+       rayface->face = face;
+
+       copy_v3_v3(rayface->v1, v1);
+       copy_v3_v3(rayface->v2, v2);
+       copy_v3_v3(rayface->v3, v3);
 
-       VECCOPY(co1, face->v1->co);
-       VECCOPY(co2, face->v2->co);
-       if(face->v4)
+       if(v4)
        {
-               VECCOPY(co3, face->v4->co);
-               VECCOPY(co4, face->v3->co);
+               copy_v3_v3(rayface->v4, v4);
+               rayface->quad = 1;
        }
        else
        {
-               VECCOPY(co3, face->v3->co);
+               rayface->quad = 0;
        }
 
-       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];
-       
-       x0= t11*r2-t12*r1;
-       x1= t12*r0-t10*r2;
-       x2= t10*r1-t11*r0;
-
-       divdet= t00*x0+t01*x1+t02*x2;
+       return RE_rayobject_unalignRayFace(rayface);
+}
 
-       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;
+MALWAYS_INLINE void rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
+{
+       rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0);
 
-               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(obi->transform_primitives)
+       {
+               mul_m4_v3(obi->mat, rayface->v1);
+               mul_m4_v3(obi->mat, rayface->v2);
+               mul_m4_v3(obi->mat, rayface->v3);
 
-                       if(v<ISECT_EPSILON && (u1 + v) > -(1.0f+ISECT_EPSILON)) {
-                               return 1;
-                       }
-               }
+               if(RE_rayface_isQuad(rayface))
+                       mul_m4_v3(obi->mat, rayface->v4);
        }
+}
 
-       if(face->v4) {
+RayObject* RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
+{
+       return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0);
+}
 
-               t20= co3[0]-co4[0];
-               t21= co3[1]-co4[1];
-               t22= co3[2]-co4[2];
+/* VlakPrimitive */
 
-               divdet= t20*x0+t21*x1+t22*x2;
-               if(divdet!=0.0f) {
-                       u2= det1/divdet;
-               
-                       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;
+RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr)
+{
+       face->ob = obi;
+       face->face = vlr;
+
+       return RE_rayobject_unalignVlakPrimitive(face);
 }
 
-static inline int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr)
+/* Checks for ignoring faces or materials */
+
+MALWAYS_INLINE int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr)
 {
        /* for baking selected to active non-traceable materials might still
         * be in the raytree */
-       if(!(vlr->mat->mode & MA_TRACEBLE))
+       if(!(vlr->flag & R_TRACEBLE))
                return 0;
 
        /* I know... cpu cycle waste, might do smarter once */
@@ -160,7 +115,7 @@ static inline int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen
                return (is->lay & obi->lay);
 }
 
-static inline int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr)
+MALWAYS_INLINE int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr)
 {
        /* solid material types only */
        if (vlr->mat->material_type == MA_TYPE_SURFACE)
@@ -169,168 +124,223 @@ static inline int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, V
                return 0;
 }
 
-static inline int vlr_check_bake(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr)
+MALWAYS_INLINE int vlr_check_bake(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr)
 {
        return (obi->obr->ob != is->userdata);
 }
 
-static inline int rayface_check_cullface(RayFace *face, Isect *is)
-{
-       float nor[3];
-       
-       /* don't intersect if the ray faces along the face normal */
-       if(face->quad) normal_quad_v3( nor,face->v1, face->v2, face->v3, face->v4);
-       else normal_tri_v3( nor,face->v1, face->v2, face->v3);
-
-       return (INPR(nor, is->vec) < 0);
-}
+/* Ray Triangle/Quad Intersection */
 
-/* ray - triangle or quad intersection */
-/* this function shall only modify Isect if it detects an hit */
-static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is)
+MALWAYS_INLINE int isec_tri_quad(float start[3], float dir[3], RayFace *face, float uv[2], float *lambda)
 {
-       float co1[3],co2[3],co3[3],co4[3]={0};
-       float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2;
-       float m0, m1, m2, divdet, det1;
-       float labda, u, v;
-       short ok=0;
-       
-       if(is->orig.ob == face->ob && is->orig.face == face->face)
-               return 0;
-               
-       /* check if we should intersect this face */
-       if(is->check == RE_CHECK_VLR_RENDER)
-       {
-               if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0)
-                       return 0;
-       }
-       else if(is->check == RE_CHECK_VLR_NON_SOLID_MATERIAL)
-       {
-               if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0)
-                       return 0;
-               if(vlr_check_intersect_solid(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
-                       return 0;
-       }
-       else if(is->check == RE_CHECK_VLR_BAKE) {
-               if(vlr_check_bake(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0)
-                       return 0;
-       }
+       float co1[3], co2[3], co3[3], co4[3];
+       float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1, l;
+       int quad;
 
-       if(is->skip & RE_SKIP_CULLFACE)
-       {
-               if(rayface_check_cullface(face, is) == 0)
-                       return 0;
-       }
+       quad= RE_rayface_isQuad(face);
 
-       RE_RC_COUNT(is->raycounter->faces.test);
+       copy_v3_v3(co1, face->v1);
+       copy_v3_v3(co2, face->v2);
+       copy_v3_v3(co3, face->v3);
 
-       //Load coords
-       VECCOPY(co1, face->v1);
-       VECCOPY(co2, face->v2);
-       if(RE_rayface_isQuad(face))
-       {
-               VECCOPY(co3, face->v4);
-               VECCOPY(co4, face->v3);
-       }
-       else
-       {
-               VECCOPY(co3, face->v3);
-       }
+       copy_v3_v3(r, dir);
 
-       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;
+       /* intersect triangle */
+       sub_v3_v3v3(t0, co3, co2);
+       sub_v3_v3v3(t1, co3, co1);
 
-       divdet= t00*x0+t01*x1+t02*x2;
+       cross_v3_v3v3(x, r, t1);
+       divdet= dot_v3v3(t0, x);
 
-       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;
+       sub_v3_v3v3(m, start, co3);
+       det1= dot_v3v3(m, x);
        
-       if(divdet!=0.0f) {
-
+       if(divdet != 0.0f) {
                divdet= 1.0f/divdet;
-               u= det1*divdet;
-               if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) {
-                       float 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);
+               v= det1*divdet;
 
-                       if(v<ISECT_EPSILON && (u + v) > -(1.0f+ISECT_EPSILON)) {
-                               labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12);
+               if(v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
+                       float cros[3];
 
-                               if(labda>-ISECT_EPSILON && labda<is->labda) {
-                                       ok= 1;
+                       cross_v3_v3v3(cros, m, t0);
+                       u= divdet*dot_v3v3(cros, r);
+
+                       if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) {
+                               l= divdet*dot_v3v3(cros, t1);
+
+                               /* check if intersection is within ray length */
+                               if(l > -RE_RAYTRACE_EPSILON && l < *lambda) {
+                                       uv[0]= u;
+                                       uv[1]= v;
+                                       *lambda= l;
+                                       return 1;
                                }
                        }
                }
        }
 
-       if(ok==0 && RE_rayface_isQuad(face)) {
-
-               t20= co3[0]-co4[0];
-               t21= co3[1]-co4[1];
-               t22= co3[2]-co4[2];
+       /* intersect second triangle in quad */
+       if(quad) {
+               copy_v3_v3(co4, face->v4);
+               sub_v3_v3v3(t0, co3, co4);
+               divdet= dot_v3v3(t0, x);
 
-               divdet= t20*x0+t21*x1+t22*x2;
-               if(divdet!=0.0f) {
+               if(divdet != 0.0f) {
                        divdet= 1.0f/divdet;
-                       u = det1*divdet;
+                       v = det1*divdet;
                        
-                       if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) {
-                               float 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 < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
+                               float cros[3];
+
+                               cross_v3_v3v3(cros, m, t0);
+                               u= divdet*dot_v3v3(cros, r);
        
-                               if(v<ISECT_EPSILON && (u + v) >-(1.0f+ISECT_EPSILON)) {
-                                       labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12);
+                               if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) {
+                                       l= divdet*dot_v3v3(cros, t1);
                                        
-                                       if(labda>-ISECT_EPSILON && labda<is->labda) {
-                                               ok= 2;
+                                       if(l >- RE_RAYTRACE_EPSILON && l < *lambda) {
+                                               uv[0]= u;
+                                               uv[1]= -(1.0f + v + u);
+                                               *lambda= l;
+                                               return 2;
                                        }
                                }
                        }
                }
        }
 
+       return 0;
+}
+
+/* Simpler yes/no Ray Triangle/Quad Intersection */
+
+MALWAYS_INLINE int isec_tri_quad_neighbour(float start[3], float dir[3], RayFace *face)
+{
+       float co1[3], co2[3], co3[3], co4[3];
+       float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1;
+       int quad;
+
+       quad= RE_rayface_isQuad(face);
+
+       copy_v3_v3(co1, face->v1);
+       copy_v3_v3(co2, face->v2);
+       copy_v3_v3(co3, face->v3);
+
+       negate_v3_v3(r, dir); /* note, different than above function */
+
+       /* intersect triangle */
+       sub_v3_v3v3(t0, co3, co2);
+       sub_v3_v3v3(t1, co3, co1);
+
+       cross_v3_v3v3(x, r, t1);
+       divdet= dot_v3v3(t0, x);
+
+       sub_v3_v3v3(m, start, co3);
+       det1= dot_v3v3(m, x);
+       
+       if(divdet != 0.0f) {
+               divdet= 1.0f/divdet;
+               v= det1*divdet;
+
+               if(v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
+                       float cros[3];
+
+                       cross_v3_v3v3(cros, m, t0);
+                       u= divdet*dot_v3v3(cros, r);
+
+                       if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON))
+                               return 1;
+               }
+       }
+
+       /* intersect second triangle in quad */
+       if(quad) {
+               copy_v3_v3(co4, face->v4);
+               sub_v3_v3v3(t0, co3, co4);
+               divdet= dot_v3v3(t0, x);
+
+               if(divdet != 0.0f) {
+                       divdet= 1.0f/divdet;
+                       v = det1*divdet;
+                       
+                       if(v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
+                               float cros[3];
+
+                               cross_v3_v3v3(cros, m, t0);
+                               u= divdet*dot_v3v3(cros, r);
+       
+                               if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON))
+                                       return 2;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+/* RayFace intersection with checks and neighbour verifaction included,
+   Isect is modified if the face is hit. */
+
+MALWAYS_INLINE int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is)
+{
+       float dist, uv[2];
+       int ok= 0;
+       
+       /* avoid self-intersection */
+       if(is->orig.ob == face->ob && is->orig.face == face->face)
+               return 0;
+               
+       /* check if we should intersect this face */
+       if(is->check == RE_CHECK_VLR_RENDER)
+       {
+               if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
+                       return 0;
+       }
+       else if(is->check == RE_CHECK_VLR_NON_SOLID_MATERIAL)
+       {
+               if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
+                       return 0;
+               if(vlr_check_intersect_solid(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
+                       return 0;
+       }
+       else if(is->check == RE_CHECK_VLR_BAKE) {
+               if(vlr_check_bake(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
+                       return 0;
+       }
+
+       /* ray counter */
+       RE_RC_COUNT(is->raycounter->faces.test);
+
+       dist= is->dist;
+       ok= isec_tri_quad(is->start, is->dir, face, uv, &dist);
+
        if(ok) {
        
-               /* 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 */
+               /* 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->skip & RE_SKIP_VLR_NEIGHBOUR)
                {
-                       if(labda < 0.1f && is->orig.ob == face->ob)
+                       if(dist < 0.1f && is->orig.ob == face->ob)
                        {
                                VlakRen * a = (VlakRen*)is->orig.face;
                                VlakRen * b = (VlakRen*)face->face;
 
-                               /* 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 */
+                               /* 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(a->v1==b->v1 || a->v2==b->v1 || a->v3==b->v1 || a->v4==b->v1
                                || a->v1==b->v2 || a->v2==b->v2 || a->v3==b->v2 || a->v4==b->v2
                                || a->v1==b->v3 || a->v2==b->v3 || a->v3==b->v3 || a->v4==b->v3
-                               || (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4)))
-                               if(!intersection2((VlakRen*)a, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]))
-                               {
-                                       return 0;
+                               || (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4))) {
+                                       /* create RayFace from original face, transformed if necessary */
+                                       RayFace origface;
+                                       ObjectInstanceRen *ob= (ObjectInstanceRen*)is->orig.ob;
+                                       rayface_from_vlak(&origface, ob, (VlakRen*)is->orig.face);
+
+                                       if(!isec_tri_quad_neighbour(is->start, is->dir, &origface))
+                                       {
+                                               return 0;
+                                       }
                                }
                        }
                }
@@ -338,8 +348,8 @@ static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is)
                RE_RC_COUNT(is->raycounter->faces.hit);
 
                is->isect= ok;  // which half of the quad
-               is->labda= labda;
-               is->u= u; is->v= v;
+               is->dist= dist;
+               is->u= uv[0]; is->v= uv[1];
 
                is->hit.ob   = face->ob;
                is->hit.face = face->face;
@@ -352,51 +362,18 @@ static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is)
        return 0;
 }
 
-RayObject* RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
-{
-       return RE_rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0 );
-}
-
-RayObject* RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4)
-{
-       rayface->ob = ob;
-       rayface->face = face;
-
-       VECCOPY(rayface->v1, v1);
-       VECCOPY(rayface->v2, v2);
-       VECCOPY(rayface->v3, v3);
-       if(v4)
-       {
-               VECCOPY(rayface->v4, v4);
-               rayface->quad = 1;
-       }
-       else
-       {
-               rayface->quad = 0;
-       }
-
-       return RE_rayobject_unalignRayFace(rayface);
-}
-
-RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr)
-{
-       face->ob = obi;
-       face->face = vlr;
-       return RE_rayobject_unalignVlakPrimitive(face);
-}
-
+/* Intersection */
 
 int RE_rayobject_raycast(RayObject *r, Isect *isec)
 {
        int i;
+
        RE_RC_COUNT(isec->raycounter->raycast.test);
 
-       /* Setup vars used on raycast */
-       isec->dist = len_v3(isec->vec);
-       
+       /* setup vars used on raycast */
        for(i=0; i<3; i++)
        {
-               isec->idot_axis[i]              = 1.0f / isec->vec[i];
+               isec->idot_axis[i]              = 1.0f / isec->dir[i];
                
                isec->bv_index[2*i]             = isec->idot_axis[i] < 0.0 ? 1 : 0;
                isec->bv_index[2*i+1]   = 1 - isec->bv_index[2*i];
@@ -406,7 +383,7 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec)
        }
 
 #ifdef RT_USE_LAST_HIT 
-       /* Last hit heuristic */
+       /* last hit heuristic */
        if(isec->mode==RE_RAY_SHADOW && isec->last_hit)
        {
                RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test);
@@ -433,6 +410,7 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec)
 #endif
                return 1;
        }
+
        return 0;
 }
 
@@ -447,103 +425,93 @@ int RE_rayobject_intersect(RayObject *r, Isect *i)
                //TODO optimize (useless copy to RayFace to avoid duplicate code)
                VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r);
                RayFace nface;
-               RE_rayface_from_vlak(&nface, face->ob, face->face);
-
-               if(face->ob->transform_primitives)
-               {
-                       mul_m4_v3(face->ob->mat, nface.v1);
-                       mul_m4_v3(face->ob->mat, nface.v2);
-                       mul_m4_v3(face->ob->mat, nface.v3);
-                       if(RE_rayface_isQuad(&nface))
-                               mul_m4_v3(face->ob->mat, nface.v4);
-               }
+               rayface_from_vlak(&nface, face->ob, face->face);
 
                return intersect_rayface(r, &nface, i);
        }
        else if(RE_rayobject_isRayAPI(r))
        {
-               r = RE_rayobject_align( r );
-               return r->api->raycast( r, i );
+               r = RE_rayobject_align(r);
+               return r->api->raycast(r, i);
+       }
+       else {
+               assert(0);
+       return 0;
        }
-       else assert(0);
-    return 0; /* wont reach this, quiet compilers */
 }
 
+/* Building */
+
 void RE_rayobject_add(RayObject *r, RayObject *o)
 {
-       r = RE_rayobject_align( r );
-       return r->api->add( r, o );
+       r = RE_rayobject_align(r);
+       return r->api->add(r, o);
 }
 
 void RE_rayobject_done(RayObject *r)
 {
-       r = RE_rayobject_align( r );
-       r->api->done( r );
+       r = RE_rayobject_align(r);
+       r->api->done(r);
 }
 
 void RE_rayobject_free(RayObject *r)
 {
-       r = RE_rayobject_align( r );
-       r->api->free( r );
+       r = RE_rayobject_align(r);
+       r->api->free(r);
 }
 
+float RE_rayobject_cost(RayObject *r)
+{
+       if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r))
+       {
+               return 1.0f;
+       }
+       else if(RE_rayobject_isRayAPI(r))
+       {
+               r = RE_rayobject_align(r);
+               return r->api->cost(r);
+       }
+       else {
+               assert(0);
+               return 1.0f;
+       }
+}
+
+/* Bounding Boxes */
+
 void RE_rayobject_merge_bb(RayObject *r, float *min, float *max)
 {
        if(RE_rayobject_isRayFace(r))
        {
                RayFace *face = (RayFace*) RE_rayobject_align(r);
                
-               DO_MINMAX( face->v1, min, max );
-               DO_MINMAX( face->v2, min, max );
-               DO_MINMAX( face->v3, min, max );
-               if(RE_rayface_isQuad(face)) DO_MINMAX( face->v4, min, max );
+               DO_MINMAX(face->v1, min, max);
+               DO_MINMAX(face->v2, min, max);
+               DO_MINMAX(face->v3, min, max);
+               if(RE_rayface_isQuad(face)) DO_MINMAX(face->v4, min, max);
        }
        else if(RE_rayobject_isVlakPrimitive(r))
        {
                VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r);
                RayFace nface;
-               RE_rayface_from_vlak(&nface, face->ob, face->face);
-
-               if(face->ob->transform_primitives)
-               {
-                       mul_m4_v3(face->ob->mat, nface.v1);
-                       mul_m4_v3(face->ob->mat, nface.v2);
-                       mul_m4_v3(face->ob->mat, nface.v3);
-                       if(RE_rayface_isQuad(&nface))
-                               mul_m4_v3(face->ob->mat, nface.v4);
-               }
-
-               DO_MINMAX( nface.v1, min, max );
-               DO_MINMAX( nface.v2, min, max );
-               DO_MINMAX( nface.v3, min, max );
-               if(RE_rayface_isQuad(&nface)) DO_MINMAX( nface.v4, min, max );
-       }
-       else if(RE_rayobject_isRayAPI(r))
-       {
-               r = RE_rayobject_align( r );
-               r->api->bb( r, min, max );
-       }
-       else assert(0);
-}
+               rayface_from_vlak(&nface, face->ob, face->face);
 
-float RE_rayobject_cost(RayObject *r)
-{
-       if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r))
-       {
-               return 1.0;
+               DO_MINMAX(nface.v1, min, max);
+               DO_MINMAX(nface.v2, min, max);
+               DO_MINMAX(nface.v3, min, max);
+               if(RE_rayface_isQuad(&nface)) DO_MINMAX(nface.v4, min, max);
        }
        else if(RE_rayobject_isRayAPI(r))
        {
-               r = RE_rayobject_align( r );
-               return r->api->cost( r );
+               r = RE_rayobject_align(r);
+               r->api->bb(r, min, max);
        }
        else
-       {
                assert(0);
-               return 1.0; /* XXX, better default value? */
-       }
 }
 
+/* Hints */
+
 void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max)
 {
        if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r))
@@ -552,60 +520,30 @@ void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max)
        }
        else if(RE_rayobject_isRayAPI(r))
        {
-               r = RE_rayobject_align( r );
-               return r->api->hint_bb( r, hint, min, max );
+               r = RE_rayobject_align(r);
+               return r->api->hint_bb(r, hint, min, max);
        }
-       else assert(0);
+       else
+               assert(0);
 }
 
+/* RayObjectControl */
+
 int RE_rayobjectcontrol_test_break(RayObjectControl *control)
 {
        if(control->test_break)
-               return control->test_break( control->data );
+               return control->test_break(control->data);
 
        return 0;
 }
 
-
-/*
- * Empty raytree
- */
-static int RE_rayobject_empty_intersect(RayObject *o, Isect *is)
+void RE_rayobject_set_control(RayObject *r, void *data, RE_rayobjectcontrol_test_break_callback test_break)
 {
-       return 0;
-}
-
-static void RE_rayobject_empty_free(RayObject *o)
-{
-}
-
-static void RE_rayobject_empty_bb(RayObject *o, float *min, float *max)
-{
-       return;
-}
-
-static float RE_rayobject_empty_cost(RayObject *o)
-{
-       return 0.0;
+       if(RE_rayobject_isRayAPI(r))
+       {
+               r = RE_rayobject_align(r);
+               r->control.data = data;
+               r->control.test_break = test_break;
+       }
 }
 
-static void RE_rayobject_empty_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
-{}
-
-static RayObjectAPI empty_api =
-{
-       RE_rayobject_empty_intersect,
-       NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob);
-       NULL, //static void RE_rayobject_instance_done(RayObject *o);
-       RE_rayobject_empty_free,
-       RE_rayobject_empty_bb,
-       RE_rayobject_empty_cost,
-       RE_rayobject_empty_hint_bb
-};
-
-static RayObject empty_raytree = { &empty_api, {0, 0} };
-
-RayObject *RE_rayobject_empty_create()
-{
-       return RE_rayobject_unalignRayAPI( &empty_raytree );
-}
similarity index 91%
rename from source/blender/render/intern/source/rayobject_blibvh.c
rename to source/blender/render/intern/raytrace/rayobject_blibvh.cpp
index fa5c32a8e8dd59a41147520258a469eb905abd30..7d59cc2df30cd02f3941515de2fe1286802ff499 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: rayobject_blibvh.cpp 29491 2010-06-16 18:57:23Z blendix $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -22,7 +22,7 @@
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): Andr Pinto.
+ * Contributor(s): André Pinto.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -33,8 +33,8 @@
 #include "BLI_kdopbvh.h"
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
-#include "RE_raytrace.h"
-#include "render_types.h"
+
+#include "rayintersection.h"
 #include "rayobject.h"
 
 static int  RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec);
@@ -71,14 +71,12 @@ typedef struct BVHObject
        RayObject **leafs, **next_leaf;
        BVHTree *bvh;
        float bb[2][3];
-
 } BVHObject;
 
-
 RayObject *RE_rayobject_blibvh_create(int size)
 {
        BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject");
-       assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */       
+       assert(RE_rayobject_isAligned(obj)); /* RayObject API assumes real data to be 4-byte aligned */ 
        
        obj->rayobj.api = &bvh_api;
        obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6);
@@ -107,7 +105,7 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr
                if(isec->mode == RE_RAY_SHADOW)
                        hit->dist = 0;
                else
-                       hit->dist = isec->labda*isec->dist;
+                       hit->dist = isec->dist;
        }
 }
 
@@ -120,11 +118,10 @@ static int  RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec)
        data.isec = isec;
        data.leafs = obj->leafs;
 
-       VECCOPY(dir, isec->vec);
-       normalize_v3(dir);
+       copy_v3_v3(dir, isec->dir);
 
        hit.index = 0;
-       hit.dist = isec->labda*isec->dist;
+       hit.dist = isec->dist;
        
        return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, (void*)&data);
 }
@@ -139,7 +136,7 @@ static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob)
        DO_MIN(min_max  , obj->bb[0]);
        DO_MAX(min_max+3, obj->bb[1]);
        
-       BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2 ); 
+       BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2);  
        *(obj->next_leaf++) = ob;
 }
 
@@ -165,6 +162,7 @@ static void RE_rayobject_blibvh_free(RayObject *o)
 static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max)
 {
        BVHObject *obj = (BVHObject*)o;
-       DO_MIN( obj->bb[0], min );
-       DO_MAX( obj->bb[1], max );
+       DO_MIN(obj->bb[0], min);
+       DO_MAX(obj->bb[1], max);
 }
+
diff --git a/source/blender/render/intern/raytrace/rayobject_empty.cpp b/source/blender/render/intern/raytrace/rayobject_empty.cpp
new file mode 100644 (file)
index 0000000..abd54ab
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 1990-1998 NeoGeo BV.
+ * All rights reserved.
+ *
+ * Contributors: 2004/2005 Blender Foundation, full recode
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "rayobject.h"
+
+/*
+ * Empty raytree
+ */
+
+static int RE_rayobject_empty_intersect(RayObject *o, Isect *is)
+{
+       return 0;
+}
+
+static void RE_rayobject_empty_free(RayObject *o)
+{
+}
+
+static void RE_rayobject_empty_bb(RayObject *o, float *min, float *max)
+{
+       return;
+}
+
+static float RE_rayobject_empty_cost(RayObject *o)
+{
+       return 0.0;
+}
+
+static void RE_rayobject_empty_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
+{}
+
+static RayObjectAPI empty_api =
+{
+       RE_rayobject_empty_intersect,
+       NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob);
+       NULL, //static void RE_rayobject_instance_done(RayObject *o);
+       RE_rayobject_empty_free,
+       RE_rayobject_empty_bb,
+       RE_rayobject_empty_cost,
+       RE_rayobject_empty_hint_bb
+};
+
+static RayObject empty_raytree = { &empty_api, {0, 0} };
+
+RayObject *RE_rayobject_empty_create()
+{
+       return RE_rayobject_unalignRayAPI( &empty_raytree );
+}
+
index 1ea59d00bac3b9694d35fd6c796948602b96e454..adb7d65227667e3f43234cf6c476cc32154dc433 100644 (file)
@@ -26,6 +26,7 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #ifndef RE_RAYTRACE_RAYOBJECT_HINT_H
 #define RE_RAYTRACE_RAYOBJECT_HINT_H
 
@@ -68,3 +69,4 @@ inline int hint_test_bb(HintFrustum &obj, float *Nmin, float *Nmax)
 */
 
 #endif
+
similarity index 79%
rename from source/blender/render/intern/source/rayobject_instance.c
rename to source/blender/render/intern/raytrace/rayobject_instance.cpp
index d7b4beb8023b85a28293afcfb00ab7db6312cf0b..c0adae71c1f6b5e541efddcf56ee843363274174 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: rayobject_instance.cpp 29542 2010-06-18 09:45:46Z blendix $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): Andr Pinto.
+ * Contributor(s): André Pinto.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #include <assert.h>
 
 #include "MEM_guardedalloc.h"
 
-
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
 
-#include "RE_raytrace.h"
+#include "rayintersection.h"
 #include "rayobject.h"
 
 #define RE_COST_INSTANCE (1.0f)
@@ -44,7 +44,7 @@ static void RE_rayobject_instance_free(RayObject *o);
 static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max);
 static float RE_rayobject_instance_cost(RayObject *o);
 
-static void RE_rayobject_instance_hint_bb(RayObject *UNUSED(o), RayHint *UNUSED(hint), float *UNUSED(min), float *UNUSED(max))
+static void RE_rayobject_instance_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
 {}
 
 static RayObjectAPI instance_api =
@@ -90,42 +90,32 @@ RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4],
 
 static int  RE_rayobject_instance_intersect(RayObject *o, Isect *isec)
 {
-       //TODO
-       // *there is probably a faster way to convert between coordinates
-       
        InstanceRayObject *obj = (InstanceRayObject*)o;
-       int res;
-       float start[3], vec[3], labda, dist;
-       int changed = 0, i;
+       float start[3], dir[3], idot_axis[3], dist;
+       int changed = 0, i, res;
        
-       //TODO - this is disabling self intersection on instances
+       // TODO - this is disabling self intersection on instances
        if(isec->orig.ob == obj->ob && obj->ob)
        {
                changed = 1;
                isec->orig.ob = obj->target_ob;
        }
        
-       
-       VECCOPY( start, isec->start );
-       VECCOPY( vec  , isec->vec   );
-       labda = isec->labda;
-       dist  = isec->dist;
-
-       //Transform to target coordinates system
-       VECADD( isec->vec, isec->vec, isec->start );    
+       // backup old values
+       copy_v3_v3(start, isec->start);
+       copy_v3_v3(dir, isec->dir);
+       copy_v3_v3(idot_axis, isec->idot_axis);
+       dist = isec->dist;
 
+       // transform to target coordinates system
        mul_m4_v3(obj->global2target, isec->start);
-       mul_m4_v3(obj->global2target, isec->vec  );
-
-       isec->dist = len_v3v3( isec->start, isec->vec );
-       VECSUB( isec->vec, isec->vec, isec->start );
+       mul_mat3_m4_v3(obj->global2target, isec->dir);
+       isec->dist *= normalize_v3(isec->dir);
        
-       isec->labda *= isec->dist / dist;
-       
-       //Update idot_axis and bv_index
+       // update idot_axis and bv_index
        for(i=0; i<3; i++)
        {
-               isec->idot_axis[i]              = 1.0f / isec->vec[i];
+               isec->idot_axis[i]              = 1.0f / isec->dir[i];
                
                isec->bv_index[2*i]             = isec->idot_axis[i] < 0.0 ? 1 : 0;
                isec->bv_index[2*i+1]   = 1 - isec->bv_index[2*i];
@@ -134,17 +124,24 @@ static int  RE_rayobject_instance_intersect(RayObject *o, Isect *isec)
                isec->bv_index[2*i+1]   = i+3*isec->bv_index[2*i+1];
        }
 
-       //Raycast
+       // raycast
        res = RE_rayobject_intersect(obj->target, isec);
 
-       //Restore coordinate space coords
+       // map dist into original coordinate space
        if(res == 0)
        {
-               isec->labda = labda;
+               isec->dist = dist;
        }
        else
        {
-               isec->labda *= dist / isec->dist;
+               // note we don't just multiply dist, because of possible
+               // non-uniform scaling in the transform matrix
+               float vec[3];
+
+               mul_v3_v3fl(vec, isec->dir, isec->dist);
+               mul_mat3_m4_v3(obj->target2global, vec);
+
+               isec->dist = len_v3(vec);
                isec->hit.ob = obj->ob;
 
 #ifdef RT_USE_LAST_HIT 
@@ -154,18 +151,18 @@ static int  RE_rayobject_instance_intersect(RayObject *o, Isect *isec)
                isec->last_hit = RE_rayobject_unalignRayAPI((RayObject*) obj);
 #endif
        }
-       isec->dist = dist;
-       VECCOPY( isec->start, start );
-       VECCOPY( isec->vec,   vec );
+
+       // restore values
+       copy_v3_v3(isec->start, start);
+       copy_v3_v3(isec->dir, dir);
+       copy_v3_v3(isec->idot_axis, idot_axis);
        
        if(changed)
                isec->orig.ob = obj->ob;
 
-       //Update idot_axis and bv_index
+       // restore bv_index
        for(i=0; i<3; i++)
        {
-               isec->idot_axis[i]              = 1.0f / isec->vec[i];
-               
                isec->bv_index[2*i]             = isec->idot_axis[i] < 0.0 ? 1 : 0;
                isec->bv_index[2*i+1]   = 1 - isec->bv_index[2*i];
                
@@ -208,3 +205,4 @@ static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max)
                DO_MINMAX(t, min, max);
        }
 }
+
diff --git a/source/blender/render/intern/raytrace/rayobject_internal.h b/source/blender/render/intern/raytrace/rayobject_internal.h
new file mode 100644 (file)
index 0000000..6067be0
--- /dev/null
@@ -0,0 +1,128 @@
+
+#ifndef RE_RAYOBJECT_INTERNAL_H
+#define RE_RAYOBJECT_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* RayObjectControl
+ *
+ * This class is intended as a place holder for control, configuration of the
+ * rayobject like:
+ *     - stop building (TODO maybe when porting build to threads this could be
+ *    implemented with some thread_cancel function)
+ *  - max number of threads and threads callback to use during build
+ *     ...
+ */    
+
+typedef int  (*RE_rayobjectcontrol_test_break_callback)(void *data);
+
+typedef struct RayObjectControl {
+       void *data;
+       RE_rayobjectcontrol_test_break_callback test_break;     
+} RayObjectControl;
+
+/* Returns true if for some reason a heavy processing function should stop
+ * (eg.: user asked to stop during a tree a build)
+ */
+
+int RE_rayobjectcontrol_test_break(RayObjectControl *c);
+
+/* 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 0x03) to define the
+       type of RayObject.
+       
+       This leads to 4 possible types of RayObject:
+
+        addr&3  - type of object
+               0               Self (reserved for each structure)
+               1       RayFace (tri/quad primitive)
+               2               RayObject (generic with API callbacks)
+               3               VlakPrimitive
+                               (vlak primitive - to be used when we have a vlak describing the data
+                                eg.: on render code)
+
+       0 means it's reserved and has it own meaning inside each ray acceleration structure
+       (this way each structure can use the allign offset to determine if a node represents a
+        RayObject primitive, which can be used to save memory)
+ */
+
+/* used to test the type of ray object */
+#define RE_rayobject_isAligned(o)              ((((intptr_t)o)&3) == 0)
+#define RE_rayobject_isRayFace(o)              ((((intptr_t)o)&3) == 1)
+#define RE_rayobject_isRayAPI(o)               ((((intptr_t)o)&3) == 2)
+#define RE_rayobject_isVlakPrimitive(o)        ((((intptr_t)o)&3) == 3)
+
+/* used to align a given ray object */
+#define RE_rayobject_align(o)                                  ((RayObject*)(((intptr_t)o)&(~3)))
+
+/* used to unalign a given ray object */
+#define RE_rayobject_unalignRayFace(o)                 ((RayObject*)(((intptr_t)o)|1))
+#define RE_rayobject_unalignRayAPI(o)                  ((RayObject*)(((intptr_t)o)|2))
+#define RE_rayobject_unalignVlakPrimitive(o)   ((RayObject*)(((intptr_t)o)|3))
+
+/*
+ * This rayobject represents a generic object. With it's own callbacks for raytrace operations.
+ * It's suitable to implement things like LOD.
+ */
+
+struct RayObject {
+       struct RayObjectAPI *api;
+       struct RayObjectControl control;
+};
+
+typedef int  (*RE_rayobject_raycast_callback)(RayObject *, struct Isect *);
+typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject);
+typedef void (*RE_rayobject_done_callback)(RayObject *);
+typedef void (*RE_rayobject_free_callback)(RayObject *);
+typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max);
+typedef float (*RE_rayobject_cost_callback)(RayObject *);
+typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, struct RayHint *, float *, float *);
+
+typedef struct RayObjectAPI {
+       RE_rayobject_raycast_callback   raycast;
+       RE_rayobject_add_callback               add;
+       RE_rayobject_done_callback              done;
+       RE_rayobject_free_callback              free;
+       RE_rayobject_merge_bb_callback  bb;
+       RE_rayobject_cost_callback              cost;
+       RE_rayobject_hint_bb_callback   hint_bb;
+} RayObjectAPI;
+
+/*
+ * Returns the expected cost of raycast on this node, primitives have a cost of 1
+ */
+float RE_rayobject_cost(RayObject *r);
+
+/*
+ * This function differs from RE_rayobject_raycast
+ * RE_rayobject_intersect does NOT perform last-hit optimization
+ * So this is probably a function to call inside raytrace structures
+ */
+int RE_rayobject_intersect(RayObject *r, struct Isect *i);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
similarity index 95%
rename from source/blender/render/intern/source/rayobject_octree.c
rename to source/blender/render/intern/raytrace/rayobject_octree.cpp
index 8a8b102c6faaa20b5edd8f4dae6a25fe0ff17d6b..0fd43dfe5ef87e60bdf40ae9be79caf4bf3dad0e 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: rayobject_octree.cpp 29491 2010-06-16 18:57:23Z blendix $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -41,8 +41,7 @@
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
 
-
-
+#include "rayintersection.h"
 #include "rayobject.h"
 
 /* ********** structs *************** */
@@ -126,8 +125,8 @@ static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x,
        float min[3], max[3];
        int ocmin, ocmax;
        
-       VECCOPY(min, v1);
-       VECCOPY(max, v1);
+       copy_v3_v3(min, v1);
+       copy_v3_v3(max, v1);
        DO_MINMAX(v2, min, max);
        DO_MINMAX(v3, min, max);
        if(v4) {
@@ -192,7 +191,7 @@ static Branch *addbranch(Octree *oc, Branch *br, short ocb)
        index= oc->branchcount>>12;
        
        if(oc->adrbranch[index]==NULL)
-               oc->adrbranch[index]= MEM_callocN(4096*sizeof(Branch), "new oc branch");
+               oc->adrbranch[index]= (Branch*)MEM_callocN(4096*sizeof(Branch), "new oc branch");
 
        if(oc->branchcount>= BRANCH_ARRAY*4096) {
                printf("error; octree branches full\n");
@@ -210,7 +209,7 @@ static Node *addnode(Octree *oc)
        index= oc->nodecount>>12;
        
        if(oc->adrnode[index]==NULL)
-               oc->adrnode[index]= MEM_callocN(4096*sizeof(Node),"addnode");
+               oc->adrnode[index]= (Node*)MEM_callocN(4096*sizeof(Node),"addnode");
 
        if(oc->nodecount> NODE_ARRAY*NODE_ARRAY) {
                printf("error; octree nodes full\n");
@@ -465,7 +464,7 @@ static void RE_rayobject_octree_free(RayObject *tree)
 
 RayObject *RE_rayobject_octree_create(int ocres, int size)
 {
-       Octree *oc= MEM_callocN(sizeof(Octree), "Octree");
+       Octree *oc= (Octree*)MEM_callocN(sizeof(Octree), "Octree");
        assert( RE_rayobject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */        
        
        oc->rayobj.api = &octree_api;
@@ -505,11 +504,11 @@ static void octree_fill_rayface(Octree *oc, RayFace *face)
 
        ocres2= oc->ocres*oc->ocres;
 
-       VECCOPY(co1, face->v1);
-       VECCOPY(co2, face->v2);
-       VECCOPY(co3, face->v3);
+       copy_v3_v3(co1, face->v1);
+       copy_v3_v3(co2, face->v2);
+       copy_v3_v3(co3, face->v3);
        if(face->v4)
-               VECCOPY(co4, face->v4);
+               copy_v3_v3(co4, face->v4);
 
        for(c=0;c<3;c++) {
                rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ;
@@ -621,13 +620,13 @@ static void RE_rayobject_octree_done(RayObject *tree)
                RE_rayobject_merge_bb( RE_rayobject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max);
                
        /* Alloc memory */
-       oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches");
-       oc->adrnode= MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes");
+       oc->adrbranch= (Branch**)MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches");
+       oc->adrnode= (Node**)MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes");
        
        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");
+       oc->ocface= (char*)MEM_callocN( 3*ocres2 + 8, "ocface");
        memset(oc->ocface, 0, 3*ocres2);
 
        for(c=0;c<3;c++) {      /* octree enlarge, still needed? */
@@ -857,20 +856,20 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
        is->userdata= oc->userdata;
 #endif
 
-       VECCOPY( start, is->start );
-       VECADDFAC( end, is->start, is->vec, is->labda );
-       ldx= is->vec[0]*is->labda;
-       olabda = is->labda;
+       copy_v3_v3( start, is->start );
+       madd_v3_v3v3fl( end, is->start, is->dir, is->dist );
+       ldx= is->dir[0]*is->dist;
+       olabda = is->dist;
        u1= 0.0f;
        u2= 1.0f;
        
        /* clip with octree cube */
        if(cliptest(-ldx, start[0]-oc->min[0], &u1,&u2)) {
                if(cliptest(ldx, oc->max[0]-start[0], &u1,&u2)) {
-                       ldy= is->vec[1]*is->labda;
+                       ldy= is->dir[1]*is->dist;
                        if(cliptest(-ldy, start[1]-oc->min[1], &u1,&u2)) {
                                if(cliptest(ldy, oc->max[1]-start[1], &u1,&u2)) {
-                                       ldz = is->vec[2]*is->labda;
+                                       ldz = is->dir[2]*is->dist;
                                        if(cliptest(-ldz, start[2]-oc->min[2], &u1,&u2)) {
                                                if(cliptest(ldz, oc->max[2]-start[2], &u1,&u2)) {
                                                        c1=1;
@@ -974,11 +973,10 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
                        ldz=0;
                        dz= 0;
                }
-
+               
                xo=ocx1; yo=ocy1; zo=ocz1;
-               ddalabda= MIN3(labdax,labday,labdaz);
-               /*labdao= ddalabda;*/ /*NEVER READ*/
-
+               labdao= ddalabda= MIN3(labdax,labday,labdaz);
+               
                vec2[0]= ox1;
                vec2[1]= oy1;
                vec2[2]= oz1;
@@ -992,18 +990,18 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
                        if(no) {
                                
                                /* calculate ray intersection with octree node */
-                               VECCOPY(vec1, vec2);
+                               copy_v3_v3(vec1, vec2);
                                // dox,y,z is negative
                                vec2[0]= ox1-ddalabda*dox;
                                vec2[1]= oy1-ddalabda*doy;
                                vec2[2]= oz1-ddalabda*doz;
                                calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2);
 
-                               //is->labda = (u1+ddalabda*(u2-u1))*olabda;
+                               //is->dist = (u1+ddalabda*(u2-u1))*olabda;
                                if( testnode(oc, is, no, ocval) )
                                        found = 1;
 
-                               if(is->labda < (u1+ddalabda*(u2-u1))*olabda)
+                               if(is->dist < (u1+ddalabda*(u2-u1))*olabda)
                                        return found;
                        }
 
index c510af540dbbedeae87d99382c39fcd8d5137f79..e8a118d3349c2d0b95aed2f947bcde54f0ff71c2 100644 (file)
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
 #include "vbvh.h"
 #include "svbvh.h"
 #include "reorganize.h"
@@ -60,10 +64,10 @@ void bvh_done<QBVHTree>(QBVHTree *obj)
                                           BLI_memarena_use_malloc(arena2);
                                           BLI_memarena_use_align(arena2, 16);
 
-       //Build and optimize the tree   
-       //TODO do this in 1 pass (half memory usage during building)    
+       //Build and optimize the tree
+       //TODO do this in 1 pass (half memory usage during building)
        VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder);       
-       
+
        if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
        {
                BLI_memarena_free(arena1);
@@ -71,28 +75,32 @@ void bvh_done<QBVHTree>(QBVHTree *obj)
                return;
        }
        
-       pushup_simd<VBVHNode,4>(root);                                     
+       pushup_simd<VBVHNode,4>(root);
+
        obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root);
        
-       //Cleanup
-       BLI_memarena_free(arena1);      
+       //Free data
+       BLI_memarena_free(arena1);
        
-       rtbuild_free( obj->builder );
-       obj->builder = NULL;
-
        obj->node_arena = arena2;
-       obj->cost = 1.0;        
-}
+       obj->cost = 1.0;
 
+       rtbuild_free(obj->builder);
+       obj->builder = NULL;
+}
 
 template<int StackSize>
 int intersect(QBVHTree *obj, Isect* isec)
 {
        //TODO renable hint support
-       if(RE_rayobject_isAligned(obj->root))
-               return bvh_node_stack_raycast<SVBVHNode,StackSize,false>( obj->root, isec);
+       if(RE_rayobject_isAligned(obj->root)) {
+               if(isec->mode == RE_RAY_SHADOW)
+                       return svbvh_node_stack_raycast<StackSize,true>(obj->root, isec);
+               else
+                       return svbvh_node_stack_raycast<StackSize,false>(obj->root, isec);
+       }
        else
-               return RE_rayobject_intersect( (RayObject*) obj->root, isec );
+               return RE_rayobject_intersect((RayObject*)obj->root, isec);
 }
 
 template<class Tree>
@@ -132,13 +140,11 @@ RayObjectAPI* bvh_get_api(int maxstacksize)
        return 0;
 }
 
-
 RayObject *RE_rayobject_qbvh_create(int size)
 {
        return bvh_create_tree<QBVHTree,DFS_STACK_SIZE>(size);
 }
 
-
 #else
 
 RayObject *RE_rayobject_qbvh_create(int size)
similarity index 97%
rename from source/blender/render/intern/source/rayobject_raycounter.c
rename to source/blender/render/intern/raytrace/rayobject_raycounter.cpp
index 16446bde5012acfbbce517be50aaa486e5b4f457..a355d4b5a06a8e0280775b7b3749456419309551 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: rayobject_raycounter.cpp 29491 2010-06-16 18:57:23Z blendix $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -26,6 +26,7 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #include "rayobject.h"
 #include "raycounter.h"
 
index 79bb3b9260fe2cb39c0f2d651709e6b65f806c82..cdaaebc7f92220bcfd9e7651740b85b20d73c6e6 100644 (file)
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): Andr Pinto.
+ * Contributor(s): André Pinto.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #include <assert.h>
 #include <math.h>
 #include <stdlib.h>
 #include <algorithm>
 
 #include "rayobject_rtbuild.h"
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
 
-
-
 static bool selected_node(RTBuilder::Object *node)
 {
        return node->selected;
@@ -94,13 +94,22 @@ void rtbuild_free(RTBuilder *b)
 
 void rtbuild_add(RTBuilder *b, RayObject *o)
 {
+       float bb[6];
+
        assert( b->primitives.begin + b->primitives.maxsize != b->primitives.end );
+
+       INIT_MINMAX(bb, bb+3);
+       RE_rayobject_merge_bb(o, bb, bb+3);
+
+       /* skip objects with zero bounding box, they are of no use, and
+          will give problems in rtbuild_heuristic_object_split later */
+       if(len_squared_v3v3(bb, bb+3) == 0.0f)
+               return;
        
+       copy_v3_v3(b->primitives.end->bb, bb);
+       copy_v3_v3(b->primitives.end->bb+3, bb+3);
        b->primitives.end->obj = o;
        b->primitives.end->cost = RE_rayobject_cost(o);
-
-       INIT_MINMAX(b->primitives.end->bb, b->primitives.end->bb+3);
-       RE_rayobject_merge_bb(o, b->primitives.end->bb, b->primitives.end->bb+3);
        
        for(int i=0; i<3; i++)
        {
@@ -333,8 +342,8 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds)
                        {
                                if(i == size-1)
                                {
-                                       VECCOPY(sweep[i].bb, obj[i]->bb);
-                                       VECCOPY(sweep[i].bb+3, obj[i]->bb+3);
+                                       copy_v3_v3(sweep[i].bb, obj[i]->bb);
+                                       copy_v3_v3(sweep[i].bb+3, obj[i]->bb+3);
                                        sweep[i].cost = obj[i]->cost;
                                }
                                else
@@ -365,8 +374,12 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds)
                                //Worst case heuristic (cost of each child is linear)
                                float hcost, left_side, right_side;
                                
-                               left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost+logf((float)i));
-                               right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf((float)size-i));
+                               // not using log seems to have no impact on raytracing perf, but
+                               // makes tree construction quicker, left out for now to test (brecht)
+                               // left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost+logf((float)i));
+                               // right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf((float)size-i));
+                               left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost);
+                               right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost);
                                hcost = left_side+right_side;
 
                                assert(left_side >= 0);
index 647c5771e4fa54f72acdf6d7b3500a2722b04a5a..c10da3ad8c045087e2d49ed5ec37b42df381ac7e 100644 (file)
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #include "MEM_guardedalloc.h"
 
+#include "BLI_utildefines.h"
+
 #include "vbvh.h"
 #include "svbvh.h"
 #include "reorganize.h"
@@ -75,7 +78,8 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
        //Build and optimize the tree
        if(0)
        {
-               VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder);
+               VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder);
+
                if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
                {
                        BLI_memarena_free(arena1);
@@ -86,11 +90,11 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
                reorganize(root);
                remove_useless(root, &root);
                bvh_refit(root);
-       
+
                pushup(root);
                pushdown(root);
                pushup_simd<VBVHNode,4>(root);
-       
+
                obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root);
        }
        else
@@ -98,6 +102,7 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
                //Finds the optimal packing of this tree using a given cost model
                //TODO this uses quite a lot of memory, find ways to reduce memory usage during building
                OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder);                      
+
                if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
                {
                        BLI_memarena_free(arena1);
@@ -108,15 +113,13 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
                VBVH_optimalPackSIMD<OVBVHNode,PackCost>(PackCost()).transform(root);
                obj->root = Reorganize_SVBVH<OVBVHNode>(arena2).transform(root);
        }
-
        
        //Free data
        BLI_memarena_free(arena1);
        
        obj->node_arena = arena2;
        obj->cost = 1.0;
-       
-       
+
        rtbuild_free( obj->builder );
        obj->builder = NULL;
 }
@@ -125,8 +128,12 @@ template<int StackSize>
 int intersect(SVBVHTree *obj, Isect* isec)
 {
        //TODO renable hint support
-       if(RE_rayobject_isAligned(obj->root))
-               return bvh_node_stack_raycast<SVBVHNode,StackSize,false>( obj->root, isec);
+       if(RE_rayobject_isAligned(obj->root)) {
+               if(isec->mode == RE_RAY_SHADOW)
+                       return svbvh_node_stack_raycast<StackSize,true>(obj->root, isec);
+               else
+                       return svbvh_node_stack_raycast<StackSize,false>(obj->root, isec);
+       }
        else
                return RE_rayobject_intersect( (RayObject*) obj->root, isec );
 }
@@ -172,6 +179,7 @@ RayObject *RE_rayobject_svbvh_create(int size)
 {
        return bvh_create_tree<SVBVHTree,DFS_STACK_SIZE>(size);
 }
+
 #else
 
 RayObject *RE_rayobject_svbvh_create(int size)
index b2104a2d557d66515c6cefccb4cb21f9d8cef52f..df5842db2bf44405b2516ce76050f71331cd5168 100644 (file)
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): Andr Pinto.
+ * Contributor(s): André Pinto.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 int tot_pushup   = 0;
 int tot_pushdown = 0;
 int tot_hints    = 0;
 
-
 #include <assert.h>
-#include "rayobject.h"
-#include "rayobject_rtbuild.h"
-#include "RE_raytrace.h"
-#include "BLI_memarena.h"
+
 #include "MEM_guardedalloc.h"
+
 #include "BKE_global.h"
 
 #include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_utildefines.h"
+
+#include "rayintersection.h"
+#include "rayobject.h"
+#include "rayobject_rtbuild.h"
 
 #include "reorganize.h"
 #include "bvh.h"
 #include "vbvh.h"
-#include "svbvh.h"
+
 #include <queue>
 #include <algorithm>
 
@@ -126,8 +130,12 @@ template<int StackSize>
 int intersect(VBVHTree *obj, Isect* isec)
 {
        //TODO renable hint support
-       if(RE_rayobject_isAligned(obj->root))
-               return bvh_node_stack_raycast<VBVHNode,StackSize,false>( obj->root, isec);
+       if(RE_rayobject_isAligned(obj->root)) {
+               if(isec->mode == RE_RAY_SHADOW)
+                       return bvh_node_stack_raycast<VBVHNode,StackSize,false,true>( obj->root, isec);
+               else
+                       return bvh_node_stack_raycast<VBVHNode,StackSize,false,false>( obj->root, isec);
+       }
        else
                return RE_rayobject_intersect( (RayObject*) obj->root, isec );
 }
index c8fbd1cfe94c673521c851341cb19d45d84c0fdc..4e2dce3213671f1c468722e0bd876feec7aca491 100644 (file)
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
+#include <float.h>
+#include <math.h>
 #include <stdio.h>
+
 #include <algorithm>
-#include <math.h>
-#include <vector>
 #include <queue>
-
-#include "BLI_utildefines.h"
+#include <vector>
 
 #include "BKE_global.h"
 
 #ifdef _WIN32
-#undef INFINITY
 #define INFINITY FLT_MAX // in mingw math.h: (1.0F/0.0F). This generates compile error, though.
 #endif
 
@@ -302,7 +302,7 @@ float bvh_refit(Node *node)
  * with the purpose to reduce the expected cost (eg.: number of BB tests).
  */
 #include <vector>
-#define MAX_CUT_SIZE   16
+#define MAX_CUT_SIZE           4                               /* svbvh assumes max 4 children! */
 #define MAX_OPTIMIZE_CHILDS    MAX_CUT_SIZE
 
 struct OVBVHNode
index 11511fccb894b4ed5cd3a240a5bb2c642264c884..832058870dde75e54fe072770a9048ea0d58f124 100644 (file)
@@ -26,6 +26,7 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #ifdef __SSE__
  
 #ifndef RE_RAYTRACE_SVBVH_H
 
 #include "bvh.h"
 #include "BLI_memarena.h"
-#include "BLI_utildefines.h"
 #include "BKE_global.h"
 #include <stdio.h>
 #include <algorithm>
 
 struct SVBVHNode
 {
+       float child_bb[24];
+       SVBVHNode *child[4];
        int nchilds;
-
-       //Array of bb, array of childs
-       float *child_bb;
-       SVBVHNode **child;
 };
 
-template<>
-inline int bvh_node_hit_test<SVBVHNode>(SVBVHNode *node, Isect *isec)
+static int svbvh_bb_intersect_test_simd4(const Isect *isec, const __m128 *bb_group)
+{
+       const __m128 tmin0 = _mm_setzero_ps();
+       const __m128 tmax0 = _mm_set_ps1(isec->dist);
+
+       const __m128 start0 = _mm_set_ps1(isec->start[0]);
+       const __m128 start1 = _mm_set_ps1(isec->start[1]);
+       const __m128 start2 = _mm_set_ps1(isec->start[2]);
+       const __m128 sub0 = _mm_sub_ps(bb_group[isec->bv_index[0]], start0);
+       const __m128 sub1 = _mm_sub_ps(bb_group[isec->bv_index[1]], start0);
+       const __m128 sub2 = _mm_sub_ps(bb_group[isec->bv_index[2]], start1);
+       const __m128 sub3 = _mm_sub_ps(bb_group[isec->bv_index[3]], start1);
+       const __m128 sub4 = _mm_sub_ps(bb_group[isec->bv_index[4]], start2);
+       const __m128 sub5 = _mm_sub_ps(bb_group[isec->bv_index[5]], start2);
+       const __m128 idot_axis0 = _mm_set_ps1(isec->idot_axis[0]);
+       const __m128 idot_axis1 = _mm_set_ps1(isec->idot_axis[1]);
+       const __m128 idot_axis2 = _mm_set_ps1(isec->idot_axis[2]);
+       const __m128 mul0 = _mm_mul_ps(sub0, idot_axis0);
+       const __m128 mul1 = _mm_mul_ps(sub1, idot_axis0);
+       const __m128 mul2 = _mm_mul_ps(sub2, idot_axis1);
+       const __m128 mul3 = _mm_mul_ps(sub3, idot_axis1);
+       const __m128 mul4 = _mm_mul_ps(sub4, idot_axis2);
+       const __m128 mul5 = _mm_mul_ps(sub5, idot_axis2);
+       const __m128 tmin1 = _mm_max_ps(tmin0, mul0);
+       const __m128 tmax1 = _mm_min_ps(tmax0, mul1);
+       const __m128 tmin2 = _mm_max_ps(tmin1, mul2);
+       const __m128 tmax2 = _mm_min_ps(tmax1, mul3);
+       const __m128 tmin3 = _mm_max_ps(tmin2, mul4);
+       const __m128 tmax3 = _mm_min_ps(tmax2, mul5);
+       
+       return _mm_movemask_ps(_mm_cmpge_ps(tmax3, tmin3));
+}
+
+static int svbvh_bb_intersect_test(const Isect *isec, const float *_bb)
 {
+       const float *bb = _bb;
+       
+       float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0];
+       float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0];
+       float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1];
+       float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1];
+       float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2];
+       float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2];
+       
+       RE_RC_COUNT(isec->raycounter->bb.test);
+
+       if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0;
+       if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0;
+       if(t1x > isec->dist || t1y > isec->dist || t1z > isec->dist) return 0;
+
+       RE_RC_COUNT(isec->raycounter->bb.hit);  
+
        return 1;
 }
 
-template<>
-inline void bvh_node_push_childs<SVBVHNode>(SVBVHNode *node, Isect *isec, SVBVHNode **stack, int &stack_pos)
+static bool svbvh_node_is_leaf(const SVBVHNode *node)
 {
-       int i=0;
-       while(i+4 <= node->nchilds)
-       {
-               int res = test_bb_group4( (__m128*) (node->child_bb+6*i), isec );
-               RE_RC_COUNT(isec->raycounter->simd_bb.test);
-               
-               if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-               if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-               if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-               if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
-               
-               i += 4;
-       }
-       while(i < node->nchilds)
+       return !RE_rayobject_isAligned(node);
+}
+
+template<int MAX_STACK_SIZE, bool SHADOW>
+static int svbvh_node_stack_raycast(SVBVHNode *root, Isect *isec)
+{
+       SVBVHNode *stack[MAX_STACK_SIZE], *node;
+       int hit = 0, stack_pos = 0;
+
+       stack[stack_pos++] = root;
+
+       while(stack_pos)
        {
-               if(RE_rayobject_bb_intersect_test(isec, (const float*)node->child_bb+6*i))
-                       stack[stack_pos++] = node->child[i];
-               i++;
+               node = stack[--stack_pos];
+
+               if(!svbvh_node_is_leaf(node))
+               {
+                       int nchilds= node->nchilds;
+
+                       if(nchilds == 4) {
+                               float *child_bb= node->child_bb;
+                               int res = svbvh_bb_intersect_test_simd4(isec, ((__m128*) (child_bb)));
+                               SVBVHNode **child= node->child;
+
+                               RE_RC_COUNT(isec->raycounter->simd_bb.test);
+
+                               if(res & 1) { stack[stack_pos++] = child[0]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+                               if(res & 2) { stack[stack_pos++] = child[1]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+                               if(res & 4) { stack[stack_pos++] = child[2]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+                               if(res & 8) { stack[stack_pos++] = child[3]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+                       }
+                       else {
+                               float *child_bb= node->child_bb;
+                               SVBVHNode **child= node->child;
+                               int i;
+
+                               for(i=0; i<nchilds; i++)
+                                       if(svbvh_bb_intersect_test(isec, (float*)child_bb+6*i))
+                                               stack[stack_pos++] = child[i];
+                       }
+               }
+               else
+               {
+                       hit |= RE_rayobject_intersect((RayObject*)node, isec);
+                       if(SHADOW && hit) break;
+               }
        }
+
+       return hit;
 }
 
+
 template<>
 inline void bvh_node_merge_bb<SVBVHNode>(SVBVHNode *node, float *min, float *max)
 {
        if(is_leaf(node))
        {
-               RE_rayobject_merge_bb( (RayObject*)node, min, max);
+               RE_rayobject_merge_bb((RayObject*)node, min, max);
        }
        else
        {
@@ -156,15 +233,13 @@ struct Reorganize_SVBVH
        {
                SVBVHNode *node = (SVBVHNode*)BLI_memarena_alloc(arena, sizeof(SVBVHNode));
                node->nchilds = nchilds;
-               node->child_bb   = (float*)BLI_memarena_alloc(arena, sizeof(float)*6*nchilds);
-               node->child= (SVBVHNode**)BLI_memarena_alloc(arena, sizeof(SVBVHNode*)*nchilds);
 
                return node;
        }
        
        void copy_bb(float *bb, const float *old_bb)
        {
-               std::copy( old_bb, old_bb+6, bb );
+               std::copy(old_bb, old_bb+6, bb);
        }
        
        void prepare_for_simd(SVBVHNode *node)
@@ -174,7 +249,7 @@ struct Reorganize_SVBVH
                {
                        float vec_tmp[4*6];
                        float *res = node->child_bb+6*i;
-                       std::copy( res, res+6*4, vec_tmp);
+                       std::copy(res, res+6*4, vec_tmp);
                        
                        for(int j=0; j<6; j++)
                        {
@@ -231,7 +306,7 @@ struct Reorganize_SVBVH
                        {
                                float bb[6];
                                INIT_MINMAX(bb, bb+3);
-                               RE_rayobject_merge_bb( (RayObject*)o_child, bb, bb+3);
+                               RE_rayobject_merge_bb((RayObject*)o_child, bb, bb+3);
                                copy_bb(node->child_bb+i*6, bb);
                                break;
                        }
@@ -240,7 +315,7 @@ struct Reorganize_SVBVH
                                copy_bb(node->child_bb+i*6, o_child->bb);
                        }
                }
-               assert( i == 0 );
+               assert(i == 0);
 
                prepare_for_simd(node);
                
@@ -251,3 +326,4 @@ struct Reorganize_SVBVH
 #endif
 
 #endif //__SSE__
+
index a5ca093de2afe212a5b2910f1cbd5ea5d20d0883..06188ede8c61fb7f565edf9919b8639eaced0eb6 100644 (file)
  *
  * ***** END GPL LICENSE BLOCK *****
  */
-#include <assert.h>
 
+#include <assert.h>
 #include <algorithm>
-#include "rayobject_rtbuild.h"
+
 #include "BLI_memarena.h"
-#include "BLI_utildefines.h"
+
+#include "rayobject_rtbuild.h"
 
 /*
  * VBVHNode represents a BVHNode with support for a variable number of childrens
@@ -167,12 +168,11 @@ struct BuildBinaryVBVH
                        
                        Node *node = create_node();
 
-                       INIT_MINMAX(node->bb, node->bb+3);
-                       rtbuild_merge_bb(builder, node->bb, node->bb+3);
-                       
                        Node **child = &node->child;
 
                        int nc = rtbuild_split(builder);
+                       INIT_MINMAX(node->bb, node->bb+3);
+
                        assert(nc == 2);
                        for(int i=0; i<nc; i++)
                        {
@@ -180,6 +180,8 @@ struct BuildBinaryVBVH
                                rtbuild_get_child(builder, i, &tmp);
                                
                                *child = _transform(&tmp);
+                               DO_MIN((*child)->bb, node->bb);
+                               DO_MAX((*child)->bb+3, node->bb+3);
                                child = &((*child)->sibling);
                        }
 
index b5c53e8cb3994ba834f855a87145ba460b9f93fa..550a063c2988889f99907212b77b25f953312e10 100644 (file)
@@ -3940,30 +3940,35 @@ static void set_phong_threshold(ObjectRen *obr)
 
 /* per face check if all samples should be taken.
    if raytrace or multisample, do always for raytraced material, or when material full_osa set */
-static void set_fullsample_flag(Render *re, ObjectRen *obr)
+static void set_fullsample_trace_flag(Render *re, ObjectRen *obr)
 {
        VlakRen *vlr;
-       int a, trace, mode;
+       int a, trace, mode, osa;
 
-       if(re->osa==0)
-               return;
-       
+       osa= re->osa;
        trace= re->r.mode & R_RAYTRACE;
        
        for(a=obr->totvlak-1; a>=0; a--) {
                vlr= RE_findOrAddVlak(obr, a);
                mode= vlr->mat->mode;
+
+               if(trace && (mode & MA_TRACEBLE))
+                       vlr->flag |= R_TRACEBLE;
                
-               if(mode & MA_FULL_OSA) 
-                       vlr->flag |= R_FULL_OSA;
-               else if(trace) {
-                       if(mode & MA_SHLESS);
-                       else if(vlr->mat->material_type == MA_TYPE_VOLUME);
-                       else if((mode & MA_RAYMIRROR) || ((mode & MA_TRANSP) && (mode & MA_RAYTRANSP)))
-                               /* for blurry reflect/refract, better to take more samples 
-                                * inside the raytrace than as OSA samples */
-                               if ((vlr->mat->gloss_mir == 1.0) && (vlr->mat->gloss_tra == 1.0)) 
-                                       vlr->flag |= R_FULL_OSA;
+               if(osa) {
+                       if(mode & MA_FULL_OSA) {
+                               vlr->flag |= R_FULL_OSA;
+                       }
+                       else if(trace) {
+                               if(mode & MA_SHLESS);
+                               else if(vlr->mat->material_type == MA_TYPE_VOLUME);
+                               else if((mode & MA_RAYMIRROR) || ((mode & MA_TRANSP) && (mode & MA_RAYTRANSP))) {
+                                       /* for blurry reflect/refract, better to take more samples 
+                                        * inside the raytrace than as OSA samples */
+                                       if ((vlr->mat->gloss_mir == 1.0) && (vlr->mat->gloss_tra == 1.0)) 
+                                               vlr->flag |= R_FULL_OSA;
+                               }
+                       }
                }
        }
 }
@@ -4158,7 +4163,7 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset)
                                        check_non_flat_quads(obr);
                        }
                        
-                       set_fullsample_flag(re, obr);
+                       set_fullsample_trace_flag(re, obr);
 
                        /* compute bounding boxes for clipping */
                        INIT_MINMAX(min, max);
index a1a06f87722684a57abfeebd71aad38f3aac1a95..d1a0860545b9cde1682aa7006f581659b25221c9 100644 (file)
@@ -60,7 +60,7 @@
 #include "texture.h"
 #include "volumetric.h"
 
-#include "RE_raytrace.h"
+#include "rayintersection.h"
 #include "rayobject.h"
 #include "raycounter.h"
 
@@ -195,7 +195,7 @@ void freeraytree(Render *re)
 static int is_raytraceable_vlr(Render *re, VlakRen *vlr)
 {
        /* note: volumetric must be tracable, wire must not */
-       if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE) || (vlr->mat->material_type == MA_TYPE_VOLUME))
+       if((re->flag & R_BAKE_TRACE) || (vlr->flag & R_TRACEBLE) || (vlr->mat->material_type == MA_TYPE_VOLUME))
                if(vlr->mat->material_type != MA_TYPE_WIRE)
                        return 1;
        return 0;
@@ -209,12 +209,13 @@ static int is_raytraceable(Render *re, ObjectInstanceRen *obi)
        if(re->excludeob && obr->ob == re->excludeob)
                return 0;
 
-       for(v=0;v<obr->totvlak;v++)
-       {
+       for(v=0;v<obr->totvlak;v++) {
                VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+
                if(is_raytraceable_vlr(re, vlr))
                        return 1;
        }
+
        return 0;
 }
 
@@ -444,11 +445,7 @@ void makeraytree(Render *re)
        if(re->r.raytrace_structure == R_RAYSTRUCTURE_OCTREE)
                re->r.raytrace_options &= ~( R_RAYTRACE_USE_INSTANCES | R_RAYTRACE_USE_LOCAL_COORDS);
 
-       if(G.f & G_DEBUG) {
-               BENCH(makeraytree_single(re), tree_build);
-       }
-       else
-               makeraytree_single(re);
+       makeraytree_single(re);
 
        if(test_break(re))
        {
@@ -522,12 +519,12 @@ void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
        VlakRen *vlr= (VlakRen*)is->hit.face;
        
        /* set up view vector */
-       VECCOPY(shi->view, is->vec);
+       VECCOPY(shi->view, is->dir);
 
        /* render co */
-       shi->co[0]= is->start[0]+is->labda*(shi->view[0]);
-       shi->co[1]= is->start[1]+is->labda*(shi->view[1]);
-       shi->co[2]= is->start[2]+is->labda*(shi->view[2]);
+       shi->co[0]= is->start[0]+is->dist*(shi->view[0]);
+       shi->co[1]= is->start[1]+is->dist*(shi->view[1]);
+       shi->co[2]= is->start[2]+is->dist*(shi->view[2]);
        
        normalize_v3(shi->view);
 
@@ -717,15 +714,15 @@ static void ray_fadeout(Isect *is, ShadeInput *shi, float *col, float *blendcol,
 
 /* the main recursive tracer itself
  * note: 'col' must be initialized */
-static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, float *start, float *vec, float *col, ObjectInstanceRen *obi, VlakRen *vlr, int traflag)
+static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, float *start, float *dir, float *col, ObjectInstanceRen *obi, VlakRen *vlr, int traflag)
 {
        ShadeInput shi= {0};
        Isect isec;
        float dist_mir = origshi->mat->dist_mir;
        
        VECCOPY(isec.start, start);
-       VECCOPY(isec.vec, vec );
-       isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST;
+       VECCOPY(isec.dir, dir );
+       isec.dist = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST;
        isec.mode= RE_RAY_MIRROR;
        isec.check = RE_CHECK_VLR_RENDER;
        isec.skip = RE_SKIP_VLR_NEIGHBOUR;
@@ -863,7 +860,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
                                
                                /* max ray distance set, but found an intersection, so fade this color
                                 * out towards the sky/material color for a smooth transition */
-                               ray_fadeout_endcolor(blendcol, origshi, &shi, origshr, &isec, vec);
+                               ray_fadeout_endcolor(blendcol, origshi, &shi, origshr, &isec, dir);
                                ray_fadeout(&isec, &shi, col, blendcol, dist_mir);
                        }
                }
@@ -875,7 +872,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
                
        }
        else {
-               ray_fadeout_endcolor(col, origshi, &shi, origshr, &isec, vec);
+               ray_fadeout_endcolor(col, origshi, &shi, origshr, &isec, dir);
        }
        RE_RC_MERGE(&origshi->raycounter, &shi.raycounter);
 }
@@ -1605,13 +1602,13 @@ static void addAlphaLight(float *shadfac, float *col, float alpha, float filter)
        shadfac[3]= (1.0f-alpha)*shadfac[3];
 }
 
-static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int traflag)
+static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int traflag, float col[4])
 {
        /* ray to lamp, find first face that intersects, check alpha properties,
           if it has col[3]>0.0f  continue. so exit when alpha is full */
        ShadeInput shi;
        ShadeResult shr;
-       float initial_labda = is->labda;
+       float initial_dist = is->dist;
        
        if(RE_rayobject_raycast(R.raytree, is)) {
                float d= 1.0f;
@@ -1639,26 +1636,26 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
                                d= shade_by_transmission(is, &shi, &shr);
                        
                        /* mix colors based on shadfac (rgb + amount of light factor) */
-                       addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter);
+                       addAlphaLight(col, shr.diff, shr.alpha, d*shi.mat->filter);
                } else if (shi.mat->material_type == MA_TYPE_VOLUME) {
-                       const float a = is->col[3];
+                       const float a = col[3];
                        
-                       is->col[0] = a*is->col[0] + shr.alpha*shr.combined[0];
-                       is->col[1] = a*is->col[1] + shr.alpha*shr.combined[1];
-                       is->col[2] = a*is->col[2] + shr.alpha*shr.combined[2];
+                       col[0] = a*col[0] + shr.alpha*shr.combined[0];
+                       col[1] = a*col[1] + shr.alpha*shr.combined[1];
+                       col[2] = a*col[2] + shr.alpha*shr.combined[2];
                        
-                       is->col[3] = (1.0 - shr.alpha)*a;
+                       col[3] = (1.0 - shr.alpha)*a;
                }
                
-               if(depth>0 && is->col[3]>0.0f) {
+               if(depth>0 && col[3]>0.0f) {
                        
                        /* adapt isect struct */
                        VECCOPY(is->start, shi.co);
-                       is->labda = initial_labda-is->labda;
+                       is->dist = initial_dist-is->dist;
                        is->orig.ob   = shi.obi;
                        is->orig.face = shi.vlr;
 
-                       ray_trace_shadow_tra(is, origshi, depth-1, traflag | RAY_TRA);
+                       ray_trace_shadow_tra(is, origshi, depth-1, traflag | RAY_TRA, col);
                }
                
                RE_RC_MERGE(&origshi->raycounter, &shi.raycounter);
@@ -1705,8 +1702,8 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
                        vec[2]-= vec[2];
                }
 
-               VECCOPY(isec.vec, vec );
-               isec.labda = RE_RAYTRACE_MAXDIST;
+               VECCOPY(isec.dir, vec );
+               isec.dist = RE_RAYTRACE_MAXDIST;
 
                if(RE_rayobject_raycast(R.raytree, &isec)) {
                        float fac;
@@ -1717,7 +1714,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
                        /* end warning! - Campbell */
                        
                        shade_ray(&isec, &shi, &shr_t);
-                       fac= isec.labda*isec.labda;
+                       fac= isec.dist*isec.dist;
                        fac= 1.0f;
                        accum[0]+= fac*(shr_t.diff[0]+shr_t.spec[0]);
                        accum[1]+= fac*(shr_t.diff[1]+shr_t.spec[1]);
@@ -1936,7 +1933,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *ao, float *env)
        else {
                VECCOPY(nrm, shi->facenor);
        }
-       
+
        ortho_basis_v3v3_v3( up, side,nrm);
        
        /* sampling init */
@@ -1954,7 +1951,6 @@ static void ray_ao_qmc(ShadeInput *shi, float *ao, float *env)
 
        QMC_initPixel(qsa, shi->thread);
        
-       
        while (samples < max_samples) {
 
                /* sampling, returns quasi-random vector in unit hemisphere */
@@ -1966,15 +1962,15 @@ static void ray_ao_qmc(ShadeInput *shi, float *ao, float *env)
                
                normalize_v3(dir);
                        
-               isec.vec[0] = -dir[0];
-               isec.vec[1] = -dir[1];
-               isec.vec[2] = -dir[2];
-               isec.labda = maxdist;
+               isec.dir[0] = -dir[0];
+               isec.dir[1] = -dir[1];
+               isec.dir[2] = -dir[2];
+               isec.dist = maxdist;
                
                prev = fac;
                
                if(RE_rayobject_raycast(R.raytree, &isec)) {
-                       if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); 
+                       if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.dist*R.wrld.aodistfac); 
                        else fac+= 1.0f;
                }
                else if(envcolor!=WO_AOPLAIN) {
@@ -2102,15 +2098,15 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *ao, float *env)
                        
                        actual++;
                        
-                       /* always set start/vec/labda */
-                       isec.vec[0] = -vec[0];
-                       isec.vec[1] = -vec[1];
-                       isec.vec[2] = -vec[2];
-                       isec.labda = maxdist;
+                       /* always set start/vec/dist */
+                       isec.dir[0] = -vec[0];
+                       isec.dir[1] = -vec[1];
+                       isec.dir[2] = -vec[2];
+                       isec.dist = maxdist;
                        
                        /* do the trace */
                        if(RE_rayobject_raycast(R.raytree, &isec)) {
-                               if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); 
+                               if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.dist*R.wrld.aodistfac); 
                                else sh+= 1.0f;
                        }
                        else if(envcolor!=WO_AOPLAIN) {
@@ -2325,26 +2321,25 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                }
 
                VECCOPY(isec->start, co);
-               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_v3(isec->vec);
+               isec->dir[0] = end[0]-isec->start[0];
+               isec->dir[1] = end[1]-isec->start[1];
+               isec->dir[2] = end[2]-isec->start[2];
+               isec->dist = normalize_v3(isec->dir);
                
                /* trace the ray */
                if(isec->mode==RE_RAY_SHADOW_TRA) {
-                       isec->col[0]= isec->col[1]= isec->col[2]=  1.0f;
-                       isec->col[3]= 1.0f;
+                       float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
                        
-                       ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0);
-                       shadfac[0] += isec->col[0];
-                       shadfac[1] += isec->col[1];
-                       shadfac[2] += isec->col[2];
-                       shadfac[3] += isec->col[3];
+                       ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0, col);
+                       shadfac[0] += col[0];
+                       shadfac[1] += col[1];
+                       shadfac[2] += col[2];
+                       shadfac[3] += col[3];
                        
                        /* for variance calc */
-                       colsq[0] += isec->col[0]*isec->col[0];
-                       colsq[1] += isec->col[1]*isec->col[1];
-                       colsq[2] += isec->col[2]*isec->col[2];
+                       colsq[0] += col[0]*col[0];
+                       colsq[1] += col[1]*col[1];
+                       colsq[2] += col[2]*col[2];
                }
                else {
                        if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f;
@@ -2427,23 +2422,22 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
                mul_m3_v3(lar->mat, vec);
                
                /* set start and vec */
-               isec->vec[0] = vec[0]+lampco[0]-isec->start[0];
-               isec->vec[1] = vec[1]+lampco[1]-isec->start[1];
-               isec->vec[2] = vec[2]+lampco[2]-isec->start[2];
-               isec->labda = 1.0f;
+               isec->dir[0] = vec[0]+lampco[0]-isec->start[0];
+               isec->dir[1] = vec[1]+lampco[1]-isec->start[1];
+               isec->dir[2] = vec[2]+lampco[2]-isec->start[2];
+               isec->dist = 1.0f;
                isec->check = RE_CHECK_VLR_RENDER;
                isec->skip = RE_SKIP_VLR_NEIGHBOUR;
                
                if(isec->mode==RE_RAY_SHADOW_TRA) {
                        /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */
-                       isec->col[0]= isec->col[1]= isec->col[2]=  1.0f;
-                       isec->col[3]= 1.0f;
+                       float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
                        
-                       ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0);
-                       shadfac[0] += isec->col[0];
-                       shadfac[1] += isec->col[1];
-                       shadfac[2] += isec->col[2];
-                       shadfac[3] += isec->col[3];
+                       ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0, col);
+                       shadfac[0] += col[0];
+                       shadfac[1] += col[1];
+                       shadfac[2] += col[2];
+                       shadfac[3] += col[3];
                }
                else if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f;
                
@@ -2524,18 +2518,17 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
                        
                        shadfac[3]= 1.0f; // 1.0=full light
                        
-                       /* set up isec vec */
+                       /* set up isec.dir */
                        VECCOPY(isec.start, shi->co);
-                       VECSUB(isec.vec, lampco, isec.start);
-                       isec.labda = 1.0f;
+                       VECSUB(isec.dir, lampco, isec.start);
+                       isec.dist = normalize_v3(isec.dir);
 
                        if(isec.mode==RE_RAY_SHADOW_TRA) {
                                /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */
-                               isec.col[0]= isec.col[1]= isec.col[2]=  1.0f;
-                               isec.col[3]= 1.0f;
+                               float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
 
-                               ray_trace_shadow_tra(&isec, shi, DEPTH_SHADOW_TRA, 0);
-                               QUATCOPY(shadfac, isec.col);
+                               ray_trace_shadow_tra(&isec, shi, DEPTH_SHADOW_TRA, 0, col);
+                               QUATCOPY(shadfac, col);
                        }
                        else if(RE_rayobject_raycast(R.raytree, &isec))
                                shadfac[3]= 0.0f;
@@ -2580,7 +2573,7 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float
        isec.orig.ob   = shi->obi;
        isec.orig.face = shi->vlr;
        
-       /* set up isec vec */
+       /* set up isec.dir */
        VECCOPY(isec.start, shi->co);
        VECCOPY(isec.end, lampco);
        
@@ -2588,11 +2581,11 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float
                /* we got a face */
                
                /* render co */
-               co[0]= isec.start[0]+isec.labda*(isec.vec[0]);
-               co[1]= isec.start[1]+isec.labda*(isec.vec[1]);
-               co[2]= isec.start[2]+isec.labda*(isec.vec[2]);
+               co[0]= isec.start[0]+isec.dist*(isec.dir[0]);
+               co[1]= isec.start[1]+isec.dist*(isec.dir[1]);
+               co[2]= isec.start[2]+isec.dist*(isec.dir[2]);
                
-               *distfac= len_v3(isec.vec);
+               *distfac= len_v3(isec.dir);
        }
        else
                *distfac= 0.0f;
index d955043b1f1b1fe3185ef450527f0cfc24df3ba3..83e9abc0906535900c18ada2de763f11fd70cbb1 100644 (file)
@@ -61,6 +61,8 @@
 #include "IMB_imbuf.h"
 
 /* local include */
+#include "rayintersection.h"
+#include "rayobject.h"
 #include "renderpipeline.h"
 #include "render_types.h"
 #include "renderdatabase.h"
@@ -71,7 +73,6 @@
 #include "shading.h"
 #include "sss.h"
 #include "zbuf.h"
-#include "RE_raytrace.h"
 
 #include "PIL_time.h"
 
@@ -2287,19 +2288,19 @@ static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, f
        /* 'dir' is always normalized */
        VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist);                                        
 
-       isect->vec[0] = dir[0]*maxdist*sign;
-       isect->vec[1] = dir[1]*maxdist*sign;
-       isect->vec[2] = dir[2]*maxdist*sign;
+       isect->dir[0] = dir[0]*sign;
+       isect->dir[1] = dir[1]*sign;
+       isect->dir[2] = dir[2]*sign;
 
-       isect->labda = maxdist;
+       isect->dist = maxdist;
 
        hit = RE_rayobject_raycast(raytree, isect);
        if(hit) {
-               hitco[0] = isect->start[0] + isect->labda*isect->vec[0];
-               hitco[1] = isect->start[1] + isect->labda*isect->vec[1];
-               hitco[2] = isect->start[2] + isect->labda*isect->vec[2];
+               hitco[0] = isect->start[0] + isect->dist*isect->dir[0];
+               hitco[1] = isect->start[1] + isect->dist*isect->dir[1];
+               hitco[2] = isect->start[2] + isect->dist*isect->dir[2];
 
-               *dist= len_v3v3(start, hitco);
+               *dist= isect->dist;
        }
 
        return hit;
index b917c1ddc9277b0bf6233c2f6a910d8a8deadb9b..c1a3b989c1fa79935157f7591b8b104c2047c7c0 100644 (file)
@@ -76,8 +76,8 @@
 #include "BKE_DerivedMesh.h"
 
 #include "RE_render_ext.h"     /* externtex */
-#include "RE_raytrace.h"
 
+#include "rayobject.h"
 #include "renderpipeline.h"
 #include "render_types.h"
 #include "renderdatabase.h"
index 2813df3744ffc573f72e911baf3fd4491f07e7f2..609e647637f29db30a88c69a1d1725d2e6efcd0c 100644 (file)
 #include "PIL_time.h"
 
 #include "RE_shader_ext.h"
-#include "RE_raytrace.h"
 
 #include "DNA_material_types.h"
 
+#include "rayintersection.h"
+#include "rayobject.h"
 #include "render_types.h"
 #include "rendercore.h"
 #include "renderdatabase.h"
@@ -74,11 +75,11 @@ int intersect_outside_volume(RayObject *tree, Isect *isect, float *offset, int l
        
        if (RE_rayobject_raycast(tree, isect)) {
                
-               isect->start[0] = isect->start[0] + isect->labda*isect->vec[0];
-               isect->start[1] = isect->start[1] + isect->labda*isect->vec[1];
-               isect->start[2] = isect->start[2] + isect->labda*isect->vec[2];
+               isect->start[0] = isect->start[0] + isect->dist*isect->dir[0];
+               isect->start[1] = isect->start[1] + isect->dist*isect->dir[1];
+               isect->start[2] = isect->start[2] + isect->dist*isect->dir[2];
                
-               isect->labda = FLT_MAX;
+               isect->dist = FLT_MAX;
                isect->skip = RE_SKIP_VLR_NEIGHBOUR;
                isect->orig.face= isect->hit.face;
                isect->orig.ob= isect->hit.ob;
@@ -93,21 +94,21 @@ int intersect_outside_volume(RayObject *tree, Isect *isect, float *offset, int l
 int point_inside_obi(RayObject *tree, ObjectInstanceRen *UNUSED(obi), float *co)
 {
        Isect isect= {{0}};
-       float vec[3] = {0.0f,0.0f,1.0f};
+       float dir[3] = {0.0f,0.0f,1.0f};
        int final_depth=0, depth=0, limit=20;
        
        /* set up the isect */
        VECCOPY(isect.start, co);
-       VECCOPY(isect.vec, vec);
+       VECCOPY(isect.dir, dir);
        isect.mode= RE_RAY_MIRROR;
        isect.last_hit= NULL;
        isect.lay= -1;
        
-       isect.labda = FLT_MAX;
+       isect.dist = FLT_MAX;
        isect.orig.face= NULL;
        isect.orig.ob = NULL;
 
-       final_depth = intersect_outside_volume(tree, &isect, vec, limit, depth);
+       final_depth = intersect_outside_volume(tree, &isect, dir, limit, depth);
        
        /* even number of intersections: point is outside
         * odd number: point is inside */
index b0aca038e7242a227e4c91e9032200b29dcf0f45..dc016a161b5afd62dcdcc187cc954d6df1ab7573 100644 (file)
@@ -40,7 +40,6 @@
 #include "BLI_utildefines.h"
 
 #include "RE_shader_ext.h"
-#include "RE_raytrace.h"
 
 #include "DNA_material_types.h"
 #include "DNA_group_types.h"
@@ -51,6 +50,8 @@
 
 #include "render_types.h"
 #include "pixelshading.h"
+#include "rayintersection.h"
+#include "rayobject.h"
 #include "shading.h"
 #include "shadbuf.h"
 #include "texture.h"
@@ -84,13 +85,13 @@ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, float *co)
                
                copy_v3_v3(is.start, co);
                if(lar->type==LA_SUN || lar->type==LA_HEMI) {
-                       is.vec[0] = -lar->vec[0];
-                       is.vec[1] = -lar->vec[1];
-                       is.vec[2] = -lar->vec[2];
-                       is.labda = R.maxdist;
+                       is.dir[0] = -lar->vec[0];
+                       is.dir[1] = -lar->vec[1];
+                       is.dir[2] = -lar->vec[2];
+                       is.dist = R.maxdist;
                } else {
-                       VECSUB( is.vec, lar->co, is.start );
-                       is.labda = len_v3( is.vec );
+                       VECSUB( is.dir, lar->co, is.start );
+                       is.dist = normalize_v3( is.dir );
                }
 
                is.mode = RE_RAY_MIRROR;
@@ -119,8 +120,8 @@ static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco,
 {
        
        VECCOPY(isect->start, co);
-       VECCOPY(isect->vec, vec );
-       isect->labda = FLT_MAX;
+       VECCOPY(isect->dir, vec );
+       isect->dist = FLT_MAX;
        isect->mode= RE_RAY_MIRROR;
        isect->last_hit = NULL;
        isect->lay= -1;
@@ -138,9 +139,9 @@ static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco,
        
        if(RE_rayobject_raycast(R.raytree, isect))
        {
-               hitco[0] = isect->start[0] + isect->labda*isect->vec[0];
-               hitco[1] = isect->start[1] + isect->labda*isect->vec[1];
-               hitco[2] = isect->start[2] + isect->labda*isect->vec[2];
+               hitco[0] = isect->start[0] + isect->dist*isect->dir[0];
+               hitco[1] = isect->start[1] + isect->dist*isect->dir[1];
+               hitco[2] = isect->start[2] + isect->dist*isect->dir[2];
                return 1;
        } else {
                return 0;
@@ -185,8 +186,8 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *co
        Isect isect;
        
        VECCOPY(isect.start, co);
-       VECCOPY(isect.vec, shi->view);
-       isect.labda = FLT_MAX;
+       VECCOPY(isect.dir, shi->view);
+       isect.dist = FLT_MAX;
        
        isect.mode= RE_RAY_MIRROR;
        isect.check = RE_CHECK_VLR_NONE;
@@ -772,7 +773,7 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct
        /* due to idiosyncracy in ray_trace_shadow_tra() */
        if (is.hit.ob == shi->obi) {
                copy_v3_v3(shi->co, hitco);
-               last_is->labda -= is.labda;
+               last_is->dist -= is.dist;
                shi->vlr = (VlakRen *)is.hit.face;
        }