<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>







<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="GENERATOR" content="Microsoft FrontPage 6.0">
<meta name="ProgId" content="FrontPage.Editor.Document"><title>ray-tree-multiple-threaded</title>

<style>
<!--
	table td.head{ 
		background-color: #3a6ba5;
		border: 1px #000000 solid;
		font-family: Verdana;
		font-weight: bold;
		font-size: 14px;
		color: #f79c19;
		padding: 6px;
	}

	table td.body{ 
		border-bottom: 1px #6699CC dotted;
		text-align: left;
		font-family: Verdana, sans-serif, Arial;
		font-weight: normal;
		font-size: 14px;
		color: #3A6BA5;
		background-color: #fafafa;
		padding: 6px;
	}
	
-->
</style></head><body>



<p align="left"><font color="#ff0000" size="6"><span lang="en-ca"><b>&nbsp; 
 
</b></span><b>&nbsp;&nbsp;&nbsp; <span lang="en-ca">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
try to put multi-threaded in ray-tree creation<br>
</span></b></font></p>
  <b><font color="#ff0000" size="5"><span lang="en-ca"></span><span lang="en-ca">The problem</span></font></b><div align="left">This
is a FAKE problem as it is not necessary! I tried to put multiple
threads during ray-tree creating of Blender which takes about 30% total
rendering time. However, this proves to another futile excises as there
is very little concurrency during the procedure. The "RE_rayobject_add"
must be synchronized which is not strange at all. Considering it is
even part of renderer API which maybe come from third-party engine! It
does a lot of work like merge bounding box etc. Therefore the majority
of work must be synchronized as all rest of code is done quite a
trivial job. However, I think it is a good practice for me to put it
into multiple-threaded.<br>
<br>
The rough idea is that the "supplier" which supplies "obi" was
reconstructed as a "pointer-to-pointer" array from original
"link-list". Then I divide the array to each thread, in hope the
work-load is even. However, the consumption of "face" and
"vlakprimitive" array usually is not even cause it depends on the
actual ray-object characteristics. And some threads will have to wait
for "feeding" when it consumes its quota while other threads may finish
without using up all its quota. The main thread have to check and
re-allocate resources which will delay the whole procedure. This is why
multiple-threaded version may even be slower than single-threaded,
apart from the synchronization issue above. (See colored part in below.)<br>


<span style="font-weight: bold;"></span></div><br>
<br>
<big style="font-weight: bold; color: red;">filename: source/blender/render/intern/source/pipeline.c</big><br><p>/*<br>
&nbsp;* $Id: rayshade.c 36282 2011-04-22 14:47:35Z campbellbarton $<br>
&nbsp;*<br>
&nbsp;* ***** BEGIN GPL LICENSE BLOCK *****<br>
&nbsp;*<br>
&nbsp;* This program is free software; you can redistribute it and/or<br>
&nbsp;* modify it under the terms of the GNU General Public License<br>
&nbsp;* as published by the Free Software Foundation; either version 2<br>
&nbsp;* of the License, or (at your option) any later version.<br>
&nbsp;*<br>
&nbsp;* This program is distributed in the hope that it will be useful,<br>
&nbsp;* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
&nbsp;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&nbsp; See the<br>
&nbsp;* GNU General Public License for more details.<br>
&nbsp;*<br>
&nbsp;* You should have received a copy of the GNU General Public License<br>
&nbsp;* along with this program; if not, write to the Free Software Foundation,<br>
&nbsp;* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br>
&nbsp;*<br>
&nbsp;* The Original Code is Copyright (C) 1990-1998 NeoGeo BV.<br>
&nbsp;* All rights reserved.<br>
&nbsp;*<br>
&nbsp;* Contributors: 2004/2005 Blender Foundation, full recode<br>
&nbsp;*<br>
&nbsp;* ***** END GPL LICENSE BLOCK *****<br>
&nbsp;*/<br>
<br>
/** \file blender/render/intern/source/rayshade.c<br>
&nbsp;*&nbsp; \ingroup render<br>
&nbsp;*/<br>
<br>
<br>
#include &lt;stdio.h&gt;<br>
#include &lt;math.h&gt;<br>
#include &lt;string.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
#include &lt;float.h&gt;<br>
#include &lt;assert.h&gt;<br>
<br>
#include "MEM_guardedalloc.h"<br>
<br>
#include "DNA_material_types.h"<br>
#include "DNA_lamp_types.h"<br>
<br>
#include "BLI_blenlib.h"<br>
#include "BLI_cpu.h"<br>
#include "BLI_jitter.h"<br>
#include "BLI_math.h"<br>
#include "BLI_rand.h"<br>
#include "BLI_utildefines.h"<br>
<br>
#include "BKE_global.h"<br>
#include "BKE_node.h"<br>
<br>
<br>
#include "PIL_time.h"<br>
<br>
#include "render_types.h"<br>
#include "renderpipeline.h"<br>
#include "rendercore.h"<br>
#include "renderdatabase.h"<br>
#include "pixelblending.h"<br>
#include "pixelshading.h"<br>
#include "shading.h"<br>
#include "texture.h"<br>
#include "volumetric.h"<br>
<br>
#include "rayintersection.h"<br>
#include "rayobject.h"<br>
#include "raycounter.h"<br>
<br>
<br>
#define RAY_TRA&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 1<br>
#define RAY_INSIDE&nbsp;&nbsp;&nbsp; 2<br>
<br>
#define DEPTH_SHADOW_TRA&nbsp; 10<br>
<br>
<br>
<br>
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */<br>
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */<br>
/* only to be used here in this file, it's for speed */<br>
extern struct Render R;<br>
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */<br>
static int test_break(void *data)<br>
{<br>
&nbsp;&nbsp;&nbsp; Render *re = (Render*)data;<br>
&nbsp;&nbsp;&nbsp; return re-&gt;test_break(re-&gt;tbh);<br>
}<br>
<br>
static void RE_rayobject_config_control(RayObject *r, Render *re)<br>
{<br>
&nbsp;&nbsp;&nbsp; if(RE_rayobject_isRayAPI(r))<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r = RE_rayobject_align( r );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r-&gt;control.data = re;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r-&gt;control.test_break = test_break;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
RayObject*&nbsp; RE_rayobject_create(Render *re, int type, int size)<br>
{<br>
&nbsp;&nbsp;&nbsp; RayObject * res = NULL;<br>
<br>
&nbsp;&nbsp;&nbsp; if(type == R_RAYSTRUCTURE_AUTO)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //TODO<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //if(detect_simd())<br>
#ifdef __SSE__<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; type = BLI_cpu_support_sse2()? R_RAYSTRUCTURE_SIMD_SVBVH: R_RAYSTRUCTURE_VBVH;<br>
#else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; type = R_RAYSTRUCTURE_VBVH;<br>
#endif<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
#ifndef __SSE__<br>
&nbsp;&nbsp;&nbsp; if(type == R_RAYSTRUCTURE_SIMD_SVBVH || type == R_RAYSTRUCTURE_SIMD_QBVH)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; puts("Warning: Using VBVH (SSE was disabled at compile time)");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; type = R_RAYSTRUCTURE_VBVH;<br>
&nbsp;&nbsp;&nbsp; }<br>
#endif<br>
<br>
<br>
&nbsp;&nbsp;&nbsp; if(type == R_RAYSTRUCTURE_OCTREE) //TODO dynamic ocres<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res = RE_rayobject_octree_create(re-&gt;r.ocres, size);<br>
&nbsp;&nbsp;&nbsp; else if(type == R_RAYSTRUCTURE_BLIBVH)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res = RE_rayobject_blibvh_create(size);<br>
&nbsp;&nbsp;&nbsp; else if(type == R_RAYSTRUCTURE_VBVH)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res = RE_rayobject_vbvh_create(size);<br>
&nbsp;&nbsp;&nbsp; else if(type == R_RAYSTRUCTURE_SIMD_SVBVH)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res = RE_rayobject_svbvh_create(size);<br>
&nbsp;&nbsp;&nbsp; else if(type == R_RAYSTRUCTURE_SIMD_QBVH)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res = RE_rayobject_qbvh_create(size);<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res = RE_rayobject_vbvh_create(size);&nbsp;&nbsp;&nbsp; //Fallback<br>
<br>
<br>
&nbsp;&nbsp;&nbsp; if(res)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_config_control( res, re );<br>
<br>
&nbsp;&nbsp;&nbsp; return res;<br>
}<br>
<br>
#ifdef RE_RAYCOUNTER<br>
RayCounter re_rc_counter[BLENDER_MAX_THREADS];<br>
#endif<br>
<br>
<br>
void freeraytree(Render *re)<br>
{<br>
&nbsp;&nbsp;&nbsp; ObjectInstanceRen *obi;<br>
<br>
&nbsp;&nbsp;&nbsp; if(re-&gt;raytree)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_free(re-&gt;raytree);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;raytree = NULL;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if(re-&gt;rayfaces)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MEM_freeN(re-&gt;rayfaces);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;rayfaces = NULL;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if(re-&gt;rayprimitives)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MEM_freeN(re-&gt;rayprimitives);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;rayprimitives = NULL;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; for(obi=re-&gt;instancetable.first; obi; obi=obi-&gt;next)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(obr-&gt;raytree)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_free(obr-&gt;raytree);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obr-&gt;raytree = NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(obr-&gt;rayfaces)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MEM_freeN(obr-&gt;rayfaces);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obr-&gt;rayfaces = NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(obi-&gt;raytree)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_free(obi-&gt;raytree);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obi-&gt;raytree = NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
#ifdef RE_RAYCOUNTER<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RayCounter sum;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; memset( &amp;sum, 0, sizeof(sum) );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int i;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(i=0; i&lt;BLENDER_MAX_THREADS; i++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_RC_MERGE(&amp;sum, re_rc_counter+i);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_RC_INFO(&amp;sum);<br>
&nbsp;&nbsp;&nbsp; }<br>
#endif<br>
}<br>
<br>
static int is_raytraceable_vlr(Render *re, VlakRen *vlr)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* note: volumetric must be tracable, wire must not */<br>
&nbsp;&nbsp;&nbsp; if((re-&gt;flag &amp; R_BAKE_TRACE) || (vlr-&gt;flag
&amp; R_TRACEBLE) || (vlr-&gt;mat-&gt;material_type == MA_TYPE_VOLUME))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(vlr-&gt;mat-&gt;material_type != MA_TYPE_WIRE)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br>
&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>
static int is_raytraceable(Render *re, ObjectInstanceRen *obi)<br>
{<br>
&nbsp;&nbsp;&nbsp; int v;<br>
&nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;<br>
<br>
&nbsp;&nbsp;&nbsp; if(re-&gt;excludeob &amp;&amp; obr-&gt;ob == re-&gt;excludeob)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br>
<br>
&nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak + (v&amp;255);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>
RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)<br>
{<br>
&nbsp;&nbsp;&nbsp; //TODO<br>
&nbsp;&nbsp;&nbsp; // out-of-memory safeproof<br>
&nbsp;&nbsp;&nbsp; // break render<br>
&nbsp;&nbsp;&nbsp; // update render stats<br>
&nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;<br>
<br>
&nbsp;&nbsp;&nbsp; if(obr-&gt;raytree == NULL)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RayObject *raytree;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RayFace *face = NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VlakPrimitive *vlakprimitive = NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int v;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Count faces<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int faces = 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak + (v&amp;255);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; faces++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (faces == 0)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return NULL;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Create Ray cast accelaration structure<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; raytree = RE_rayobject_create( re,&nbsp; re-&gt;r.raytrace_structure, faces );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(&nbsp; (re-&gt;r.raytrace_options &amp; R_RAYTRACE_USE_LOCAL_COORDS) )<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vlakprimitive
= obr-&gt;rayprimitives =
(VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen
primitives");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; face =
obr-&gt;rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace),
"ObjectRen faces");<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obr-&gt;rayobi = obi;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak + (v&amp;255);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if(&nbsp; (re-&gt;r.raytrace_options &amp;
R_RAYTRACE_USE_LOCAL_COORDS) )<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_add( raytree,
RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ) );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vlakprimitive++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayface_from_vlak( face, obi,
vlr );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_add( raytree,
RE_rayobject_unalignRayFace(face) );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; face++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_done( raytree );<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* in case of cancel during build, raytree is not usable */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(test_break(re))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_free(raytree);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obr-&gt;raytree= raytree;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(obr-&gt;raytree) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((obi-&gt;flag &amp; R_TRANSFORMED) &amp;&amp; obi-&gt;raytree == NULL)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obi-&gt;transform_primitives = 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
obi-&gt;raytree = RE_rayobject_instance_create( obr-&gt;raytree,
obi-&gt;mat, obi, obi-&gt;obr-&gt;rayobi );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(obi-&gt;raytree) return obi-&gt;raytree;<br>
&nbsp;&nbsp;&nbsp; return obi-&gt;obr-&gt;raytree;<br>
}<br>
<br>
<br>
static int has_special_rayobject(Render *re, ObjectInstanceRen *obi)<br>
{<br>
&nbsp;&nbsp;&nbsp; if( (obi-&gt;flag &amp; R_TRANSFORMED) &amp;&amp;
(re-&gt;r.raytrace_options &amp; R_RAYTRACE_USE_INSTANCES) )<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int v, faces = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak + (v&amp;255);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; faces++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(faces &gt; 4)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>
<span style="background-color: rgb(204, 102, 0);">#ifdef NICK_EDIT</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">typedef struct MakeRayTreeThreadData</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">{</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; Render *re;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; ObjectInstanceRen**obi;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int nObi;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; RayFace *face;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int nFace;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; VlakPrimitive *vlakprimitive;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int nVlak;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int finished;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">} MakeRayTreeThreadData;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">static void* do_make_raytree_single(void* ptr)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">{</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; MakeRayTreeThreadData* threadData = (MakeRayTreeThreadData*)ptr;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; Render *re;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; RayObject *raytree = NULL;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; ObjectInstanceRen *obi = NULL;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; // we assume threadData is valid pointer</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; re = threadData-&gt;re;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; raytree = re-&gt;raytree;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; while (threadData-&gt;nObi &gt; 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obi = *(threadData-&gt;obi);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadData-&gt;obi ++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadData-&gt;nObi --;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (test_break(re))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(has_special_rayobject(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RayObject *obj = makeraytree_object(re, obi);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(test_break(re))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (obj)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // lets assume sync is not needed</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; BLI_lock_thread(LOCK_RAYTREE_WRITE);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; RE_rayobject_add( re-&gt;raytree, obj);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; BLI_unlock_thread(LOCK_RAYTREE_WRITE);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int v;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(obi-&gt;flag &amp; R_TRANSFORMED)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obi-&gt;transform_primitives = 1;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak +
(v&amp;255);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if( (re-&gt;r.raytrace_options
&amp; R_RAYTRACE_USE_LOCAL_COORDS) )</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int bHasVlak =
FALSE;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; do</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if (threadData-&gt;nVlak &gt; 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RayObject *obj =
RE_vlakprimitive_from_vlak(threadData-&gt;vlakprimitive, obi, vlr);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
BLI_lock_thread(LOCK_RAYTREE_WRITE);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_add( raytree, obj );</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
BLI_unlock_thread(LOCK_RAYTREE_WRITE);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadData-&gt;vlakprimitive++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadData-&gt;nVlak --;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bHasVlak = TRUE;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bHasVlak = FALSE;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CreateTiming("thread waiting for
vlakprimitives...");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PIL_sleep_ms(50);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while
(bHasVlak == FALSE);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int bHasFace =
FALSE;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; do</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if (threadData-&gt;nFace &gt; 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
RE_rayface_from_vlak(threadData-&gt;face, obi, vlr);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((obi-&gt;flag &amp;
R_TRANSFORMED))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
mul_m4_v3(obi-&gt;mat, threadData-&gt;face-&gt;v1);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
mul_m4_v3(obi-&gt;mat, threadData-&gt;face-&gt;v2);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
mul_m4_v3(obi-&gt;mat, threadData-&gt;face-&gt;v3);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if(RE_rayface_isQuad(threadData-&gt;face))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; mul_m4_v3(obi-&gt;mat, threadData-&gt;face-&gt;v4);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
BLI_lock_thread(LOCK_RAYTREE_WRITE);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_add(raytree,
RE_rayobject_unalignRayFace(threadData-&gt;face));</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
BLI_unlock_thread(LOCK_RAYTREE_WRITE);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadData-&gt;face++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadData-&gt;nFace --;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bHasFace = TRUE;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bHasFace = FALSE;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CreateTiming("thread waiting for
faces...");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PIL_sleep_ms(50);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while
(bHasFace == FALSE);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; // lets assume read lock is relatively less used than write lock</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; threadData-&gt;finished = 1;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; return NULL;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">}</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">/*</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;* create a single raytrace structure with all faces</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;*/</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">static void makeraytree_single(Render *re)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">{</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; ListBase threads;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; ObjectInstanceRen *obi;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; RayObject *raytree;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; RayFace *face = NULL;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; VlakPrimitive *vlakprimitive = NULL;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int faces = 0, obs = 0, special = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int nObiCounter = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; ObjectInstanceRen** obiPtrArray;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; MakeRayTreeThreadData makeRayTreeThreadData;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; CreateTiming("makeraytree_single new begins...");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; for(obi=re-&gt;instancetable.first; obi; obi=obi-&gt;next)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nObiCounter ++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int v;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obs++;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(has_special_rayobject(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; special++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak +
(v&amp;255);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; faces++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; if(faces + special == 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;raytree = RE_rayobject_empty_create();</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; //Create raytree</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; raytree = re-&gt;raytree = RE_rayobject_create( re, re-&gt;r.raytrace_structure, faces+special );</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; if( (re-&gt;r.raytrace_options &amp; R_RAYTRACE_USE_LOCAL_COORDS) )</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; vlakprimitive = re-&gt;rayprimitives =
(VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "Raytrace
vlak-primitives");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; face = re-&gt;rayfaces&nbsp;&nbsp;&nbsp; =
(RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; // here we start threading...</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; BLI_init_threads(&amp;threads, do_make_raytree_single, re-&gt;r.threads);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
obiPtrArray = (ObjectInstanceRen**)MEM_callocN(nObiCounter *
sizeof(ObjectInstanceRen*), "ObjectInstanceRen pointer array");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int i = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; for(obi=re-&gt;instancetable.first, i = 0; obi; obi=obi-&gt;next, i++)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obiPtrArray[i] = obi;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; // initialize the global data for threads...</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
MakeRayTreeThreadData* threadDataArray =
(MakeRayTreeThreadData*)MEM_callocN(re-&gt;r.threads *
sizeof(MakeRayTreeThreadData),</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "MakeRayTreeThreadData array");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int nObiAssigned = 0, nFaceAssigned = 0, nVlakAssigned = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; re-&gt;r.threads; i ++)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].re = re;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].obi = obiPtrArray + nObiAssigned;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].nObi = nObiCounter / re-&gt;r.threads;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nObiAssigned += threadDataArray[i].nObi;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].face = face + nFaceAssigned;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].nFace = faces / re-&gt;r.threads;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nFaceAssigned += threadDataArray[i].nFace;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].vlakprimitive = vlakprimitive + nVlakAssigned;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].nVlak = faces/ re-&gt;r.threads;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nVlakAssigned += threadDataArray[i].nVlak;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (i == re-&gt;r.threads - 1)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // the last one takes all...</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].nObi += nObiCounter - nObiAssigned;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].nFace += faces - nFaceAssigned;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].nVlak += faces - nVlakAssigned;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[i].finished = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_insert_thread(&amp;threads, threadDataArray+i);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int nFinished = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; while (1)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nFinished = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int nNeedFace = -1, nNeedVlak = -1, nHaveFace = -1, nHaveVlak = -1;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (i = 0; i &lt; re-&gt;r.threads; i ++)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nFinished += threadDataArray[i].finished;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (threadDataArray[i].finished ==1)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (threadDataArray[i].nFace &gt; 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nHaveFace = i;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (threadDataArray[i].nVlak &gt;0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nHaveVlak = i;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (threadDataArray[i].nFace == 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nNeedFace = i;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (threadDataArray[i].nVlak == 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nNeedVlak = i;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (nFinished == re-&gt;r.threads)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (nNeedFace != -1 &amp;&amp; nHaveFace != -1)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[nNeedFace].face = threadDataArray[nHaveFace].face;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // the thread is already finished, we can safely do this</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[nNeedFace].nFace = threadDataArray[nHaveFace].nFace;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[nHaveFace].nFace = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (nNeedVlak != -1 &amp;&amp; nHaveVlak != -1)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
threadDataArray[nNeedVlak].vlakprimitive =
threadDataArray[nHaveVlak].vlakprimitive;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // the thread
is already finished, we can safely do this</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
threadDataArray[nNeedVlak].nVlak = threadDataArray[nHaveVlak].nVlak;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadDataArray[nHaveVlak].nVlak = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PIL_sleep_ms(50);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; MEM_freeN(threadDataArray);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; MEM_freeN(obiPtrArray);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; BLI_end_threads(&amp;threads);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; if(!test_break(re))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;i.infostr= "Raytree.. building";</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;stats_draw(re-&gt;sdh, &amp;re-&gt;i);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_done( raytree );</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; CreateTiming("makeraytree_single new ends...");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">}</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">#else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">/*</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;* create a single raytrace structure with all faces</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;*/</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">static void makeraytree_single(Render *re)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">{</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; ObjectInstanceRen *obi;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; RayObject *raytree;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; RayFace *face = NULL;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; VlakPrimitive *vlakprimitive = NULL;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; int faces = 0, obs = 0, special = 0;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; CreateTiming("makeraytree_single old begins...");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; for(obi=re-&gt;instancetable.first; obi; obi=obi-&gt;next)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int v;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obs++;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(has_special_rayobject(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; special++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak +
(v&amp;255);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; faces++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; if(faces + special == 0)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;raytree = RE_rayobject_empty_create();</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; //Create raytree</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; raytree = re-&gt;raytree = RE_rayobject_create( re, re-&gt;r.raytrace_structure, faces+special );</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; if( (re-&gt;r.raytrace_options &amp; R_RAYTRACE_USE_LOCAL_COORDS) )</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; vlakprimitive = re-&gt;rayprimitives =
(VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "Raytrace
vlak-primitives");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; face = re-&gt;rayfaces&nbsp;&nbsp;&nbsp; =
(RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; for(obi=re-&gt;instancetable.first; obi; obi=obi-&gt;next)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(test_break(re))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(has_special_rayobject(re, obi))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RayObject *obj = makeraytree_object(re, obi);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(test_break(re))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (obj)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; RE_rayobject_add( re-&gt;raytree, obj );</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int v;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ObjectRen *obr = obi-&gt;obr;</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(obi-&gt;flag &amp; R_TRANSFORMED)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obi-&gt;transform_primitives = 1;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(v=0;v&lt;obr-&gt;totvlak;v++)</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; VlakRen *vlr = obr-&gt;vlaknodes[v&gt;&gt;8].vlak +
(v&amp;255);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(is_raytraceable_vlr(re, vlr))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if( (re-&gt;r.raytrace_options
&amp; R_RAYTRACE_USE_LOCAL_COORDS) )</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RayObject *obj
= RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr );</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
RE_rayobject_add( raytree, obj );</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
vlakprimitive++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
RE_rayface_from_vlak(face, obi, vlr);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if((obi-&gt;flag &amp; R_TRANSFORMED))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; mul_m4_v3(obi-&gt;mat, face-&gt;v1);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; mul_m4_v3(obi-&gt;mat, face-&gt;v2);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; mul_m4_v3(obi-&gt;mat, face-&gt;v3);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if(RE_rayface_isQuad(face))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_m4_v3(obi-&gt;mat,
face-&gt;v4);</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) );</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; face++;</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; if(!test_break(re))</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;i.infostr= "Raytree.. building";</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;stats_draw(re-&gt;sdh, &amp;re-&gt;i);</span><br style="background-color: rgb(204, 102, 0);">
<br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_done( raytree );</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">&nbsp;&nbsp;&nbsp; CreateTiming("makeraytree_single old ends...");</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">}</span><br style="background-color: rgb(204, 102, 0);">
<span style="background-color: rgb(204, 102, 0);">#endif</span><br>
<br>
void makeraytree(Render *re)<br>
{<br>
&nbsp;&nbsp;&nbsp; float min[3], max[3], sub[3];<br>
&nbsp;&nbsp;&nbsp; int i;<br>
<br>
<br>
&nbsp;&nbsp;&nbsp; re-&gt;i.infostr= "Raytree.. preparing";<br>
&nbsp;&nbsp;&nbsp; re-&gt;stats_draw(re-&gt;sdh, &amp;re-&gt;i);<br>
<br>
&nbsp;&nbsp;&nbsp; /* disable options not yet supported by octree,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; they might actually never be supported (unless people really need it) */<br>
&nbsp;&nbsp;&nbsp; if(re-&gt;r.raytrace_structure == R_RAYSTRUCTURE_OCTREE)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;r.raytrace_options &amp;=
~( R_RAYTRACE_USE_INSTANCES | R_RAYTRACE_USE_LOCAL_COORDS);<br>
<br>
&nbsp;&nbsp;&nbsp; makeraytree_single(re);<br>
<br>
&nbsp;&nbsp;&nbsp; if(test_break(re))<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; freeraytree(re);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;i.infostr= "Raytree building canceled";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;stats_draw(re-&gt;sdh, &amp;re-&gt;i);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Calculate raytree max_size<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; INIT_MINMAX(min, max);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_rayobject_merge_bb( re-&gt;raytree, min, max );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(i=0; i&lt;3; i++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; min[i] += 0.01f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max[i] += 0.01f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sub[i] = max[i]-min[i];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;maxdist= sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(re-&gt;maxdist &gt; 0.0f) re-&gt;maxdist= sqrt(re-&gt;maxdist);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;i.infostr= "Raytree finished";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;stats_draw(re-&gt;sdh, &amp;re-&gt;i);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
#ifdef RE_RAYCOUNTER<br>
&nbsp;&nbsp;&nbsp; memset( re_rc_counter, 0, sizeof(re_rc_counter) );<br>
#endif<br>
}<br>
<br>
/* &nbsp;&nbsp;&nbsp; if(shi-&gt;osatex)&nbsp; */<br>
static void shade_ray_set_derivative(ShadeInput *shi)<br>
{<br>
&nbsp;&nbsp;&nbsp; float detsh, t00, t10, t01, t11, xn, yn, zn;<br>
&nbsp;&nbsp;&nbsp; int axis1, axis2;<br>
<br>
&nbsp;&nbsp;&nbsp; /* find most stable axis to project */<br>
&nbsp;&nbsp;&nbsp; xn= fabs(shi-&gt;facenor[0]);<br>
&nbsp;&nbsp;&nbsp; yn= fabs(shi-&gt;facenor[1]);<br>
&nbsp;&nbsp;&nbsp; zn= fabs(shi-&gt;facenor[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; if(zn&gt;=xn &amp;&amp; zn&gt;=yn) { axis1= 0; axis2= 1; }<br>
&nbsp;&nbsp;&nbsp; else if(yn&gt;=xn &amp;&amp; yn&gt;=zn) { axis1= 0; axis2= 2; }<br>
&nbsp;&nbsp;&nbsp; else { axis1= 1; axis2= 2; }<br>
<br>
&nbsp;&nbsp;&nbsp; /* compute u,v and derivatives */<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;obi-&gt;flag &amp; R_TRANSFORMED) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float v1[3], v2[3], v3[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_m3v3(v1, shi-&gt;obi-&gt;nmat, shi-&gt;v1-&gt;co);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_m3v3(v2, shi-&gt;obi-&gt;nmat, shi-&gt;v2-&gt;co);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_m3v3(v3, shi-&gt;obi-&gt;nmat, shi-&gt;v3-&gt;co);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* same as below */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2];<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float *v1= shi-&gt;v1-&gt;co;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float *v2= shi-&gt;v2-&gt;co;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float *v3= shi-&gt;v3-&gt;co;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* same as above */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2];<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; detsh= 1.0f/(t00*t11-t10*t01);<br>
&nbsp;&nbsp;&nbsp; t00*= detsh; t01*=detsh;<br>
&nbsp;&nbsp;&nbsp; t10*=detsh; t11*=detsh;<br>
<br>
&nbsp;&nbsp;&nbsp; shi-&gt;dx_u=&nbsp; shi-&gt;dxco[axis1]*t11- shi-&gt;dxco[axis2]*t10;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;dx_v=&nbsp; shi-&gt;dxco[axis2]*t00- shi-&gt;dxco[axis1]*t01;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;dy_u=&nbsp; shi-&gt;dyco[axis1]*t11- shi-&gt;dyco[axis2]*t10;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;dy_v=&nbsp; shi-&gt;dyco[axis2]*t00- shi-&gt;dyco[axis1]*t01;<br>
<br>
}<br>
<br>
<br>
void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)<br>
{<br>
&nbsp;&nbsp;&nbsp; ObjectInstanceRen *obi= (ObjectInstanceRen*)is-&gt;hit.ob;<br>
&nbsp;&nbsp;&nbsp; VlakRen *vlr= (VlakRen*)is-&gt;hit.face;<br>
<br>
&nbsp;&nbsp;&nbsp; /* set up view vector */<br>
&nbsp;&nbsp;&nbsp; VECCOPY(shi-&gt;view, is-&gt;dir);<br>
<br>
&nbsp;&nbsp;&nbsp; /* render co */<br>
&nbsp;&nbsp;&nbsp; shi-&gt;co[0]= is-&gt;start[0]+is-&gt;dist*(shi-&gt;view[0]);<br>
&nbsp;&nbsp;&nbsp; shi-&gt;co[1]= is-&gt;start[1]+is-&gt;dist*(shi-&gt;view[1]);<br>
&nbsp;&nbsp;&nbsp; shi-&gt;co[2]= is-&gt;start[2]+is-&gt;dist*(shi-&gt;view[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; normalize_v3(shi-&gt;view);<br>
<br>
&nbsp;&nbsp;&nbsp; shi-&gt;obi= obi;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;obr= obi-&gt;obr;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;vlr= vlr;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;mat= vlr-&gt;mat;<br>
&nbsp;&nbsp;&nbsp; shade_input_init_material(shi);<br>
<br>
&nbsp;&nbsp;&nbsp; if(is-&gt;isect==2)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);<br>
<br>
&nbsp;&nbsp;&nbsp; shi-&gt;u= is-&gt;u;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;v= is-&gt;v;<br>
&nbsp;&nbsp;&nbsp; shi-&gt;dx_u= shi-&gt;dx_v= shi-&gt;dy_u= shi-&gt;dy_v=&nbsp; 0.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;osatex)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_ray_set_derivative(shi);<br>
&nbsp;&nbsp;&nbsp; shade_input_set_normals(shi);<br>
<br>
&nbsp;&nbsp;&nbsp; shade_input_set_shade_texco(shi);<br>
&nbsp;&nbsp;&nbsp; if (shi-&gt;mat-&gt;material_type == MA_TYPE_VOLUME) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(ELEM(is-&gt;mode, RE_RAY_SHADOW, RE_RAY_SHADOW_TRA)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_volume_shadow(shi, shr, is);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_volume_outside(shi, shr);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else if(is-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* temp hack to prevent recursion */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi-&gt;nodes==0 &amp;&amp;
shi-&gt;mat-&gt;nodetree &amp;&amp; shi-&gt;mat-&gt;use_nodes) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ntreeShaderExecTree(shi-&gt;mat-&gt;nodetree, shi, shr);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi-&gt;mat=
vlr-&gt;mat;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* shi-&gt;mat is
being set in nodetree */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_color(shi, shr);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi-&gt;mat-&gt;nodetree &amp;&amp; shi-&gt;mat-&gt;use_nodes) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ntreeShaderExecTree(shi-&gt;mat-&gt;nodetree, shi, shr);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi-&gt;mat=
vlr-&gt;mat;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* shi-&gt;mat is
being set in nodetree */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_material_loop(shi, shr);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* raytrace likes to separate the spec color */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECSUB(shr-&gt;diff, shr-&gt;combined, shr-&gt;spec);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
}<br>
<br>
static int refraction(float *refract, float *n, float *view, float index)<br>
{<br>
&nbsp;&nbsp;&nbsp; float dot, fac;<br>
<br>
&nbsp;&nbsp;&nbsp; VECCOPY(refract, view);<br>
<br>
&nbsp;&nbsp;&nbsp; dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2];<br>
<br>
&nbsp;&nbsp;&nbsp; if(dot&gt;0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; index = 1.0f/index;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= 1.0f - (1.0f - dot*dot)*index*index;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(fac&lt;= 0.0f) return 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= -dot*index + sqrt(fac);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= 1.0f - (1.0f - dot*dot)*index*index;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(fac&lt;= 0.0f) return 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= -dot*index - sqrt(fac);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; refract[0]= index*view[0] + fac*n[0];<br>
&nbsp;&nbsp;&nbsp; refract[1]= index*view[1] + fac*n[1];<br>
&nbsp;&nbsp;&nbsp; refract[2]= index*view[2] + fac*n[2];<br>
<br>
&nbsp;&nbsp;&nbsp; return 1;<br>
}<br>
<br>
/* orn = original face normal */<br>
static void reflection(float *ref, float *n, float *view, float *orn)<br>
{<br>
&nbsp;&nbsp;&nbsp; float f1;<br>
<br>
&nbsp;&nbsp;&nbsp; f1= -2.0f*(n[0]*view[0]+ n[1]*view[1]+ n[2]*view[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; ref[0]= (view[0]+f1*n[0]);<br>
&nbsp;&nbsp;&nbsp; ref[1]= (view[1]+f1*n[1]);<br>
&nbsp;&nbsp;&nbsp; ref[2]= (view[2]+f1*n[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; if(orn) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* test phong normals, then we should prevent vector going to the back */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f1= ref[0]*orn[0]+ ref[1]*orn[1]+ ref[2]*orn[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(f1&gt;0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f1+= .01f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ref[0]-= f1*orn[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ref[1]-= f1*orn[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ref[2]-= f1*orn[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
#if 0<br>
static void color_combine(float *result, float fac1, float fac2, float *col1, float *col2)<br>
{<br>
&nbsp;&nbsp;&nbsp; float col1t[3], col2t[3];<br>
<br>
&nbsp;&nbsp;&nbsp; col1t[0]= sqrt(col1[0]);<br>
&nbsp;&nbsp;&nbsp; col1t[1]= sqrt(col1[1]);<br>
&nbsp;&nbsp;&nbsp; col1t[2]= sqrt(col1[2]);<br>
&nbsp;&nbsp;&nbsp; col2t[0]= sqrt(col2[0]);<br>
&nbsp;&nbsp;&nbsp; col2t[1]= sqrt(col2[1]);<br>
&nbsp;&nbsp;&nbsp; col2t[2]= sqrt(col2[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; result[0]= (fac1*col1t[0] + fac2*col2t[0]);<br>
&nbsp;&nbsp;&nbsp; result[0]*= result[0];<br>
&nbsp;&nbsp;&nbsp; result[1]= (fac1*col1t[1] + fac2*col2t[1]);<br>
&nbsp;&nbsp;&nbsp; result[1]*= result[1];<br>
&nbsp;&nbsp;&nbsp; result[2]= (fac1*col1t[2] + fac2*col2t[2]);<br>
&nbsp;&nbsp;&nbsp; result[2]*= result[2];<br>
}<br>
#endif<br>
<br>
static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr)<br>
{<br>
&nbsp;&nbsp;&nbsp; float dx, dy, dz, d, p;<br>
<br>
&nbsp;&nbsp;&nbsp; if (0 == (shi-&gt;mat-&gt;mode &amp; MA_TRANSP))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return -1;<br>
<br>
&nbsp;&nbsp;&nbsp; if (shi-&gt;mat-&gt;tx_limit &lt;= 0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; d= 1.0f;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* shi.co[] calculated by shade_ray() */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dx= shi-&gt;co[0] - is-&gt;start[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dy= shi-&gt;co[1] - is-&gt;start[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dz= shi-&gt;co[2] - is-&gt;start[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; d= sqrt(dx*dx+dy*dy+dz*dz);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (d &gt; shi-&gt;mat-&gt;tx_limit)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; d= shi-&gt;mat-&gt;tx_limit;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; p = shi-&gt;mat-&gt;tx_falloff;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(p &lt; 0.0f) p= 0.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if (p &gt; 10.0f) p= 10.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;alpha *= pow(d, p);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (shr-&gt;alpha &gt; 1.0f)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;alpha= 1.0f;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; return d;<br>
}<br>
<br>
static void ray_fadeout_endcolor(float *col, ShadeInput *origshi, ShadeInput *shi, ShadeResult *shr, Isect *isec, float *vec)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* un-intersected rays get either rendered material color or sky color */<br>
&nbsp;&nbsp;&nbsp; if (origshi-&gt;mat-&gt;fadeto_mir == MA_RAYMIR_FADETOMAT) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(col, shr-&gt;combined);<br>
&nbsp;&nbsp;&nbsp; } else if (origshi-&gt;mat-&gt;fadeto_mir == MA_RAYMIR_FADETOSKY) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(shi-&gt;view, vec);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(shi-&gt;view);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadeSkyView(col, isec-&gt;start, shi-&gt;view, NULL, shi-&gt;thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadeSunView(col, shi-&gt;view);<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
static void ray_fadeout(Isect *is, ShadeInput *shi, float *col, float *blendcol, float dist_mir)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* if fading out, linear blend against fade color */<br>
&nbsp;&nbsp;&nbsp; float blendfac;<br>
<br>
&nbsp;&nbsp;&nbsp; blendfac = 1.0 - len_v3v3(shi-&gt;co, is-&gt;start)/dist_mir;<br>
<br>
&nbsp;&nbsp;&nbsp; col[0] = col[0]*blendfac + (1.0 - blendfac)*blendcol[0];<br>
&nbsp;&nbsp;&nbsp; col[1] = col[1]*blendfac + (1.0 - blendfac)*blendcol[1];<br>
&nbsp;&nbsp;&nbsp; col[2] = col[2]*blendfac + (1.0 - blendfac)*blendcol[2];<br>
}<br>
<br>
/* the main recursive tracer itself<br>
&nbsp;* note: 'col' must be initialized */<br>
static void traceray(ShadeInput *origshi, ShadeResult *origshr, short
depth, float *start, float *dir, float *col, ObjectInstanceRen *obi,
VlakRen *vlr, int traflag)<br>
{<br>
&nbsp;&nbsp;&nbsp; ShadeInput shi= {0};<br>
&nbsp;&nbsp;&nbsp; Isect isec;<br>
&nbsp;&nbsp;&nbsp; float dist_mir = origshi-&gt;mat-&gt;dist_mir;<br>
<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec.start, start);<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec.dir, dir );<br>
&nbsp;&nbsp;&nbsp; isec.dist = dist_mir &gt; 0 ? dist_mir : RE_RAYTRACE_MAXDIST;<br>
&nbsp;&nbsp;&nbsp; isec.mode= RE_RAY_MIRROR;<br>
&nbsp;&nbsp;&nbsp; isec.check = RE_CHECK_VLR_RENDER;<br>
&nbsp;&nbsp;&nbsp; isec.skip = RE_SKIP_VLR_NEIGHBOUR;<br>
&nbsp;&nbsp;&nbsp; isec.hint = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; isec.orig.ob&nbsp;&nbsp; = obi;<br>
&nbsp;&nbsp;&nbsp; isec.orig.face = vlr;<br>
&nbsp;&nbsp;&nbsp; RE_RC_INIT(isec, shi);<br>
<br>
&nbsp;&nbsp;&nbsp; if(RE_rayobject_raycast(R.raytree, &amp;isec)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ShadeResult shr= {{0}};<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float d= 1.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* for as long we don't have proper dx/dy transform for rays we copy over original */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(shi.dxco, origshi-&gt;dxco);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(shi.dyco, origshi-&gt;dyco);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.mask= origshi-&gt;mask;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.osatex= origshi-&gt;osatex;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.depth= origshi-&gt;depth +
1;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* only used to indicate tracing
*/<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.thread= origshi-&gt;thread;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //shi.sample= 0; // memset above, so dont need this<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.xs= origshi-&gt;xs;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.ys= origshi-&gt;ys;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.lay= origshi-&gt;lay;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.combinedflag=
0xFFFFFF;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/* ray trace does
all options */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //shi.do_preview= 0; // memset above, so dont need this<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.light_override= origshi-&gt;light_override;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.mat_override= origshi-&gt;mat_override;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_ray(&amp;isec, &amp;shi, &amp;shr);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* ray has traveled inside the material, so shade by transmission */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (traflag &amp; RAY_INSIDE)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; d= shade_by_transmission(&amp;isec, &amp;shi, &amp;shr);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(depth&gt;0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float fr, fg, fb, f, f1;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if((shi.mat-&gt;mode_l &amp; MA_TRANSP) &amp;&amp; shr.alpha &lt; 1.0f
&amp;&amp; (shi.mat-&gt;mode_l &amp; (MA_ZTRANSP | MA_RAYTRANSP))) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float nf, f, refract[3], tracol[4];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tracol[0]= shi.r;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tracol[1]= shi.g;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tracol[2]= shi.b;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; tracol[3]= col[3];&nbsp;&nbsp;&nbsp; // we pass on
and accumulate alpha<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if((shi.mat-&gt;mode &amp; MA_TRANSP) &amp;&amp;
(shi.mat-&gt;mode &amp; MA_RAYTRANSP)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(traflag &amp; RAY_INSIDE) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* inside the
material, so use inverse normal */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float norm[3];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; norm[0]= -
shi.vn[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; norm[1]= -
shi.vn[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; norm[2]= -
shi.vn[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if
(refraction(refract, norm, shi.view, shi.ang)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* ray comes out from the material into air */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; traflag &amp;= ~RAY_INSIDE;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* total internal reflection (ray stays inside the
material) */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; reflection(refract, norm, shi.view, shi.vn);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if
(refraction(refract, shi.vn, shi.view, shi.ang)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* ray goes in to the material from air */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; traflag |= RAY_INSIDE;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* total external reflection (ray doesn't enter the
material) */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; reflection(refract, shi.vn, shi.view, shi.vn);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; traceray(origshi, origshr,
depth-1, shi.co, refract, tracol, shi.obi, shi.vlr, traflag);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; traceray(origshi, origshr,
depth-1, shi.co, shi.view, tracol, shi.obi, shi.vlr, 0);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f= shr.alpha; f1= 1.0f-f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nf= d * shi.mat-&gt;filter;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fr= 1.0f+ nf*(shi.r-1.0f);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fg= 1.0f+ nf*(shi.g-1.0f);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fb= 1.0f+ nf*(shi.b-1.0f);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr.diff[0]= f*shr.diff[0] + f1*fr*tracol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr.diff[1]= f*shr.diff[1] + f1*fg*tracol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr.diff[2]= f*shr.diff[2] + f1*fb*tracol[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr.spec[0] *=f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr.spec[1] *=f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr.spec[2] *=f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[3]= f1*tracol[3] + f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[3]= 1.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi.mat-&gt;mode_l &amp; MA_RAYMIRROR) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f= shi.ray_mirror;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if(f!=0.0f) f*= fresnel_fac(shi.view, shi.vn,
shi.mat-&gt;fresnel_mir_i, shi.mat-&gt;fresnel_mir);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else f= 0.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(f!=0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float mircol[4];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float ref[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; reflection(ref, shi.vn, shi.view, NULL);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; traceray(origshi, origshr, depth-1, shi.co, ref,
mircol, shi.obi, shi.vlr, 0);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f1= 1.0f-f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* combine */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; //color_combine(col, f*fr*(1.0f-shr.spec[0]), f1,
col, shr.diff);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //col[0]+= shr.spec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //col[1]+= shr.spec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //col[2]+= shr.spec[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fr= shi.mirr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fg= shi.mirg;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fb= shi.mirb;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; col[0]= f*fr*(1.0f-shr.spec[0])*mircol[0] +
f1*shr.diff[0] + shr.spec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; col[1]= f*fg*(1.0f-shr.spec[1])*mircol[1] +
f1*shr.diff[1] + shr.spec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; col[2]= f*fb*(1.0f-shr.spec[2])*mircol[2] +
f1*shr.diff[2] + shr.spec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[0]= shr.diff[0] + shr.spec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[1]= shr.diff[1] + shr.spec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[2]= shr.diff[2] + shr.spec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (dist_mir &gt; 0.0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float blendcol[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* max ray distance set, but found an intersection,
so fade this color<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;* out towards the sky/material color for a
smooth transition */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; ray_fadeout_endcolor(blendcol, origshi, &amp;shi,
origshr, &amp;isec, dir);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; ray_fadeout(&amp;isec, &amp;shi, col, blendcol,
dist_mir);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[0]= shr.diff[0] + shr.spec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[1]= shr.diff[1] + shr.spec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[2]= shr.diff[2] + shr.spec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_fadeout_endcolor(col, origshi, &amp;shi, origshr, &amp;isec, dir);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; RE_RC_MERGE(&amp;origshi-&gt;raycounter, &amp;shi.raycounter);<br>
}<br>
<br>
/* **************** jitter blocks ********** */<br>
<br>
/* calc distributed planar energy */<br>
<br>
static void DP_energy(float *table, float *vec, int tot, float xsize, float ysize)<br>
{<br>
&nbsp;&nbsp;&nbsp; int x, y, a;<br>
&nbsp;&nbsp;&nbsp; float *fp, force[3], result[3];<br>
&nbsp;&nbsp;&nbsp; float dx, dy, dist, min;<br>
<br>
&nbsp;&nbsp;&nbsp; min= MIN2(xsize, ysize);<br>
&nbsp;&nbsp;&nbsp; min*= min;<br>
&nbsp;&nbsp;&nbsp; result[0]= result[1]= 0.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; for(y= -1; y&lt;2; y++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dy= ysize*y;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(x= -1; x&lt;2; x++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dx= xsize*x;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fp= table;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(a=0; a&lt;tot; a++, fp+= 2) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; force[0]= vec[0] - fp[0]-dx;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; force[1]= vec[1] - fp[1]-dy;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dist= force[0]*force[0] + force[1]*force[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(dist &lt; min &amp;&amp; dist&gt;0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; result[0]+= force[0]/dist;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; result[1]+= force[1]/dist;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; vec[0] += 0.1*min*result[0]/(float)tot;<br>
&nbsp;&nbsp;&nbsp; vec[1] += 0.1*min*result[1]/(float)tot;<br>
&nbsp;&nbsp;&nbsp; // cyclic clamping<br>
&nbsp;&nbsp;&nbsp; vec[0]= vec[0] - xsize*floor(vec[0]/xsize + 0.5);<br>
&nbsp;&nbsp;&nbsp; vec[1]= vec[1] - ysize*floor(vec[1]/ysize + 0.5);<br>
}<br>
<br>
// random offset of 1 in 2<br>
static void jitter_plane_offset(float *jitter1, float *jitter2, int tot, float sizex, float sizey, float ofsx, float ofsy)<br>
{<br>
&nbsp;&nbsp;&nbsp; float dsizex= sizex*ofsx;<br>
&nbsp;&nbsp;&nbsp; float dsizey= sizey*ofsy;<br>
&nbsp;&nbsp;&nbsp; float hsizex= 0.5*sizex, hsizey= 0.5*sizey;<br>
&nbsp;&nbsp;&nbsp; int x;<br>
<br>
&nbsp;&nbsp;&nbsp; for(x=tot; x&gt;0; x--, jitter1+=2, jitter2+=2) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jitter2[0]= jitter1[0] + dsizex;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jitter2[1]= jitter1[1] + dsizey;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(jitter2[0] &gt; hsizex) jitter2[0]-= sizex;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(jitter2[1] &gt; hsizey) jitter2[1]-= sizey;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
/* called from convertBlenderScene.c */<br>
/* we do this in advance to get consistent random, not alter the render seed, and be threadsafe */<br>
void init_jitter_plane(LampRen *lar)<br>
{<br>
&nbsp;&nbsp;&nbsp; float *fp;<br>
&nbsp;&nbsp;&nbsp; int x, iter=12, tot= lar-&gt;ray_totsamp;<br>
<br>
&nbsp;&nbsp;&nbsp; /* test if already initialized */<br>
&nbsp;&nbsp;&nbsp; if(lar-&gt;jitter) return;<br>
<br>
&nbsp;&nbsp;&nbsp; /* at least 4, or max threads+1 tables */<br>
&nbsp;&nbsp;&nbsp; if(BLENDER_MAX_THREADS &lt; 4) x= 4;<br>
&nbsp;&nbsp;&nbsp; else x= BLENDER_MAX_THREADS+1;<br>
&nbsp;&nbsp;&nbsp; fp= lar-&gt;jitter= MEM_callocN(x*tot*2*sizeof(float), "lamp jitter tab");<br>
<br>
&nbsp;&nbsp;&nbsp; /* if 1 sample, we leave table to be zero's */<br>
&nbsp;&nbsp;&nbsp; if(tot&gt;1) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* set per-lamp fixed seed */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_srandom(tot);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* fill table with random locations, area_size large */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(x=0; x&lt;tot; x++, fp+=2) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fp[0]= (BLI_frand()-0.5)*lar-&gt;area_size;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fp[1]= (BLI_frand()-0.5)*lar-&gt;area_sizey;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while(iter--) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fp= lar-&gt;jitter;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(x=tot; x&gt;0; x--, fp+=2) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; DP_energy(lar-&gt;jitter, fp, tot,
lar-&gt;area_size, lar-&gt;area_sizey);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; /* create the dithered tables (could just check lamp type!) */<br>
&nbsp;&nbsp;&nbsp; jitter_plane_offset(lar-&gt;jitter,
lar-&gt;jitter+2*tot, tot, lar-&gt;area_size, lar-&gt;area_sizey, 0.5f,
0.0f);<br>
&nbsp;&nbsp;&nbsp; jitter_plane_offset(lar-&gt;jitter,
lar-&gt;jitter+4*tot, tot, lar-&gt;area_size, lar-&gt;area_sizey, 0.5f,
0.5f);<br>
&nbsp;&nbsp;&nbsp; jitter_plane_offset(lar-&gt;jitter,
lar-&gt;jitter+6*tot, tot, lar-&gt;area_size, lar-&gt;area_sizey, 0.0f,
0.5f);<br>
}<br>
<br>
/* table around origin, -0.5*size to 0.5*size */<br>
static float *give_jitter_plane(LampRen *lar, int thread, int xs, int ys)<br>
{<br>
&nbsp;&nbsp;&nbsp; int tot;<br>
<br>
&nbsp;&nbsp;&nbsp; tot= lar-&gt;ray_totsamp;<br>
<br>
&nbsp;&nbsp;&nbsp; if(lar-&gt;ray_samp_type &amp; LA_SAMP_JITTER) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* made it threadsafe */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(lar-&gt;xold[thread]!=xs || lar-&gt;yold[thread]!=ys) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
jitter_plane_offset(lar-&gt;jitter, lar-&gt;jitter+2*(thread+1)*tot,
tot, lar-&gt;area_size, lar-&gt;area_sizey, BLI_thread_frand(thread),
BLI_thread_frand(thread));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lar-&gt;xold[thread]= xs;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lar-&gt;yold[thread]= ys;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return lar-&gt;jitter+2*(thread+1)*tot;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if(lar-&gt;ray_samp_type &amp; LA_SAMP_DITHER) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return lar-&gt;jitter + 2*tot*((xs &amp; 1)+2*(ys &amp; 1));<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; return lar-&gt;jitter;<br>
}<br>
<br>
<br>
/* **************** QMC sampling *************** */<br>
<br>
static void halton_sample(double *ht_invprimes, double *ht_nums, double *v)<br>
{<br>
&nbsp;&nbsp;&nbsp; // incremental halton sequence generator, from:<br>
&nbsp;&nbsp;&nbsp; // "Instant Radiosity", Keller A.<br>
&nbsp;&nbsp;&nbsp; unsigned int i;<br>
<br>
&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; 2; i++)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double r = fabs((1.0 - ht_nums[i]) - 1e-10);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (ht_invprimes[i] &gt;= r)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double lasth;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double h = ht_invprimes[i];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; do {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lasth = h;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; h *= ht_invprimes[i];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } while (h &gt;= r);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ht_nums[i] += ((lasth + h) - 1.0);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ht_nums[i] += ht_invprimes[i];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v[i] = (float)ht_nums[i];<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
/* Generate Hammersley points in [0,1)^2<br>
&nbsp;* From Lucille renderer */<br>
static void hammersley_create(double *out, int n)<br>
{<br>
&nbsp;&nbsp;&nbsp; double p, t;<br>
&nbsp;&nbsp;&nbsp; int k, kk;<br>
<br>
&nbsp;&nbsp;&nbsp; for (k = 0; k &lt; n; k++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; t = 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (p = 0.5, kk = k; kk; p *= 0.5, kk &gt;&gt;= 1) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (kk &amp;
1) {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* kk mod 2 =
1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; t += p;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; out[2 * k + 0] = (double)k / (double)n;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; out[2 * k + 1] = t;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
static struct QMCSampler *QMC_initSampler(int type, int tot)<br>
{<br>
&nbsp;&nbsp;&nbsp; QMCSampler *qsa = MEM_callocN(sizeof(QMCSampler), "qmc sampler");<br>
&nbsp;&nbsp;&nbsp; qsa-&gt;samp2d = MEM_callocN(2*sizeof(double)*tot, "qmc sample table");<br>
<br>
&nbsp;&nbsp;&nbsp; qsa-&gt;tot = tot;<br>
&nbsp;&nbsp;&nbsp; qsa-&gt;type = type;<br>
<br>
&nbsp;&nbsp;&nbsp; if (qsa-&gt;type==SAMP_TYPE_HAMMERSLEY)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hammersley_create(qsa-&gt;samp2d, qsa-&gt;tot);<br>
<br>
&nbsp;&nbsp;&nbsp; return qsa;<br>
}<br>
<br>
static void QMC_initPixel(QMCSampler *qsa, int thread)<br>
{<br>
&nbsp;&nbsp;&nbsp; if (qsa-&gt;type==SAMP_TYPE_HAMMERSLEY)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* hammersley sequence is fixed, already created in QMCSampler init.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* per pixel, gets a random
offset. We create separate offsets per thread, for write-safety */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa-&gt;offs[thread][0] = 0.5 * BLI_thread_frand(thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa-&gt;offs[thread][1] = 0.5 * BLI_thread_frand(thread);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else { &nbsp;&nbsp;&nbsp; /* SAMP_TYPE_HALTON */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* generate a new randomised halton sequence per pixel<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* to alleviate qmc artifacts and make it reproducable<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* between threads/frames */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double ht_invprimes[2], ht_nums[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double r[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int i;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ht_nums[0] = BLI_thread_frand(thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ht_nums[1] = BLI_thread_frand(thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ht_invprimes[0] = 0.5;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ht_invprimes[1] = 1.0/3.0;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (i=0; i&lt; qsa-&gt;tot; i++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; halton_sample(ht_invprimes, ht_nums, r);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa-&gt;samp2d[2*i+0] = r[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa-&gt;samp2d[2*i+1] = r[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
static void QMC_freeSampler(QMCSampler *qsa)<br>
{<br>
&nbsp;&nbsp;&nbsp; MEM_freeN(qsa-&gt;samp2d);<br>
&nbsp;&nbsp;&nbsp; MEM_freeN(qsa);<br>
}<br>
<br>
static void QMC_getSample(double *s, QMCSampler *qsa, int thread, int num)<br>
{<br>
&nbsp;&nbsp;&nbsp; if (qsa-&gt;type == SAMP_TYPE_HAMMERSLEY) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s[0] = fmod(qsa-&gt;samp2d[2*num+0] + qsa-&gt;offs[thread][0], 1.0f);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s[1] = fmod(qsa-&gt;samp2d[2*num+1] + qsa-&gt;offs[thread][1], 1.0f);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else { /* SAMP_TYPE_HALTON */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s[0] = qsa-&gt;samp2d[2*num+0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s[1] = qsa-&gt;samp2d[2*num+1];<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
/* phong weighted disc using 'blur' for exponent, centred on 0,0 */<br>
static void QMC_samplePhong(float *vec, QMCSampler *qsa, int thread, int num, float blur)<br>
{<br>
&nbsp;&nbsp;&nbsp; double s[2];<br>
&nbsp;&nbsp;&nbsp; float phi, pz, sqr;<br>
<br>
&nbsp;&nbsp;&nbsp; QMC_getSample(s, qsa, thread, num);<br>
<br>
&nbsp;&nbsp;&nbsp; phi = s[0]*2*M_PI;<br>
&nbsp;&nbsp;&nbsp; pz = pow(s[1], blur);<br>
&nbsp;&nbsp;&nbsp; sqr = sqrt(1.0f-pz*pz);<br>
<br>
&nbsp;&nbsp;&nbsp; vec[0] = cos(phi)*sqr;<br>
&nbsp;&nbsp;&nbsp; vec[1] = sin(phi)*sqr;<br>
&nbsp;&nbsp;&nbsp; vec[2] = 0.0f;<br>
}<br>
<br>
/* rect of edge lengths sizex, sizey, centred on 0.0,0.0 i.e. ranging from -sizex/2 to +sizey/2 */<br>
static void QMC_sampleRect(float *vec, QMCSampler *qsa, int thread, int num, float sizex, float sizey)<br>
{<br>
&nbsp;&nbsp;&nbsp; double s[2];<br>
<br>
&nbsp;&nbsp;&nbsp; QMC_getSample(s, qsa, thread, num);<br>
<br>
&nbsp;&nbsp;&nbsp; vec[0] = (s[0] - 0.5) * sizex;<br>
&nbsp;&nbsp;&nbsp; vec[1] = (s[1] - 0.5) * sizey;<br>
&nbsp;&nbsp;&nbsp; vec[2] = 0.0f;<br>
}<br>
<br>
/* disc of radius 'radius', centred on 0,0 */<br>
static void QMC_sampleDisc(float *vec, QMCSampler *qsa, int thread, int num, float radius)<br>
{<br>
&nbsp;&nbsp;&nbsp; double s[2];<br>
&nbsp;&nbsp;&nbsp; float phi, sqr;<br>
<br>
&nbsp;&nbsp;&nbsp; QMC_getSample(s, qsa, thread, num);<br>
<br>
&nbsp;&nbsp;&nbsp; phi = s[0]*2*M_PI;<br>
&nbsp;&nbsp;&nbsp; sqr = sqrt(s[1]);<br>
<br>
&nbsp;&nbsp;&nbsp; vec[0] = cos(phi)*sqr* radius/2.0;<br>
&nbsp;&nbsp;&nbsp; vec[1] = sin(phi)*sqr* radius/2.0;<br>
&nbsp;&nbsp;&nbsp; vec[2] = 0.0f;<br>
}<br>
<br>
/* uniform hemisphere sampling */<br>
static void QMC_sampleHemi(float *vec, QMCSampler *qsa, int thread, int num)<br>
{<br>
&nbsp;&nbsp;&nbsp; double s[2];<br>
&nbsp;&nbsp;&nbsp; float phi, sqr;<br>
<br>
&nbsp;&nbsp;&nbsp; QMC_getSample(s, qsa, thread, num);<br>
<br>
&nbsp;&nbsp;&nbsp; phi = s[0]*2.f*M_PI;<br>
&nbsp;&nbsp;&nbsp; sqr = sqrt(s[1]);<br>
<br>
&nbsp;&nbsp;&nbsp; vec[0] = cos(phi)*sqr;<br>
&nbsp;&nbsp;&nbsp; vec[1] = sin(phi)*sqr;<br>
&nbsp;&nbsp;&nbsp; vec[2] = 1.f - s[1]*s[1];<br>
}<br>
<br>
#if 0 /* currently not used */<br>
/* cosine weighted hemisphere sampling */<br>
static void QMC_sampleHemiCosine(float *vec, QMCSampler *qsa, int thread, int num)<br>
{<br>
&nbsp;&nbsp;&nbsp; double s[2];<br>
&nbsp;&nbsp;&nbsp; float phi, sqr;<br>
<br>
&nbsp;&nbsp;&nbsp; QMC_getSample(s, qsa, thread, num);<br>
<br>
&nbsp;&nbsp;&nbsp; phi = s[0]*2.f*M_PI;<br>
&nbsp;&nbsp;&nbsp; sqr = s[1]*sqrt(2-s[1]*s[1]);<br>
<br>
&nbsp;&nbsp;&nbsp; vec[0] = cos(phi)*sqr;<br>
&nbsp;&nbsp;&nbsp; vec[1] = sin(phi)*sqr;<br>
&nbsp;&nbsp;&nbsp; vec[2] = 1.f - s[1]*s[1];<br>
<br>
}<br>
#endif<br>
<br>
/* called from convertBlenderScene.c */<br>
void init_render_qmcsampler(Render *re)<br>
{<br>
&nbsp;&nbsp;&nbsp; re-&gt;qmcsamplers= MEM_callocN(sizeof(ListBase)*BLENDER_MAX_THREADS, "QMCListBase");<br>
}<br>
<br>
static QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot)<br>
{<br>
&nbsp;&nbsp;&nbsp; QMCSampler *qsa;<br>
<br>
&nbsp;&nbsp;&nbsp; /* create qmc samplers as needed, since recursion makes it hard to<br>
&nbsp;&nbsp;&nbsp; &nbsp;* predict how many are needed */<br>
<br>
&nbsp;&nbsp;&nbsp; for(qsa=re-&gt;qmcsamplers[thread].first; qsa; qsa=qsa-&gt;next) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(qsa-&gt;type == type &amp;&amp; qsa-&gt;tot == tot &amp;&amp; !qsa-&gt;used) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa-&gt;used= 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return qsa;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; qsa= QMC_initSampler(type, tot);<br>
&nbsp;&nbsp;&nbsp; qsa-&gt;used= 1;<br>
&nbsp;&nbsp;&nbsp; BLI_addtail(&amp;re-&gt;qmcsamplers[thread], qsa);<br>
<br>
&nbsp;&nbsp;&nbsp; return qsa;<br>
}<br>
<br>
static void release_thread_qmcsampler(Render *re, int thread, QMCSampler *qsa)<br>
{<br>
&nbsp;&nbsp;&nbsp; qsa-&gt;used= 0;<br>
}<br>
<br>
void free_render_qmcsampler(Render *re)<br>
{<br>
&nbsp;&nbsp;&nbsp; QMCSampler *qsa, *next;<br>
&nbsp;&nbsp;&nbsp; int a;<br>
<br>
&nbsp;&nbsp;&nbsp; if(re-&gt;qmcsamplers) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(a=0; a&lt;BLENDER_MAX_THREADS; a++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(qsa=re-&gt;qmcsamplers[a].first; qsa; qsa=next) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; next= qsa-&gt;next;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QMC_freeSampler(qsa);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;qmcsamplers[a].first= re-&gt;qmcsamplers[a].last= NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MEM_freeN(re-&gt;qmcsamplers);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; re-&gt;qmcsamplers= NULL;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
static int adaptive_sample_variance(int samples, float *col, float *colsq, float thresh)<br>
{<br>
&nbsp;&nbsp;&nbsp; float var[3], mean[3];<br>
<br>
&nbsp;&nbsp;&nbsp; /* scale threshold just to give a bit more precision in input rather than dealing with<br>
&nbsp;&nbsp;&nbsp; &nbsp;* tiny tiny numbers in the UI */<br>
&nbsp;&nbsp;&nbsp; thresh /= 2;<br>
<br>
&nbsp;&nbsp;&nbsp; mean[0] = col[0] / (float)samples;<br>
&nbsp;&nbsp;&nbsp; mean[1] = col[1] / (float)samples;<br>
&nbsp;&nbsp;&nbsp; mean[2] = col[2] / (float)samples;<br>
<br>
&nbsp;&nbsp;&nbsp; var[0] = (colsq[0] / (float)samples) - (mean[0]*mean[0]);<br>
&nbsp;&nbsp;&nbsp; var[1] = (colsq[1] / (float)samples) - (mean[1]*mean[1]);<br>
&nbsp;&nbsp;&nbsp; var[2] = (colsq[2] / (float)samples) - (mean[2]*mean[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; if ((var[0] * 0.4 &lt; thresh) &amp;&amp; (var[1] * 0.3 &lt; thresh) &amp;&amp; (var[2] * 0.6 &lt; thresh))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>
static int adaptive_sample_contrast_val(int samples, float prev, float val, float thresh)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* if the last sample's contribution to the total value was below a small threshold<br>
&nbsp;&nbsp;&nbsp; &nbsp;* (i.e. the samples taken are very similar), then taking more samples that are probably<br>
&nbsp;&nbsp;&nbsp; &nbsp;* going to be the same is wasting effort */<br>
&nbsp;&nbsp;&nbsp; if (fabs( prev/(float)(samples-1) - val/(float)samples ) &lt; thresh) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br>
&nbsp;&nbsp;&nbsp; } else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>
static float get_avg_speed(ShadeInput *shi)<br>
{<br>
&nbsp;&nbsp;&nbsp; float pre_x, pre_y, post_x, post_y, speedavg;<br>
<br>
&nbsp;&nbsp;&nbsp; pre_x = (shi-&gt;winspeed[0] == PASS_VECTOR_MAX)?0.0:shi-&gt;winspeed[0];<br>
&nbsp;&nbsp;&nbsp; pre_y = (shi-&gt;winspeed[1] == PASS_VECTOR_MAX)?0.0:shi-&gt;winspeed[1];<br>
&nbsp;&nbsp;&nbsp; post_x = (shi-&gt;winspeed[2] == PASS_VECTOR_MAX)?0.0:shi-&gt;winspeed[2];<br>
&nbsp;&nbsp;&nbsp; post_y = (shi-&gt;winspeed[3] == PASS_VECTOR_MAX)?0.0:shi-&gt;winspeed[3];<br>
<br>
&nbsp;&nbsp;&nbsp; speedavg = (sqrt(pre_x*pre_x + pre_y*pre_y) + sqrt(post_x*post_x + post_y*post_y)) / 2.0;<br>
<br>
&nbsp;&nbsp;&nbsp; return speedavg;<br>
}<br>
<br>
/* ***************** main calls ************** */<br>
<br>
<br>
static void trace_refract(float *col, ShadeInput *shi, ShadeResult *shr)<br>
{<br>
&nbsp;&nbsp;&nbsp; QMCSampler *qsa=NULL;<br>
&nbsp;&nbsp;&nbsp; int samp_type;<br>
&nbsp;&nbsp;&nbsp; int traflag=0;<br>
<br>
&nbsp;&nbsp;&nbsp; float samp3d[3], orthx[3], orthy[3];<br>
&nbsp;&nbsp;&nbsp; float v_refract[3], v_refract_new[3];<br>
&nbsp;&nbsp;&nbsp; float sampcol[4], colsq[4];<br>
<br>
&nbsp;&nbsp;&nbsp; float blur = pow(1.0 - shi-&gt;mat-&gt;gloss_tra, 3);<br>
&nbsp;&nbsp;&nbsp; short max_samples = shi-&gt;mat-&gt;samp_gloss_tra;<br>
&nbsp;&nbsp;&nbsp; float adapt_thresh = shi-&gt;mat-&gt;adapt_thresh_tra;<br>
<br>
&nbsp;&nbsp;&nbsp; int samples=0;<br>
<br>
&nbsp;&nbsp;&nbsp; colsq[0] = colsq[1] = colsq[2] = 0.0;<br>
&nbsp;&nbsp;&nbsp; col[0] = col[1] = col[2] = 0.0;<br>
&nbsp;&nbsp;&nbsp; col[3]= shr-&gt;alpha;<br>
<br>
&nbsp;&nbsp;&nbsp; if (blur &gt; 0.0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (adapt_thresh != 0.0) samp_type = SAMP_TYPE_HALTON;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else samp_type = SAMP_TYPE_HAMMERSLEY;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* all samples are generated per pixel */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa = get_thread_qmcsampler(&amp;R, shi-&gt;thread, samp_type, max_samples);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QMC_initPixel(qsa, shi-&gt;thread);<br>
&nbsp;&nbsp;&nbsp; } else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples = 1;<br>
<br>
<br>
&nbsp;&nbsp;&nbsp; while (samples &lt; max_samples) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(refraction(v_refract, shi-&gt;vn, shi-&gt;view, shi-&gt;ang)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; traflag |= RAY_INSIDE;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* total
external reflection can happen for materials with IOR &lt; 1.0 */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((shi-&gt;vlr-&gt;flag &amp; R_SMOOTH))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; reflection(v_refract, shi-&gt;vn, shi-&gt;view,
shi-&gt;facenor);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; reflection(v_refract, shi-&gt;vn, shi-&gt;view,
NULL);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* can't blur total external reflection */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples = 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (max_samples &gt; 1) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* get a quasi-random vector from a phong-weighted disc */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QMC_samplePhong(samp3d, qsa, shi-&gt;thread, samples, blur);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ortho_basis_v3v3_v3( orthx, orthy,v_refract);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(orthx, samp3d[0]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(orthy, samp3d[1]);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* and perturb the refraction vector in it */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; add_v3_v3v3(v_refract_new, v_refract, orthx);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; add_v3_v3(v_refract_new, orthy);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(v_refract_new);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* no blurriness, use the original normal */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(v_refract_new, v_refract);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sampcol[0]= sampcol[1]= sampcol[2]= sampcol[3]= 0.0f;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //CreateTiming("Raytracing begins...");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; traceray(shi, shr,
shi-&gt;mat-&gt;ray_depth_tra, shi-&gt;co, v_refract_new, sampcol,
shi-&gt;obi, shi-&gt;vlr, traflag);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //CreateTiming("Raytracing ends...");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[0] += sampcol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[1] += sampcol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[2] += sampcol[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[3] += sampcol[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* for variance calc */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[0] += sampcol[0]*sampcol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[1] += sampcol[1]*sampcol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[2] += sampcol[2]*sampcol[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; samples++;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* adaptive sampling */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (adapt_thresh &lt; 1.0 &amp;&amp; samples &gt; max_samples/2)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (adaptive_sample_variance(samples, col, colsq, adapt_thresh))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* if the
pixel so far is very dark, we can get away with less samples */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ( (col[0] + col[1] + col[2])/3.0/(float)samples &lt; 0.01 )<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples--;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; col[0] /= (float)samples;<br>
&nbsp;&nbsp;&nbsp; col[1] /= (float)samples;<br>
&nbsp;&nbsp;&nbsp; col[2] /= (float)samples;<br>
&nbsp;&nbsp;&nbsp; col[3] /= (float)samples;<br>
<br>
&nbsp;&nbsp;&nbsp; if (qsa)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; release_thread_qmcsampler(&amp;R, shi-&gt;thread, qsa);<br>
}<br>
<br>
static void trace_reflect(float *col, ShadeInput *shi, ShadeResult *shr, float fresnelfac)<br>
{<br>
&nbsp;&nbsp;&nbsp; QMCSampler *qsa=NULL;<br>
&nbsp;&nbsp;&nbsp; int samp_type;<br>
<br>
&nbsp;&nbsp;&nbsp; float samp3d[3], orthx[3], orthy[3];<br>
&nbsp;&nbsp;&nbsp; float v_nor_new[3], v_reflect[3];<br>
&nbsp;&nbsp;&nbsp; float sampcol[4], colsq[4];<br>
<br>
&nbsp;&nbsp;&nbsp; float blur = pow(1.0 - shi-&gt;mat-&gt;gloss_mir, 3);<br>
&nbsp;&nbsp;&nbsp; short max_samples = shi-&gt;mat-&gt;samp_gloss_mir;<br>
&nbsp;&nbsp;&nbsp; float adapt_thresh = shi-&gt;mat-&gt;adapt_thresh_mir;<br>
&nbsp;&nbsp;&nbsp; float aniso = 1.0 - shi-&gt;mat-&gt;aniso_gloss_mir;<br>
<br>
&nbsp;&nbsp;&nbsp; int samples=0;<br>
<br>
&nbsp;&nbsp;&nbsp; col[0] = col[1] = col[2] = 0.0;<br>
&nbsp;&nbsp;&nbsp; colsq[0] = colsq[1] = colsq[2] = 0.0;<br>
<br>
&nbsp;&nbsp;&nbsp; if (blur &gt; 0.0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (adapt_thresh != 0.0) samp_type = SAMP_TYPE_HALTON;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else samp_type = SAMP_TYPE_HAMMERSLEY;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* all samples are generated per pixel */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa = get_thread_qmcsampler(&amp;R, shi-&gt;thread, samp_type, max_samples);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QMC_initPixel(qsa, shi-&gt;thread);<br>
&nbsp;&nbsp;&nbsp; } else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples = 1;<br>
<br>
&nbsp;&nbsp;&nbsp; while (samples &lt; max_samples) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (max_samples &gt; 1) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* get a quasi-random vector from a phong-weighted disc */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QMC_samplePhong(samp3d, qsa, shi-&gt;thread, samples, blur);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* find the normal's perpendicular plane, blurring along tangents<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* if tangent shading enabled */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (shi-&gt;mat-&gt;mode &amp; (MA_TANGENT_V)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; cross_v3_v3v3(orthx, shi-&gt;vn,
shi-&gt;tang);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // bitangent<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(orthy, shi-&gt;tang);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(orthx, samp3d[0]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(orthy, samp3d[1]*aniso);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ortho_basis_v3v3_v3( orthx, orthy,shi-&gt;vn);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(orthx, samp3d[0]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(orthy, samp3d[1]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* and perturb the normal in it */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; add_v3_v3v3(v_nor_new, shi-&gt;vn, orthx);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; add_v3_v3(v_nor_new, orthy);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(v_nor_new);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* no blurriness, use the original normal */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(v_nor_new, shi-&gt;vn);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((shi-&gt;vlr-&gt;flag &amp; R_SMOOTH))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; reflection(v_reflect, v_nor_new, shi-&gt;view, shi-&gt;facenor);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; reflection(v_reflect, v_nor_new, shi-&gt;view, NULL);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sampcol[0]= sampcol[1]= sampcol[2]= sampcol[3]= 0.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; traceray(shi, shr,
shi-&gt;mat-&gt;ray_depth, shi-&gt;co, v_reflect, sampcol, shi-&gt;obi,
shi-&gt;vlr, 0);<br>
<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[0] += sampcol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[1] += sampcol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[2] += sampcol[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* for variance calc */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[0] += sampcol[0]*sampcol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[1] += sampcol[1]*sampcol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[2] += sampcol[2]*sampcol[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; samples++;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* adaptive sampling */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (adapt_thresh &gt; 0.0 &amp;&amp; samples &gt; max_samples/3)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (adaptive_sample_variance(samples, col, colsq, adapt_thresh))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* if the
pixel so far is very dark, we can get away with less samples */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ( (col[0] + col[1] + col[2])/3.0/(float)samples &lt; 0.01 )<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples--;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* reduce
samples when reflection is dim due to low ray mirror blend value or
fresnel factor<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* and when reflection is blurry */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (fresnelfac &lt; 0.1 * (blur+1)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples--;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* even more for very dim */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (fresnelfac &lt; 0.05 * (blur+1))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples--;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; col[0] /= (float)samples;<br>
&nbsp;&nbsp;&nbsp; col[1] /= (float)samples;<br>
&nbsp;&nbsp;&nbsp; col[2] /= (float)samples;<br>
<br>
&nbsp;&nbsp;&nbsp; if (qsa)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; release_thread_qmcsampler(&amp;R, shi-&gt;thread, qsa);<br>
}<br>
<br>
/* extern call from render loop */<br>
void ray_trace(ShadeInput *shi, ShadeResult *shr)<br>
{<br>
&nbsp;&nbsp;&nbsp; float i, f, f1, fr, fg, fb;<br>
&nbsp;&nbsp;&nbsp; float mircol[4], tracol[4];<br>
&nbsp;&nbsp;&nbsp; float diff[3];<br>
&nbsp;&nbsp;&nbsp; int do_tra, do_mir;<br>
<br>
&nbsp;&nbsp;&nbsp; do_tra= ((shi-&gt;mode &amp; MA_TRANSP) &amp;&amp;
(shi-&gt;mode &amp; MA_RAYTRANSP) &amp;&amp; shr-&gt;alpha!=1.0f
&amp;&amp; (shi-&gt;depth &lt;= shi-&gt;mat-&gt;ray_depth_tra));<br>
&nbsp;&nbsp;&nbsp; do_mir= ((shi-&gt;mat-&gt;mode &amp; MA_RAYMIRROR)
&amp;&amp; shi-&gt;ray_mirror!=0.0f &amp;&amp; (shi-&gt;depth &lt;=
shi-&gt;mat-&gt;ray_depth));<br>
<br>
&nbsp;&nbsp;&nbsp; /* raytrace mirror amd refract like to separate the spec color */<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;combinedflag &amp; SCE_PASS_SPEC)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECSUB(diff, shr-&gt;combined, shr-&gt;spec) /* no ; */<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(diff, shr-&gt;combined);<br>
<br>
&nbsp;&nbsp;&nbsp; if(do_tra) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float olddiff[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; trace_refract(tracol, shi, shr);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f= shr-&gt;alpha; f1= 1.0f-f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fr= 1.0f+ shi-&gt;mat-&gt;filter*(shi-&gt;r-1.0f);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fg= 1.0f+ shi-&gt;mat-&gt;filter*(shi-&gt;g-1.0f);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fb= 1.0f+ shi-&gt;mat-&gt;filter*(shi-&gt;b-1.0f);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* for refract pass */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(olddiff, diff);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff[0]= f*diff[0] + f1*fr*tracol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff[1]= f*diff[1] + f1*fg*tracol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff[2]= f*diff[2] + f1*fb*tracol[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi-&gt;passflag &amp; SCE_PASS_REFRACT)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECSUB(shr-&gt;refr, diff, olddiff);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(!(shi-&gt;combinedflag &amp; SCE_PASS_REFRACT))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECSUB(diff, diff, shr-&gt;refr);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;alpha= MIN2(1.0f, tracol[3]);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(do_mir) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i=
shi-&gt;ray_mirror*fresnel_fac(shi-&gt;view, shi-&gt;vn,
shi-&gt;mat-&gt;fresnel_mir_i, shi-&gt;mat-&gt;fresnel_mir);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(i!=0.0f) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; trace_reflect(mircol, shi, shr, i);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fr= i*shi-&gt;mirr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fg= i*shi-&gt;mirg;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fb= i*shi-&gt;mirb;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi-&gt;passflag &amp; SCE_PASS_REFLECT) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* mirror pass is not blocked out with spec */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;refl[0]= fr*mircol[0] - fr*diff[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;refl[1]= fg*mircol[1] - fg*diff[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;refl[2]= fb*mircol[2] - fb*diff[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi-&gt;combinedflag &amp; SCE_PASS_REFLECT) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* values in shr-&gt;spec can be greater then 1.0.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;* In this case the mircol uses a zero blending
factor, so ignoring it is ok.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;* Fixes bug #18837 - when the spec is higher
then 1.0,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;* diff can become a negative color -
Campbell&nbsp; */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f1= 1.0f-i;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff[0] *= f1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff[1] *= f1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff[2] *= f1;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if(shr-&gt;spec[0]&lt;1.0f)&nbsp;&nbsp;&nbsp;
diff[0] += mircol[0] * (fr*(1.0f-shr-&gt;spec[0]));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if(shr-&gt;spec[1]&lt;1.0f)&nbsp;&nbsp;&nbsp;
diff[1] += mircol[1] * (fg*(1.0f-shr-&gt;spec[1]));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if(shr-&gt;spec[2]&lt;1.0f)&nbsp;&nbsp;&nbsp;
diff[2] += mircol[2] * (fb*(1.0f-shr-&gt;spec[2]));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; /* put back together */<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;combinedflag &amp; SCE_PASS_SPEC)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECADD(shr-&gt;combined, diff, shr-&gt;spec) /* no ; */<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(shr-&gt;combined, diff);<br>
}<br>
<br>
/* color 'shadfac' passes through 'col' with alpha and filter */<br>
/* filter is only applied on alpha defined transparent part */<br>
static void addAlphaLight(float *shadfac, float *col, float alpha, float filter)<br>
{<br>
&nbsp;&nbsp;&nbsp; float fr, fg, fb;<br>
<br>
&nbsp;&nbsp;&nbsp; fr= 1.0f+ filter*(col[0]-1.0f);<br>
&nbsp;&nbsp;&nbsp; fg= 1.0f+ filter*(col[1]-1.0f);<br>
&nbsp;&nbsp;&nbsp; fb= 1.0f+ filter*(col[2]-1.0f);<br>
<br>
&nbsp;&nbsp;&nbsp; shadfac[0]= alpha*col[0] + fr*(1.0f-alpha)*shadfac[0];<br>
&nbsp;&nbsp;&nbsp; shadfac[1]= alpha*col[1] + fg*(1.0f-alpha)*shadfac[1];<br>
&nbsp;&nbsp;&nbsp; shadfac[2]= alpha*col[2] + fb*(1.0f-alpha)*shadfac[2];<br>
<br>
&nbsp;&nbsp;&nbsp; shadfac[3]= (1.0f-alpha)*shadfac[3];<br>
}<br>
<br>
static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int traflag, float col[4])<br>
{<br>
&nbsp;&nbsp;&nbsp; /* ray to lamp, find first face that intersects, check alpha properties,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; if it has col[3]&gt;0.0f&nbsp; continue. so exit when alpha is full */<br>
&nbsp;&nbsp;&nbsp; ShadeInput shi;<br>
&nbsp;&nbsp;&nbsp; ShadeResult shr;<br>
&nbsp;&nbsp;&nbsp; float initial_dist = is-&gt;dist;<br>
<br>
&nbsp;&nbsp;&nbsp; if(RE_rayobject_raycast(R.raytree, is)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float d= 1.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* we got a face */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* Warning, This is not that nice, and possibly a bit slow for every ray,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; however some variables were not
initialized properly in, unless using shade_input_initialize(...), we
need to do a memset */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; memset(&amp;shi, 0, sizeof(ShadeInput));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* end warning! - Campbell */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.depth= origshi-&gt;depth +
1;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* only used to indicate tracing
*/<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.mask= origshi-&gt;mask;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.thread= origshi-&gt;thread;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.passflag= SCE_PASS_COMBINED;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.combinedflag=
0xFFFFFF;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/* ray trace does
all options */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.xs= origshi-&gt;xs;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.ys= origshi-&gt;ys;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.lay= origshi-&gt;lay;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shi.nodes= origshi-&gt;nodes;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_ray(is, &amp;shi, &amp;shr);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (shi.mat-&gt;material_type == MA_TYPE_SURFACE) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (traflag &amp; RAY_TRA)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; d= shade_by_transmission(is, &amp;shi, &amp;shr);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* mix colors based on shadfac (rgb + amount of light factor) */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; addAlphaLight(col, shr.diff, shr.alpha, d*shi.mat-&gt;filter);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else if (shi.mat-&gt;material_type == MA_TYPE_VOLUME) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; const float a = col[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[0] = a*col[0] + shr.alpha*shr.combined[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[1] = a*col[1] + shr.alpha*shr.combined[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[2] = a*col[2] + shr.alpha*shr.combined[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; col[3] = (1.0 - shr.alpha)*a;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(depth&gt;0 &amp;&amp; col[3]&gt;0.0f) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* adapt isect struct */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(is-&gt;start, shi.co);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; is-&gt;dist = initial_dist-is-&gt;dist;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; is-&gt;orig.ob&nbsp;&nbsp; = shi.obi;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; is-&gt;orig.face = shi.vlr;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_trace_shadow_tra(is, origshi, depth-1, traflag | RAY_TRA, col);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RE_RC_MERGE(&amp;origshi-&gt;raycounter, &amp;shi.raycounter);<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
/* not used, test function for ambient occlusion (yaf: pathlight) */<br>
/* main problem; has to be called within shading loop, giving unwanted recursion */<br>
int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)<br>
{<br>
&nbsp;&nbsp;&nbsp; static int counter=0, only_one= 0;<br>
&nbsp;&nbsp;&nbsp; extern float hashvectf[];<br>
&nbsp;&nbsp;&nbsp; Isect isec;<br>
&nbsp;&nbsp;&nbsp; ShadeInput shi;<br>
&nbsp;&nbsp;&nbsp; ShadeResult shr_t;<br>
&nbsp;&nbsp;&nbsp; float vec[3], accum[3], div= 0.0f;<br>
&nbsp;&nbsp;&nbsp; int a;<br>
<br>
&nbsp;&nbsp;&nbsp; assert(0);<br>
<br>
&nbsp;&nbsp;&nbsp; if(only_one) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; only_one= 1;<br>
<br>
&nbsp;&nbsp;&nbsp; accum[0]= accum[1]= accum[2]= 0.0f;<br>
&nbsp;&nbsp;&nbsp; isec.mode= RE_RAY_MIRROR;<br>
&nbsp;&nbsp;&nbsp; isec.orig.ob&nbsp;&nbsp; = ship-&gt;obi;<br>
&nbsp;&nbsp;&nbsp; isec.orig.face = ship-&gt;vlr;<br>
&nbsp;&nbsp;&nbsp; isec.hint = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec.start, ship-&gt;co);<br>
<br>
&nbsp;&nbsp;&nbsp; RE_RC_INIT(isec, shi);<br>
<br>
&nbsp;&nbsp;&nbsp; for(a=0; a&lt;8*8; a++) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; counter+=3;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; counter %= 768;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(vec, hashvectf+counter);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(ship-&gt;vn[0]*vec[0]+ship-&gt;vn[1]*vec[1]+ship-&gt;vn[2]*vec[2]&gt;0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec[0]-= vec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec[1]-= vec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec[2]-= vec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(isec.dir, vec );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dist = RE_RAYTRACE_MAXDIST;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(RE_rayobject_raycast(R.raytree, &amp;isec)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float fac;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* Warning,
This is not that nice, and possibly a bit slow for every ray,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; however some
variables were not initialized properly in, unless using
shade_input_initialize(...), we need to do a memset */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; memset(&amp;shi, 0, sizeof(ShadeInput));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* end warning! - Campbell */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shade_ray(&amp;isec, &amp;shi, &amp;shr_t);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= isec.dist*isec.dist;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= 1.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; accum[0]+= fac*(shr_t.diff[0]+shr_t.spec[0]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; accum[1]+= fac*(shr_t.diff[1]+shr_t.spec[1]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; accum[2]+= fac*(shr_t.diff[2]+shr_t.spec[2]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; div+= fac;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else div+= 1.0f;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(div!=0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;diff[0]+= accum[0]/div;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;diff[1]+= accum[1]/div;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shr-&gt;diff[2]+= accum[2]/div;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; shr-&gt;alpha= 1.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; only_one= 0;<br>
&nbsp;&nbsp;&nbsp; return 1;<br>
}<br>
<br>
/* aolight: function to create random unit sphere vectors for total random sampling */<br>
static void RandomSpherical(float *v)<br>
{<br>
&nbsp;&nbsp;&nbsp; float r;<br>
&nbsp;&nbsp;&nbsp; v[2] = 2.f*BLI_frand()-1.f;<br>
&nbsp;&nbsp;&nbsp; if ((r = 1.f - v[2]*v[2])&gt;0.f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float a = 6.283185307f*BLI_frand();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r = sqrt(r);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v[0] = r * cos(a);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v[1] = r * sin(a);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else v[2] = 1.f;<br>
}<br>
<br>
/* calc distributed spherical energy */<br>
static void DS_energy(float *sphere, int tot, float *vec)<br>
{<br>
&nbsp;&nbsp;&nbsp; float *fp, fac, force[3], res[3];<br>
&nbsp;&nbsp;&nbsp; int a;<br>
<br>
&nbsp;&nbsp;&nbsp; res[0]= res[1]= res[2]= 0.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; for(a=0, fp=sphere; a&lt;tot; a++, fp+=3) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sub_v3_v3v3(force, vec, fp);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= force[0]*force[0] + force[1]*force[1] + force[2]*force[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(fac!=0.0f) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac= 1.0f/fac;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res[0]+= fac*force[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res[1]+= fac*force[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res[2]+= fac*force[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; mul_v3_fl(res, 0.5);<br>
&nbsp;&nbsp;&nbsp; add_v3_v3(vec, res);<br>
&nbsp;&nbsp;&nbsp; normalize_v3(vec);<br>
<br>
}<br>
<br>
/* called from convertBlenderScene.c */<br>
/* creates an equally distributed spherical sample pattern */<br>
/* and allocates threadsafe memory */<br>
void init_ao_sphere(World *wrld)<br>
{<br>
&nbsp;&nbsp;&nbsp; float *fp;<br>
&nbsp;&nbsp;&nbsp; int a, tot, iter= 16;<br>
<br>
&nbsp;&nbsp;&nbsp; /* we make twice the amount of samples, because only a hemisphere is used */<br>
&nbsp;&nbsp;&nbsp; tot= 2*wrld-&gt;aosamp*wrld-&gt;aosamp;<br>
<br>
&nbsp;&nbsp;&nbsp; wrld-&gt;aosphere= MEM_mallocN(3*tot*sizeof(float), "AO sphere");<br>
<br>
&nbsp;&nbsp;&nbsp; /* fixed random */<br>
&nbsp;&nbsp;&nbsp; BLI_srandom(tot);<br>
<br>
&nbsp;&nbsp;&nbsp; /* init */<br>
&nbsp;&nbsp;&nbsp; fp= wrld-&gt;aosphere;<br>
&nbsp;&nbsp;&nbsp; for(a=0; a&lt;tot; a++, fp+= 3) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RandomSpherical(fp);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; while(iter--) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(a=0, fp= wrld-&gt;aosphere; a&lt;tot; a++, fp+= 3) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DS_energy(wrld-&gt;aosphere, tot, fp);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; /* tables */<br>
&nbsp;&nbsp;&nbsp; wrld-&gt;aotables= MEM_mallocN(BLENDER_MAX_THREADS*3*tot*sizeof(float), "AO tables");<br>
}<br>
<br>
/* give per thread a table, we have to compare xs ys because of way OSA works... */<br>
static float *threadsafe_table_sphere(int test, int thread, int xs, int ys, int tot)<br>
{<br>
&nbsp;&nbsp;&nbsp; static int xso[BLENDER_MAX_THREADS], yso[BLENDER_MAX_THREADS];<br>
&nbsp;&nbsp;&nbsp; static int firsttime= 1;<br>
<br>
&nbsp;&nbsp;&nbsp; if(firsttime) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; memset(xso, 255, sizeof(xso));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; memset(yso, 255, sizeof(yso));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; firsttime= 0;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(xs==xso[thread] &amp;&amp; ys==yso[thread]) return R.wrld.aotables+ thread*tot*3;<br>
&nbsp;&nbsp;&nbsp; if(test) return NULL;<br>
&nbsp;&nbsp;&nbsp; xso[thread]= xs; yso[thread]= ys;<br>
&nbsp;&nbsp;&nbsp; return R.wrld.aotables+ thread*tot*3;<br>
}<br>
<br>
static float *sphere_sampler(int type, int resol, int thread, int xs, int ys, int reset)<br>
{<br>
&nbsp;&nbsp;&nbsp; int tot;<br>
&nbsp;&nbsp;&nbsp; float *vec;<br>
<br>
&nbsp;&nbsp;&nbsp; tot= 2*resol*resol;<br>
<br>
&nbsp;&nbsp;&nbsp; if (type &amp; WO_AORNDSMP) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float *sphere;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int a;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // always returns table<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sphere= threadsafe_table_sphere(0, thread, xs, ys, tot);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* total random sampling. NOT THREADSAFE! (should be removed, is not useful) */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec= sphere;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (a=0; a&lt;tot; a++, vec+=3) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RandomSpherical(vec);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return sphere;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float *sphere;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float cosfi, sinfi, cost, sint;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float ang, *vec1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int a;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // returns table if xs and ys were equal to last call, and not resetting<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sphere= (reset)? NULL: threadsafe_table_sphere(1, thread, xs, ys, tot);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(sphere==NULL) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sphere= threadsafe_table_sphere(0, thread, xs, ys, tot);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // random rotation<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ang= BLI_thread_frand(thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sinfi= sin(ang); cosfi= cos(ang);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ang= BLI_thread_frand(thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sint= sin(ang); cost= cos(ang);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec= R.wrld.aosphere;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec1= sphere;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (a=0; a&lt;tot; a++, vec+=3, vec1+=3) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; vec1[0]= cost*cosfi*vec[0] - sinfi*vec[1] +
sint*cosfi*vec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; vec1[1]= cost*sinfi*vec[0] + cosfi*vec[1] +
sint*sinfi*vec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec1[2]= -sint*vec[0] + cost*vec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return sphere;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
static void ray_ao_qmc(ShadeInput *shi, float *ao, float *env)<br>
{<br>
&nbsp;&nbsp;&nbsp; Isect isec;<br>
&nbsp;&nbsp;&nbsp; RayHint point_hint;<br>
&nbsp;&nbsp;&nbsp; QMCSampler *qsa=NULL;<br>
&nbsp;&nbsp;&nbsp; float samp3d[3];<br>
&nbsp;&nbsp;&nbsp; float up[3], side[3], dir[3], nrm[3];<br>
<br>
&nbsp;&nbsp;&nbsp; float maxdist = R.wrld.aodist;<br>
&nbsp;&nbsp;&nbsp; float fac=0.0f, prev=0.0f;<br>
&nbsp;&nbsp;&nbsp; float adapt_thresh = R.wrld.ao_adapt_thresh;<br>
&nbsp;&nbsp;&nbsp; float adapt_speed_fac = R.wrld.ao_adapt_speed_fac;<br>
<br>
&nbsp;&nbsp;&nbsp; int samples=0;<br>
&nbsp;&nbsp;&nbsp; int max_samples = R.wrld.aosamp*R.wrld.aosamp;<br>
<br>
&nbsp;&nbsp;&nbsp; float dxyview[3], skyadded=0;<br>
&nbsp;&nbsp;&nbsp; int envcolor;<br>
<br>
&nbsp;&nbsp;&nbsp; RE_RC_INIT(isec, *shi);<br>
&nbsp;&nbsp;&nbsp; isec.orig.ob&nbsp;&nbsp; = shi-&gt;obi;<br>
&nbsp;&nbsp;&nbsp; isec.orig.face = shi-&gt;vlr;<br>
&nbsp;&nbsp;&nbsp; isec.check = RE_CHECK_VLR_NON_SOLID_MATERIAL;<br>
&nbsp;&nbsp;&nbsp; isec.skip = RE_SKIP_VLR_NEIGHBOUR;<br>
&nbsp;&nbsp;&nbsp; isec.hint = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; isec.hit.ob&nbsp;&nbsp; = 0;<br>
&nbsp;&nbsp;&nbsp; isec.hit.face = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; isec.last_hit = NULL;<br>
<br>
&nbsp;&nbsp;&nbsp; isec.mode= (R.wrld.aomode &amp; WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW;<br>
&nbsp;&nbsp;&nbsp; isec.lay= -1;<br>
<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec.start, shi-&gt;co);<br>
&nbsp;&nbsp;&nbsp; RE_rayobject_hint_bb( R.raytree, &amp;point_hint, isec.start, isec.start );<br>
&nbsp;&nbsp;&nbsp; isec.hint = &amp;point_hint;<br>
<br>
&nbsp;&nbsp;&nbsp; zero_v3(ao);<br>
&nbsp;&nbsp;&nbsp; zero_v3(env);<br>
<br>
&nbsp;&nbsp;&nbsp; /* prevent sky colors to be added for only shadow (shadow becomes alpha) */<br>
&nbsp;&nbsp;&nbsp; envcolor= R.wrld.aocolor;<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;mat-&gt;mode &amp; MA_ONLYSHADOW)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; envcolor= WO_AOPLAIN;<br>
<br>
&nbsp;&nbsp;&nbsp; if(envcolor == WO_AOSKYTEX) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dxyview[0]= 1.0f/(float)R.wrld.aosamp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dxyview[1]= 1.0f/(float)R.wrld.aosamp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dxyview[2]= 0.0f;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;vlr-&gt;flag &amp; R_SMOOTH) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(nrm, shi-&gt;vn);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(nrm, shi-&gt;facenor);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; ortho_basis_v3v3_v3( up, side,nrm);<br>
<br>
&nbsp;&nbsp;&nbsp; /* sampling init */<br>
&nbsp;&nbsp;&nbsp; if (R.wrld.ao_samp_method==WO_AOSAMP_HALTON) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float speedfac;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; speedfac = get_avg_speed(shi) * adapt_speed_fac;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CLAMP(speedfac, 1.0, 1000.0);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; max_samples /= speedfac;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (max_samples &lt; 5) max_samples = 5;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa = get_thread_qmcsampler(&amp;R, shi-&gt;thread, SAMP_TYPE_HALTON, max_samples);<br>
&nbsp;&nbsp;&nbsp; } else if (R.wrld.ao_samp_method==WO_AOSAMP_HAMMERSLEY)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa = get_thread_qmcsampler(&amp;R, shi-&gt;thread, SAMP_TYPE_HAMMERSLEY, max_samples);<br>
<br>
&nbsp;&nbsp;&nbsp; QMC_initPixel(qsa, shi-&gt;thread);<br>
<br>
&nbsp;&nbsp;&nbsp; while (samples &lt; max_samples) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* sampling, returns quasi-random vector in unit hemisphere */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QMC_sampleHemi(samp3d, qsa, shi-&gt;thread, samples);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dir[0] = (samp3d[0]*up[0] + samp3d[1]*side[0] + samp3d[2]*nrm[0]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dir[1] = (samp3d[0]*up[1] + samp3d[1]*side[1] + samp3d[2]*nrm[1]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dir[2] = (samp3d[0]*up[2] + samp3d[1]*side[2] + samp3d[2]*nrm[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(dir);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dir[0] = -dir[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dir[1] = -dir[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dir[2] = -dir[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dist = maxdist;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; prev = fac;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(RE_rayobject_raycast(R.raytree, &amp;isec)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if
(R.wrld.aomode &amp; WO_AODIST) fac+= exp(-isec.dist*R.wrld.aodistfac);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else fac+= 1.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(envcolor!=WO_AOPLAIN) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float skycol[4];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float skyfac, view[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; view[0]= -dir[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; view[1]= -dir[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; view[2]= -dir[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(view);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(envcolor==WO_AOSKYCOL) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; skyfac= 0.5*(1.0f+view[0]*R.grvec[0]+
view[1]*R.grvec[1]+ view[2]*R.grvec[2]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; env[0]+= (1.0f-skyfac)*R.wrld.horr +
skyfac*R.wrld.zenr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; env[1]+= (1.0f-skyfac)*R.wrld.horg +
skyfac*R.wrld.zeng;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; env[2]+= (1.0f-skyfac)*R.wrld.horb +
skyfac*R.wrld.zenb;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {&nbsp;&nbsp;&nbsp; /* WO_AOSKYTEX */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; shadeSkyView(skycol, isec.start, view, dxyview,
shi-&gt;thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadeSunView(skycol, shi-&gt;view);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[0]+= skycol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[1]+= skycol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[2]+= skycol[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; skyadded++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; samples++;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (qsa-&gt;type == SAMP_TYPE_HALTON) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* adaptive
sampling - consider samples below threshold as in shadow (or vice
versa) and exit early */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (adapt_thresh &gt; 0.0 &amp;&amp; (samples &gt; max_samples/2) ) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if (adaptive_sample_contrast_val(samples, prev, fac,
adapt_thresh)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; /* average color times distances/hits formula */<br>
&nbsp;&nbsp;&nbsp; ao[0]= ao[1]= ao[2]= 1.0f - fac/(float)samples;<br>
<br>
&nbsp;&nbsp;&nbsp; if(envcolor!=WO_AOPLAIN &amp;&amp; skyadded)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(env, (1.0f - fac/(float)samples)/((float)skyadded));<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; copy_v3_v3(env, ao);<br>
<br>
&nbsp;&nbsp;&nbsp; if (qsa)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; release_thread_qmcsampler(&amp;R, shi-&gt;thread, qsa);<br>
}<br>
<br>
/* extern call from shade_lamp_loop, ambient occlusion calculus */<br>
static void ray_ao_spheresamp(ShadeInput *shi, float *ao, float *env)<br>
{<br>
&nbsp;&nbsp;&nbsp; Isect isec;<br>
&nbsp;&nbsp;&nbsp; RayHint point_hint;<br>
&nbsp;&nbsp;&nbsp; float *vec, *nrm, bias, sh=0.0f;<br>
&nbsp;&nbsp;&nbsp; float maxdist = R.wrld.aodist;<br>
&nbsp;&nbsp;&nbsp; float dxyview[3];<br>
&nbsp;&nbsp;&nbsp; int j= -1, tot, actual=0, skyadded=0, envcolor, resol= R.wrld.aosamp;<br>
<br>
&nbsp;&nbsp;&nbsp; RE_RC_INIT(isec, *shi);<br>
&nbsp;&nbsp;&nbsp; isec.orig.ob&nbsp;&nbsp; = shi-&gt;obi;<br>
&nbsp;&nbsp;&nbsp; isec.orig.face = shi-&gt;vlr;<br>
&nbsp;&nbsp;&nbsp; isec.check = RE_CHECK_VLR_RENDER;<br>
&nbsp;&nbsp;&nbsp; isec.skip = RE_SKIP_VLR_NEIGHBOUR;<br>
&nbsp;&nbsp;&nbsp; isec.hint = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; isec.hit.ob&nbsp;&nbsp; = 0;<br>
&nbsp;&nbsp;&nbsp; isec.hit.face = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; isec.last_hit = NULL;<br>
<br>
&nbsp;&nbsp;&nbsp; isec.mode= (R.wrld.aomode &amp; WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW;<br>
&nbsp;&nbsp;&nbsp; isec.lay= -1;<br>
<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec.start, shi-&gt;co);<br>
&nbsp;&nbsp;&nbsp; RE_rayobject_hint_bb( R.raytree, &amp;point_hint, isec.start, isec.start );<br>
&nbsp;&nbsp;&nbsp; isec.hint = &amp;point_hint;<br>
<br>
&nbsp;&nbsp;&nbsp; zero_v3(ao);<br>
&nbsp;&nbsp;&nbsp; zero_v3(env);<br>
<br>
&nbsp;&nbsp;&nbsp; /* bias prevents smoothed faces to appear flat */<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;vlr-&gt;flag &amp; R_SMOOTH) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bias= R.wrld.aobias;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nrm= shi-&gt;vn;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bias= 0.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nrm= shi-&gt;facenor;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; /* prevent sky colors to be added for only shadow (shadow becomes alpha) */<br>
&nbsp;&nbsp;&nbsp; envcolor= R.wrld.aocolor;<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;mat-&gt;mode &amp; MA_ONLYSHADOW)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; envcolor= WO_AOPLAIN;<br>
<br>
&nbsp;&nbsp;&nbsp; if(resol&gt;32) resol= 32;<br>
<br>
&nbsp;&nbsp;&nbsp; /* get sphere samples. for faces we get the same samples for sample x/y values,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; for strand render we always require a new sampler because x/y are not set */<br>
&nbsp;&nbsp;&nbsp; vec= sphere_sampler(R.wrld.aomode, resol, shi-&gt;thread, shi-&gt;xs, shi-&gt;ys, shi-&gt;strand != NULL);<br>
<br>
&nbsp;&nbsp;&nbsp; // warning: since we use full sphere now, and dotproduct is below, we do twice as much<br>
&nbsp;&nbsp;&nbsp; tot= 2*resol*resol;<br>
<br>
&nbsp;&nbsp;&nbsp; if(envcolor == WO_AOSKYTEX) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dxyview[0]= 1.0f/(float)resol;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dxyview[1]= 1.0f/(float)resol;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dxyview[2]= 0.0f;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; while(tot--) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ((vec[0]*nrm[0] + vec[1]*nrm[1] + vec[2]*nrm[2]) &gt; bias) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* only ao samples for mask */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(R.r.mode &amp; R_OSA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; j++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(j==R.osa) j= 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(!(shi-&gt;mask &amp; (1&lt;&lt;j))) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec+=3;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; continue;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; actual++;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* always set start/vec/dist */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dir[0] = -vec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dir[1] = -vec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dir[2] = -vec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dist = maxdist;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* do the trace */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(RE_rayobject_raycast(R.raytree, &amp;isec)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; if (R.wrld.aomode &amp; WO_AODIST) sh+=
exp(-isec.dist*R.wrld.aodistfac);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else sh+= 1.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(envcolor!=WO_AOPLAIN) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float skycol[4];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float fac, view[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; view[0]= -vec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; view[1]= -vec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; view[2]= -vec[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(view);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(envcolor==WO_AOSKYCOL) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fac=
0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[0]+= (1.0f-fac)*R.wrld.horr +
fac*R.wrld.zenr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[1]+= (1.0f-fac)*R.wrld.horg +
fac*R.wrld.zeng;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[2]+= (1.0f-fac)*R.wrld.horb +
fac*R.wrld.zenb;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {&nbsp;&nbsp;&nbsp; /* WO_AOSKYTEX */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadeSkyView(skycol, isec.start,
view, dxyview, shi-&gt;thread);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadeSunView(skycol,
shi-&gt;view);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[0]+= skycol[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[1]+= skycol[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; env[2]+= skycol[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; skyadded++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // samples<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec+= 3;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(actual==0) sh= 1.0f;<br>
&nbsp;&nbsp;&nbsp; else sh = 1.0f - sh/((float)actual);<br>
<br>
&nbsp;&nbsp;&nbsp; /* average color times distances/hits formula */<br>
&nbsp;&nbsp;&nbsp; ao[0]= ao[1]= ao[2]= sh;<br>
<br>
&nbsp;&nbsp;&nbsp; if(envcolor!=WO_AOPLAIN &amp;&amp; skyadded)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_v3_fl(env, sh/((float)skyadded));<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; copy_v3_v3(env, ao);<br>
}<br>
<br>
void ray_ao(ShadeInput *shi, float *ao, float *env)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* Unfortunately, the unusual way that the sphere sampler calculates roughly twice as many<br>
&nbsp;&nbsp;&nbsp; &nbsp;* samples as are actually traced, and skips them based on bias and OSA settings makes it very difficult<br>
&nbsp;&nbsp;&nbsp; &nbsp;* to reuse code between these two functions. This is the easiest way I can think of to do it<br>
&nbsp;&nbsp;&nbsp; &nbsp;* --broken */<br>
&nbsp;&nbsp;&nbsp; if (ELEM(R.wrld.ao_samp_method, WO_AOSAMP_HAMMERSLEY, WO_AOSAMP_HALTON))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_ao_qmc(shi, ao, env);<br>
&nbsp;&nbsp;&nbsp; else if (R.wrld.ao_samp_method == WO_AOSAMP_CONSTANT)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_ao_spheresamp(shi, ao, env);<br>
}<br>
<br>
static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_MAX_OSA][3], int *totjitco)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* magic numbers for reordering sample positions to give better<br>
&nbsp;&nbsp;&nbsp; &nbsp;* results with adaptive sample, when it usually only takes 4 samples */<br>
&nbsp;&nbsp;&nbsp; int order8[8] = {0, 1, 5, 6, 2, 3, 4, 7};<br>
&nbsp;&nbsp;&nbsp; int order11[11] = {1, 3, 8, 10, 0, 2, 4, 5, 6, 7, 9};<br>
&nbsp;&nbsp;&nbsp; int order16[16] = {1, 3, 9, 12, 0, 6, 7, 8, 13, 2, 4, 5, 10, 11, 14, 15};<br>
&nbsp;&nbsp;&nbsp; int count = count_mask(shi-&gt;mask);<br>
<br>
&nbsp;&nbsp;&nbsp; /* for better antialising shadow samples are distributed over the subpixel<br>
&nbsp;&nbsp;&nbsp; &nbsp;* sample coordinates, this only works for raytracing depth 0 though */<br>
&nbsp;&nbsp;&nbsp; if(!shi-&gt;strand &amp;&amp; shi-&gt;depth == 0 &amp;&amp; count &gt; 1 &amp;&amp; count &lt;= max) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float xs, ys, zs, view[3];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int samp, ordsamp, tot= 0;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(samp=0; samp&lt;R.osa; samp++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(R.osa == 8) ordsamp = order8[samp];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(R.osa == 11) ordsamp = order11[samp];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(R.osa == 16) ordsamp = order16[samp];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else ordsamp = samp;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi-&gt;mask &amp; (1&lt;&lt;ordsamp)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* zbuffer has this inverse corrected, ensures xs,ys
are inside pixel */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; xs= (float)shi-&gt;scanco[0] + R.jit[ordsamp][0] +
0.5f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; ys= (float)shi-&gt;scanco[1] + R.jit[ordsamp][1] +
0.5f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; zs= shi-&gt;scanco[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; shade_input_calc_viewco(shi, xs, ys, zs, view, NULL,
jitco[tot], NULL, NULL);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tot++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *totjitco= tot;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(jitco[0], shi-&gt;co);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *totjitco= 1;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec)<br>
{<br>
&nbsp;&nbsp;&nbsp; QMCSampler *qsa=NULL;<br>
&nbsp;&nbsp;&nbsp; int samples=0;<br>
&nbsp;&nbsp;&nbsp; float samp3d[3];<br>
<br>
&nbsp;&nbsp;&nbsp; float fac=0.0f, vec[3], end[3];<br>
&nbsp;&nbsp;&nbsp; float colsq[4];<br>
&nbsp;&nbsp;&nbsp; float adapt_thresh = lar-&gt;adapt_thresh;<br>
&nbsp;&nbsp;&nbsp; int min_adapt_samples=4, max_samples = lar-&gt;ray_totsamp;<br>
&nbsp;&nbsp;&nbsp; float *co;<br>
&nbsp;&nbsp;&nbsp; int do_soft=1, full_osa=0, i;<br>
<br>
&nbsp;&nbsp;&nbsp; float min[3], max[3];<br>
&nbsp;&nbsp;&nbsp; RayHint bb_hint;<br>
<br>
&nbsp;&nbsp;&nbsp; float jitco[RE_MAX_OSA][3];<br>
&nbsp;&nbsp;&nbsp; int totjitco;<br>
<br>
&nbsp;&nbsp;&nbsp; colsq[0] = colsq[1] = colsq[2] = 0.0;<br>
&nbsp;&nbsp;&nbsp; if(isec-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f;<br>
&nbsp;&nbsp;&nbsp; } else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3]= 1.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; if (lar-&gt;ray_totsamp &lt; 2) do_soft = 0;<br>
&nbsp;&nbsp;&nbsp; if ((R.r.mode &amp; R_OSA) &amp;&amp; (R.osa &gt; 0)
&amp;&amp; (shi-&gt;vlr-&gt;flag &amp; R_FULL_OSA)) full_osa = 1;<br>
<br>
&nbsp;&nbsp;&nbsp; if (full_osa) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (do_soft) max_samples&nbsp; = max_samples/R.osa + 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else max_samples = 1;<br>
&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (do_soft) max_samples = lar-&gt;ray_totsamp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if (shi-&gt;depth == 0) max_samples = (R.osa &gt; 4)?R.osa:5;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else max_samples = 1;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; ray_shadow_jittered_coords(shi, max_samples, jitco, &amp;totjitco);<br>
<br>
&nbsp;&nbsp;&nbsp; /* sampling init */<br>
&nbsp;&nbsp;&nbsp; if (lar-&gt;ray_samp_method==LA_SAMP_HALTON)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa = get_thread_qmcsampler(&amp;R, shi-&gt;thread, SAMP_TYPE_HALTON, max_samples);<br>
&nbsp;&nbsp;&nbsp; else if (lar-&gt;ray_samp_method==LA_SAMP_HAMMERSLEY)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qsa = get_thread_qmcsampler(&amp;R, shi-&gt;thread, SAMP_TYPE_HAMMERSLEY, max_samples);<br>
<br>
&nbsp;&nbsp;&nbsp; QMC_initPixel(qsa, shi-&gt;thread);<br>
<br>
&nbsp;&nbsp;&nbsp; INIT_MINMAX(min, max);<br>
&nbsp;&nbsp;&nbsp; for(i=0; i&lt;totjitco; i++)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DO_MINMAX(jitco[i], min, max);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; RE_rayobject_hint_bb( R.raytree, &amp;bb_hint, min, max);<br>
<br>
&nbsp;&nbsp;&nbsp; isec-&gt;hint = &amp;bb_hint;<br>
&nbsp;&nbsp;&nbsp; isec-&gt;check = RE_CHECK_VLR_RENDER;<br>
&nbsp;&nbsp;&nbsp; isec-&gt;skip = RE_SKIP_VLR_NEIGHBOUR;<br>
&nbsp;&nbsp;&nbsp; VECCOPY(vec, lampco);<br>
<br>
&nbsp;&nbsp;&nbsp; while (samples &lt; max_samples) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;orig.ob&nbsp;&nbsp; = shi-&gt;obi;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;orig.face = shi-&gt;vlr;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* manually jitter the start shading co-ord per sample<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* based on the pre-generated OSA texture sampling offsets,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* for anti-aliasing sharp shadow edges. */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; co = jitco[samples % totjitco];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (do_soft) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* sphere shadow source */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (lar-&gt;type == LA_LOCAL) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float ru[3], rv[3], v[3], s[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* calc tangent plane vectors */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v[0] = co[0] - lampco[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v[1] = co[1] - lampco[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v[2] = co[2] - lampco[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(v);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ortho_basis_v3v3_v3( ru, rv,v);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* sampling, returns quasi-random vector in
area_size disc */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; QMC_sampleDisc(samp3d, qsa, shi-&gt;thread,
samples,lar-&gt;area_size);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* distribute disc samples across the tangent plane
*/<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s[0] = samp3d[0]*ru[0] + samp3d[1]*rv[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s[1] = samp3d[0]*ru[1] + samp3d[1]*rv[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s[2] = samp3d[0]*ru[2] + samp3d[1]*rv[2];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(samp3d, s);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* sampling, returns quasi-random vector in
[sizex,sizey]^2 plane */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; QMC_sampleRect(samp3d, qsa, shi-&gt;thread, samples,
lar-&gt;area_size, lar-&gt;area_sizey);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* align samples to lamp vector */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_m3_v3(lar-&gt;mat, samp3d);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; end[0] = vec[0]+samp3d[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; end[1] = vec[1]+samp3d[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; end[2] = vec[2]+samp3d[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(end, vec);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(shi-&gt;strand) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* bias away somewhat to avoid self intersection */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float jitbias= 0.5f*(len_v3(shi-&gt;dxco) + len_v3(shi-&gt;dyco));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float v[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECSUB(v, co, end);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; normalize_v3(v);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; co[0] -= jitbias*v[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; co[1] -= jitbias*v[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; co[2] -= jitbias*v[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(isec-&gt;start, co);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dir[0] = end[0]-isec-&gt;start[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dir[1] = end[1]-isec-&gt;start[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dir[2] = end[2]-isec-&gt;start[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dist = normalize_v3(isec-&gt;dir);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* trace the ray */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(isec-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0, col);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[0] += col[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[1] += col[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[2] += col[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3] += col[3];<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* for variance calc */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[0] += col[0]*col[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[1] += col[1]*col[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colsq[2] += col[2]*col[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; samples++;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (lar-&gt;ray_samp_method == LA_SAMP_HALTON) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* adaptive
sampling - consider samples below threshold as in shadow (or vice
versa) and exit early */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if
((max_samples &gt; min_adapt_samples) &amp;&amp; (adapt_thresh &gt;
0.0) &amp;&amp; (samples &gt; max_samples / 3)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (isec-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ((shadfac[3] / samples &gt;
(1.0-adapt_thresh)) || (shadfac[3] / samples &lt; adapt_thresh))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if
(adaptive_sample_variance(samples, shadfac, colsq, adapt_thresh))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ((fac / samples &gt;
(1.0-adapt_thresh)) || (fac / samples &lt; adapt_thresh))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(isec-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[0] /= samples;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[1] /= samples;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[2] /= samples;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3] /= samples;<br>
&nbsp;&nbsp;&nbsp; } else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3]= 1.0f-fac/samples;<br>
<br>
&nbsp;&nbsp;&nbsp; if (qsa)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; release_thread_qmcsampler(&amp;R, shi-&gt;thread, qsa);<br>
}<br>
<br>
static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* area soft shadow */<br>
&nbsp;&nbsp;&nbsp; float *jitlamp;<br>
&nbsp;&nbsp;&nbsp; float fac=0.0f, div=0.0f, vec[3];<br>
&nbsp;&nbsp;&nbsp; int a, j= -1, mask;<br>
&nbsp;&nbsp;&nbsp; RayHint point_hint;<br>
<br>
&nbsp;&nbsp;&nbsp; if(isec-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else shadfac[3]= 1.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; fac= 0.0f;<br>
&nbsp;&nbsp;&nbsp; jitlamp= give_jitter_plane(lar, shi-&gt;thread, shi-&gt;xs, shi-&gt;ys);<br>
<br>
&nbsp;&nbsp;&nbsp; a= lar-&gt;ray_totsamp;<br>
<br>
&nbsp;&nbsp;&nbsp; /* this correction to make sure we always take at least 1 sample */<br>
&nbsp;&nbsp;&nbsp; mask= shi-&gt;mask;<br>
&nbsp;&nbsp;&nbsp; if(a==4) mask |= (mask&gt;&gt;4)|(mask&gt;&gt;8);<br>
&nbsp;&nbsp;&nbsp; else if(a==9) mask |= (mask&gt;&gt;9);<br>
<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec-&gt;start, shi-&gt;co);<br>
&nbsp;&nbsp;&nbsp; isec-&gt;orig.ob&nbsp;&nbsp; = shi-&gt;obi;<br>
&nbsp;&nbsp;&nbsp; isec-&gt;orig.face = shi-&gt;vlr;<br>
&nbsp;&nbsp;&nbsp; RE_rayobject_hint_bb( R.raytree, &amp;point_hint, isec-&gt;start, isec-&gt;start );<br>
&nbsp;&nbsp;&nbsp; isec-&gt;hint = &amp;point_hint;<br>
<br>
&nbsp;&nbsp;&nbsp; while(a--) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(R.r.mode &amp; R_OSA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; j++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(j&gt;=R.osa) j= 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(!(mask &amp; (1&lt;&lt;j))) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jitlamp+= 2;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; continue;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec[0]= jitlamp[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec[1]= jitlamp[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vec[2]= 0.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mul_m3_v3(lar-&gt;mat, vec);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* set start and vec */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dir[0] = vec[0]+lampco[0]-isec-&gt;start[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dir[1] = vec[1]+lampco[1]-isec-&gt;start[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dir[2] = vec[2]+lampco[2]-isec-&gt;start[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;dist = 1.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;check = RE_CHECK_VLR_RENDER;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec-&gt;skip = RE_SKIP_VLR_NEIGHBOUR;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(isec-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* isec.col is
like shadfac, so defines amount of light (0.0 is full shadow) */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0, col);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[0] += col[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[1] += col[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[2] += col[2];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3] += col[3];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; div+= 1.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jitlamp+= 2;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(isec-&gt;mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[0] /= div;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[1] /= div;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[2] /= div;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3] /= div;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // sqrt makes nice umbra effect<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(lar-&gt;ray_samp_type &amp; LA_SAMP_UMBRA)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3]= sqrt(1.0f-fac/div);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3]= 1.0f-fac/div;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
/* extern call from shade_lamp_loop */<br>
void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)<br>
{<br>
&nbsp;&nbsp;&nbsp; Isect isec;<br>
&nbsp;&nbsp;&nbsp; float lampco[3];<br>
<br>
&nbsp;&nbsp;&nbsp; /* setup isec */<br>
&nbsp;&nbsp;&nbsp; RE_RC_INIT(isec, *shi);<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;mat-&gt;mode &amp; MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA;<br>
&nbsp;&nbsp;&nbsp; else isec.mode= RE_RAY_SHADOW;<br>
&nbsp;&nbsp;&nbsp; isec.hint = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; if(lar-&gt;mode &amp; (LA_LAYER|LA_LAYER_SHADOW))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.lay= lar-&gt;lay;<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.lay= -1;<br>
<br>
&nbsp;&nbsp;&nbsp; /* only when not mir tracing, first hit optimm */<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;depth==0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.last_hit = lar-&gt;last_hit[shi-&gt;thread];<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.last_hit = NULL;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(lar-&gt;type==LA_SUN || lar-&gt;type==LA_HEMI) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* jitter and QMC sampling add a displace vector to the lamp position<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* that's incorrect because a SUN lamp does not has an exact position<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* and the displace should be done at the ray vector instead of the<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* lamp position.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* This is easily verified by noticing that shadows of SUN lights change<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* with the scene BB.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;*<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* This was detected during SoC 2009 - Raytrace Optimization, but to keep<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* consistency with older render code it wasn't removed.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;*<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* If the render code goes through some recode/serious bug-fix then this<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;* is something to consider!<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;*/<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lampco[0]= shi-&gt;co[0] - R.maxdist*lar-&gt;vec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lampco[1]= shi-&gt;co[1] - R.maxdist*lar-&gt;vec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lampco[2]= shi-&gt;co[2] - R.maxdist*lar-&gt;vec[2];<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(lampco, lar-&gt;co);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if (ELEM(lar-&gt;ray_samp_method, LA_SAMP_HALTON, LA_SAMP_HAMMERSLEY)) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_shadow_qmc(shi, lar, lampco, shadfac, &amp;isec);<br>
<br>
&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(lar-&gt;ray_totsamp&lt;2) {<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.orig.ob&nbsp;&nbsp; = shi-&gt;obi;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.orig.face = shi-&gt;vlr;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3]= 1.0f; // 1.0=full light<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* set up isec.dir */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(isec.start, shi-&gt;co);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECSUB(isec.dir, lampco, isec.start);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isec.dist = normalize_v3(isec.dir);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(isec.mode==RE_RAY_SHADOW_TRA) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* isec.col is like shadfac, so defines amount of
light (0.0 is full shadow) */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; ray_trace_shadow_tra(&amp;isec, shi,
DEPTH_SHADOW_TRA, 0, col);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QUATCOPY(shadfac, col);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(RE_rayobject_raycast(R.raytree, &amp;isec))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shadfac[3]= 0.0f;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ray_shadow_jitter(shi, lar, lampco, shadfac, &amp;isec);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; /* for first hit optim, set last interesected shadow face */<br>
&nbsp;&nbsp;&nbsp; if(shi-&gt;depth==0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lar-&gt;last_hit[shi-&gt;thread] = isec.last_hit;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
}<br>
<br>
#if 0<br>
/* only when face points away from lamp, in direction of lamp, trace ray and find first exit point */<br>
static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co)<br>
{<br>
&nbsp;&nbsp;&nbsp; Isect isec;<br>
&nbsp;&nbsp;&nbsp; float lampco[3];<br>
<br>
&nbsp;&nbsp;&nbsp; assert(0);<br>
<br>
&nbsp;&nbsp;&nbsp; /* setup isec */<br>
&nbsp;&nbsp;&nbsp; RE_RC_INIT(isec, *shi);<br>
&nbsp;&nbsp;&nbsp; isec.mode= RE_RAY_SHADOW_TRA;<br>
&nbsp;&nbsp;&nbsp; isec.hint = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; if(lar-&gt;mode &amp; LA_LAYER) isec.lay= lar-&gt;lay; else isec.lay= -1;<br>
<br>
&nbsp;&nbsp;&nbsp; if(lar-&gt;type==LA_SUN || lar-&gt;type==LA_HEMI) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lampco[0]= shi-&gt;co[0] - RE_RAYTRACE_MAXDIST*lar-&gt;vec[0];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lampco[1]= shi-&gt;co[1] - RE_RAYTRACE_MAXDIST*lar-&gt;vec[1];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lampco[2]= shi-&gt;co[2] - RE_RAYTRACE_MAXDIST*lar-&gt;vec[2];<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; VECCOPY(lampco, lar-&gt;co);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; isec.orig.ob&nbsp;&nbsp; = shi-&gt;obi;<br>
&nbsp;&nbsp;&nbsp; isec.orig.face = shi-&gt;vlr;<br>
<br>
&nbsp;&nbsp;&nbsp; /* set up isec.dir */<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec.start, shi-&gt;co);<br>
&nbsp;&nbsp;&nbsp; VECCOPY(isec.end, lampco);<br>
<br>
&nbsp;&nbsp;&nbsp; if(RE_rayobject_raycast(R.raytree, &amp;isec)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* we got a face */<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* render co */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; co[0]= isec.start[0]+isec.dist*(isec.dir[0]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; co[1]= isec.start[1]+isec.dist*(isec.dir[1]);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; co[2]= isec.start[2]+isec.dist*(isec.dir[2]);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *distfac= len_v3(isec.dir);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *distfac= 0.0f;<br>
}<br>
<br>
#endif<br>
<br>
<br>
<br>
<br>
</p>
<p>&#12288;</p>


<pre></pre>

<pre></pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; <a href="PocketRuler.htm">                  







                       <img src="picture/back.gif" style="border: medium none ;" alt="back.gif (341 bytes)" height="35" width="32"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<a href="index.htm">
<img src="picture/up.gif" style="border: medium none ;" alt="up.gif (335 bytes)" height="32" width="35"></a>       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                         
<img src="picture/next.gif" style="border: medium none ;" alt="next.gif (337 bytes)" height="35" width="32">          


</p>

</body></html>