Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2011-02-05 16:41:29 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2011-02-05 16:41:29 +0300
commit04299657a7eaee212b983b27bed6b66793f7a985 (patch)
tree02dc6e965d8ef08135234da893a85ece7ef7ac2c /source/blender/render
parent90cf78eb5409a77c912b90fb812a4391e31897ae (diff)
Raytrace modifications from the Render Branch.
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.
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/CMakeLists.txt14
-rw-r--r--source/blender/render/extern/include/RE_raytrace.h217
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h1
-rw-r--r--source/blender/render/intern/include/raycounter.h30
-rw-r--r--source/blender/render/intern/include/rayintersection.h124
-rw-r--r--source/blender/render/intern/include/rayobject.h195
-rw-r--r--source/blender/render/intern/include/render_types.h1
-rw-r--r--source/blender/render/intern/include/rendercore.h3
-rw-r--r--source/blender/render/intern/include/volumetric.h4
-rw-r--r--source/blender/render/intern/raytrace/bvh.h64
-rw-r--r--source/blender/render/intern/raytrace/rayobject.cpp648
-rw-r--r--source/blender/render/intern/raytrace/rayobject_blibvh.cpp (renamed from source/blender/render/intern/source/rayobject_blibvh.c)26
-rw-r--r--source/blender/render/intern/raytrace/rayobject_empty.cpp75
-rw-r--r--source/blender/render/intern/raytrace/rayobject_hint.h2
-rw-r--r--source/blender/render/intern/raytrace/rayobject_instance.cpp (renamed from source/blender/render/intern/source/rayobject_instance.c)74
-rw-r--r--source/blender/render/intern/raytrace/rayobject_internal.h128
-rw-r--r--source/blender/render/intern/raytrace/rayobject_octree.cpp (renamed from source/blender/render/intern/source/rayobject_octree.c)54
-rw-r--r--source/blender/render/intern/raytrace/rayobject_qbvh.cpp38
-rw-r--r--source/blender/render/intern/raytrace/rayobject_raycounter.cpp (renamed from source/blender/render/intern/source/rayobject_raycounter.c)3
-rw-r--r--source/blender/render/intern/raytrace/rayobject_rtbuild.cpp33
-rw-r--r--source/blender/render/intern/raytrace/rayobject_svbvh.cpp24
-rw-r--r--source/blender/render/intern/raytrace/rayobject_vbvh.cpp26
-rw-r--r--source/blender/render/intern/raytrace/reorganize.h12
-rw-r--r--source/blender/render/intern/raytrace/svbvh.h142
-rw-r--r--source/blender/render/intern/raytrace/vbvh.h14
-rw-r--r--source/blender/render/intern/source/convertblender.c37
-rw-r--r--source/blender/render/intern/source/rayshade.c157
-rw-r--r--source/blender/render/intern/source/rendercore.c19
-rw-r--r--source/blender/render/intern/source/renderdatabase.c2
-rw-r--r--source/blender/render/intern/source/volume_precache.c19
-rw-r--r--source/blender/render/intern/source/volumetric.c31
31 files changed, 1171 insertions, 1046 deletions
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 58aad270583..ee99e3af3b9 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -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
index cf463c0795e..00000000000
--- a/source/blender/render/extern/include/RE_raytrace.h
+++ /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__*/
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 26e34a741f7..2b451810e37 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -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 */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/include/raycounter.h b/source/blender/render/intern/include/raycounter.h
index 5377a1147af..1a9b91c17a8 100644
--- a/source/blender/render/intern/include/raycounter.h
+++ b/source/blender/render/intern/include/raycounter.h
@@ -26,16 +26,27 @@
*
* ***** 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
index 00000000000..5a8b989abbc
--- /dev/null
+++ b/source/blender/render/intern/include/rayintersection.h
@@ -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__ */
+
diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h
index e16ec83fb61..61b7a23cf54 100644
--- a/source/blender/render/intern/include/rayobject.h
+++ b/source/blender/render/intern/include/rayobject.h
@@ -26,6 +26,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
#ifndef RE_RAYOBJECT_H
#define RE_RAYOBJECT_H
@@ -33,176 +34,86 @@
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
+
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 84fa7e931b2..a599b1306fb 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -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
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index e9e30f64fdd..3b0929bbe27 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -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 *);
diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h
index 37b1bd7ca29..827aaf3672c 100644
--- a/source/blender/render/intern/include/volumetric.h
+++ b/source/blender/render/intern/include/volumetric.h
@@ -26,6 +26,10 @@
* ***** 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_);
diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h
index c31d1213b99..dd23967297a 100644
--- a/source/blender/render/intern/raytrace/bvh.h
+++ b/source/blender/render/intern/raytrace/bvh.h
@@ -26,12 +26,16 @@
*
* ***** 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>
@@ -45,21 +49,49 @@
#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;
diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp
index c267b89fc2c..dd4932f0bd9 100644
--- a/source/blender/render/intern/raytrace/rayobject.cpp
+++ b/source/blender/render/intern/raytrace/rayobject.cpp
@@ -22,135 +22,90 @@
*
* 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 );
-}
diff --git a/source/blender/render/intern/source/rayobject_blibvh.c b/source/blender/render/intern/raytrace/rayobject_blibvh.cpp
index fa5c32a8e8d..7d59cc2df30 100644
--- a/source/blender/render/intern/source/rayobject_blibvh.c
+++ b/source/blender/render/intern/raytrace/rayobject_blibvh.cpp
@@ -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
index 00000000000..abd54ab9fab
--- /dev/null
+++ b/source/blender/render/intern/raytrace/rayobject_empty.cpp
@@ -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 );
+}
+
diff --git a/source/blender/render/intern/raytrace/rayobject_hint.h b/source/blender/render/intern/raytrace/rayobject_hint.h
index 1ea59d00bac..adb7d652276 100644
--- a/source/blender/render/intern/raytrace/rayobject_hint.h
+++ b/source/blender/render/intern/raytrace/rayobject_hint.h
@@ -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
+
diff --git a/source/blender/render/intern/source/rayobject_instance.c b/source/blender/render/intern/raytrace/rayobject_instance.cpp
index d7b4beb8023..c0adae71c1f 100644
--- a/source/blender/render/intern/source/rayobject_instance.c
+++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rayobject_instance.cpp 29542 2010-06-18 09:45:46Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -22,19 +22,19 @@
*
* 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
index 00000000000..6067be07c50
--- /dev/null
+++ b/source/blender/render/intern/raytrace/rayobject_internal.h
@@ -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
+
diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/raytrace/rayobject_octree.cpp
index 8a8b102c6fa..0fd43dfe5ef 100644
--- a/source/blender/render/intern/source/rayobject_octree.c
+++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp
@@ -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;
}
diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
index c510af540db..e8a118d3349 100644
--- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
@@ -26,7 +26,11 @@
*
* ***** 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)
diff --git a/source/blender/render/intern/source/rayobject_raycounter.c b/source/blender/render/intern/raytrace/rayobject_raycounter.cpp
index 16446bde501..a355d4b5a06 100644
--- a/source/blender/render/intern/source/rayobject_raycounter.c
+++ b/source/blender/render/intern/raytrace/rayobject_raycounter.cpp
@@ -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"
diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
index 79bb3b9260f..cdaaebc7f92 100644
--- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
@@ -22,23 +22,23 @@
*
* 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);
diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
index 647c5771e4f..c10da3ad8c0 100644
--- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
@@ -26,8 +26,11 @@
*
* ***** 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)
diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
index b2104a2d557..df5842db2bf 100644
--- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
@@ -22,29 +22,33 @@
*
* 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 );
}
diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h
index c8fbd1cfe94..4e2dce32136 100644
--- a/source/blender/render/intern/raytrace/reorganize.h
+++ b/source/blender/render/intern/raytrace/reorganize.h
@@ -26,18 +26,18 @@
*
* ***** 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
diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h
index 11511fccb89..832058870dd 100644
--- a/source/blender/render/intern/raytrace/svbvh.h
+++ b/source/blender/render/intern/raytrace/svbvh.h
@@ -26,6 +26,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
#ifdef __SSE__
#ifndef RE_RAYTRACE_SVBVH_H
@@ -33,56 +34,132 @@
#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__
+
diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h
index a5ca093de2a..06188ede8c6 100644
--- a/source/blender/render/intern/raytrace/vbvh.h
+++ b/source/blender/render/intern/raytrace/vbvh.h
@@ -26,12 +26,13 @@
*
* ***** 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);
}
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index b5c53e8cb39..550a063c298 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -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);
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index a1a06f87722..d1a0860545b 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -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;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index d955043b1f1..83e9abc0906 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -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;
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index b917c1ddc92..c1a3b989c1f 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -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"
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 2813df3744f..609e647637f 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -42,10 +42,11 @@
#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 */
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index b0aca038e72..dc016a161b5 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -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;
}