Hopefully a working merge with trunk (could be one error left in raytrace.c - will...
authorDaniel Genrich <daniel.genrich@gmx.net>
Mon, 20 Apr 2009 00:19:16 +0000 (00:19 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Mon, 20 Apr 2009 00:19:16 +0000 (00:19 +0000)
Merging 18706 - 19804

58 files changed:
release/beos-4.5-i386/specific.sh [changed mode: 0755->0644]
release/beos-5.0-i386/specific.sh [changed mode: 0755->0644]
release/irix-6.2-mips/specific.sh [changed mode: 0755->0644]
release/scripts/export_m3g.py
release/scripts/image_auto_layout.py
release/scripts/image_edit.py
release/scripts/import_dxf.py
release/scripts/import_lightwave_motion.py
release/scripts/scripttemplate_gamelogic.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_texture.h
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/BLI_kdopbvh.h
source/blender/blenlib/intern/BLI_kdopbvh.c
source/blender/blenlib/intern/arithb.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_texture_types.h
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/pointdensity.h [new file with mode: 0644]
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/rendercore.h
source/blender/render/intern/include/shading.h
source/blender/render/intern/include/texture.h
source/blender/render/intern/include/volume_precache.h [new file with mode: 0644]
source/blender/render/intern/include/volumetric.h [new file with mode: 0644]
source/blender/render/intern/include/voxeldata.h [new file with mode: 0644]
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/occlusion.c
source/blender/render/intern/source/pointdensity.c [new file with mode: 0644]
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/raytrace.c
source/blender/render/intern/source/renderdatabase.c
source/blender/render/intern/source/shadeinput.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/texture.c
source/blender/render/intern/source/volume_precache.c [new file with mode: 0644]
source/blender/render/intern/source/volumetric.c [new file with mode: 0644]
source/blender/render/intern/source/voxeldata.c [new file with mode: 0644]
source/blender/src/butspace.c
source/blender/src/buttons_object.c
source/blender/src/buttons_shading.c
source/blender/src/drawnode.c
source/blender/src/previewrender.c
source/gameengine/Ketsji/KX_Dome.cpp
source/gameengine/Ketsji/KX_Dome.h
source/gameengine/Ketsji/KX_PythonInitTypes.cpp
source/gameengine/Ketsji/KX_PythonInitTypes.h
source/gameengine/Physics/common/PHY_IController.cpp
source/gameengine/Physics/common/PHY_IController.h
source/gameengine/Physics/common/PHY_IGraphicController.cpp
source/gameengine/Physics/common/PHY_IGraphicController.h

old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index c74e7acbcd37fff72e9e7b6abf6b4b88ddb89e65..86ac03cc407a97134c3a32d41122f097cd7d5bdd 100644 (file)
@@ -11,7 +11,7 @@ Tooltip: 'Export to M3G'
 #
 # Source: http://www.nelson-games.de/bl2m3g/source
 #
-# $Id$
+# $Id: m3g_export.py,v 0.1 2005/04/19 12:25 gerhardv Exp gerhardv $
 #
 # Author: Gerhard Völkl
 #
index d19ba1da6629737db1056f7786e5fd37bbd6766e..b45963bed334496e423d2d107ea857d8df0fd4e5 100644 (file)
@@ -265,8 +265,8 @@ def consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PR
        render_context.setRenderWinSize(100)
        render_context.setImageType(Render.PNG)
        render_context.enableExtensions(True) 
-       render_context.enablePremultiply() # No alpha needed.
-       render_context.enableRGBAColor()
+       render_context.enableSky() # No alpha needed.
+       render_context.enableRGBColor()
        render_context.threads = 2
        
        #Render.EnableDispView() # Broken??
index cae40b7409737ec04e2f03a79400b1c09daad3b3..a7132a4f986fe1b00905071a911c2ac512396755 100644 (file)
@@ -1,6 +1,6 @@
 #!BPY
 """
-Name: 'Edit Externally'
+Name: 'Edit Externaly'
 Blender: 242a
 Group: 'Image'
 Tooltip: 'Open in an application for editing. (hold Shift to configure)'
@@ -9,23 +9,22 @@ Tooltip: 'Open in an application for editing. (hold Shift to configure)'
 __author__ = "Campbell Barton"
 __url__ = ["blender", "blenderartists.org"]
 __version__ = "1.0"
+
 __bpydoc__ = """\
 This script opens the current image in an external application for editing.
 
-Usage:
+Useage:
 Choose an image for editing in the UV/Image view.
 
-To configure the application to open the image with, hold Shift as you
-click on this menu item.
+To configure the application to open the image with, hold Shift as you click on
+this menu item.
 
-For first time users try running the default application for your
-operating system.  If the application does not open you can type in
-the full path.  You can choose that the last entered application will
-be saved as a default.
+For first time users try running the default application for your operating system.
+If the application does not open you can type in the full path.
+You can choose that the last entered application will be saved as a default.
 
-* Note, default commants for opening an image are "start" for win32
-and "open" for macos.  This will use the system default associated
-application.
+* Note, default commants for opening an image are "start" for win32 and "open" for macos.
+This will use the system default assosiated application.
 """
 
 # ***** BEGIN GPL LICENSE BLOCK *****
@@ -49,36 +48,17 @@ application.
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender
-from Blender import Image, sys, Draw, Registry
 
 try:
-       import subprocess
+       import os
        import sys as py_sys
        platform = py_sys.platform
 except:
-       Draw.PupMenu('Error: Recent version of Python not installed.')
-       subprocess=None
+       Draw.PupMenu('Error, python not installed')
+       os=None
 
-def os_run(appstring, filename):
-       '''
-       Run the app, take into account different python versions etc
-       looks like python 2.6 wants a list for 
-       '''
-       
-       # evil trick, temp replace spaces so we can allow spaces in filenames
-       # also allows multiple instances of %f
-       appstring = appstring.replace(' ', '\t')
-       appstring = appstring.replace('%f', filename)
-       appstring = appstring.split('\t')
-       
-       print ' '.join(appstring)
-       
-       try: # only python 2.6 wants a list?
-               p = subprocess.Popen(appstring)
-       except:
-               p = subprocess.Popen(' '.join(appstring))
-       
+import Blender
+from Blender import Image, sys, Draw, Registry
 
 def edit_extern(image=None):
        
@@ -86,7 +66,7 @@ def edit_extern(image=None):
                image = Image.GetCurrent()
        
        if not image: # Image is None
-               Draw.PupMenu('ERROR: Please select active Image.')
+               Draw.PupMenu('ERROR: You must select an active Image.')
                return
        if image.packed:
                Draw.PupMenu('ERROR: Image is packed, unpack before editing.')
@@ -114,19 +94,16 @@ def edit_extern(image=None):
        if new_text:
                pupblock.append('first time, set path.')
                if platform == 'win32':
-                       # Example of path to popular image editor... ;-)
-                       # appstring = '"C:\\Program Files\\Adobe\\Photoshop CS\\photoshop.exe" "%f"'
-                       # Have to add "cmd /c" to make sure we're using Windows shell.
-                       appstring = 'cmd /c start "" /B "%f"'
+                       appstring = 'start "" /B "%f"'
                elif platform == 'darwin':
                        appstring = 'open "%f"'
                else:
-                       appstring = 'gimp %f'
+                       appstring = 'gimp-remote "%f"'
        
        appstring_but = Draw.Create(appstring)
        save_default_but = Draw.Create(0)
        
-       pupblock.append(('editor: ', appstring_but, 0, 99, 'Path to application, %f will be replaced with the image path.'))
+       pupblock.append(('editor: ', appstring_but, 0, 48, 'Path to application, %f will be replaced with the image path.'))
        pupblock.append(('Set Default', save_default_but, 'Store this path in the blender registry.'))
        
        # Only configure if Shift is held,
@@ -141,18 +118,19 @@ def edit_extern(image=None):
                Registry.SetKey('ExternalImageEditor', {'path':appstring}, True)
        
        if appstring.find('%f') == -1:
-               Draw.PupMenu('ERROR: No filename specified! ("%f")')
+               Draw.PupMenu('ERROR: The comment you entered did not contain the filename ("%f")')
                return
        
        # -------------------------------
        
-       os_run(appstring, imageFileName)
-
+       appstring = appstring.replace('%f', imageFileName)
+       print '\tediting image with command "%s"' % appstring
+       os.system(appstring)
 
 
 def main():
        edit_extern()
        
 
-if __name__ == '__main__' and subprocess:
-       main()
+if __name__ == '__main__' and os != None:
+       main()
\ No newline at end of file
index ceb4dd567220f89836f8f84edc61308dc7e6ae45..4de1de1ee39c525397545ba1d4959820e28c31ff 100644 (file)
@@ -311,7 +311,7 @@ import Blender
 from Blender import Mathutils, BezTriple, Draw, Registry, sys,\
 Text3d, Window, Mesh, Material, Group
 #from Blender.Mathutils import Vector, Matrix
-#import bpy #not used yet
+import bpy
 #import BPyMessages
 
 from dxfReader import readDXF
@@ -366,7 +366,7 @@ THIN_RESOLUTION = 8   #(4-64) thin_cylinder arc_resolution - number of segments
 MIN_THICK = MIN_DIST * 10.0  #minimal thickness by forced thickness
 MIN_WIDTH = MIN_DIST * 10.0  #minimal width by forced width
 TRIM_LIMIT = 3.0        #limit for triming of polylines-wide-segments (values:0.0 - 5.0)
-ELEVATION = 0.0 #standard elevation = coordinate Z value
+ELEVATION = 0.0 #standard elevation = coordinate Z
 
 BYBLOCK = 0
 BYLAYER = 256
@@ -860,7 +860,6 @@ class Line:  #-----------------------------------------------------------------
                        curve.append(BezTriple.New(points[1]))
                        for point in curve:
                                point.handleTypes = [VECT, VECT]
-                               point.radius = 1.0
                        curve.flagU = 0 # 0 sets the curve not cyclic=open
                        c.setResolu(settings.var['curve_res'])
                        c.update() #important for handles calculation
@@ -1325,11 +1324,9 @@ class Polyline:  #--------------------------------------------------------------
                                nurbs_points.append(pkt)
                        firstpoint = nurbs_points[0]
                        curve = pline.appendNurb(firstpoint)
-                       curve.setType(4) # set curve_type NURBS
-                       print 'deb: dir(curve):', dir(curve[-1]) #----------------
+                       curve.setType(4) # set curvetype NURBS
                        for point in nurbs_points[1:]:
                                curve.append(point)
-                               #TODO: what is the trick for bevel radius? curve[-1].radius = 1.0
                        if self.closed:
                                curve.flagU = 1+0 # Set curve cyclic=close and uni
                        else:
@@ -1352,7 +1349,6 @@ class Polyline:  #--------------------------------------------------------------
                                curve.append(BezTriple.New(p))
                        for point in curve:
                                point.handleTypes = [AUTO, AUTO]
-                               point.radius = 1.0
                        #curve.setType(1) #Bezier curve
                        if self.closed:
                                curve.flagU = 5 #1 # Set curve cyclic=close
@@ -1365,7 +1361,6 @@ class Polyline:  #--------------------------------------------------------------
                                        p0h1 = [p0h1[i]+begtangent[i] for i in range(3)]
                                        curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2))
                                curve[0].handleTypes = [FREE, ALIGN]   #remi--todo-----
-                               curve[0].radius = 1.0
                                if endtangent:
                                        #print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #-----
                                        #print 'deb:polyline2dCurve.draw endtangent:', endtangent #-----
@@ -1375,7 +1370,6 @@ class Polyline:  #--------------------------------------------------------------
                                        curve.__setitem__(-1,BezTriple.New(p0h1+p0+p0h2))
                                        #print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #-----
                                curve[-1].handleTypes = [ALIGN, FREE]   #remi--todo-----
-                               curve[-1].radius = 1.0
 
 
 
@@ -1412,7 +1406,6 @@ class Polyline:  #--------------------------------------------------------------
                                        for p in VectorTriples[1:-1]:
                                                curve.append(BezTriple.New(p))
                                                curve[-1].handleTypes = [FREE, FREE]
-                                               curve[-1].radius = 1.0
 
                                        prevHandleVect = VectorTriples[-1][:3]
                                        prevHandleType = FREE
@@ -1448,12 +1441,10 @@ class Polyline:  #--------------------------------------------------------------
                                        curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2))
 
                                        curve[0].handleTypes = [FREE,prevHandleType2]
-                                       curve[0].radius = 1.0
                                        #print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #----------
                                        #print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #----------
                                else: 
                                        curve[0].handleTypes[0] = VECT
-                                       curve[0].radius = 1.0
                        else: 
                                curve.flagU = 0 # Set curve not cyclic=open
 
@@ -2095,10 +2086,9 @@ DXF: X value; APP: 3D point, Y and Z values of control points (in WCS) (one entr
                self.ctrlpk_len = getit(obj, 73, 0) # Number of control points
                self.fit_pk_len = getit(obj, 74, 0) # Number of fit points (if any)
 
-               #TODO: import SPLINE as Bezier curve directly, possible?
                #print 'deb:Spline self.fit_pk_len=', self.fit_pk_len #------------------------
                #self.fit_pk_len = 0 # temp for debug
-               if self.fit_pk_len and settings.var['splines_as']==5:
+               if self.fit_pk_len and 'spline_as'==5:
                        self.spline = False
                        self.curved = True
                else:
@@ -2776,7 +2766,6 @@ class Arc:  #-----------------------------------------------------------------
                                curve.append(BezTriple.New(p))
                        for point in curve:
                                point.handleTypes = [FREE, FREE]
-                               point.radius = 1.0
                        curve.flagU = 0 # 0 sets the curve not cyclic=open
                        arc.setResolu(settings.var['curve_res'])
 
@@ -3308,7 +3297,6 @@ class Ellipse:  #---------------------------------------------------------------
                                        curve.append(BezTriple.New(p))
                                for point in curve:
                                        point.handleTypes = [FREE, FREE]
-                                       point.radius = 1.0
                                curve.flagU = 1 # 0 sets the curve not cyclic=open
                                if settings.var['fill_on']:
                                        arc.setFlag(6) # 2+4 set top and button caps
@@ -3319,7 +3307,6 @@ class Ellipse:  #---------------------------------------------------------------
                                        curve.append(BezTriple.New(p))
                                for point in curve:
                                        point.handleTypes = [FREE, FREE]
-                                       point.radius = 1.0
                                curve.flagU = 0 # 0 sets the curve not cyclic=open
 
                        arc.setResolu(settings.var['curve_res'])
@@ -4255,7 +4242,8 @@ def       analyzeDXF(dxfFile): #---------------------------------------
                Draw.PupMenu('DXF importer: report saved in INF-file:%t|' + '\'%s\'' %infFile)
        except:
                Draw.PupMenu('DXF importer: ERROR by writing report in INF-file:%t|' + '\'%s\'' %infFile)
-       #finally: f.close()
+       finally:
+               f.close()
 
 
 
@@ -4274,8 +4262,7 @@ def main(dxfFile):  #---------------#############################-----------
        global cur_COUNTER  #counter for progress_bar
        cur_COUNTER = 0
 
-       #try:
-       if 1:
+       try:
                #print "Getting settings..."
                global GUI_A, GUI_B, g_scale_as
                if not GUI_A['g_scale_on'].val:
@@ -4393,7 +4380,7 @@ def main(dxfFile):  #---------------#############################-----------
                #settings.write(message)
                if UI_MODE: Draw.PupMenu('DXF importer: Done!|finished in %.4f sec.' % time_text)
 
-       #finally:
+       finally:
                # restore state even if things didn't work
                #print 'deb:drawEntities finally!' #-----------------------
                Window.WaitCursor(False)
@@ -5085,7 +5072,6 @@ def drawCurveCircle(circle):  #--- no more used --------------------------------
        curve.append(p4)
        for point in curve:
                point.handleTypes = [AUTO, AUTO]
-               point.radius = 1.0
        curve.flagU = 1 # Set curve cyclic
        c.update()
 
@@ -5127,7 +5113,6 @@ def drawCurveArc(self):  #---- only for ELLIPSE --------------------------------
        curve.append(p4)
        for point in curve:
                point.handleTypes = [AUTO, AUTO]
-               point.radius = 1.0
        curve.flagU = 1 # Set curve cyclic
        a.update()
 
@@ -5167,12 +5152,12 @@ GUI_B = {}  # GUI-buttons dictionary for drawingTypes
 # settings default, initialize ------------------------
 
 points_as_menu  = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4|*curve.vertex %x5"
-lines_as_menu   = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|thin box %x4|Bezier-curve %x5|*NURBS-curve %x6"
+lines_as_menu   = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
 mlines_as_menu  = "convert to: %t|*edge %x1|*mesh %x2|*thin cylinder %x3|*thin box %x|*curve %x5"
 plines_as_menu  = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
-splines_as_menu = "convert to: %t|mesh %x2|*thin cylinder %x3|*thin box %x4|*Bezier-curve %x5|NURBS-curve %x6"
+splines_as_menu = "convert to: %t|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
 plines3_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
-plmesh_as_menu  = "convert to: %t|*edge %x1|mesh %x2|*NURBS-surface %x6"
+plmesh_as_menu  = "convert to: %t|*edge %x1|mesh %x2|NURBS-surface %x6"
 solids_as_menu  = "convert to: %t|*edge %x1|mesh %x2"
 blocks_as_menu  = "convert to: %t|dupliGroup %x1|*real.Group %x2|*exploded %x3"
 texts_as_menu   = "convert to: %t|text %x1|*mesh %x2|*curve %x5"
@@ -5353,9 +5338,11 @@ def saveConfig():  #--todo-----------------------------------------------
                else:
                        #if BPyMessages.Warning_SaveOver(iniFile): #<- remi find it too abstarct
                        if sys.exists(iniFile):
-                               f = file(iniFile, 'r')
-                               header_str = f.readline()
-                               f.close()
+                               try:
+                                       f = file(iniFile, 'r')
+                                       try: header_str = f.readline()
+                                       finally: f.close()
+                               except: pass
                                if header_str.startswith(INIFILE_HEADER[0:13]):
                                        if Draw.PupMenu('  OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile) == 1:
                                                save_ok = True
@@ -5375,9 +5362,10 @@ def saveConfig():  #--todo-----------------------------------------------
                                output_str = '{\n'.join(output_str.split('{'))
                                try:
                                        f = file(iniFile, 'w')
-                                       f.write(INIFILE_HEADER + '\n# this is a comment line\n')
-                                       f.write(output_str)
-                                       f.close()
+                                       try:
+                                               f.write(INIFILE_HEADER + '\n# this is a comment line\n')
+                                               f.write(output_str)
+                                       finally: f.close()
                                        #Draw.PupMenu('DXF importer: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile)
                                except:
                                        Draw.PupMenu('DXF importer: INI-file: Error!%t|failure by writing to ' + '\'%s\'|no config-data saved!' %iniFile)
@@ -5402,22 +5390,25 @@ def loadConfig():  #remi--todo-----------------------------------------------
        update_RegistryKey('iniFileName', iniFile)
        #print 'deb:loadConfig iniFile: ', iniFile #----------------------
        if iniFile.lower().endswith(INIFILE_EXTENSION) and sys.exists(iniFile):
-               f = file(iniFile, 'r')
-               header_str = f.readline()
-               if header_str.startswith(INIFILE_HEADER):
-                       data_str = f.read()
-                       f.close()
-                       #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-----------------
-                       data = eval(data_str)
-                       for k, v in data[0].iteritems():
-                               try: GUI_A[k].val = v
-                               except: GUI_A[k] = Draw.Create(v)
-                       for k, v in data[1].iteritems():
-                               try: GUI_B[k].val = v
-                               except: GUI_B[k] = Draw.Create(v)
-               else:
-                       f.close()
-                       Draw.PupMenu('DXF importer: INI-file:  Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile)
+               try:
+                       f = file(iniFile, 'r')
+                       try:
+                               header_str = f.readline()
+                               if header_str.startswith(INIFILE_HEADER):
+                                       data_str = f.read()
+                                       f.close()
+                                       #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-----------------
+                                       data = eval(data_str)
+                                       for k, v in data[0].iteritems():
+                                               try: GUI_A[k].val = v
+                                               except: GUI_A[k] = Draw.Create(v)
+                                       for k, v in data[1].iteritems():
+                                               try: GUI_B[k].val = v
+                                               except: GUI_B[k] = Draw.Create(v)
+                               else:
+                                       Draw.PupMenu('DXF importer: INI-file:  Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile)
+                       finally: f.close()
+               except: pass
        else:
                Draw.PupMenu('DXF importer: INI-file:  Alert!%t|no valid INI-file selected!')
                print "DXF importer: Alert!: no valid INI-file selected."
index 20c87dfd5c633761db1b14fa5e8234d077f6bf16..c242a9f6bd3ee9507de7848c48ee0d06e056fcc2 100644 (file)
@@ -22,7 +22,7 @@ Be sure to set the framerate correctly
 
 """
 
-# $Id$
+# $Id: export_lightwave_motion.py 9924 2007-01-27 02:15:14Z campbellbarton $
 # --------------------------------------------------------------------------
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
index 01348e86d0a04fe2830db82aee26840e562fb02d..a4c82f98328cc19dc16e940615dfa01d53350944 100644 (file)
@@ -86,8 +86,7 @@ def main():
                        own.life += ob.life
                        ob.life = 0
        print own.life
-       """
-
+       """\r
 main()
 '''
 
index d49a5425b61f0049a05498fbce19721870ef0a60..bb7925281e7eda77532882728c2ff4de859eb2e7 100644 (file)
@@ -1,3 +1,4 @@
+
 /**
  * blenlib/BKE_blender.h (mar-2001 nzc)
  *     
index cfcae3c44bc5a17a8932737c9a28cd5bbb4e63db..985094a7e622a458d4514e03a93b0cfda3a874e7 100644 (file)
@@ -39,6 +39,8 @@ struct ColorBand;
 struct HaloRen;
 struct TexMapping;
 struct EnvMap;
+struct PointDensity;
+struct VoxelData;
 
 /*  in ColorBand struct */
 #define MAXCOLORBAND 32
@@ -74,6 +76,16 @@ void    BKE_free_envmap(struct EnvMap *env);
 struct EnvMap *BKE_add_envmap(void);
 struct EnvMap *BKE_copy_envmap(struct EnvMap *env);
 
+void    BKE_free_pointdensitydata(struct PointDensity *pd);
+void    BKE_free_pointdensity(struct PointDensity *pd);
+struct PointDensity *BKE_add_pointdensity(void);
+struct PointDensity *BKE_copy_pointdensity(struct PointDensity *pd);
+
+void BKE_free_voxeldatadata(struct VoxelData *vd);
+void BKE_free_voxeldata(struct VoxelData *vd);
+struct VoxelData *BKE_add_voxeldata(void);
+struct VoxelData *BKE_copy_voxeldata(struct VoxelData *vd);
+
 int     BKE_texture_dependsOnTime(const struct Tex *texture);
 
 #endif
index cca5d68167e74084b2fe0aed94a02a938cb2a822..0614e4a387f1cbdc102d04d571579db0e6c09ea9 100644 (file)
@@ -419,6 +419,28 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
                        VecAddf(field,field,mag_vec);
 
                        break;
+               case PFIELD_SPIN:
+               {
+                       float inward[3];
+
+                       Projf(temp, velocity, eff_vel);
+                       Crossf(mag_vec,eff_vel,vec_to_part);
+                       Crossf(inward, mag_vec, eff_vel);
+
+                       Normalize(mag_vec);
+                       Normalize(inward);
+
+                       VecSubf(mag_vec, mag_vec, inward);
+                       VecMulf(mag_vec,force_val*distance*falloff);
+
+                       VecAddf(mag_vec, mag_vec, temp);
+                       
+                       //VecCopyf(velocity, mag_vec);
+                       VecSubf(mag_vec, mag_vec, velocity);
+                       VecAddf(field, field, mag_vec);
+                       
+                       break;
+               }
                case PFIELD_MAGNET:
                        if(planar)
                                VecCopyf(temp,eff_vel);
index 753058b1fdda661d2048eb7515ceb7d4fe24c566..a5832711a81c2383d1bf1a5c4b51072eed54d138 100644 (file)
@@ -170,7 +170,15 @@ void init_material(Material *ma)
        ma->sss_texfac= 0.0f;
        ma->sss_front= 1.0f;
        ma->sss_back= 1.0f;
-
+       
+       ma->vol_density_scale = 1.0f;
+       ma->vol_stepsize = 0.2f;
+       ma->vol_shade_stepsize = 0.2f;
+       ma->vol_absorption = 1.0f;
+       ma->vol_scattering = 1.0f;
+       ma->vol_absorption_col[0] = ma->vol_absorption_col[1] = ma->vol_absorption_col[2] = 0.0f;
+       ma->vol_precache_resolution = 50;
+       
        ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR;
 
        ma->preview = NULL;
index 52b88de06e0a1d3538d1cdb5fc3b1805838104ac..c9cae91da6fd7326ac93364f641803492c2b16cc 100644 (file)
@@ -43,6 +43,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 #include "BLI_rand.h"
+#include "BLI_kdopbvh.h"
 
 #include "DNA_texture_types.h"
 #include "DNA_key_types.h"
@@ -418,6 +419,8 @@ void free_texture(Tex *tex)
        free_plugin_tex(tex->plugin);
        if(tex->coba) MEM_freeN(tex->coba);
        if(tex->env) BKE_free_envmap(tex->env);
+       if(tex->pd) BKE_free_pointdensity(tex->pd);
+       if(tex->vd) BKE_free_voxeldata(tex->vd);
        BKE_previewimg_free(&tex->preview);
        BKE_icon_delete((struct ID*)tex);
        tex->id.icon_id = 0;
@@ -484,6 +487,16 @@ void default_tex(Tex *tex)
                tex->env->depth=0;
        }
 
+       if (tex->pd) {
+               tex->pd->radius = 0.3f;
+               tex->pd->falloff_type = TEX_PD_FALLOFF_STD;
+       }
+       
+       if (tex->vd) {
+               tex->vd->resolX=50;
+               tex->vd->interp_type=0;
+       }
+
        pit = tex->plugin;
        if (pit) {
                varstr= pit->varstr;
@@ -580,6 +593,8 @@ Tex *copy_texture(Tex *tex)
        
        if(texn->coba) texn->coba= MEM_dupallocN(texn->coba);
        if(texn->env) texn->env= BKE_copy_envmap(texn->env);
+       if(texn->pd) texn->pd= BKE_copy_pointdensity(texn->pd);
+       if(texn->vd) texn->vd=BKE_copy_voxeldata(texn->vd);
        
        if(tex->preview) texn->preview = BKE_previewimg_copy(tex->preview);
 
@@ -881,6 +896,104 @@ void BKE_free_envmap(EnvMap *env)
        
 }
 
+/* ------------------------------------------------------------------------- */
+
+PointDensity *BKE_add_pointdensity(void)
+{
+       PointDensity *pd;
+       
+       pd= MEM_callocN(sizeof(PointDensity), "pointdensity");
+       pd->flag = 0;
+       pd->radius = 0.3f;
+       pd->falloff_type = TEX_PD_FALLOFF_STD;
+       pd->falloff_softness = 2.0;
+       pd->source = TEX_PD_PSYS;
+       pd->point_tree = NULL;
+       pd->point_data = NULL;
+       pd->noise_size = 0.5f;
+       pd->noise_depth = 1;
+       pd->noise_fac = 1.0f;
+       pd->noise_influence = TEX_PD_NOISE_STATIC;
+       pd->coba = add_colorband(1);
+       pd->speed_scale = 1.0f;
+       pd->totpoints = 0;
+       pd->coba = add_colorband(1);
+       return pd;
+} 
+
+PointDensity *BKE_copy_pointdensity(PointDensity *pd)
+{
+       PointDensity *pdn;
+
+       pdn= MEM_dupallocN(pd);
+       pdn->point_tree = NULL;
+       pdn->point_data = NULL;
+       if(pdn->coba) pdn->coba= MEM_dupallocN(pdn->coba);
+       
+       return pdn;
+}
+
+void BKE_free_pointdensitydata(PointDensity *pd)
+{
+       if (pd->point_tree) {
+               BLI_bvhtree_free(pd->point_tree);
+               pd->point_tree = NULL;
+       }
+       if (pd->point_data) {
+               MEM_freeN(pd->point_data);
+               pd->point_data = NULL;
+       }
+       if(pd->coba) MEM_freeN(pd->coba);
+}
+
+void BKE_free_pointdensity(PointDensity *pd)
+{
+       BKE_free_pointdensitydata(pd);
+       MEM_freeN(pd);
+}
+
+
+void BKE_free_voxeldatadata(struct VoxelData *vd)
+{
+       if (vd->dataset) {
+               MEM_freeN(vd->dataset);
+               vd->dataset = NULL;
+       }
+
+}
+void BKE_free_voxeldata(struct VoxelData *vd)
+{
+       BKE_free_voxeldatadata(vd);
+       MEM_freeN(vd);
+}
+struct VoxelData *BKE_add_voxeldata(void)
+{
+       VoxelData *vd;
+
+       vd= MEM_callocN(sizeof(struct VoxelData), "voxeldata");
+       vd->dataset = NULL;
+       vd->resolX = 1;
+       vd->resolY = 1;
+       vd->resolZ = 1;
+       vd->interp_type= TEX_VD_NEARESTNEIGHBOR;
+       vd->int_multiplier = 1.0;
+       
+       return vd;
+ }
+struct VoxelData *BKE_copy_voxeldata(struct VoxelData *vd)
+{
+       VoxelData *vdn;
+
+       vdn= MEM_dupallocN(vd); 
+       vdn->dataset = NULL;
+
+       return vdn;
+}
+
+
 /* ------------------------------------------------------------------------- */
 int BKE_texture_dependsOnTime(const struct Tex *texture)
 {
index 092ed00fbe5d6739082f7e153b5047baa068be03..796213ef793decdcdd6fe3a96cbc5c7f8de8fd36 100644 (file)
@@ -253,6 +253,7 @@ void printvec4f(char *str, float v[4]);
 
 void VecAddf(float *v, float *v1, float *v2);
 void VecSubf(float *v, float *v1, float *v2);
+void VecMulVecf(float *v, float *v1, float *v2);
 void VecLerpf(float *target, float *a, float *b, float t);
 void VecMidf(float *v, float *v1, float *v2);
 
index e3591a84e98c5fbef717da7793825b63a03e5998..dabf12d48d383edfdf5f720dc2d60b360137f28b 100644 (file)
@@ -71,6 +71,9 @@ typedef void (*BVHTree_NearestPointCallback) (void *userdata, int index, const f
 /* callback must update hit in case it finds a nearest successful hit */
 typedef void (*BVHTree_RayCastCallback) (void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit);
 
+/* callback to range search query */
+typedef void (*BVHTree_RangeQuery) (void *userdata, int index, float squared_dist);
+
 
 BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis);
 void BLI_bvhtree_free(BVHTree *tree);
@@ -93,5 +96,9 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea
 
 int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata);
 
+/* range query */
+int BLI_bvhtree_range_query(BVHTree *tree, const float *co, float radius, BVHTree_RangeQuery callback, void *userdata);
+
+
 #endif // BLI_KDOPBVH_H
 
index 30472beb3e638ff04eb6222f865ca7eeda9a0d31..df37ff457f6149496538ac681a4095557f2ebd10 100644 (file)
@@ -1171,7 +1171,7 @@ static float squared_dist(const float *a, const float *b)
 }
 
 //Determines the nearest point of the given node BV. Returns the squared distance to that point.
-static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *nearest)
+static float calc_nearest_point(const float *proj, BVHNode *node, float *nearest)
 {
        int i;
        const float *bv = node->bv;
@@ -1179,12 +1179,12 @@ static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *near
        //nearest on AABB hull
        for(i=0; i != 3; i++, bv += 2)
        {
-               if(bv[0] > data->proj[i])
+               if(bv[0] > proj[i])
                        nearest[i] = bv[0];
-               else if(bv[1] < data->proj[i])
+               else if(bv[1] < proj[i])
                        nearest[i] = bv[1];
                else
-                       nearest[i] = data->proj[i];
+                       nearest[i] = proj[i];
        }
 
 /*
@@ -1206,7 +1206,7 @@ static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *near
                }
        }
 */
-       return squared_dist(data->co, nearest);
+       return squared_dist(proj, nearest);
 }
 
 
@@ -1229,7 +1229,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
                else
                {
                        data->nearest.index     = node->index;
-                       data->nearest.dist      = calc_nearest_point(data, node, data->nearest.co);
+                       data->nearest.dist      = calc_nearest_point(data->proj, node, data->nearest.co);
                }
        }
        else
@@ -1243,7 +1243,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
 
                        for(i=0; i != node->totnode; i++)
                        {
-                               if( calc_nearest_point(data, node->children[i], nearest) >= data->nearest.dist) continue;
+                               if( calc_nearest_point(data->proj, node->children[i], nearest) >= data->nearest.dist) continue;
                                dfs_find_nearest_dfs(data, node->children[i]);
                        }
                }
@@ -1251,7 +1251,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
                {
                        for(i=node->totnode-1; i >= 0 ; i--)
                        {
-                               if( calc_nearest_point(data, node->children[i], nearest) >= data->nearest.dist) continue;
+                               if( calc_nearest_point(data->proj, node->children[i], nearest) >= data->nearest.dist) continue;
                                dfs_find_nearest_dfs(data, node->children[i]);
                        }
                }
@@ -1261,7 +1261,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
 static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
 {
        float nearest[3], sdist;
-       sdist = calc_nearest_point(data, node, nearest);
+       sdist = calc_nearest_point(data->proj, node, nearest);
        if(sdist >= data->nearest.dist) return;
        dfs_find_nearest_dfs(data, node);
 }
@@ -1298,7 +1298,7 @@ static void bfs_find_nearest(BVHNearestData *data, BVHNode *node)
        }
 
        current.node = node;
-       current.dist = calc_nearest_point(data, node, nearest);
+       current.dist = calc_nearest_point(data->proj, node, nearest);
 
        while(current.dist < data->nearest.dist)
        {
@@ -1326,7 +1326,7 @@ static void bfs_find_nearest(BVHNearestData *data, BVHNode *node)
                                }
 
                                heap[heap_size].node = current.node->children[i];
-                               heap[heap_size].dist = calc_nearest_point(data, current.node->children[i], nearest);
+                               heap[heap_size].dist = calc_nearest_point(data->proj, current.node->children[i], nearest);
 
                                if(heap[heap_size].dist >= data->nearest.dist) continue;
                                heap_size++;
@@ -1524,3 +1524,90 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float
        return data.hit.index;
 }
 
+/*
+ * Range Query - as request by broken :P
+ *
+ * Allocs and fills an array with the indexs of node that are on the given spherical range (center, radius) 
+ * Returns the size of the array.
+ */
+typedef struct RangeQueryData
+{
+       BVHTree *tree;
+       const float *center;
+       float radius;                   //squared radius
+
+       int hits;
+
+       BVHTree_RangeQuery callback;
+       void *userdata;
+
+
+} RangeQueryData;
+
+
+static void dfs_range_query(RangeQueryData *data, BVHNode *node)
+{
+       if(node->totnode == 0)
+       {
+
+               //Calculate the node min-coords (if the node was a point then this is the point coordinates)
+               float co[3];
+               co[0] = node->bv[0];
+               co[1] = node->bv[2];
+               co[2] = node->bv[4];
+
+       }
+       else
+       {
+               int i;
+               for(i=0; i != node->totnode; i++)
+               {
+                       float nearest[3];
+                       float dist = calc_nearest_point(data->center, node->children[i], nearest);
+                       if(dist < data->radius)
+                       {
+                               //Its a leaf.. call the callback
+                               if(node->children[i]->totnode == 0)
+                               {
+                                       data->hits++;
+                                       data->callback( data->userdata, node->children[i]->index, dist );
+                               }
+                               else
+                                       dfs_range_query( data, node->children[i] );
+                       }
+               }
+       }
+}
+
+int BLI_bvhtree_range_query(BVHTree *tree, const float *co, float radius, BVHTree_RangeQuery callback, void *userdata)
+{
+       BVHNode * root = tree->nodes[tree->totleaf];
+
+       RangeQueryData data;
+       data.tree = tree;
+       data.center = co;
+       data.radius = radius*radius;
+       data.hits = 0;
+
+       data.callback = callback;
+       data.userdata = userdata;
+
+       if(root != NULL)
+       {
+               float nearest[3];
+               float dist = calc_nearest_point(data.center, root, nearest);
+               if(dist < data.radius)
+               {
+                       //Its a leaf.. call the callback
+                       if(root->totnode == 0)
+                       {
+                               data.hits++;
+                               data.callback( data.userdata, root->index, dist );
+                       }
+                       else
+                               dfs_range_query( &data, root );
+               }
+       }
+
+       return data.hits;
+}
index ad1dc1ca12c53dfa7cbfdcbb5609c48c8a57f71e..5c1a6f28d42f44f04080f84627b7974372626efc 100644 (file)
@@ -2151,6 +2151,13 @@ void VecSubf(float *v, float *v1, float *v2)
        v[2]= v1[2]- v2[2];
 }
 
+void VecMulVecf(float *v, float *v1, float *v2)
+{
+       v[0] = v1[0] * v2[0];
+       v[1] = v1[1] * v2[1];
+       v[2] = v1[2] * v2[2];
+}
+
 void VecLerpf(float *target, float *a, float *b, float t)
 {
        float s = 1.0f-t;
@@ -3324,6 +3331,12 @@ float Normalize2(float *n)
        return d;
 }
 
+float rgb_to_luminance(float r, float g, float b)
+{
+       /* Rec. 709 HDTV */
+       return (0.2126*r + 0.7152*g + 0.0722*b);
+}
+
 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
 {
        int i;
index c88e06a9993d2a37770dd2497a4e74203390abd7..59c11297478f75991b238741a00550ee7a9562af 100644 (file)
@@ -2505,6 +2505,7 @@ static void lib_link_texture(FileData *fd, Main *main)
                        tex->ima= newlibadr_us(fd, tex->id.lib, tex->ima);
                        tex->ipo= newlibadr_us(fd, tex->id.lib, tex->ipo);
                        if(tex->env) tex->env->object= newlibadr(fd, tex->id.lib, tex->env->object);
+                       if(tex->pd) tex->pd->object= newlibadr(fd, tex->id.lib, tex->pd->object);
 
                        if(tex->nodetree)
                                lib_link_ntree(fd, &tex->id, tex->nodetree);
@@ -2534,6 +2535,17 @@ static void direct_link_texture(FileData *fd, Tex *tex)
                memset(tex->env->cube, 0, 6*sizeof(void *));
                tex->env->ok= 0;
        }
+
+       tex->pd= newdataadr(fd, tex->pd);
+       if(tex->pd) {
+               tex->pd->point_tree = NULL;
+               tex->pd->coba= newdataadr(fd, tex->pd->coba);
+       }
+       
+       tex->vd= newdataadr(fd, tex->vd);
+       if(tex->vd) {
+               tex->vd->dataset = NULL;
+       }
        
        tex->nodetree= newdataadr(fd, tex->nodetree);
        if(tex->nodetree)
@@ -7740,6 +7752,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) {
                Object *ob;
                bActionStrip *strip;
+
                
                /* nla-strips - scale */                
                for (ob= main->object.first; ob; ob= ob->id.next) {
@@ -7763,6 +7776,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ob->soft->shearstiff = 1.0f; 
                        }
                }
+               
        }
 
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 14)) {
@@ -7908,6 +7922,57 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        la->skyblendtype= MA_RAMP_ADD;
                        la->skyblendfac= 1.0f;
                }
+               
+       }
+       
+       if (main->versionfile <= 247) {
+               Material *ma;
+               Tex *tex;
+               
+               for(ma=main->mat.first; ma; ma= ma->id.next) {
+                       /* trigger for non-volumetric file */
+                       if (ma->vol_shade_stepsize < 0.0001f) {
+                               ma->vol_shade_stepsize = 0.2f;
+                               ma->vol_stepsize = 0.2f;
+                               ma->vol_absorption = 1.0f;
+                               ma->vol_scattering = 1.0f;
+                               ma->vol_absorption_col[0] = ma->vol_absorption_col[1] = ma->vol_absorption_col[2] = 0.0f;       
+                       }
+                       if (ma->vol_density_scale < 0.0001f)
+                               ma->vol_density_scale = 1.0f;
+                       if (ma->vol_precache_resolution == 0)
+                               ma->vol_precache_resolution = 50;
+                       if (ma->vol_depth_cutoff < 0.0001)
+                               ma->vol_depth_cutoff = 0.05;
+               }
+               
+               for(tex=main->tex.first; tex; tex= tex->id.next) {
+                       if (tex->pd == NULL) 
+                               tex->pd = BKE_add_pointdensity();
+                       else if (tex->pd->noise_size < 0.0001f) {
+                               tex->pd->noise_size = 0.5f;
+                               tex->pd->noise_depth = 1;
+                               tex->pd->noise_fac = 1.0f;
+                               tex->pd->noise_influence = TEX_PD_NOISE_STATIC;
+                       }
+                       if (tex->pd->falloff_softness < 1.0f)
+                               tex->pd->falloff_softness = 2.0f;
+                       if (tex->pd->coba == NULL) {
+                               tex->pd->coba = add_colorband(1);
+                               tex->pd->speed_scale = 1.0f;
+                       }
+                       
+                       if (tex->vd == NULL) {
+                               tex->vd = BKE_add_voxeldata();
+                       } else if (tex->vd->resolX == 0) {
+                               tex->vd->dataset = NULL;
+                               tex->vd->resolX = 1;
+                               tex->vd->resolY = 1;
+                               tex->vd->resolZ = 1;
+                               tex->vd->interp_type= TEX_VD_NEARESTNEIGHBOR;
+                               tex->vd->int_multiplier = 1.0;
+                       }
+               }
        }
        
        /* set the curve radius interpolation to 2.47 default - easy */
@@ -7932,6 +7997,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        }
                }
        }
+
        /* direction constraint actuators were always local in previous version */
        if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 7)) {
                bActuator *act;
@@ -8004,7 +8070,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        }
                }
        }
-       
+
+       if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 3)) {
+               Tex *tex;
+               Material *ma;
+               
+               /* blend texture extrapolation */
+               for(tex=main->tex.first; tex; tex= tex->id.next) {
+                       if (tex->type == TEX_BLEND)
+                               tex->extend = TEX_EXTEND;
+               }
+               
+               for(ma=main->mat.first; ma; ma= ma->id.next) {
+                       if (ma->vol_shadeflag & 2) { // old MA_VOL_ATTENUATED
+                               ma->vol_shade_type = MA_VOL_SHADE_SINGLE;
+                               ma->vol_ms_diff = 0.5f;
+                               ma->vol_ms_steps = 5;
+                               ma->vol_ms_intensity = 1.0;
+                       }
+               }
+       }
+
        if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 2)) {
                Scene *sce;
                
index cf8109fe9b3b218ea566d59413836dbec43edcdd..739b0f11e7eb1084da030d6fa0766b64b83ef5a5 100644 (file)
@@ -1335,6 +1335,11 @@ static void write_textures(WriteData *wd, ListBase *idbase)
                        if(tex->type == TEX_PLUGIN && tex->plugin) writestruct(wd, DATA, "PluginTex", 1, tex->plugin);
                        if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba);
                        if(tex->type == TEX_ENVMAP && tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env);
+                       if(tex->pd) {
+                               writestruct(wd, DATA, "PointDensity", 1, tex->pd);
+                               if(tex->pd->coba) writestruct(wd, DATA, "ColorBand", 1, tex->pd->coba);
+                       }
+                       if(tex->vd) writestruct(wd, DATA, "VoxelData", 1, tex->vd);
                        
                        /* nodetree is integral part of texture, no libdata */
                        if(tex->nodetree) {
index 8a9c1933c974a3bb60e89c9c8b03eae248d998fb..cd9898de9b09d7500d36fd086087c4d6e0f3453b 100644 (file)
@@ -267,6 +267,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
 #define B_ENV_FREE_ALL 1357
 #define B_TEX_USENODES         1358
 
+#define B_VOXELDATA_LOAD       1359
+
 
 /* **************** animbuts = object buttons ******* */
 #define B_ANIMBUTS             1500
index aa8470505810d694e47165e35c8a69582e26a14f..dafa816cb968ad71ae5fcfd1747ae6a9e546589f 100644 (file)
@@ -62,6 +62,27 @@ typedef struct Material {
        float translucency;
        /* end synced with render_types.h */
        
+       short material_type; /* solid, halo, volumetric */
+       short pad5;
+       
+       /* volumetrics */
+       short vol_stepsize_type;
+       short vol_precache_resolution;
+       float vol_stepsize, vol_shade_stepsize;
+       float vol_depth_cutoff;
+       short vol_shade_type;
+       short vpad;
+       float vol_density_scale;
+       float vol_absorption, vol_scattering;
+       float vol_absorption_col[3];
+       short vol_shadeflag;
+       short vol_phasefunc_type;
+       float vol_phasefunc_g;
+       float vpad2;
+       
+       float vol_ms_diff, vol_ms_intensity;
+       int vol_ms_steps;
+               
        float fresnel_mir, fresnel_mir_i;
        float fresnel_tra, fresnel_tra_i;
        float filter;           /* filter added, for raytrace transparency and transmissivity */
@@ -153,6 +174,13 @@ typedef struct Material {
 /* flag */
                /* for render */
 #define MA_IS_USED             1
+#define MA_IS_TEXTURED 2
+
+/* material_type */
+#define MA_SOLID               0
+#define MA_PTHALO              1
+#define MA_VOLUME              2
+#define MA_VOLUMESOLID 3
 
 /* mode (is int) */
 #define MA_TRACEBLE            1
@@ -283,7 +311,7 @@ typedef struct Material {
 #define MAP_AMB                        2048
 #define MAP_DISPLACE   4096
 #define MAP_WARP               8192
-#define MAP_LAYER              16384
+#define MAP_LAYER              16384   
 
 /* mapto for halo */
 //#define MAP_HA_COL           1
@@ -328,5 +356,30 @@ typedef struct Material {
 /* sss_flag */
 #define MA_DIFF_SSS            1
 
+/* vol_stepsize_type */
+#define MA_VOL_STEP_RANDOMIZED 0
+#define MA_VOL_STEP_CONSTANT   1
+#define MA_VOL_STEP_ADAPTIVE   2
+
+/* vol_shadeflag */
+#define MA_VOL_SHADED          1
+#define MA_VOL_RECVSHADOW      4
+#define MA_VOL_PRECACHESHADING 8
+#define MA_VOL_USEALPHA                16
+
+/* vol_shading_type */
+#define MA_VOL_SHADE_NONE                                      0
+#define MA_VOL_SHADE_SINGLE                                    1
+#define MA_VOL_SHADE_MULTIPLE                          2
+#define MA_VOL_SHADE_SINGLEPLUSMULTIPLE                3
+
+/* vol_phasefunc_type */
+#define MA_VOL_PH_ISOTROPIC            0
+#define MA_VOL_PH_MIEHAZY              1
+#define MA_VOL_PH_MIEMURKY             2
+#define MA_VOL_PH_RAYLEIGH             3
+#define MA_VOL_PH_HG                   4
+#define MA_VOL_PH_SCHLICK              5
+
 #endif
 
index 49435000820d81f4ca96779897a27e91ea7ddfcd..f8582460650219a546546b8013b3ddbb4aa2b6ec 100644 (file)
@@ -210,6 +210,7 @@ typedef struct SoftBody {
 #define PFIELD_HARMONIC        7
 #define PFIELD_CHARGE  8
 #define PFIELD_LENNARDJ        9
+#define PFIELD_SPIN            10
 
 
 /* pd->flag: various settings */
index 6e07336a4b153ae32c752103a7666a78b445f513..420850ce396ef74f5d6a85b5eda41121a2c450f7 100644 (file)
@@ -127,6 +127,54 @@ typedef struct EnvMap {
        short recalc, lastsize;
 } EnvMap;
 
+typedef struct PointDensity {
+       short flag;
+
+       short falloff_type;
+       float falloff_softness;
+       float radius;
+       short source;
+       short color_source;
+       int totpoints;
+       
+       int pdpad;
+
+       struct Object *object;  /* for 'Object' or 'Particle system' type - source object */
+       short psys_cache_space;         /* cache points in worldspace, object space, ... ? */
+       short psysindex;                /* for 'Particle system' type - object's psys number */
+       
+       short ob_cache_space;           /* cache points in worldspace, object space, ... ? */
+       
+       short pdpad2;
+       
+       void *point_tree;               /* the acceleration tree containing points */
+       float *point_data;              /* dynamically allocated extra for extra information, like particle age */
+       
+       float noise_size;
+       short noise_depth;
+       short noise_influence;
+       short noise_basis;
+    short pdpad3[3];
+       float noise_fac;
+       
+       float speed_scale;
+       struct ColorBand *coba; /* for time -> color */
+       
+} PointDensity;
+
+typedef struct VoxelData {
+       int resolX, resolY, resolZ;
+       int interp_type;
+
+       float int_multiplier;
+       float vxpad;
+       
+       int still, still_frame;
+       char source_path[240];
+       float *dataset;
+} VoxelData;
+
 typedef struct Tex {
        ID id;
        
@@ -173,6 +221,8 @@ typedef struct Tex {
        struct ColorBand *coba;
        struct EnvMap *env;
        struct PreviewImage * preview;
+       struct PointDensity *pd;
+       struct VoxelData *vd;
        
        char use_nodes;
        char pad[7];
@@ -212,6 +262,9 @@ typedef struct TexMapping {
 #define TEX_MUSGRAVE   11
 #define TEX_VORONOI            12
 #define TEX_DISTNOISE  13
+/* predicting ocean texture for 14 */
+#define TEX_POINTDENSITY       15
+#define TEX_VOXELDATA          16
 
 /* musgrave stype */
 #define TEX_MFRACTAL           0
@@ -389,5 +442,51 @@ typedef struct TexMapping {
 #define ENV_NORMAL     1
 #define ENV_OSA                2
 
+/* **************** PointDensity ********************* */
+
+/* source */
+#define TEX_PD_PSYS                    0
+#define TEX_PD_OBJECT          1
+#define TEX_PD_FILE                    2
+
+/* falloff_type */
+#define TEX_PD_FALLOFF_STD             0
+#define TEX_PD_FALLOFF_SMOOTH  1
+#define TEX_PD_FALLOFF_SOFT            2
+#define TEX_PD_FALLOFF_CONSTANT        3
+#define TEX_PD_FALLOFF_ROOT            4
+
+/* psys_cache_space */
+#define TEX_PD_OBJECTLOC       0
+#define TEX_PD_OBJECTSPACE     1
+#define TEX_PD_WORLDSPACE      2
+
+/* flag */
+#define TEX_PD_TURBULENCE      1
+
+
+/* noise_influence */
+#define TEX_PD_NOISE_STATIC            0
+#define TEX_PD_NOISE_VEL               1
+#define TEX_PD_NOISE_AGE               2
+#define TEX_PD_NOISE_TIME              3
+
+/* color_source */
+#define TEX_PD_COLOR_CONSTANT  0
+#define TEX_PD_COLOR_PARTAGE   1
+#define TEX_PD_COLOR_PARTSPEED 2
+#define TEX_PD_COLOR_PARTVEL   3
+
+#define POINT_DATA_VEL         1
+#define POINT_DATA_LIFE                2
+
+/******************** Voxel Data *****************************/ 
+#define TEX_VD_CUBIC              0
+#define TEX_VD_PARALLELOGRAM      1
+#define TEX_VD_NEARESTNEIGHBOR         0
+#define TEX_VD_LINEAR                  1
+#define TEX_VD_TRICUBIC                                2
+
 #endif
 
index 2cee2673a269f8591b4fea9f78e36b7ff2bbfead..a37862aa0aef4c6442ce141622c6e39b87bea3a6 100644 (file)
@@ -113,7 +113,7 @@ typedef struct ShadeInput
        
        /* internal face coordinates */
        float u, v, dx_u, dx_v, dy_u, dy_v;
-       float co[3], view[3];
+       float co[3], view[3], camera_co[3];
        
        /* copy from material, keep synced so we can do memcopy */
        /* current size: 23*4 */
@@ -161,6 +161,7 @@ typedef struct ShadeInput
        
        int samplenr;                   /* sample counter, to detect if we should do shadow again */
        int depth;                              /* 1 or larger on raytrace shading */
+       int volume_depth;               /* number of intersections through volumes */
        
        /* stored copy of original face normal (facenor) 
         * before flipping. Used in Front/back output on geometry node */
diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h
new file mode 100644 (file)
index 0000000..93cdef3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Matt Ebb
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef POINTDENSITY_H
+#define POINTDENSITY_H 
+
+/**
+ * Make point density kd-trees for all point density textures in the scene
+ */
+
+struct Render;
+struct TexResult;
+
+void make_pointdensities(struct Render *re);
+void free_pointdensities(struct Render *re);
+int pointdensitytex(struct Tex *tex, float *texvec, struct TexResult *texres);
+
+#endif /* POINTDENSITY_H */
+
index 1768b052b54fc431458613d077bdbfecb0cb9f9b..8dbdde777266d7f3d6eb2ca3790b6fcb36185e20 100644 (file)
@@ -201,6 +201,10 @@ struct Render
        ListBase customdata_names;
 
        struct Object *excludeob;
+       
+       ListBase render_volumes_inside;
+       ListBase volumes;
+       ListBase volume_precache_parts;
 
        /* arena for allocating data for use during render, for
                * example dynamic TFaces to go in the VlakRen structure.
@@ -285,6 +289,8 @@ typedef struct ObjectInstanceRen {
 
        float dupliorco[3], dupliuv[2];
        float (*duplitexmat)[4];
+       
+       float *volume_precache;
 
        float *vectors;
        int totvector;
@@ -345,6 +351,7 @@ typedef struct HaloRen
     struct Material *mat;
 } HaloRen;
 
+
 /* ------------------------------------------------------------------------- */
 
 typedef struct StrandVert {
@@ -395,6 +402,38 @@ typedef struct StrandRen {
        float orco[3];
 } StrandRen;
 
+/* ------------------------------------------------------------------------- */
+
+typedef struct VolumeOb
+{
+       struct VolumeOb *next, *prev;
+       struct Material *ma;
+       struct ObjectRen *obr;
+} VolumeOb;
+
+typedef struct MatInside {
+       struct MatInside *next, *prev;
+       struct Material *ma;
+} MatInside;
+
+typedef struct VolPrecachePart
+{
+       struct VolPrecachePart *next, *prev;
+       struct RayTree *tree;
+       struct ShadeInput *shi;
+       struct ObjectInstanceRen *obi;
+       int num;
+       int minx, maxx;
+       int miny, maxy;
+       int minz, maxz;
+       int res;
+       float bbmin[3];
+       float voxel[3];
+       int working, done;
+} VolPrecachePart;
+
+
+/* ------------------------------------------------------------------------- */
 
 struct LampRen;
 struct MTex;
index 4b28529a1472cbd1b23f4448a91ddea2d4be6620..972071764d29022a48b791b06419458fa63e5ba2 100644 (file)
@@ -48,6 +48,7 @@ struct RenderPart;
 struct RenderLayer;
 struct ObjectRen;
 struct ListBase;
+struct Isect;
 
 /* ------------------------------------------------------------------------- */
 
@@ -98,6 +99,7 @@ extern void makeraytree(Render *re);
 
 extern void ray_shadow(ShadeInput *, LampRen *, float *);
 extern void ray_trace(ShadeInput *, ShadeResult *);
+extern void ray_trace_shadow_tra(struct Isect *is, int depth, int traflag);
 extern void ray_ao(ShadeInput *, float *);
 extern void init_jitter_plane(LampRen *lar);
 extern void init_ao_sphere(struct World *wrld);
index 54311d2515a3d1eb7b2092cbac5f726950506800..8aa102a04a43b459ea3d550ad762ad9caaa7df0e 100644 (file)
@@ -33,6 +33,7 @@ struct VlakRen;
 struct StrandSegment;
 struct StrandPoint;
 struct ObjectInstanceRen obi;
+struct Isect;
 
 /* shadeinput.c */
 
@@ -52,6 +53,7 @@ typedef struct ShadeSample {
 
        /* also the node shader callback */
 void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr);
+void shade_volume_loop(struct ShadeInput *shi, struct ShadeResult *shr);
 
 void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3);
 void shade_input_set_triangle(struct ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip);
@@ -86,7 +88,11 @@ void shade_color(struct ShadeInput *shi, ShadeResult *shr);
 void ambient_occlusion_to_diffuse(struct ShadeInput *shi, float *diff);
 void ambient_occlusion(struct ShadeInput *shi);
 
+ListBase *get_lights(struct ShadeInput *shi);
 float lamp_get_visibility(struct LampRen *lar, float *co, float *lv, float *dist);
 void lamp_get_shadow(struct LampRen *lar, ShadeInput *shi, float inp, float *shadfac, int do_real);
 
 float  fresnel_fac(float *view, float *vn, float fresnel, float fac);
+
+/* rayshade.c */
+extern void shade_ray(struct Isect *is, struct ShadeInput *shi, struct ShadeResult *shr);
index c254b76829294761c66f40b5f9e4d97292bcafa6..23abec2f9efe5dc897322ab59bce6665a58fdc23 100644 (file)
@@ -56,6 +56,7 @@ void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
 void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag, short thread);
 void do_material_tex(struct ShadeInput *shi);
 void do_lamp_tex(LampRen *la, float *lavec, struct ShadeInput *shi, float *colf, int effect);
+void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, float *val);
 
 void init_render_textures(Render *re);
 void end_render_textures(void);
diff --git a/source/blender/render/intern/include/volume_precache.h b/source/blender/render/intern/include/volume_precache.h
new file mode 100644 (file)
index 0000000..d8a94c2
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+void volume_precache(Render *re);
+void free_volume_precache(Render *re);
+int point_inside_volume_objectinstance(ObjectInstanceRen *obi, float *co);
+int using_lightcache(Material *ma);
+
+#define VOL_MS_TIMESTEP        0.1f
\ No newline at end of file
diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h
new file mode 100644 (file)
index 0000000..40d79e8
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+float vol_get_stepsize(struct ShadeInput *shi, int context);
+float vol_get_density(struct ShadeInput *shi, float *co);
+void vol_get_scattering(ShadeInput *shi, float *scatter, float *co, float stepsize, float density);
+
+void shade_volume_outside(ShadeInput *shi, ShadeResult *shr);
+void shade_volume_inside(ShadeInput *shi, ShadeResult *shr);
+void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is);
+
+#define STEPSIZE_VIEW  0
+#define STEPSIZE_SHADE 1
+
+#define VOL_IS_BACKFACE                        1
+#define VOL_IS_SAMEMATERIAL            2
+
+#define VOL_BOUNDS_DEPTH       0
+#define VOL_BOUNDS_SS          1
+
+#define VOL_SHADE_OUTSIDE      0
+#define VOL_SHADE_INSIDE       1
\ No newline at end of file
diff --git a/source/blender/render/intern/include/voxeldata.h b/source/blender/render/intern/include/voxeldata.h
new file mode 100644 (file)
index 0000000..190a5a5
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Raul Fernandez Hernandez (Farsthary), Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef VOXELDATA_H
+#define VOXELDATA_H 
+
+/**
+ * Load voxel data for all point density textures in the scene
+ */
+
+struct Render;
+struct TexResult;
+
+typedef struct VoxelDataHeader
+{
+int resolX, resolY, resolZ;
+int frames;
+} VoxelDataHeader;
+
+inline int _I(int x, int y, int z, int *n);
+void make_voxeldata(struct Render *re);
+void free_voxeldata(struct Render *re);
+int voxeldatatex(struct Tex *tex, float *texvec, struct TexResult *texres);
+
+
+#endif /* VOXELDATA_H */
index 06ba8f16a3b3f9caccedd99ae0841aca09d7b393..cd245b3f7783c8c2f28008130cf7173c8ef60ab8 100644 (file)
@@ -41,6 +41,7 @@
 #include "BLI_rand.h"
 #include "BLI_memarena.h"
 #include "BLI_ghash.h"
+#include "BLI_kdtree.h"
 
 #include "DNA_armature_types.h"
 #include "DNA_camera_types.h"
 #include "envmap.h"
 #include "multires.h"
 #include "occlusion.h"
+#include "pointdensity.h"
+#include "voxeldata.h"
 #include "render_types.h"
 #include "rendercore.h"
 #include "renderdatabase.h"
 #include "shading.h"
 #include "strand.h"
 #include "texture.h"
+#include "volume_precache.h"
 #include "sss.h"
 #include "strand.h"
 #include "zbuf.h"
@@ -921,6 +925,28 @@ static void flag_render_node_material(Render *re, bNodeTree *ntree)
        }
 }
 
+static void check_material_is_textured(Material *ma)
+{
+       MTex *mtex;
+       Tex *tex;
+       int tex_nr;
+       
+       for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
+               if(ma->septex & (1<<tex_nr))
+                       continue;
+               
+               if(ma->mtex[tex_nr]) {
+                       mtex= ma->mtex[tex_nr];
+                       tex= mtex->tex;
+                       if(tex==NULL)
+                               continue;
+                       else
+                               ma->flag |= MA_IS_TEXTURED;
+                               return;
+               }
+       }
+}
+
 static Material *give_render_material(Render *re, Object *ob, int nr)
 {
        extern Material defmaterial;    /* material.c */
@@ -941,6 +967,8 @@ static Material *give_render_material(Render *re, Object *ob, int nr)
        if(ma->nodetree && ma->use_nodes)
                flag_render_node_material(re, ma->nodetree);
        
+       check_material_is_textured(ma);
+       
        return ma;
 }
 
@@ -1951,6 +1979,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset);
 
 /* 4. clean up */
+
        if(ma) do_mat_ipo(ma);
 
        if(orco1)
@@ -2928,6 +2957,53 @@ static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge,
        }
 }
 
+static void free_camera_inside_volumes(Render *re)
+{
+       BLI_freelistN(&re->render_volumes_inside);
+}
+
+static void init_camera_inside_volumes(Render *re)
+{
+       ObjectInstanceRen *obi;
+       VolumeOb *vo;
+       float co[3] = {0.f, 0.f, 0.f};
+
+       for(vo= re->volumes.first; vo; vo= vo->next) {
+               for(obi= re->instancetable.first; obi; obi= obi->next) {
+                       if (obi->obr == vo->obr) {
+                               if (point_inside_volume_objectinstance(obi, co)) {
+                                       MatInside *mi;
+                                       
+                                       mi = MEM_mallocN(sizeof(MatInside), "camera inside material");
+                                       mi->ma = vo->ma;
+                                       
+                                       BLI_addtail(&(re->render_volumes_inside), mi);
+                               }
+                       }
+               }
+       }
+       
+       {
+       MatInside *m;
+       for (m=re->render_volumes_inside.first; m; m=m->next) {
+               printf("matinside: ma: %s \n", m->ma->id.name+2);
+       }
+       
+       }
+}
+
+static void add_volume(Render *re, ObjectRen *obr, Material *ma)
+{
+       struct VolumeOb *vo;
+       
+       vo = MEM_mallocN(sizeof(VolumeOb), "volume object");
+       
+       vo->ma = ma;
+       vo->obr = obr;
+       
+       BLI_addtail(&re->volumes, vo);
+}
+
 static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 {
        Object *ob= obr->ob;
@@ -2982,6 +3058,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
                        if(re->r.mode & R_RADIO)
                                if(ma->mode & MA_RADIO) 
                                        do_autosmooth= 1;
+                       
+                       if (ma->material_type == MA_VOLUME)
+                               add_volume(re, obr, ma);
                }
        }
 
@@ -4315,6 +4394,8 @@ void RE_Database_Free(Render *re)
        
        BLI_freelistN(&re->lampren);
        BLI_freelistN(&re->lights);
+       
+       free_volume_precache(re);
 
        free_renderdata_tables(re);
        
@@ -4338,6 +4419,11 @@ void RE_Database_Free(Render *re)
        end_render_materials();
        end_render_textures();
        
+       free_pointdensities(re);
+       free_voxeldata(re);
+       
+       free_camera_inside_volumes(re);
+       
        if(re->wrld.aosphere) {
                MEM_freeN(re->wrld.aosphere);
                re->wrld.aosphere= NULL;
@@ -4725,6 +4811,8 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
 
        /* MAKE RENDER DATA */
        database_init_objects(re, lay, 0, 0, 0, 0);
+       
+       init_camera_inside_volumes(re);
 
        if(!re->test_break()) {
                int tothalo;
@@ -4772,6 +4860,13 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
                        /* ENVIRONMENT MAPS */
                        if(!re->test_break())
                                make_envmaps(re);
+                               
+                       /* point density texture */
+                       if(!re->test_break())
+                               make_pointdensities(re);
+                       /* voxel data texture */
+                       if(!re->test_break())
+                               make_voxeldata(re);//Volumetrics
                }
                
                if(!re->test_break())
@@ -4788,6 +4883,10 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
                if((re->r.mode & R_SSS) && !re->test_break())
                        if(re->r.renderer==R_INTERN)
                                make_sss_tree(re);
+               
+               if(!re->test_break())
+                       if(re->r.mode & R_RAYTRACE)
+                               volume_precache(re);
        }
        
        if(re->test_break())
index 494feb96c187ff1a0d302bea7e7317900409390a..9ce274ba775207f5f76b7cebb2710509681ab47c 100644 (file)
@@ -630,7 +630,7 @@ static OcclusionTree *occ_tree_build(Render *re)
                        if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
                        else vlr++;
 
-                       if(vlr->mat->mode & MA_TRACEBLE)
+                       if((vlr->mat->mode & MA_TRACEBLE) && (vlr->mat->material_type == MA_SOLID))
                                totface++;
                }
        }
@@ -663,7 +663,7 @@ static OcclusionTree *occ_tree_build(Render *re)
                        if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
                        else vlr++;
 
-                       if(vlr->mat->mode & MA_TRACEBLE) {
+                       if((vlr->mat->mode & MA_TRACEBLE) && (vlr->mat->material_type == MA_SOLID)) {
                                tree->face[b].obi= c;
                                tree->face[b].facenr= a;
                                tree->occlusion[b]= 1.0f;
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
new file mode 100644 (file)
index 0000000..2c8b6aa
--- /dev/null
@@ -0,0 +1,490 @@
+/* 
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributors: Matt Ebb
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_kdopbvh.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_texture.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_particle_types.h"
+
+#include "render_types.h"
+#include "renderdatabase.h"
+#include "texture.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+static int point_data_used(PointDensity *pd)
+{
+       int pd_bitflag = 0;
+       
+       if ((pd->noise_influence == TEX_PD_NOISE_VEL) || (pd->color_source == TEX_PD_COLOR_PARTVEL) || (pd->color_source == TEX_PD_COLOR_PARTSPEED))
+               pd_bitflag |= POINT_DATA_VEL;
+       if ((pd->noise_influence == TEX_PD_NOISE_AGE) || (pd->color_source == TEX_PD_COLOR_PARTAGE)) 
+               pd_bitflag |= POINT_DATA_LIFE;
+               
+       return pd_bitflag;
+}
+
+
+/* additional data stored alongside the point density BVH, 
+ * accessible by point index number to retrieve other information 
+ * such as particle velocity or lifetime */
+static void alloc_point_data(PointDensity *pd, int total_particles, int point_data_used)
+{
+       int data_size = 0;
+       
+       if (point_data_used & POINT_DATA_VEL) {
+               /* store 3 channels of velocity data */
+               data_size += 3;
+       }
+       if (point_data_used & POINT_DATA_LIFE) {
+               /* store 1 channel of lifetime data */
+               data_size += 1;
+       }
+
+       if (data_size)
+               pd->point_data = MEM_mallocN(sizeof(float)*data_size*total_particles, "particle point data");
+}
+
+static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys)
+{
+       DerivedMesh* dm;
+       ParticleKey state;
+       ParticleData *pa=NULL;
+       float cfra=bsystem_time(ob,(float)G.scene->r.cfra,0.0);
+       int i, childexists;
+       int total_particles, offset=0;
+       int data_used = point_data_used(pd);
+       float partco[3];
+       float obview[4][4];
+       
+       
+       /* init everything */
+       if (!psys || !ob || !pd) return;
+       
+       Mat4MulMat4(obview, re->viewinv, ob->obmat);
+       
+       /* Just to create a valid rendering context for particles */
+       psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0);
+       
+       dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+       
+       if ( !psys_check_enabled(ob, psys)) {
+               psys_render_restore(ob, psys);
+               return;
+       }
+       
+       /* in case ob->imat isn't up-to-date */
+       Mat4Invert(ob->imat, ob->obmat);
+       
+       total_particles = psys->totpart+psys->totchild;
+       psys->lattice=psys_get_lattice(ob,psys);
+       
+       pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
+       alloc_point_data(pd, total_particles, data_used);
+       pd->totpoints = total_particles;
+       if (data_used & POINT_DATA_VEL) offset = pd->totpoints*3;
+       
+       if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
+               childexists = 1;
+       
+       for (i=0, pa=psys->particles; i < total_particles; i++, pa++) {
+
+               state.time = cfra;
+               if(psys_get_particle_state(ob, psys, i, &state, 0)) {
+                       
+                       VECCOPY(partco, state.co);
+                       
+                       if (pd->psys_cache_space == TEX_PD_OBJECTSPACE)
+                               Mat4MulVecfl(ob->imat, partco);
+                       else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
+                               float obloc[3];
+                               VECCOPY(obloc, ob->loc);
+                               VecSubf(partco, partco, obloc);
+                       } else {
+                               /* TEX_PD_WORLDSPACE */
+                       }
+                       
+                       BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
+                       
+                       if (data_used & POINT_DATA_VEL) {
+                               pd->point_data[i*3 + 0] = state.vel[0];
+                               pd->point_data[i*3 + 1] = state.vel[1];
+                               pd->point_data[i*3 + 2] = state.vel[2];
+                       } 
+                       if (data_used & POINT_DATA_LIFE) {
+                               float pa_time;
+                               
+                               if (i < psys->totpart) {
+                                       pa_time = (cfra - pa->time)/pa->lifetime;
+                               } else {
+                                       ChildParticle *cpa= (psys->child + i) - psys->totpart;
+                                       pa_time = psys_get_child_time(psys, cpa, cfra);
+                               }
+                               
+                               pd->point_data[offset + i] = pa_time;
+                       }
+               }
+       }
+       
+       BLI_bvhtree_balance(pd->point_tree);
+       dm->release(dm);
+       
+       if(psys->lattice){
+               end_latt_deform();
+               psys->lattice=0;
+       }
+       
+       psys_render_restore(ob, psys);
+}
+
+
+static void pointdensity_cache_object(Render *re, PointDensity *pd, ObjectRen *obr)
+{
+       int i;
+       
+       if (!obr || !pd) return;
+       if(!obr->vertnodes) return;
+       
+       /* in case ob->imat isn't up-to-date */
+       Mat4Invert(obr->ob->imat, obr->ob->obmat);
+       
+       pd->point_tree = BLI_bvhtree_new(obr->totvert, 0.0, 4, 6);
+       pd->totpoints = obr->totvert;
+       
+       for(i=0; i<obr->totvert; i++) {
+               float ver_co[3];
+               VertRen *ver= RE_findOrAddVert(obr, i);
+               
+               VECCOPY(ver_co, ver->co);
+               Mat4MulVecfl(re->viewinv, ver_co);
+               
+               if (pd->ob_cache_space == TEX_PD_OBJECTSPACE) {
+                       Mat4MulVecfl(obr->ob->imat, ver_co);
+               } else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
+                       VecSubf(ver_co, ver_co, obr->ob->loc);
+               } else {
+                       /* TEX_PD_WORLDSPACE */
+               }
+               
+               BLI_bvhtree_insert(pd->point_tree, i, ver_co, 1);
+       }
+       
+       BLI_bvhtree_balance(pd->point_tree);
+
+}
+static void cache_pointdensity(Render *re, Tex *tex)
+{
+       PointDensity *pd = tex->pd;
+
+       if (pd->point_tree) {
+               BLI_bvhtree_free(pd->point_tree);
+               pd->point_tree = NULL;
+       }
+       
+       if (pd->source == TEX_PD_PSYS) {
+               ParticleSystem *psys;
+               Object *ob = pd->object;
+               int i;
+               
+               if (!ob) return;
+               if (BLI_countlist(&ob->particlesystem) == 0) return;
+               
+               
+               for(psys=ob->particlesystem.first, i=0; i< pd->psysindex-1; i++)
+                       psys= psys->next;
+               
+               if (!psys) return;
+               
+               pointdensity_cache_psys(re, pd, ob, psys);
+       }
+       else if (pd->source == TEX_PD_OBJECT) {
+               Object *ob = pd->object;
+               ObjectRen *obr;
+               int found=0;
+
+               /* find the obren that corresponds to the object */
+               for (obr=re->objecttable.first; obr; obr=obr->next) {
+                       if (obr->ob == ob) {
+                               found=1;
+                               break;
+                       }
+               }
+               if (!found) return;
+               
+               pointdensity_cache_object(re, pd, obr);
+       }
+}
+
+static void free_pointdensity(Render *re, Tex *tex)
+{
+       PointDensity *pd = tex->pd;
+
+       if (!pd) return;
+       
+       if (pd->point_tree) {
+               BLI_bvhtree_free(pd->point_tree);
+               pd->point_tree = NULL;
+       }
+
+       if (pd->point_data) {
+               MEM_freeN(pd->point_data);
+               pd->point_data = NULL;
+       }
+       pd->totpoints = 0;
+}
+
+
+
+void make_pointdensities(Render *re)
+{
+       Tex *tex;
+       
+       if(re->scene->r.scemode & R_PREVIEWBUTS)
+               return;
+       
+       re->i.infostr= "Caching Point Densities";
+       re->stats_draw(&re->i);
+
+       for (tex= G.main->tex.first; tex; tex= tex->id.next) {
+               if(tex->id.us && tex->type==TEX_POINTDENSITY) {
+                       cache_pointdensity(re, tex);
+               }
+       }
+       
+       re->i.infostr= NULL;
+       re->stats_draw(&re->i);
+}
+
+void free_pointdensities(Render *re)
+{
+       Tex *tex;
+       
+       if(re->scene->r.scemode & R_PREVIEWBUTS)
+               return;
+       
+       for (tex= G.main->tex.first; tex; tex= tex->id.next) {
+               if(tex->id.us && tex->type==TEX_POINTDENSITY) {
+                       free_pointdensity(re, tex);
+               }
+       }
+}
+
+typedef struct PointDensityRangeData
+{
+    float *density;
+    float squared_radius;
+    float *point_data;
+       float *vec;
+       float softness;
+    short falloff_type;
+       short noise_influence;
+       float *age;
+       int point_data_used;
+       int offset;
+} PointDensityRangeData;
+
+void accum_density(void *userdata, int index, float squared_dist)
+{
+       PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
+       const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
+       float density;
+       
+       if (pdr->falloff_type == TEX_PD_FALLOFF_STD)
+               density = dist;
+       else if (pdr->falloff_type == TEX_PD_FALLOFF_SMOOTH)
+               density = 3.0f*dist*dist - 2.0f*dist*dist*dist;
+       else if (pdr->falloff_type == TEX_PD_FALLOFF_SOFT)
+               density = pow(dist, pdr->softness);
+       else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT)
+               density = pdr->squared_radius;
+       else if (pdr->falloff_type == TEX_PD_FALLOFF_ROOT)
+               density = sqrt(dist);
+       
+       if (pdr->point_data_used & POINT_DATA_VEL) {
+               pdr->vec[0] += pdr->point_data[index*3 + 0]; //* density;
+               pdr->vec[1] += pdr->point_data[index*3 + 1]; //* density;
+               pdr->vec[2] += pdr->point_data[index*3 + 2]; //* density;
+       }
+       if (pdr->point_data_used & POINT_DATA_LIFE) {
+               *pdr->age += pdr->point_data[pdr->offset + index]; // * density;
+       }
+       
+       *pdr->density += density;
+}
+
+
+static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr, float *density, float *vec, float *age)
+{
+       pdr->squared_radius = pd->radius*pd->radius;
+       pdr->density = density;
+       pdr->point_data = pd->point_data;
+       pdr->falloff_type = pd->falloff_type;
+       pdr->vec = vec;
+       pdr->age = age;
+       pdr->softness = pd->falloff_softness;
+       pdr->noise_influence = pd->noise_influence;
+       pdr->point_data_used = point_data_used(pd);
+       pdr->offset = (pdr->point_data_used & POINT_DATA_VEL)?pd->totpoints*3:0;
+}
+
+
+int pointdensitytex(Tex *tex, float *texvec, TexResult *texres)
+{
+       int retval = TEX_INT;
+       PointDensity *pd = tex->pd;
+       PointDensityRangeData pdr;
+       float density=0.0f, age=0.0f, time=0.0f;
+       float vec[3] = {0.0f, 0.0f, 0.0f}, co[3];
+       float col[4];
+       float turb, noise_fac;
+       int num=0;
+       
+       texres->tin = 0.0f;
+       
+       if ((!pd) || (!pd->point_tree))         
+               return 0;
+               
+       init_pointdensityrangedata(pd, &pdr, &density, vec, &age);
+       noise_fac = pd->noise_fac * 0.5f;       /* better default */
+       
+       VECCOPY(co, texvec);
+       
+       if (point_data_used(pd)) {
+               /* does a BVH lookup to find accumulated density and additional point data *
+                * stores particle velocity vector in 'vec', and particle lifetime in 'time' */
+               num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
+               if (num > 0) {
+                       age /= num;
+                       VecMulf(vec, 1.0f/num);
+               }
+               
+               /* reset */
+               density = vec[0] = vec[1] = vec[2] = 0.0f;
+       }
+       
+       if (pd->flag & TEX_PD_TURBULENCE) {
+       
+               if (pd->noise_influence == TEX_PD_NOISE_AGE) {
+                       turb = BLI_gTurbulence(pd->noise_size, texvec[0]+age, texvec[1]+age, texvec[2]+age, pd->noise_depth, 0, pd->noise_basis);
+               }
+               else if (pd->noise_influence == TEX_PD_NOISE_TIME) {
+                       time = R.cfra / (float)R.r.efra;
+                       turb = BLI_gTurbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth, 0, pd->noise_basis);
+                       //turb = BLI_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth);
+               }
+               else {
+                       turb = BLI_gTurbulence(pd->noise_size, texvec[0]+vec[0], texvec[1]+vec[1], texvec[2]+vec[2], pd->noise_depth, 0, pd->noise_basis);
+               }
+
+               turb -= 0.5f;   /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
+               
+               /* now we have an offset coordinate to use for the density lookup */
+               co[0] = texvec[0] + noise_fac * turb;
+               co[1] = texvec[1] + noise_fac * turb;
+               co[2] = texvec[2] + noise_fac * turb;
+       }
+
+       /* BVH query with the potentially perturbed coordinates */
+       num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
+       if (num > 0) {
+               age /= num;
+               VecMulf(vec, 1.0f/num);
+       }
+       
+       texres->tin = density;
+       BRICONT;
+       
+       if (pd->color_source == TEX_PD_COLOR_CONSTANT)
+               return retval;
+       
+       retval |= TEX_RGB;
+       
+       switch (pd->color_source) {
+               case TEX_PD_COLOR_PARTAGE:
+                       if (pd->coba) {
+                               if (do_colorband(pd->coba, age, col)) {
+                                       texres->talpha= 1;
+                                       VECCOPY(&texres->tr, col);
+                                       texres->tin *= col[3];
+                                       texres->ta = texres->tin;
+                               }
+                       }
+                       break;
+               case TEX_PD_COLOR_PARTSPEED:
+               {
+                       float speed = VecLength(vec) * pd->speed_scale;
+                       
+                       if (pd->coba) {
+                               if (do_colorband(pd->coba, speed, col)) {
+                                       texres->talpha= 1;      
+                                       VECCOPY(&texres->tr, col);
+                                       texres->tin *= col[3];
+                                       texres->ta = texres->tin;
+                               }
+                       }
+                       break;
+               }
+               case TEX_PD_COLOR_PARTVEL:
+                       texres->talpha= 1;
+                       VecMulf(vec, pd->speed_scale);
+                       VECCOPY(&texres->tr, vec);
+                       texres->ta = texres->tin;
+                       break;
+               case TEX_PD_COLOR_CONSTANT:
+               default:
+                       texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
+                       break;
+       }
+       BRICONTRGB;
+       
+       return retval;
+       
+       /*
+       if (texres->nor!=NULL) {
+               texres->nor[0] = texres->nor[1] = texres->nor[2] = 0.0f;
+       }
+       */
+}
index 46a7a1c556c596aa1feab2e2e3de3e9cd7d6b7c6..d09bd5c707aa97b1a11bb5fbe2bc140ad56ae438 100644 (file)
@@ -54,6 +54,7 @@
 #include "pixelshading.h"
 #include "shading.h"
 #include "texture.h"
+#include "volumetric.h"
 
 #include "RE_raytrace.h"
 
@@ -95,6 +96,17 @@ static int vlr_check_intersect(Isect *is, int ob, RayFace *face)
                return (is->lay & obi->lay);
 }
 
+static int vlr_check_intersect_solid(Isect *is, int ob, RayFace *face)
+{
+       VlakRen *vlr = (VlakRen*)face;
+
+       /* solid material types only */
+       if (vlr->mat->material_type == MA_SOLID)
+               return 1;
+       else
+               return 0;
+}
+
 static float *vlr_get_transform(void *userdata, int i)
 {
        ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)userdata, i);
@@ -205,7 +217,7 @@ void makeraytree(Render *re)
        re->stats_draw(&re->i);
 }
 
-static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
+void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
 {
        VlakRen *vlr= (VlakRen*)is->face;
        ObjectInstanceRen *obi= RAY_OBJECT_GET(&R, is->ob);
@@ -262,21 +274,40 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
 
        shade_input_set_shade_texco(shi);
        
-       if(is->mode==RE_RAY_SHADOW_TRA) 
+       if (shi->mat->material_type == MA_VOLUME) {
+               if(ELEM(is->mode, RE_RAY_SHADOW, RE_RAY_SHADOW_TRA)) {
+                       shade_volume_shadow(shi, shr, is);
+               } else {
+                       shade_volume_outside(shi, shr);
+               }
+       }
+       else if(is->mode==RE_RAY_SHADOW_TRA) 
                if(shi->mat->nodetree && shi->mat->use_nodes) {
                        ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
                        shi->mat= vlr->mat;             /* shi->mat is being set in nodetree */
                }
-               else
+               else {
                        shade_color(shi, shr);
+               }
        else {
                if(shi->mat->nodetree && shi->mat->use_nodes) {
                        ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
                        shi->mat= vlr->mat;             /* shi->mat is being set in nodetree */
                }
-               else
-                       shade_material_loop(shi, shr);
-               
+               else {
+                       int tempdepth;
+                       /* XXX dodgy business here, set ray depth to -1
+                        * to ignore raytrace in shade_material_loop()
+                        * this could really use a refactor --Matt */
+                       if (shi->volume_depth == 0) {
+                               tempdepth = shi->depth;
+                               shi->depth = -1;
+                               shade_material_loop(shi, shr);
+                               shi->depth = tempdepth;
+                       } else {
+                               shade_material_loop(shi, shr);
+                       }
+               }
                /* raytrace likes to separate the spec color */
                VECSUB(shr->diff, shr->combined, shr->spec);
        }       
@@ -447,7 +478,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
                
                shi.mask= origshi->mask;
                shi.osatex= origshi->osatex;
-               shi.depth= 1;                                   /* only used to indicate tracing */
+               shi.depth = origshi->depth + 1;                                 /* only used to indicate tracing */
                shi.thread= origshi->thread;
                //shi.sample= 0; // memset above, so dont need this
                shi.xs= origshi->xs;
@@ -462,6 +493,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
                memset(&shr, 0, sizeof(ShadeResult));
                
                shade_ray(&isec, &shi, &shr);
+
                if (traflag & RAY_TRA)
                        d= shade_by_transmission(&isec, &shi, &shr);
                
@@ -1273,7 +1305,7 @@ static void addAlphaLight(float *shadfac, float *col, float alpha, float filter)
        shadfac[3]= (1.0f-alpha)*shadfac[3];
 }
 
-static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
+void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
 {
        /* ray to lamp, find first face that intersects, check alpha properties,
           if it has col[3]>0.0f  continue. so exit when alpha is full */
@@ -1302,11 +1334,16 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
                shi.mat_override= NULL;*/
                
                shade_ray(is, &shi, &shr);
-               if (traflag & RAY_TRA)
-                       d= shade_by_transmission(is, &shi, &shr);
-               
-               /* mix colors based on shadfac (rgb + amount of light factor) */
-               addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter);
+               if (shi.mat->material_type == MA_SOLID) {
+                       if (traflag & RAY_TRA)
+                               d= shade_by_transmission(is, &shi, &shr);
+                       
+                       /* mix colors based on shadfac (rgb + amount of light factor) */
+                       addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter);
+               } else {
+                       // MA_VOLUME
+                       addAlphaLight(is->col, shr.combined, shr.alpha, 1.0f);
+               }
                
                if(depth>0 && is->col[3]>0.0f) {
                        
@@ -1607,7 +1644,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac)
                
                prev = fac;
                
-               if(RE_ray_tree_intersect(R.raytree, &isec)) {
+               if(RE_ray_tree_intersect_check(R.raytree, &isec, vlr_check_intersect_solid)) {
                        if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); 
                        else fac+= 1.0f;
                }
@@ -1732,7 +1769,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
                        isec.end[2] = shi->co[2] - maxdist*vec[2];
                        
                        /* do the trace */
-                       if(RE_ray_tree_intersect(R.raytree, &isec)) {
+                       if(RE_ray_tree_intersect_check(R.raytree, &isec, vlr_check_intersect_solid)) {
                                if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); 
                                else sh+= 1.0f;
                        }
index 09d3711885afc4a72f3f4c759a34b65d91ed012d..b34fe6a70397cdb0da79e677299099ece188be49 100644 (file)
@@ -931,7 +931,7 @@ int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, Ra
                intersection to be detected in its neighbour face */
                
                if(is->facecontr && is->faceisect);     // optimizing, the tests below are not needed
-               else if(is->labda< .1) {
+               else if(is->labda< .1 && is->faceorig) {
                        RayFace *face= is->faceorig;
                        float *origv1, *origv2, *origv3, *origv4;
                        short de= 0;
index 621831fb34111883f64f8423e43c9d9afbfdbedb..484857fbbbcdbf7a5aafb32f0652e39e7af14413 100644 (file)
@@ -1325,6 +1325,7 @@ ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob,
        obi->index= index;
        obi->psysindex= psysindex;
        obi->lay= lay;
+       obi->volume_precache = NULL;
 
        if(mat) {
                Mat4CpyMat4(obi->mat, mat);
index 1cd8ec110f9729795b61ce3430d59404159dfb0a..294175460bff7c1f3ac4124a9999cd4779452605 100644 (file)
@@ -121,7 +121,7 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
        }
        
        /* depth >= 1 when ray-shading */
-       if(shi->depth==0) {
+       if(shi->depth >= 0 && (shi->depth < MAX2(shi->mat->ray_depth_tra, shi->mat->ray_depth))) {
                if(R.r.mode & R_RAYTRACE) {
                        if(shi->ray_mirror!=0.0f || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0f)) {
                                /* ray trace works on combined, but gives pass info */
@@ -132,10 +132,13 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
                if(shi->mat->mode & MA_RAYTRANSP) 
                        if((shi->layflag & SCE_LAY_SKY) && (R.r.alphamode==R_ADDSKY))
                                shr->alpha= 1.0f;
-       }       
+       }
+       
+       if(R.r.mode & R_RAYTRACE) {
+               shade_volume_inside(shi, shr);
+       }
 }
 
-
 /* do a shade, finish up some passes, apply mist */
 void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
 {
@@ -151,7 +154,12 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
                memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
                shi->har= shi->mat->har;
                
-               shade_material_loop(shi, shr);
+               if (shi->mat->material_type == MA_SOLID) {
+                       shade_material_loop(shi, shr);
+               } else if (shi->mat->material_type == MA_VOLUME) {
+                       if(R.r.mode & R_RAYTRACE)
+                               shade_volume_outside(shi, shr);
+               }
        }
        
        /* copy additional passes */
@@ -667,6 +675,10 @@ void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float *
                }
        }
        
+       /* set camera coords - for scanline, it's always 0.0,0.0,0.0 (render is in camera space)
+        * however for raytrace it can be different - the position of the last intersection */
+       shi->camera_co[0] = shi->camera_co[1] = shi->camera_co[2] = 0.0f;
+       
        /* cannot normalize earlier, code above needs it at viewplane level */
        Normalize(view);
 }
index 4c627056c1dcfb04f8eaf7784857a709b614db67..04b3a0bd266496c04634bfe897c9f70f2c8d21e5 100644 (file)
@@ -58,7 +58,7 @@
 extern struct Render R;
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 
-static ListBase *get_lights(ShadeInput *shi)
+ListBase *get_lights(ShadeInput *shi)
 {
        
        if(shi->light_override)
index 61e9d9cf4128948900e6c250c0a30c0e116cfa96..d1115e1d399720d18b6621c65bdb3b403018679c 100644 (file)
@@ -64,6 +64,8 @@
 #include "BKE_ipo.h"
 
 #include "envmap.h"
+#include "pointdensity.h"
+#include "voxeldata.h"
 #include "renderpipeline.h"
 #include "render_types.h"
 #include "rendercore.h"
@@ -195,6 +197,23 @@ static int blend(Tex *tex, float *texvec, TexResult *texres)
                y= texvec[1];
        }
 
+       if (tex->extend == TEX_REPEAT) {
+               if (x < -1.0 || x > 1.0) {
+                       const float x2 = (x + 1.0)* 0.5;                        /* to 0.0, 1.0 */
+                       x = (x2 - floor(x2) - 0.5) * 2.0;       /* to -1.0, 1.0 */
+               }
+               if (y < -1.0 || y > 1.0) {
+                       const float y2 = (y + 1.0)* 0.5;                        /* to 0.0, 1.0 */
+                       y = (y2 - floor(y2) - 0.5) * 2.0;       /* to -1.0, 1.0 */
+               }
+       } else if (tex->extend == TEX_CLIP) {
+               if (x < -1.0 || x > 1.0 || y < -1.0 || y > 1.0) {
+                       texres->tin = 0.f;
+                       BRICONT;
+                       return TEX_INT;
+               }
+       }
+
        if(tex->stype==TEX_LIN) {       /* lin */
                texres->tin= (1.0+x)/2.0;
        }
@@ -1253,6 +1272,13 @@ static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex,
                
                retval= mg_distNoiseTex(tex, tmpvec, texres);
                break;
+       case TEX_POINTDENSITY:
+               retval= pointdensitytex(tex, texvec, texres);
+               break;
+       case TEX_VOXELDATA:
+               retval= voxeldatatex(tex, texvec, texres);  
+               break;
+
        }
 
        if (tex->flag & TEX_COLORBAND) {
@@ -1492,6 +1518,164 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen
        return in;
 }
 
+void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, float *val)
+{
+       MTex *mtex;
+       Tex *tex;
+       TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
+       int tex_nr, rgbnor= 0;
+       float co[3], texvec[3];
+       float fact, stencilTin=1.0;
+       
+       if (R.r.scemode & R_NO_TEX) return;
+       /* here: test flag if there's a tex (todo) */
+       
+       for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
+               /* separate tex switching */
+               if(shi->mat->septex & (1<<tex_nr)) continue;
+               
+               if(shi->mat->mtex[tex_nr]) {
+                       mtex= shi->mat->mtex[tex_nr];
+                       tex= mtex->tex;
+                       if(tex==0) continue;
+                       
+                       /* only process if this texture is mapped 
+                        * to one that we're interested in */
+                       if (!(mtex->mapto & mapto_flag)) continue;
+                       
+                       /* which coords */
+                       if(mtex->texco==TEXCO_OBJECT) { 
+                               Object *ob= mtex->object;
+                               ob= mtex->object;
+                               if(ob) {                                                
+                                       VECCOPY(co, xyz);       
+                                       if(mtex->texflag & MTEX_OB_DUPLI_ORIG) {
+                                               if(shi->obi && shi->obi->duplitexmat)
+                                                       MTC_Mat4MulVecfl(shi->obi->duplitexmat, co);                                    
+                                       } 
+                                       MTC_Mat4MulVecfl(ob->imat, co);
+                               }
+                       }
+                       /* not really orco, but 'local' */
+                       else if(mtex->texco==TEXCO_ORCO) {
+                               
+                               if(mtex->texflag & MTEX_DUPLI_MAPTO) {
+                                       VECCOPY(co, shi->duplilo);
+                               }
+                               else {
+                                       Object *ob= shi->obi->ob;
+                                       VECCOPY(co, xyz);
+                                       MTC_Mat4MulVecfl(ob->imat, co);
+                               }
+                       }
+                       else if(mtex->texco==TEXCO_GLOB) {                                                      
+                          VECCOPY(co, xyz);
+                          MTC_Mat4MulVecfl(R.viewinv, co);
+                       }
+                       else continue;  // can happen when texco defines disappear and it renders old files
+
+                       texres.nor= NULL;
+                       
+                       if(tex->type==TEX_IMAGE) {
+                               continue;       /* not supported yet */
+                       }
+                       else {
+                               /* placement */
+                               if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+                               else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+                               if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+                               else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+                               if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+                               else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+                       }
+                       
+
+                       rgbnor= multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output);   /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+                       
+                       /* texture output */
+
+                       if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
+                               texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
+                               rgbnor-= TEX_RGB;
+                       }
+                       if(mtex->texflag & MTEX_NEGATIVE) {
+                               if(rgbnor & TEX_RGB) {
+                                       texres.tr= 1.0-texres.tr;
+                                       texres.tg= 1.0-texres.tg;
+                                       texres.tb= 1.0-texres.tb;
+                               }
+                               texres.tin= 1.0-texres.tin;
+                       }
+                       if(mtex->texflag & MTEX_STENCIL) {
+                               if(rgbnor & TEX_RGB) {
+                                       fact= texres.ta;
+                                       texres.ta*= stencilTin;
+                                       stencilTin*= fact;
+                               }
+                               else {
+                                       fact= texres.tin;
+                                       texres.tin*= stencilTin;
+                                       stencilTin*= fact;
+                               }
+                       }
+                       
+                       
+                       if((mapto_flag & (MAP_COL+MAP_COLMIR)) && (mtex->mapto & (MAP_COL+MAP_COLMIR))) {
+                               float tcol[3], colfac;
+                               
+                               /* stencil maps on the texture control slider, not texture intensity value */
+                               colfac= mtex->colfac*stencilTin;
+                               
+                               if((rgbnor & TEX_RGB)==0) {
+                                       tcol[0]= mtex->r;
+                                       tcol[1]= mtex->g;
+                                       tcol[2]= mtex->b;
+                               } else {
+                                       tcol[0]=texres.tr;
+                                       tcol[1]=texres.tg;
+                                       tcol[2]=texres.tb;
+                               }
+                               
+                               if((mapto_flag & MAP_COL) && (mtex->mapto & MAP_COL)) {
+                                       texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
+                               }
+                               
+                               /* MAP_COLMIR is abused for absorption colour at the moment */
+                               if((mapto_flag & MAP_COLMIR) && (mtex->mapto & MAP_COLMIR)) {
+                                       texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
+                               }
+                       }
+                       
+                       if((mapto_flag & MAP_VARS) && (mtex->mapto & MAP_VARS)) {
+                               /* stencil maps on the texture control slider, not texture intensity value */
+                               float varfac= mtex->varfac*stencilTin;
+                               
+                               /* convert RGB to intensity if intensity info isn't provided */
+                               if (!(rgbnor & TEX_INT)) {
+                                       if (rgbnor & TEX_RGB) {
+                                               if(texres.talpha) texres.tin= texres.ta;
+                                               else texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
+                                       }
+                               }
+                               
+                               if((mapto_flag & MAP_EMIT) && (mtex->mapto & MAP_EMIT)) {
+                                       int flip= mtex->maptoneg & MAP_EMIT;
+
+                                       *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
+                                       if(*val<0.0) *val= 0.0;
+                               }
+                               if((mapto_flag & MAP_ALPHA) && (mtex->mapto & MAP_ALPHA)) {
+                                       int flip= mtex->maptoneg & MAP_ALPHA;
+
+                                       *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
+                                       CLAMP(*val, 0.0, 1.0);
+                               }
+                       }
+               }
+       }
+}
 
 void do_material_tex(ShadeInput *shi)
 {
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
new file mode 100644 (file)
index 0000000..b3cffb4
--- /dev/null
@@ -0,0 +1,712 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_threads.h"
+
+#include "PIL_time.h"
+
+#include "RE_shader_ext.h"
+#include "RE_raytrace.h"
+
+#include "DNA_material_types.h"
+
+#include "render_types.h"
+#include "renderdatabase.h"
+#include "volumetric.h"
+#include "volume_precache.h"
+
+#if defined( _MSC_VER ) && !defined( __cplusplus )
+# define inline __inline
+#endif // defined( _MSC_VER ) && !defined( __cplusplus )
+
+#include "BKE_global.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+/* Recursive test for intersections, from a point inside the mesh, to outside
+ * Number of intersections (depth) determine if a point is inside or outside the mesh */
+int intersect_outside_volume(RayTree *tree, Isect *isect, float *offset, int limit, int depth)
+{
+       if (limit == 0) return depth;
+       
+       if (RE_ray_tree_intersect(tree, isect)) {
+               float hitco[3];
+               
+               hitco[0] = isect->start[0] + isect->labda*isect->vec[0];
+               hitco[1] = isect->start[1] + isect->labda*isect->vec[1];
+               hitco[2] = isect->start[2] + isect->labda*isect->vec[2];
+               VecAddf(isect->start, hitco, offset);
+
+               return intersect_outside_volume(tree, isect, offset, limit-1, depth+1);
+       } else {
+               return depth;
+       }
+}
+
+/* Uses ray tracing to check if a point is inside or outside an ObjectInstanceRen */
+int point_inside_obi(RayTree *tree, ObjectInstanceRen *obi, float *co)
+{
+       float maxsize = RE_ray_tree_max_size(tree);
+       Isect isect;
+       float vec[3] = {0.0f,0.0f,1.0f};
+       int final_depth=0, depth=0, limit=20;
+       
+       /* set up the isect */
+       memset(&isect, 0, sizeof(isect));
+       VECCOPY(isect.start, co);
+       isect.end[0] = co[0] + vec[0] * maxsize;
+       isect.end[1] = co[1] + vec[1] * maxsize;
+       isect.end[2] = co[2] + vec[2] * maxsize;
+       
+       /* and give it a little offset to prevent self-intersections */
+       VecMulf(vec, 1e-5);
+       VecAddf(isect.start, isect.start, vec);
+       
+       isect.mode= RE_RAY_MIRROR;
+       isect.face_last= NULL;
+       isect.lay= -1;
+       
+       final_depth = intersect_outside_volume(tree, &isect, vec, limit, depth);
+       
+       /* even number of intersections: point is outside
+        * odd number: point is inside */
+       if (final_depth % 2 == 0) return 0;
+       else return 1;
+}
+
+static int inside_check_func(Isect *is, int ob, RayFace *face)
+{
+       return 1;
+}
+static void vlr_face_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4)
+{
+       VlakRen *vlr= (VlakRen*)face;
+
+       *v1 = (vlr->v1)? vlr->v1->co: NULL;
+       *v2 = (vlr->v2)? vlr->v2->co: NULL;
+       *v3 = (vlr->v3)? vlr->v3->co: NULL;
+       *v4 = (vlr->v4)? vlr->v4->co: NULL;
+}
+
+RayTree *create_raytree_obi(ObjectInstanceRen *obi, float *bbmin, float *bbmax)
+{
+       int v;
+       VlakRen *vlr= NULL;
+       
+       /* create empty raytree */
+       RayTree *tree = RE_ray_tree_create(64, obi->obr->totvlak, bbmin, bbmax,
+               vlr_face_coords, inside_check_func, NULL, NULL);
+       
+       /* fill it with faces */
+       for(v=0; v<obi->obr->totvlak; v++) {
+               if((v & 255)==0)
+                       vlr= obi->obr->vlaknodes[v>>8].vlak;
+               else
+                       vlr++;
+       
+               RE_ray_tree_add_face(tree, 0, vlr);
+       }
+       
+       RE_ray_tree_done(tree);
+       
+       return tree;
+}
+
+static float get_avg_surrounds(float *cache, int res, int res_2, int res_3, int rgb, int xx, int yy, int zz)
+{
+       int x, y, z, x_, y_, z_;
+       int added=0;
+       float tot=0.0f;
+       int i;
+       
+       for (x=-1; x <= 1; x++) {
+               x_ = xx+x;
+               if (x_ >= 0 && x_ <= res-1) {
+               
+                       for (y=-1; y <= 1; y++) {
+                               y_ = yy+y;
+                               if (y_ >= 0 && y_ <= res-1) {
+                               
+                                       for (z=-1; z <= 1; z++) {
+                                               z_ = zz+z;
+                                               if (z_ >= 0 && z_ <= res-1) {
+                                               
+                                                       i = rgb*res_3 + x_*res_2 + y_*res + z_;
+                                                       if (cache[i] > 0.0f) {
+                                                               tot += cache[i];
+                                                               added++;
+                                                       }
+                                                       
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       tot /= added;
+       
+       return ((added>0)?tot:0.0f);
+}
+
+/* function to filter the edges of the light cache, where there was no volume originally.
+ * For each voxel which was originally external to the mesh, it finds the average values of
+ * the surrounding internal voxels and sets the original external voxel to that average amount.
+ * Works almost a bit like a 'dilate' filter */
+static void lightcache_filter(float *cache, int res)
+{
+       int x, y, z, rgb;
+       int res_2, res_3;
+       int i;
+       
+       res_2 = res*res;
+       res_3 = res*res*res;
+
+       for (x=0; x < res; x++) {
+               for (y=0; y < res; y++) {
+                       for (z=0; z < res; z++) {
+                               for (rgb=0; rgb < 3; rgb++) {
+                                       i = rgb*res_3 + x*res_2 + y*res + z;
+
+                                       /* trigger for outside mesh */
+                                       if (cache[i] < -0.5f) cache[i] = get_avg_surrounds(cache, res, res_2, res_3, rgb, x, y, z);
+                               }
+                       }
+               }
+       }
+}
+
+static inline int I(int x,int y,int z,int n) //has a pad of 1 voxel surrounding the core for boundary simulation
+{ 
+       return (x*(n+2)+y)*(n+2)+z;
+}
+
+
+/* get the total amount of light energy in the light cache. used to normalise after multiple scattering */
+static float total_ss_energy(float *cache, const int res)
+{
+       int x, y, z, rgb;
+       int res_2, res_3;
+       int i;
+       float energy=0.f;
+       
+       res_2 = res*res;
+       res_3 = res*res*res;
+
+       for (x=0; x < res; x++) {
+               for (y=0; y < res; y++) {
+                       for (z=0; z < res; z++) {
+                               for (rgb=0; rgb < 3; rgb++) {
+                                       i = rgb*res_3 + x*res_2 + y*res + z;
+                                       
+                                       if (cache[i] > 0.f) energy += cache[i];
+                               }
+                       }
+               }
+       }
+       
+       return energy;
+}
+
+static float total_ms_energy(float *sr, float *sg, float *sb, const int res)
+{
+       int x, y, z, i;
+       float energy=0.f;
+       
+       for (z=1;z<=res;z++) {
+               for (y=1;y<=res;y++) {
+                       for (x=1;x<=res;x++) {
+                       
+                               i = I(x,y,z,res);
+                               if (sr[i] > 0.f) energy += sr[i];
+                               if (sg[i] > 0.f) energy += sg[i];
+                               if (sb[i] > 0.f) energy += sb[i];
+                       }
+               }
+       }
+       
+       return energy;
+}
+
+static void ms_diffuse(int b, float* x0, float* x, float diff, int n)
+{
+       int i, j, k, l;
+       const float dt = VOL_MS_TIMESTEP;
+       const float a = dt*diff*n*n*n;
+       
+       for (l=0; l<20; l++)
+       {
+               for (k=1; k<=n; k++)
+               {
+                       for (j=1; j<=n; j++)
+                       {
+                               for (i=1; i<=n; i++)
+                               {
+                                       x[I(i,j,k,n)] = (x0[I(i,j,k,n)] + a*(
+                                                                                                                x[I(i-1,j,k,n)]+x[I(i+1,j,k,n)]+
+                                                                                                                x[I(i,j-1,k,n)]+x[I(i,j+1,k,n)]+
+                                                                                                                x[I(i,j,k-1,n)]+x[I(i,j,k+1,n)]))/(1+6*a);
+                               }
+                       }
+               }
+       }
+}
+
+void multiple_scattering_diffusion(Render *re, float *cache, int res, Material *ma)
+{
+       const float diff = ma->vol_ms_diff * 0.001f;    /* compensate for scaling for a nicer UI range */
+       const float simframes = ma->vol_ms_steps;
+       const int shade_type = ma->vol_shade_type;
+       float fac = ma->vol_ms_intensity;
+       
+       int i, j, k, m;
+       int n = res;
+       const int size = (n+2)*(n+2)*(n+2);
+       double time, lasttime= PIL_check_seconds_timer();
+       float total;
+       float c=1.0f;
+       int index;
+       float origf;    /* factor for blending in original light cache */
+       float energy_ss, energy_ms;
+
+       float *sr0=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer");
+       float *sr=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer");
+       float *sg0=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer");
+       float *sg=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer");
+       float *sb0=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer");
+       float *sb=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer");
+
+       total = (float)(n*n*n*simframes);
+       
+       energy_ss = total_ss_energy(cache, res);
+       
+       /* Scattering as diffusion pass */
+       for (m=0; m<simframes; m++)
+       {
+               /* add sources */
+               for (k=1; k<=n; k++)
+               {
+                       for (j=1; j<=n; j++)
+                       {
+                               for (i=1; i<=n; i++)
+                               {
+                                       time= PIL_check_seconds_timer();
+                                       c++;
+                                       
+                                       index=(i-1)*n*n + (j-1)*n + k-1;
+                                       
+                                       if (cache[index] > 0.0f)
+                                               sr[I(i,j,k,n)] += cache[index];
+                                       if (cache[1*n*n*n + index] > 0.0f)
+                                               sg[I(i,j,k,n)] += cache[1*n*n*n + index];
+                                       if (cache[2*n*n*n + index] > 0.0f)
+                                               sb[I(i,j,k,n)] += cache[2*n*n*n + index];
+
+
+                                       /* Displays progress every second */
+                                       if(time-lasttime>1.0f) {
+                                               char str[64];
+                                               sprintf(str, "Simulating multiple scattering: %d%%", (int)
+                                                               (100.0f * (c / total)));
+                                               re->i.infostr= str;
+                                               re->stats_draw(&re->i);
+                                               re->i.infostr= NULL;
+                                               lasttime= time;
+                                       }
+                               }
+                       }
+               }
+               SWAP(float *, sr, sr0);
+               SWAP(float *, sg, sg0);
+               SWAP(float *, sb, sb0);
+
+               /* main diffusion simulation */
+               ms_diffuse(0, sr0, sr, diff, n);
+               ms_diffuse(0, sg0, sg, diff, n);
+               ms_diffuse(0, sb0, sb, diff, n);
+               
+               if (re->test_break()) break;
+       }
+       
+       /* normalisation factor to conserve energy */
+       energy_ms = total_ms_energy(sr, sg, sb, res);
+       fac *= (energy_ss / energy_ms);
+       
+       /* blend multiple scattering back in the light cache */
+       if (shade_type == MA_VOL_SHADE_SINGLEPLUSMULTIPLE) {
+               /* conserve energy - half single, half multiple */
+               origf = 0.5f;
+               fac *= 0.5f;
+       } else {
+               origf = 0.0f;
+       }
+
+       for (k=1;k<=n;k++)
+       {
+               for (j=1;j<=n;j++)
+               {
+                       for (i=1;i<=n;i++)
+                       {
+                               index=(i-1)*n*n + (j-1)*n + k-1;
+                               cache[index]                    = origf * cache[index]  + fac * sr[I(i,j,k,n)];
+                               cache[1*n*n*n + index]  = origf * cache[1*n*n*n + index] + fac * sg[I(i,j,k,n)];
+                               cache[2*n*n*n + index]  = origf * cache[2*n*n*n + index] + fac * sb[I(i,j,k,n)];
+                       }
+               }
+       }
+
+       MEM_freeN(sr0);
+       MEM_freeN(sr);
+       MEM_freeN(sg0);
+       MEM_freeN(sg);
+       MEM_freeN(sb0);
+       MEM_freeN(sb);
+}
+
+
+
+#if 0 // debug stuff
+static void *vol_precache_part_test(void *data)
+{
+       VolPrecachePart *pa = data;
+
+       printf("part number: %d \n", pa->num);
+       printf("done: %d \n", pa->done);
+       printf("x min: %d   x max: %d \n", pa->minx, pa->maxx);
+       printf("y min: %d   y max: %d \n", pa->miny, pa->maxy);
+       printf("z min: %d   z max: %d \n", pa->minz, pa->maxz);
+
+       return NULL;
+}
+#endif
+
+/* Iterate over the 3d voxel grid, and fill the voxels with scattering information
+ *
+ * It's stored in memory as 3 big float grids next to each other, one for each RGB channel.
+ * I'm guessing the memory alignment may work out better this way for the purposes
+ * of doing linear interpolation, but I haven't actually tested this theory! :)
+ */
+static void *vol_precache_part(void *data)
+{
+       VolPrecachePart *pa =  (VolPrecachePart *)data;
+       ObjectInstanceRen *obi = pa->obi;
+       RayTree *tree = pa->tree;
+       ShadeInput *shi = pa->shi;
+       float density, scatter_col[3] = {0.f, 0.f, 0.f};
+       float co[3];
+       int x, y, z;
+       const int res=pa->res, res_2=pa->res*pa->res, res_3=pa->res*pa->res*pa->res;
+       const float stepsize = vol_get_stepsize(shi, STEPSIZE_VIEW);
+
+       for (x= pa->minx; x < pa->maxx; x++) {
+               co[0] = pa->bbmin[0] + (pa->voxel[0] * x);
+               
+               for (y= pa->miny; y < pa->maxy; y++) {
+                       co[1] = pa->bbmin[1] + (pa->voxel[1] * y);
+                       
+                       for (z=pa->minz; z < pa->maxz; z++) {
+                               co[2] = pa->bbmin[2] + (pa->voxel[2] * z);
+                               
+                               // don't bother if the point is not inside the volume mesh
+                               if (!point_inside_obi(tree, obi, co)) {
+                                       obi->volume_precache[0*res_3 + x*res_2 + y*res + z] = -1.0f;
+                                       obi->volume_precache[1*res_3 + x*res_2 + y*res + z] = -1.0f;
+                                       obi->volume_precache[2*res_3 + x*res_2 + y*res + z] = -1.0f;
+                                       continue;
+                               }
+                               
+                               VecCopyf(shi->view, co);
+                               Normalize(shi->view);
+                               density = vol_get_density(shi, co);
+                               vol_get_scattering(shi, scatter_col, co, stepsize, density);
+                       
+                               obi->volume_precache[0*res_3 + x*res_2 + y*res + z] = scatter_col[0];
+                               obi->volume_precache[1*res_3 + x*res_2 + y*res + z] = scatter_col[1];
+                               obi->volume_precache[2*res_3 + x*res_2 + y*res + z] = scatter_col[2];
+                       }
+               }
+       }
+       
+       pa->done = 1;
+       
+       return 0;
+}
+
+
+static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma, ShadeInput *shi)
+{
+       memset(shi, 0, sizeof(ShadeInput)); 
+       shi->depth= 1;
+       shi->mask= 1;
+       shi->mat = ma;
+       shi->vlr = NULL;
+       memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));        // note, keep this synced with render_types.h
+       shi->har= shi->mat->har;
+       shi->obi= obi;
+       shi->obr= obi->obr;
+       shi->lay = re->scene->lay;
+}
+
+static void precache_init_parts(Render *re, RayTree *tree, ShadeInput *shi, ObjectInstanceRen *obi, float *bbmin, float *bbmax, int res, int totthread, int *parts)
+{
+       int i=0, x, y, z;
+       float voxel[3];
+       int sizex, sizey, sizez;
+       int minx, maxx;
+       int miny, maxy;
+       int minz, maxz;
+       
+       BLI_freelistN(&re->volume_precache_parts);
+       
+       /* currently we just subdivide the box, number of threads per side */
+       parts[0] = parts[1] = parts[2] = totthread;
+       
+       VecSubf(voxel, bbmax, bbmin);
+       if ((voxel[0] < FLT_EPSILON) || (voxel[1] < FLT_EPSILON) || (voxel[2] < FLT_EPSILON))
+               return;
+       VecMulf(voxel, 1.0f/res);
+
+       for (x=0; x < parts[0]; x++) {
+               sizex = ceil(res / (float)parts[0]);
+               minx = x * sizex;
+               maxx = minx + sizex;
+               maxx = (maxx>res)?res:maxx;
+               
+               for (y=0; y < parts[1]; y++) {
+                       sizey = ceil(res / (float)parts[1]);
+                       miny = y * sizey;
+                       maxy = miny + sizey;
+                       maxy = (maxy>res)?res:maxy;
+                       
+                       for (z=0; z < parts[2]; z++) {
+                               VolPrecachePart *pa= MEM_callocN(sizeof(VolPrecachePart), "new precache part");
+                               
+                               sizez = ceil(res / (float)parts[2]);
+                               minz = z * sizez;
+                               maxz = minz + sizez;
+                               maxz = (maxz>res)?res:maxz;
+                                               
+                               pa->done = 0;
+                               pa->working = 0;
+                               
+                               pa->num = i;
+                               pa->tree = tree;
+                               pa->shi = shi;
+                               pa->obi = obi;
+                               VECCOPY(pa->bbmin, bbmin);
+                               VECCOPY(pa->voxel, voxel);
+                               pa->res = res;
+                               
+                               pa->minx = minx; pa->maxx = maxx;
+                               pa->miny = miny; pa->maxy = maxy;
+                               pa->minz = minz; pa->maxz = maxz;
+                               
+                               
+                               BLI_addtail(&re->volume_precache_parts, pa);
+                               
+                               i++;
+                       }
+               }
+       }
+}
+
+static VolPrecachePart *precache_get_new_part(Render *re)
+{
+       VolPrecachePart *pa, *nextpa=NULL;
+       
+       for (pa = re->volume_precache_parts.first; pa; pa=pa->next)
+       {
+               if (pa->done==0 && pa->working==0) {
+                       nextpa = pa;
+                       break;
+               }
+       }
+
+       return nextpa;
+}
+
+/* Precache a volume into a 3D voxel grid.
+ * The voxel grid is stored in the ObjectInstanceRen, 
+ * in camera space, aligned with the ObjectRen's bounding box.
+ * Resolution is defined by the user.
+ */
+void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma, float *bbmin, float *bbmax)
+{
+       VolPrecachePart *nextpa, *pa;
+       RayTree *tree;
+       ShadeInput shi;
+       ListBase threads;
+       const int res = ma->vol_precache_resolution;
+       int parts[3], totparts;
+       
+       int caching=1, counter=0;
+       int totthread = re->r.threads;
+       
+       double time, lasttime= PIL_check_seconds_timer();
+       
+       R = *re;
+
+       /* create a raytree with just the faces of the instanced ObjectRen, 
+        * used for checking if the cached point is inside or outside. */
+       tree = create_raytree_obi(obi, bbmin, bbmax);
+       if (!tree) return;
+       
+       obi->volume_precache = MEM_callocN(sizeof(float)*res*res*res*3, "volume light cache");
+
+       /* Need a shadeinput to calculate scattering */
+       precache_setup_shadeinput(re, obi, ma, &shi);
+       
+       precache_init_parts(re, tree, &shi, obi, bbmin, bbmax, res, totthread, parts);
+       totparts = parts[0] * parts[1] * parts[2];
+       
+       BLI_init_threads(&threads, vol_precache_part, totthread);
+       
+       while(caching) {
+
+               if(BLI_available_threads(&threads) && !(re->test_break())) {
+                       nextpa = precache_get_new_part(re);
+                       if (nextpa) {
+                               nextpa->working = 1;
+                               BLI_insert_thread(&threads, nextpa);
+                       }
+               }
+               else PIL_sleep_ms(50);
+
+               caching=0;
+               counter=0;
+               for(pa= re->volume_precache_parts.first; pa; pa= pa->next) {
+                       
+                       if(pa->done) {
+                               counter++;
+                               BLI_remove_thread(&threads, pa);
+                       } else
+                               caching = 1;
+               }
+               
+               if (re->test_break() && BLI_available_threads(&threads)==totthread)
+                       caching=0;
+               
+               time= PIL_check_seconds_timer();
+               if(time-lasttime>1.0f) {
+                       char str[64];
+                       sprintf(str, "Precaching volume: %d%%", (int)(100.0f * ((float)counter / (float)totparts)));
+                       re->i.infostr= str;
+                       re->stats_draw(&re->i);
+                       re->i.infostr= NULL;
+                       lasttime= time;
+               }
+       }
+       
+       BLI_end_threads(&threads);
+       BLI_freelistN(&re->volume_precache_parts);
+       
+       if(tree) {
+               RE_ray_tree_free(tree);
+               tree= NULL;
+       }
+       
+       lightcache_filter(obi->volume_precache, res);
+       
+       if (ELEM(ma->vol_shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE))
+       {
+               multiple_scattering_diffusion(re, obi->volume_precache, res, ma);
+       }
+}
+
+int using_lightcache(Material *ma)
+{
+       return (((ma->vol_shadeflag & MA_VOL_PRECACHESHADING) && (ma->vol_shade_type == MA_VOL_SHADE_SINGLE))
+               || (ELEM(ma->vol_shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE)));
+}
+
+/* loop through all objects (and their associated materials)
+ * marked for pre-caching in convertblender.c, and pre-cache them */
+void volume_precache(Render *re)
+{
+       ObjectInstanceRen *obi;
+       VolumeOb *vo;
+
+       /* ignore light cache and multiple scattering for preview render .. for now? */
+       if (re->r.scemode & R_PREVIEWBUTS) return;
+
+       for(vo= re->volumes.first; vo; vo= vo->next) {
+               if (using_lightcache(vo->ma)) {
+                       for(obi= re->instancetable.first; obi; obi= obi->next) {
+                               if (obi->obr == vo->obr) {
+                                       vol_precache_objectinstance_threads(re, obi, vo->ma, obi->obr->boundbox[0], obi->obr->boundbox[1]);
+                               }
+                       }
+               }
+       }
+       
+       re->i.infostr= NULL;
+       re->stats_draw(&re->i);
+}
+
+void free_volume_precache(Render *re)
+{
+       ObjectInstanceRen *obi;
+       
+       for(obi= re->instancetable.first; obi; obi= obi->next) {
+               if (obi->volume_precache)
+                       MEM_freeN(obi->volume_precache);
+       }
+       
+       BLI_freelistN(&re->volumes);
+}
+
+int point_inside_volume_objectinstance(ObjectInstanceRen *obi, float *co)
+{
+       RayTree *tree;
+       int inside=0;
+       
+       tree = create_raytree_obi(obi, obi->obr->boundbox[0], obi->obr->boundbox[1]);
+       if (!tree) return 0;
+       
+       inside = point_inside_obi(tree, obi, co);
+       
+       RE_ray_tree_free(tree);
+       tree= NULL;
+       
+       return inside;
+}
+
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
new file mode 100644 (file)
index 0000000..01c4ac8
--- /dev/null
@@ -0,0 +1,771 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Matt Ebb, Raul Fernandez Hernandez (Farsthary)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "RE_shader_ext.h"
+#include "RE_raytrace.h"
+
+#include "DNA_material_types.h"
+#include "DNA_group_types.h"
+#include "DNA_lamp_types.h"
+
+#include "BKE_global.h"
+
+#include "render_types.h"
+#include "pixelshading.h"
+#include "shading.h"
+#include "texture.h"
+#include "volumetric.h"
+
+#if defined( _MSC_VER ) && !defined( __cplusplus )
+# define inline __inline
+#endif // defined( _MSC_VER ) && !defined( __cplusplus )
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static int vol_backface_intersect_check(Isect *is, int ob, RayFace *face)
+{
+       VlakRen *vlr = (VlakRen *)face;
+       
+       /* only consider faces away, so overlapping layers
+        * of foward facing geometry don't cause the ray to stop */
+       return (INPR(is->vec, vlr->n) < 0.0f);
+}
+
+/* TODO: Box or sphere intersection types could speed things up */
+static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco, Isect *isect, int intersect_type, int checkfunc)
+{
+       float maxsize = RE_ray_tree_max_size(R.raytree);
+       int intersected=0;
+
+       /* TODO: use object's bounding box to calculate max size */
+       VECCOPY(isect->start, co);
+       isect->end[0] = co[0] + vec[0] * maxsize;
+       isect->end[1] = co[1] + vec[1] * maxsize;
+       isect->end[2] = co[2] + vec[2] * maxsize;
+       
+       isect->mode= RE_RAY_MIRROR;
+       isect->oborig= RAY_OBJECT_SET(&R, shi->obi);
+       isect->face_last= NULL;
+       isect->ob_last= 0;
+       isect->lay= -1;
+       
+       if (intersect_type == VOL_BOUNDS_DEPTH) isect->faceorig= (RayFace*)shi->vlr;
+       else if (intersect_type == VOL_BOUNDS_SS) isect->faceorig= NULL;
+       
+       if (checkfunc==VOL_IS_BACKFACE)
+               intersected = RE_ray_tree_intersect_check(R.raytree, isect, vol_backface_intersect_check);
+       else
+               intersected = RE_ray_tree_intersect(R.raytree, isect);
+       
+       if(intersected)
+       {
+               float isvec[3];
+
+               VECCOPY(isvec, isect->vec);
+               hitco[0] = isect->start[0] + isect->labda*isvec[0];
+               hitco[1] = isect->start[1] + isect->labda*isvec[1];
+               hitco[2] = isect->start[2] + isect->labda*isvec[2];
+               
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+float vol_get_stepsize(struct ShadeInput *shi, int context)
+{
+       if (shi->mat->vol_stepsize_type == MA_VOL_STEP_RANDOMIZED) {
+               /* range between 0.75 and 1.25 */
+               const float rnd = 0.5f * BLI_thread_frand(shi->thread) + 0.75f;
+       
+               if (context == STEPSIZE_VIEW)
+                       return shi->mat->vol_stepsize * rnd;
+               else if (context == STEPSIZE_SHADE)
+                       return shi->mat->vol_shade_stepsize * rnd;
+       }
+       else {  // MA_VOL_STEP_CONSTANT
+               
+               if (context == STEPSIZE_VIEW)
+                       return shi->mat->vol_stepsize;
+               else if (context == STEPSIZE_SHADE)
+                       return shi->mat->vol_shade_stepsize;
+       }
+       
+       return shi->mat->vol_stepsize;
+}
+
+static float vol_get_depth_cutoff(struct ShadeInput *shi)
+{
+       return shi->mat->vol_depth_cutoff;
+}
+
+/* SHADING */
+
+static float D(ShadeInput *shi, int rgb, int x, int y, int z)
+{
+       const int res = shi->mat->vol_precache_resolution;
+       CLAMP(x, 0, res-1);
+       CLAMP(y, 0, res-1);
+       CLAMP(z, 0, res-1);
+       return shi->obi->volume_precache[rgb*res*res*res + x*res*res + y*res + z];
+}
+
+static inline float lerp(float t, float v1, float v2) {
+       return (1.f - t) * v1 + t * v2;
+}
+
+/* trilinear interpolation */
+static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, float *co)
+{
+       const int res = shi->mat->vol_precache_resolution;
+       float voxx, voxy, voxz;
+       int vx, vy, vz;
+       float dx, dy, dz;
+       float d00, d10, d01, d11, d0, d1, d_final;
+       float bbmin[3], bbmax[3], dim[3];
+       int rgb;
+       
+       if (!shi->obi->volume_precache) return;
+       
+       VECCOPY(bbmin, shi->obi->obr->boundbox[0]);
+       VECCOPY(bbmax, shi->obi->obr->boundbox[1]);
+       VecSubf(dim, bbmax, bbmin);
+       
+       voxx = ((co[0] - bbmin[0]) / dim[0]) * res - 0.5f;
+       voxy = ((co[1] - bbmin[1]) / dim[1]) * res - 0.5f;
+       voxz = ((co[2] - bbmin[2]) / dim[2]) * res - 0.5f;
+       
+       vx = (int)voxx; vy = (int)voxy; vz = (int)voxz;
+       
+       dx = voxx - vx; dy = voxy - vy; dz = voxz - vz;
+       
+       for (rgb=0; rgb < 3; rgb++) {
+               d00 = lerp(dx, D(shi, rgb, vx, vy, vz),                 D(shi, rgb, vx+1, vy, vz));
+               d10 = lerp(dx, D(shi, rgb, vx, vy+1, vz),               D(shi, rgb, vx+1, vy+1, vz));
+               d01 = lerp(dx, D(shi, rgb, vx, vy, vz+1),               D(shi, rgb, vx+1, vy, vz+1));
+               d11 = lerp(dx, D(shi, rgb, vx, vy+1, vz+1),     D(shi, rgb, vx+1, vy+1, vz+1));
+               d0 = lerp(dy, d00, d10);
+               d1 = lerp(dy, d01, d11);
+               d_final = lerp(dz, d0, d1);
+               
+               scatter_col[rgb] = d_final;
+       }
+}
+
+/* no interpolation */
+static void vol_get_precached_scattering_nearest(ShadeInput *shi, float *scatter_col, float *co)
+{
+       const int res = shi->mat->vol_precache_resolution;
+       int x,y,z;
+       float bbmin[3], bbmax[3], dim[3];
+
+       if (!shi->obi->volume_precache) return;
+       
+       VECCOPY(bbmin, shi->obi->obr->boundbox[0]);
+       VECCOPY(bbmax, shi->obi->obr->boundbox[1]);
+       VecSubf(dim, bbmax, bbmin);
+       
+       x = (int)(((co[0] - bbmin[0]) / dim[0]) * res);
+       y = (int)(((co[1] - bbmin[1]) / dim[1]) * res);
+       z = (int)(((co[2] - bbmin[2]) / dim[2]) * res);
+       
+       scatter_col[0] = shi->obi->volume_precache[0*res*res*res + x*res*res + y*res + z];
+       scatter_col[1] = shi->obi->volume_precache[1*res*res*res + x*res*res + y*res + z];
+       scatter_col[2] = shi->obi->volume_precache[2*res*res*res + x*res*res + y*res + z];
+}
+
+float vol_get_density(struct ShadeInput *shi, float *co)
+{
+       float density = shi->mat->alpha;
+       float density_scale = shi->mat->vol_density_scale;
+       float col[3] = {0.0, 0.0, 0.0};
+       
+       if (shi->mat->flag & MA_IS_TEXTURED) {
+               do_volume_tex(shi, co, MAP_ALPHA, col, &density);
+       }
+       
+       return density * density_scale;
+}
+
+/* compute emission component, amount of radiance to add per segment
+ * can be textured with 'emit' */
+void vol_get_emission(ShadeInput *shi, float *em, float *co, float density)
+{
+       float emission = shi->mat->emit;
+       float col[3] = {0.0, 0.0, 0.0};
+       
+       VECCOPY(col, &shi->mat->r);
+       
+       do_volume_tex(shi, co, MAP_EMIT+MAP_COL, col, &emission);
+       
+       em[0] = em[1] = em[2] = emission * density;
+       VecMulVecf(em, em, col);
+}
+
+/* scattering multiplier, values above 1.0 are non-physical, 
+ * but can be useful to tweak lighting */
+void vol_get_scattering_fac(ShadeInput *shi, float *scatter_fac, float *co, float density)
+{
+       *scatter_fac = shi->mat->vol_scattering;
+}
+
+/* phase function - determines in which directions the light 
+ * is scattered in the volume relative to incoming direction 
+ * and view direction */
+float vol_get_phasefunc(ShadeInput *shi, short phasefunc_type, float g, float *w, float *wp)
+{
+       const float costheta = Inpf(w, wp);
+       
+       if (phasefunc_type == MA_VOL_PH_ISOTROPIC) {
+               return 1.f / (4.f * M_PI);
+       }
+       else if (phasefunc_type == MA_VOL_PH_MIEHAZY) {
+               return (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)) / (4.f*M_PI);
+       }
+       else if (phasefunc_type == MA_VOL_PH_MIEMURKY) {
+               return (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)) / (4.f*M_PI);
+       }
+       else if (phasefunc_type == MA_VOL_PH_RAYLEIGH) {
+               return 3.f/(16.f*M_PI) * (1 + costheta * costheta);
+       }
+       else if (phasefunc_type == MA_VOL_PH_HG) {
+               return 1.f / (4.f * M_PI) * (1.f - g*g) / powf(1.f + g*g - 2.f * g * costheta, 1.5f);
+       }
+       else if (phasefunc_type == MA_VOL_PH_SCHLICK) {
+               const float k = 1.55f * g - .55f * g * g * g;
+               const float kcostheta = k * costheta;
+               return 1.f / (4.f * M_PI) * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta));
+       } else {
+               return 1.0f;
+       }
+}
+
+void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co)
+{
+       float dummy = 1.0f;
+       const float absorption = shi->mat->vol_absorption;
+       
+       VECCOPY(absorb_col, shi->mat->vol_absorption_col);
+       
+       if (shi->mat->flag & MA_IS_TEXTURED)
+               do_volume_tex(shi, co, MAP_COLMIR, absorb_col, &dummy);
+       
+       absorb_col[0] = (1.0f - absorb_col[0]) * absorption;
+       absorb_col[1] = (1.0f - absorb_col[1]) * absorption;
+       absorb_col[2] = (1.0f - absorb_col[2]) * absorption;
+}
+
+/* Compute attenuation, otherwise known as 'optical thickness', extinction, or tau.
+ * Used in the relationship Transmittance = e^(-attenuation)
+ */
+void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, float density, float stepsize)
+{
+       /* input density = density at co */
+       float absorb_col[3];
+       int s, nsteps;
+       float step_vec[3], step_sta[3], step_end[3];
+       const float dist = VecLenf(co, endco);
+
+       vol_get_absorption(shi, absorb_col, co);
+
+       nsteps = (int)((dist / stepsize) + 0.5);
+       
+       /* trigger for recalculating density */
+       if (density < -0.001f) density = vol_get_density(shi, co);
+       
+       if (nsteps == 1) {
+               /* homogenous volume within the sampled distance */
+               tau[0] = tau[1] = tau[2] = dist * density;
+               
+               VecMulVecf(tau, tau, absorb_col);
+               return;
+       } else {
+               tau[0] = tau[1] = tau[2] = 0.0;
+       }
+       
+       VecSubf(step_vec, endco, co);
+       VecMulf(step_vec, 1.0f / nsteps);
+       
+       VecCopyf(step_sta, co);
+       VecAddf(step_end, step_sta, step_vec);
+       
+       for (s = 0;  s < nsteps; s++) {
+               if (s > 0)
+                       density = vol_get_density(shi, step_sta);
+               
+               tau[0] += stepsize * density;
+               tau[1] += stepsize * density;
+               tau[2] += stepsize * density;
+               
+               if (s < nsteps-1) {
+                       VECCOPY(step_sta, step_end);
+                       VecAddf(step_end, step_end, step_vec);
+               }
+       }
+       VecMulVecf(tau, tau, absorb_col);
+}
+
+void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *lacol, float stepsize, float density)
+{
+       float visifac, lv[3], lampdist;
+       float tau[3], tr[3]={1.0,1.0,1.0};
+       float hitco[3], *atten_co;
+       float p;
+       float scatter_fac;
+       float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE);
+       
+       if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return;
+       if ((lar->lay & shi->lay)==0) return;
+       if (lar->energy == 0.0) return;
+       
+       visifac= lamp_get_visibility(lar, co, lv, &lampdist);
+       if(visifac==0.0f) return;
+
+       lacol[0] = lar->r;
+       lacol[1] = lar->g;
+       lacol[2] = lar->b;
+       
+       if(lar->mode & LA_TEXTURE) {
+               shi->osatex= 0;
+               do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE);
+       }
+
+       VecMulf(lacol, visifac*lar->energy);
+
+       if (ELEM(lar->type, LA_SUN, LA_HEMI))
+               VECCOPY(lv, lar->vec);
+       VecMulf(lv, -1.0f);
+       
+       p = vol_get_phasefunc(shi, shi->mat->vol_phasefunc_type, shi->mat->vol_phasefunc_g, shi->view, lv);
+       VecMulf(lacol, p);
+       
+       if (shi->mat->vol_shade_type != MA_VOL_SHADE_NONE) {
+               Isect is;
+               
+               /* find minimum of volume bounds, or lamp coord */
+               if (vol_get_bounds(shi, co, lv, hitco, &is, VOL_BOUNDS_SS, 0)) {
+                       float dist = VecLenf(co, hitco);
+                       VlakRen *vlr = (VlakRen *)is.face;
+                       
+                       /* simple internal shadowing */
+                       if (vlr->mat->material_type == MA_SOLID) {
+                               lacol[0] = lacol[1] = lacol[2] = 0.0f;
+                               return;
+                       }
+
+                       if (ELEM(lar->type, LA_SUN, LA_HEMI))
+                               atten_co = hitco;
+                       else if ( lampdist < dist ) {
+                               atten_co = lar->co;
+                       } else
+                               atten_co = hitco;
+                       
+                       vol_get_attenuation(shi, tau, co, atten_co, density, shade_stepsize);
+                       tr[0] = exp(-tau[0]);
+                       tr[1] = exp(-tau[1]);
+                       tr[2] = exp(-tau[2]);
+                       
+                       VecMulVecf(lacol, lacol, tr);
+               }
+               else {
+                       /* Point is on the outside edge of the volume,
+                        * therefore no attenuation, full transmission.
+                        * Radiance from lamp remains unchanged */
+               }
+       }
+       
+       vol_get_scattering_fac(shi, &scatter_fac, co, density);
+       VecMulf(lacol, scatter_fac);
+}
+
+/* single scattering only for now */
+void vol_get_scattering(ShadeInput *shi, float *scatter, float *co, float stepsize, float density)
+{
+       ListBase *lights;
+       GroupObject *go;
+       LampRen *lar;
+       float col[3] = {0.f, 0.f, 0.f};
+       int i=0;
+
+       lights= get_lights(shi);
+       for(go=lights->first; go; go= go->next)
+       {
+               float lacol[3] = {0.f, 0.f, 0.f};
+       
+               i++;
+       
+               lar= go->lampren;
+               if (lar) {
+                       vol_shade_one_lamp(shi, co, lar, lacol, stepsize, density);
+                       VecAddf(col, col, lacol);
+               }
+       }
+       
+       VECCOPY(scatter, col);
+}
+
+       
+/*
+The main volumetric integrator, using an emission/absorption/scattering model.
+
+Incoming radiance = 
+
+outgoing radiance from behind surface * beam transmittance/attenuation
++ added radiance from all points along the ray due to participating media
+       --> radiance for each segment = 
+               (radiance added by scattering + radiance added by emission) * beam transmittance/attenuation
+
+-- To find transmittance:
+       compute optical thickness with tau (perhaps involving monte carlo integration)
+       transmittance = exp(-tau)
+       
+-- To find radiance from segments along the way:
+       find radiance for one step: 
+       - loop over lights and weight by phase function
+*/
+static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco)
+{
+       float tr[3] = {1.0f, 1.0f, 1.0f};
+       float radiance[3] = {0.f, 0.f, 0.f}, d_radiance[3] = {0.f, 0.f, 0.f};
+       float stepsize = vol_get_stepsize(shi, STEPSIZE_VIEW);
+       int nsteps, s;
+       float tau[3], emit_col[3], scatter_col[3] = {0.0, 0.0, 0.0};
+       float stepvec[3], step_sta[3], step_end[3], step_mid[3];
+       float density = vol_get_density(shi, co);
+       const float depth_cutoff = vol_get_depth_cutoff(shi);
+       
+       /* multiply col_behind with beam transmittance over entire distance */
+       vol_get_attenuation(shi, tau, co, endco, density, stepsize);
+       tr[0] *= exp(-tau[0]);
+       tr[1] *= exp(-tau[1]);
+       tr[2] *= exp(-tau[2]);
+       VecMulVecf(radiance, tr, col);  
+       tr[0] = tr[1] = tr[2] = 1.0f;
+       
+       /* ray marching */
+       nsteps = (int)((VecLenf(co, endco) / stepsize) + 0.5);
+       
+       VecSubf(stepvec, endco, co);
+       VecMulf(stepvec, 1.0f / nsteps);
+       VecCopyf(step_sta, co);
+       VecAddf(step_end, step_sta, stepvec);
+       
+       /* get radiance from all points along the ray due to participating media */
+       for (s = 0; s < nsteps; s++) {
+
+               if (s > 0) density = vol_get_density(shi, step_sta);
+               
+               /* there's only any use in shading here if there's actually some density to shade! */
+               if (density > 0.01f) {
+               
+                       /* transmittance component (alpha) */
+                       vol_get_attenuation(shi, tau, step_sta, step_end, density, stepsize);
+                       tr[0] *= exp(-tau[0]);
+                       tr[1] *= exp(-tau[1]);
+                       tr[2] *= exp(-tau[2]);
+                       
+                       step_mid[0] = step_sta[0] + (stepvec[0] * 0.5);
+                       step_mid[1] = step_sta[1] + (stepvec[1] * 0.5);
+                       step_mid[2] = step_sta[2] + (stepvec[2] * 0.5);
+               
+                       /* incoming light via emission or scattering (additive) */
+                       vol_get_emission(shi, emit_col, step_mid, density);
+                       
+                       
+                       if (R.r.scemode & R_PREVIEWBUTS) {
+                               vol_get_scattering(shi, scatter_col, step_mid, stepsize, density);
+                       } else if (using_lightcache(shi->mat)) {
+                               vol_get_precached_scattering(shi, scatter_col, step_mid);
+                       } else
+                               vol_get_scattering(shi, scatter_col, step_mid, stepsize, density);
+                                               
+                       VecMulf(scatter_col, density);
+                       VecAddf(d_radiance, emit_col, scatter_col);
+                       
+                       /*   Lv += Tr * (Lve() + Ld) */
+                       VecMulVecf(d_radiance, tr, d_radiance);
+                       VecMulf(d_radiance, stepsize);
+                       
+                       VecAddf(radiance, radiance, d_radiance);        
+               }
+
+               VecCopyf(step_sta, step_end);
+               VecAddf(step_end, step_end, stepvec);
+               
+               /* luminance rec. 709 */
+               if ((0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]) < depth_cutoff) break; 
+       }
+       
+       VecCopyf(col, radiance);
+       col[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f;
+}
+
+static void shade_intersection(ShadeInput *shi, float *col, Isect *is)
+{
+       ShadeInput shi_new;
+       ShadeResult shr_new;
+       
+       memset(&shi_new, 0, sizeof(ShadeInput)); 
+       
+       shi_new.mask= shi->mask;
+       shi_new.osatex= shi->osatex;
+       shi_new.thread= shi->thread;
+       shi_new.depth = shi->depth + 1;
+       shi_new.volume_depth= shi->volume_depth + 1;
+       shi_new.xs= shi->xs;
+       shi_new.ys= shi->ys;
+       shi_new.lay= shi->lay;
+       shi_new.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */
+       shi_new.combinedflag= 0xFFFFFF;          /* ray trace does all options */
+       shi_new.light_override= shi->light_override;
+       shi_new.mat_override= shi->mat_override;
+       
+       VECCOPY(shi_new.camera_co, is->start);
+       
+       memset(&shr_new, 0, sizeof(ShadeResult));
+
+       /* hardcoded limit of 100 for now - prevents problems in weird geometry */
+       if (shi->volume_depth < 100) {
+               shade_ray(is, &shi_new, &shr_new);
+       }
+       
+       col[0] = shr_new.combined[0];
+       col[1] = shr_new.combined[1];
+       col[2] = shr_new.combined[2];
+       col[3] = shr_new.alpha;
+}
+
+static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *col)
+{
+       Isect isect;
+       float maxsize = RE_ray_tree_max_size(R.raytree);
+
+       VECCOPY(isect.start, co);
+       isect.end[0] = isect.start[0] + shi->view[0] * maxsize;
+       isect.end[1] = isect.start[1] + shi->view[1] * maxsize;
+       isect.end[2] = isect.start[2] + shi->view[2] * maxsize;
+
+       isect.faceorig= (RayFace *)vlr;
+       
+       isect.mode= RE_RAY_MIRROR;
+       isect.oborig= RAY_OBJECT_SET(&R, shi->obi);
+       isect.face_last= NULL;
+       isect.ob_last= 0;
+       isect.lay= -1;
+       
+       /* check to see if there's anything behind the volume, otherwise shade the sky */
+       if(RE_ray_tree_intersect(R.raytree, &isect)) {
+               shade_intersection(shi, col, &isect);
+       } else {
+               shadeSkyView(col, co, shi->view, NULL, shi->thread);
+               shadeSunView(col, shi->view);
+       }
+}
+
+/* the main entry point for volume shading */
+static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int inside_volume)
+{
+       float hitco[3], col[4] = {0.f,0.f,0.f,0.f};
+       int trace_behind = 1;
+       Isect is;
+
+       /* check for shading an internal face a volume object directly */
+       if (inside_volume == VOL_SHADE_INSIDE) {
+               trace_behind = 0;
+       }
+       if (inside_volume == VOL_SHADE_OUTSIDE) {
+               if (shi->flippednor)
+                       inside_volume = VOL_SHADE_INSIDE;
+       }
+
+       if (inside_volume == VOL_SHADE_INSIDE) {
+               
+               if (trace_behind) {
+                       /* trace behind the volume object */
+                       vol_trace_behind(shi, shi->vlr, shi->co, col);
+               } else {
+                       /* we're tracing through the volume between the camera 
+                        * and a solid surface, so use that pre-shaded radiance */
+                       QUATCOPY(col, shr->combined);
+               }
+               
+               /* shade volume from 'camera' to 1st hit point */
+               volumeintegrate(shi, col, shi->camera_co, shi->co);
+               
+               shr->combined[0] = col[0];
+               shr->combined[1] = col[1];
+               shr->combined[2] = col[2];
+               
+               if (shi->mat->vol_shadeflag & MA_VOL_USEALPHA) {
+                       if (col[3] > 1.0f)
+                               col[3] = 1.0f;
+               }
+               else
+                       col[3] = 1.0f;
+               shr->combined[3] = col[3];
+               shr->alpha = col[3];
+               
+               VECCOPY(shr->diff, shr->combined);
+       }
+       /* trace to find a backface, the other side bounds of the volume */
+       /* (ray intersect ignores front faces here) */
+       else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH, 0)) {
+               VlakRen *vlr = (VlakRen *)is.face;
+               
+               /* if it's another face in the same material */
+               if (vlr->mat == shi->mat) {
+                       /* trace behind the 2nd (raytrace) hit point */
+                       vol_trace_behind(shi, (VlakRen *)is.face, hitco, col);
+               } else {
+                       shade_intersection(shi, col, &is);
+               }
+       
+               /* shade volume from 1st hit point to 2nd hit point */
+               volumeintegrate(shi, col, shi->co, hitco);
+               
+               shr->combined[0] = col[0];
+               shr->combined[1] = col[1];
+               shr->combined[2] = col[2];
+               
+               if (shi->mat->vol_shadeflag & MA_VOL_USEALPHA) {
+                       if (col[3] > 1.0f)
+                               col[3] = 1.0f;
+               }
+               else
+                       col[3] = 1.0f;
+               shr->combined[3] = col[3];
+               shr->alpha = col[3];
+               
+               VECCOPY(shr->diff, shr->combined);
+       }
+       else {
+               shr->combined[0] = 0.0f;
+               shr->combined[1] = 0.0f;
+               shr->combined[2] = 0.0f;
+               shr->combined[3] = shr->alpha =  1.0f;
+       }
+}
+
+/* Traces a shadow through the object, 
+ * pretty much gets the transmission over a ray path */
+void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is)
+{
+       float hitco[3];
+       float tr[3] = {1.0,1.0,1.0};
+       float tau[3] = {0.0,0.0,0.0};
+       Isect is;
+       float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE);
+
+       memset(shr, 0, sizeof(ShadeResult));
+       
+       /* if 1st hit normal is facing away from the camera, 
+        * then we're inside the volume already. */
+       if (shi->flippednor) {
+       
+               vol_get_attenuation(shi, tau, last_is->start, shi->co, -1.0f, shade_stepsize);
+               tr[0] = exp(-tau[0]);
+               tr[1] = exp(-tau[1]);
+               tr[2] = exp(-tau[2]);
+               
+               shr->combined[0] = tr[0];
+               shr->combined[1] = tr[1];
+               shr->combined[2] = tr[2];
+               
+               shr->combined[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f;
+               shr->alpha = shr->combined[3];
+       }
+       /* trace to find a backface, the other side bounds of the volume */
+       /* (ray intersect ignores front faces here) */
+       else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH, 0)) {
+               
+               vol_get_attenuation(shi, tau, shi->co, hitco, -1.0f, shade_stepsize);
+               tr[0] = exp(-tau[0]);
+               tr[1] = exp(-tau[1]);
+               tr[2] = exp(-tau[2]);
+               
+               shr->combined[0] = tr[0];
+               shr->combined[1] = tr[1];
+               shr->combined[2] = tr[2];
+               
+               shr->combined[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f;
+               shr->alpha = shr->combined[3];
+
+       }
+       else {
+               shr->combined[0] = 0.0f;
+               shr->combined[1] = 0.0f;
+               shr->combined[2] = 0.0f;
+               shr->combined[3] = shr->alpha =  0.0f;
+       }
+}
+
+
+/* delivers a fully filled in ShadeResult, for all passes */
+void shade_volume_outside(ShadeInput *shi, ShadeResult *shr)
+{
+       memset(shr, 0, sizeof(ShadeResult));
+       
+       volume_trace(shi, shr, VOL_SHADE_OUTSIDE);
+}
+
+
+void shade_volume_inside(ShadeInput *shi, ShadeResult *shr)
+{
+       MatInside *m;
+       Material *mat_backup;
+       
+       if (BLI_countlist(&R.render_volumes_inside) == 0) return;
+       
+       mat_backup = shi->mat;
+       
+//     for (m=R.render_volumes_inside.first; m; m=m->next) {
+//             printf("matinside: ma: %s \n", m->ma->id.name+2);
+//     }
+
+       m = R.render_volumes_inside.first;
+       shi->mat = m->ma;
+       
+       volume_trace(shi, shr, VOL_SHADE_INSIDE);
+
+       shi->mat = mat_backup;
+}
\ No newline at end of file
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
new file mode 100644 (file)
index 0000000..86cc54c
--- /dev/null
@@ -0,0 +1,497 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Raul Fernandez Hernandez (Farsthary), Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "DNA_texture_types.h"
+#include "render_types.h"
+#include "renderdatabase.h"
+#include "texture.h"
+#include "voxeldata.h"
+
+#if defined( _MSC_VER ) && !defined( __cplusplus )
+# define inline __inline
+#endif // defined( _MSC_VER ) && !defined( __cplusplus )
+
+/*---------------------------Utils----------------------------------------*/
+inline int _I(int x, int y, int z, int *n)
+{
+       return (z*(n[1])+y)*(n[2])+x;
+}
+
+float Linear(float xx, float yy, float zz, float *x0, int *n)
+{
+       float sx1,sx0,sy1,sy0,sz1,sz0,v0,v1;
+       int i0,i1,j0,j1,k0,k1;
+       
+       if (xx<0.5) xx=0.5f; if (xx>n[0]+0.5) xx=n[0]+0.5f; i0=(int)xx; i1=i0+1;
+       if (yy<0.5) yy=0.5f; if (yy>n[1]+0.5) yy=n[1]+0.5f; j0=(int)yy; j1=j0+1;
+       if (zz<0.5) zz=0.5f; if (zz>n[2]+0.5) zz=n[2]+0.5f; k0=(int)zz; k1=k0+1;
+       
+       sx1 = xx-i0; sx0 = 1-sx1;
+       sy1 = yy-j0; sy0 = 1-sy1;
+       sz1 = zz-k0; sz0 = 1-sz1;
+       v0 = sx0*(sy0*x0[_I(i0,j0,k0,n)]+sy1*x0[_I(i0,j1,k0,n)])+sx1*(sy0*x0[_I(i1,j0,k0,n)]+sy1*x0[_I(i1,j1,k0,n)]);
+       v1 = sx0*(sy0*x0[_I(i0,j0,k1,n)]+sy1*x0[_I(i0,j1,k1,n)])+sx1*(sy0*x0[_I(i1,j0,k1,n)]+sy1*x0[_I(i1,j1,k1,n)]);
+       return sz0*v0 + sz1*v1;
+}
+
+
+static float D(float *data, int *res, int x, int y, int z)
+{
+       CLAMP(x, 0, res[0]-1);
+       CLAMP(y, 0, res[1]-1);
+       CLAMP(z, 0, res[2]-1);
+       return data[ _I(x, y, z, res) ];
+}
+
+static inline float lerp(float t, float v1, float v2) {
+       return (1.f - t) * v1 + t * v2;
+}
+
+/* trilinear interpolation */
+static float trilinear(float *data, int *res, float *co)
+{
+       float voxx, voxy, voxz;
+       int vx, vy, vz;
+       float dx, dy, dz;
+       float d00, d10, d01, d11, d0, d1, d_final;
+
+       if (!data) return 0.f;
+       
+       voxx = co[0] * res[0] - 0.5f;
+       voxy = co[1] * res[1] - 0.5f;
+       voxz = co[2] * res[2] - 0.5f;
+       
+       vx = (int)voxx; vy = (int)voxy; vz = (int)voxz;
+       
+       dx = voxx - vx; dy = voxy - vy; dz = voxz - vz;
+       
+       d00 = lerp(dx, D(data, res, vx, vy, vz),                D(data, res, vx+1, vy, vz));
+       d10 = lerp(dx, D(data, res, vx, vy+1, vz),              D(data, res, vx+1, vy+1, vz));
+       d01 = lerp(dx, D(data, res, vx, vy, vz+1),              D(data, res, vx+1, vy, vz+1));
+       d11 = lerp(dx, D(data, res, vx, vy+1, vz+1),    D(data, res, vx+1, vy+1, vz+1));
+       d0 = lerp(dy, d00, d10);
+       d1 = lerp(dy, d01, d11);
+       d_final = lerp(dz, d0, d1);
+       
+       return d_final;
+}
+
+
+int C[64][64] = {
+       { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {-3, 3, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 2,-2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 9,-9,-9, 9, 0, 0, 0, 0, 6, 3,-6,-3, 0, 0, 0, 0, 6,-6, 3,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {-6, 6, 6,-6, 0, 0, 0, 0,-3,-3, 3, 3, 0, 0, 0, 0,-4, 4,-2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-2,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {-6, 6, 6,-6, 0, 0, 0, 0,-4,-2, 4, 2, 0, 0, 0, 0,-3, 3,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 4,-4,-4, 4, 0, 0, 0, 0, 2, 2,-2,-2, 0, 0, 0, 0, 2,-2, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,-9,-9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3,-6,-3, 0, 0, 0, 0, 6,-6, 3,-3, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3,-3, 3, 3, 0, 0, 0, 0,-4, 4,-2, 2, 0, 0, 0, 0,-2,-2,-1,-1, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4,-2, 4, 2, 0, 0, 0, 0,-3, 3,-3, 3, 0, 0, 0, 0,-2,-1,-2,-1, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,-4,-4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,-2,-2, 0, 0, 0, 0, 2,-2, 2,-2, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0},
+       {-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 9,-9, 0, 0,-9, 9, 0, 0, 6, 3, 0, 0,-6,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-6, 0, 0, 3,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {-6, 6, 0, 0, 6,-6, 0, 0,-3,-3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 4, 0, 0,-2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-2, 0, 0,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,-9, 0, 0,-9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0,-6,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-6, 0, 0, 3,-3, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3,-3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 4, 0, 0,-2, 2, 0, 0,-2,-2, 0, 0,-1,-1, 0, 0},
+       { 9, 0,-9, 0,-9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0,-6, 0,-3, 0, 6, 0,-6, 0, 3, 0,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,-9, 0,-9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0,-6, 0,-3, 0, 6, 0,-6, 0, 3, 0,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0},
+       {-27,27,27,-27,27,-27,-27,27,-18,-9,18, 9,18, 9,-18,-9,-18,18,-9, 9,18,-18, 9,-9,-18,18,18,-18,-9, 9, 9,-9,-12,-6,-6,-3,12, 6, 6, 3,-12,-6,12, 6,-6,-3, 6, 3,-12,12,-6, 6,-6, 6,-3, 3,-8,-4,-4,-2,-4,-2,-2,-1},
+       {18,-18,-18,18,-18,18,18,-18, 9, 9,-9,-9,-9,-9, 9, 9,12,-12, 6,-6,-12,12,-6, 6,12,-12,-12,12, 6,-6,-6, 6, 6, 6, 3, 3,-6,-6,-3,-3, 6, 6,-6,-6, 3, 3,-3,-3, 8,-8, 4,-4, 4,-4, 2,-2, 4, 4, 2, 2, 2, 2, 1, 1},
+       {-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0,-3, 0, 3, 0, 3, 0,-4, 0, 4, 0,-2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-2, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0,-3, 0, 3, 0, 3, 0,-4, 0, 4, 0,-2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-2, 0,-1, 0,-1, 0},
+       {18,-18,-18,18,-18,18,18,-18,12, 6,-12,-6,-12,-6,12, 6, 9,-9, 9,-9,-9, 9,-9, 9,12,-12,-12,12, 6,-6,-6, 6, 6, 3, 6, 3,-6,-3,-6,-3, 8, 4,-8,-4, 4, 2,-4,-2, 6,-6, 6,-6, 3,-3, 3,-3, 4, 2, 4, 2, 2, 1, 2, 1},
+       {-12,12,12,-12,12,-12,-12,12,-6,-6, 6, 6, 6, 6,-6,-6,-6, 6,-6, 6, 6,-6, 6,-6,-8, 8, 8,-8,-4, 4, 4,-4,-3,-3,-3,-3, 3, 3, 3, 3,-4,-4, 4, 4,-2,-2, 2, 2,-4, 4,-4, 4,-2, 2,-2, 2,-2,-2,-2,-2,-1,-1,-1,-1},
+       { 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {-6, 6, 0, 0, 6,-6, 0, 0,-4,-2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 4,-4, 0, 0,-4, 4, 0, 0, 2, 2, 0, 0,-2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4,-2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0,-2,-1, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,-4, 0, 0,-4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0,-2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0},
+       {-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 0,-2, 0, 4, 0, 2, 0,-3, 0, 3, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 0,-2, 0, 4, 0, 2, 0,-3, 0, 3, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0,-2, 0,-1, 0},
+       {18,-18,-18,18,-18,18,18,-18,12, 6,-12,-6,-12,-6,12, 6,12,-12, 6,-6,-12,12,-6, 6, 9,-9,-9, 9, 9,-9,-9, 9, 8, 4, 4, 2,-8,-4,-4,-2, 6, 3,-6,-3, 6, 3,-6,-3, 6,-6, 3,-3, 6,-6, 3,-3, 4, 2, 2, 1, 4, 2, 2, 1},
+       {-12,12,12,-12,12,-12,-12,12,-6,-6, 6, 6, 6, 6,-6,-6,-8, 8,-4, 4, 8,-8, 4,-4,-6, 6, 6,-6,-6, 6, 6,-6,-4,-4,-2,-2, 4, 4, 2, 2,-3,-3, 3, 3,-3,-3, 3, 3,-4, 4,-2, 2,-4, 4,-2, 2,-2,-2,-1,-1,-2,-2,-1,-1},
+       { 4, 0,-4, 0,-4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,-2, 0,-2, 0, 2, 0,-2, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,-4, 0,-4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,-2, 0,-2, 0, 2, 0,-2, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0},
+       {-12,12,12,-12,12,-12,-12,12,-8,-4, 8, 4, 8, 4,-8,-4,-6, 6,-6, 6, 6,-6, 6,-6,-6, 6, 6,-6,-6, 6, 6,-6,-4,-2,-4,-2, 4, 2, 4, 2,-4,-2, 4, 2,-4,-2, 4, 2,-3, 3,-3, 3,-3, 3,-3, 3,-2,-1,-2,-1,-2,-1,-2,-1},
+       { 8,-8,-8, 8,-8, 8, 8,-8, 4, 4,-4,-4,-4,-4, 4, 4, 4,-4, 4,-4,-4, 4,-4, 4, 4,-4,-4, 4, 4,-4,-4, 4, 2, 2, 2, 2,-2,-2,-2,-2, 2, 2,-2,-2, 2, 2,-2,-2, 2,-2, 2,-2, 2,-2, 2,-2, 1, 1, 1, 1, 1, 1, 1, 1}};
+
+int ijk2n(int i, int j, int k) {
+       return(i+4*j+16*k);
+}
+
+void tricubic_get_coeff_stacked(float a[64], float x[64]) {
+       int i,j;
+       for (i=0;i<64;i++) {
+               a[i]=(float)(0.0);
+               for (j=0;j<64;j++) {
+                       a[i]+=C[i][j]*x[j];
+               }
+       }
+}
+
+void point2xyz(int p, int *x, int *y, int *z) {
+       switch (p) {
+               case 0: *x=0; *y=0; *z=0; break;
+               case 1: *x=1; *y=0; *z=0; break;
+               case 2: *x=0; *y=1; *z=0; break;
+               case 3: *x=1; *y=1; *z=0; break;
+               case 4: *x=0; *y=0; *z=1; break;
+               case 5: *x=1; *y=0; *z=1; break;
+               case 6: *x=0; *y=1; *z=1; break;
+               case 7: *x=1; *y=1; *z=1; break;
+               default:*x=0; *y=0; *z=0;
+       }
+}
+
+
+void tricubic_get_coeff(float a[64], float f[8], float dfdx[8], float dfdy[8], float dfdz[8], float d2fdxdy[8], float d2fdxdz[8], float d2fdydz[8], float d3fdxdydz[8]) {
+       int i;
+       float x[64];
+       for (i=0;i<8;i++) {
+               x[0+i]=f[i];
+               x[8+i]=dfdx[i];
+               x[16+i]=dfdy[i];
+               x[24+i]=dfdz[i];
+               x[32+i]=d2fdxdy[i];
+               x[40+i]=d2fdxdz[i];
+               x[48+i]=d2fdydz[i];
+               x[56+i]=d3fdxdydz[i];
+       }
+       tricubic_get_coeff_stacked(a,x);
+}
+
+float tricubic_eval(float a[64], float x, float y, float z) {
+       int i,j,k;
+       float ret=(float)(0.0);
+       
+       for (i=0;i<4;i++) {
+               for (j=0;j<4;j++) {
+                       for (k=0;k<4;k++) {
+                               ret+=a[ijk2n(i,j,k)]*pow(x,i)*pow(y,j)*pow(z,k);
+                       }
+               }
+       }
+       return(ret);
+}
+
+
+float tricubic(float xx, float yy, float zz, float *heap, int *n)
+{
+       
+       int xi,yi,zi;
+       float dx,dy,dz;
+       float a[64];
+
+       if (xx<0.5) xx=0.5f; if (xx>n[0]+0.5) xx=n[0]+0.5f; xi=(int)xx;
+       if (yy<0.5) yy=0.5f; if (yy>n[1]+0.5) yy=n[1]+0.5f; yi=(int)yy;
+       if (zz<0.5) zz=0.5f; if (zz>n[2]+0.5) zz=n[2]+0.5f; zi=(int)zz;
+       
+       {
+       float fval[8]={heap[_I(xi,yi,zi,n)],heap[_I(xi+1,yi,zi,n)],heap[_I(xi,yi+1,zi,n)],heap[_I(xi+1,yi+1,zi,n)],heap[_I(xi,yi,zi+1,n)],heap[_I(xi+1,yi,zi+1,n)],heap[_I(xi,yi+1,zi+1,n)],heap[_I(xi+1,yi+1,zi+1,n)]}; 
+       
+       float dfdxval[8]={0.5f*(heap[_I(xi+1,yi,zi,n)]-heap[_I(xi-1,yi,zi,n)]),0.5f*(heap[_I(xi+2,yi,zi,n)]-heap[_I(xi,yi,zi,n)]),
+               0.5f*(heap[_I(xi+1,yi+1,zi,n)]-heap[_I(xi-1,yi+1,zi,n)]),0.5f*(heap[_I(xi+2,yi+1,zi,n)]-heap[_I(xi,yi+1,zi,n)]),
+               0.5f*(heap[_I(xi+1,yi,zi+1,n)]-heap[_I(xi-1,yi,zi+1,n)]),0.5f*(heap[_I(xi+2,yi,zi+1,n)]-heap[_I(xi,yi,zi+1,n)]),
+               0.5f*(heap[_I(xi+1,yi+1,zi+1,n)]-heap[_I(xi-1,yi+1,zi+1,n)]),
+       0.5f*(heap[_I(xi+2,yi+1,zi+1,n)]-heap[_I(xi,yi+1,zi+1,n)])};                                            
+       
+       float dfdyval[8]={0.5f*(heap[_I(xi,yi+1,zi,n)]-heap[_I(xi,yi-1,zi,n)]),0.5f*(heap[_I(xi+1,yi+1,zi,n)]-heap[_I(xi+1,yi-1,zi,n)]),
+               0.5f*(heap[_I(xi,yi+2,zi,n)]-heap[_I(xi,yi,zi,n)]),0.5f*(heap[_I(xi+1,yi+2,zi,n)]-heap[_I(xi+1,yi,zi,n)]),
+               0.5f*(heap[_I(xi,yi+1,zi+1,n)]-heap[_I(xi,yi-1,zi+1,n)]),0.5f*(heap[_I(xi+1,yi+1,zi+1,n)]-heap[_I(xi+1,yi-1,zi+1,n)]),
+               0.5f*(heap[_I(xi,yi+2,zi+1,n)]-heap[_I(xi,yi,zi+1,n)]),
+       0.5f*(heap[_I(xi+1,yi+2,zi+1,n)]-heap[_I(xi+1,yi,zi+1,n)])};                                             
+       
+       float dfdzval[8]={0.5f*(heap[_I(xi,yi,zi+1,n)]-heap[_I(xi,yi,zi-1,n)]),0.5f*(heap[_I(xi+1,yi,zi+1,n)]-heap[_I(xi+1,yi,zi-1,n)]),
+               0.5f*(heap[_I(xi,yi+1,zi+1,n)]-heap[_I(xi,yi+1,zi-1,n)]),0.5f*(heap[_I(xi+1,yi+1,zi+1,n)]-heap[_I(xi+1,yi+1,zi-1,n)]),
+               0.5f*(heap[_I(xi,yi,zi+2,n)]-heap[_I(xi,yi,zi,n)]),0.5f*(heap[_I(xi+1,yi,zi+2,n)]-heap[_I(xi+1,yi,zi,n)]),
+               0.5f*(heap[_I(xi,yi+1,zi+2,n)]-heap[_I(xi,yi+1,zi,n)]),
+       0.5f*(heap[_I(xi+1,yi+1,zi+2,n)]-heap[_I(xi+1,yi+1,zi,n)])};                                             
+       
+       float d2fdxdyval[8]={0.25*(heap[_I(xi+1,yi+1,zi,n)]-heap[_I(xi-1,yi+1,zi,n)]-heap[_I(xi+1,yi-1,zi,n)]+heap[_I(xi-1,yi-1,zi,n)]),
+               0.25*(heap[_I(xi+2,yi+1,zi,n)]-heap[_I(xi,yi+1,zi,n)]-heap[_I(xi+2,yi-1,zi,n)]+heap[_I(xi,yi-1,zi,n)]),
+               0.25*(heap[_I(xi+1,yi+2,zi,n)]-heap[_I(xi-1,yi+2,zi,n)]-heap[_I(xi+1,yi,zi,n)]+heap[_I(xi-1,yi,zi,n)]),
+               0.25*(heap[_I(xi+2,yi+2,zi,n)]-heap[_I(xi,yi+2,zi,n)]-heap[_I(xi+2,yi,zi,n)]+heap[_I(xi,yi,zi,n)]),
+               0.25*(heap[_I(xi+1,yi+1,zi+1,n)]-heap[_I(xi-1,yi+1,zi+1,n)]-heap[_I(xi+1,yi-1,zi+1,n)]+heap[_I(xi-1,yi-1,zi+1,n)]),
+               0.25*(heap[_I(xi+2,yi+1,zi+1,n)]-heap[_I(xi,yi+1,zi+1,n)]-heap[_I(xi+2,yi-1,zi+1,n)]+heap[_I(xi,yi-1,zi+1,n)]),
+               0.25*(heap[_I(xi+1,yi+2,zi+1,n)]-heap[_I(xi-1,yi+2,zi+1,n)]-heap[_I(xi+1,yi,zi+1,n)]+heap[_I(xi-1,yi,zi+1,n)]),
+       0.25*(heap[_I(xi+2,yi+2,zi+1,n)]-heap[_I(xi,yi+2,zi+1,n)]-heap[_I(xi+2,yi,zi+1,n)]+heap[_I(xi,yi,zi+1,n)])};                                             
+       
+       float d2fdxdzval[8]={0.25f*(heap[_I(xi+1,yi,zi+1,n)]-heap[_I(xi-1,yi,zi+1,n)]-heap[_I(xi+1,yi,zi-1,n)]+heap[_I(xi-1,yi,zi-1,n)]),
+               0.25f*(heap[_I(xi+2,yi,zi+1,n)]-heap[_I(xi,yi,zi+1,n)]-heap[_I(xi+2,yi,zi-1,n)]+heap[_I(xi,yi,zi-1,n)]),
+               0.25f*(heap[_I(xi+1,yi+1,zi+1,n)]-heap[_I(xi-1,yi+1,zi+1,n)]-heap[_I(xi+1,yi+1,zi-1,n)]+heap[_I(xi-1,yi+1,zi-1,n)]),
+               0.25f*(heap[_I(xi+2,yi+1,zi+1,n)]-heap[_I(xi,yi+1,zi+1,n)]-heap[_I(xi+2,yi+1,zi-1,n)]+heap[_I(xi,yi+1,zi-1,n)]),
+               0.25f*(heap[_I(xi+1,yi,zi+2,n)]-heap[_I(xi-1,yi,zi+2,n)]-heap[_I(xi+1,yi,zi,n)]+heap[_I(xi-1,yi,zi,n)]),
+               0.25f*(heap[_I(xi+2,yi,zi+2,n)]-heap[_I(xi,yi,zi+2,n)]-heap[_I(xi+2,yi,zi,n)]+heap[_I(xi,yi,zi,n)]),
+               0.25f*(heap[_I(xi+1,yi+1,zi+2,n)]-heap[_I(xi-1,yi+1,zi+2,n)]-heap[_I(xi+1,yi+1,zi,n)]+heap[_I(xi-1,yi+1,zi,n)]),
+       0.25f*(heap[_I(xi+2,yi+1,zi+2,n)]-heap[_I(xi,yi+1,zi+2,n)]-heap[_I(xi+2,yi+1,zi,n)]+heap[_I(xi,yi+1,zi,n)])};
+       
+       
+       float d2fdydzval[8]={0.25f*(heap[_I(xi,yi+1,zi+1,n)]-heap[_I(xi,yi-1,zi+1,n)]-heap[_I(xi,yi+1,zi-1,n)]+heap[_I(xi,yi-1,zi-1,n)]),
+               0.25f*(heap[_I(xi+1,yi+1,zi+1,n)]-heap[_I(xi+1,yi-1,zi+1,n)]-heap[_I(xi+1,yi+1,zi-1,n)]+heap[_I(xi+1,yi-1,zi-1,n)]),
+               0.25f*(heap[_I(xi,yi+2,zi+1,n)]-heap[_I(xi,yi,zi+1,n)]-heap[_I(xi,yi+2,zi-1,n)]+heap[_I(xi,yi,zi-1,n)]),
+               0.25f*(heap[_I(xi+1,yi+2,zi+1,n)]-heap[_I(xi+1,yi,zi+1,n)]-heap[_I(xi+1,yi+2,zi-1,n)]+heap[_I(xi+1,yi,zi-1,n)]),
+               0.25f*(heap[_I(xi,yi+1,zi+2,n)]-heap[_I(xi,yi-1,zi+2,n)]-heap[_I(xi,yi+1,zi,n)]+heap[_I(xi,yi-1,zi,n)]),
+               0.25f*(heap[_I(xi+1,yi+1,zi+2,n)]-heap[_I(xi+1,yi-1,zi+2,n)]-heap[_I(xi+1,yi+1,zi,n)]+heap[_I(xi+1,yi-1,zi,n)]),
+               0.25f*(heap[_I(xi,yi+2,zi+2,n)]-heap[_I(xi,yi,zi+2,n)]-heap[_I(xi,yi+2,zi,n)]+heap[_I(xi,yi,zi,n)]),
+       0.25f*(heap[_I(xi+1,yi+2,zi+2,n)]-heap[_I(xi+1,yi,zi+2,n)]-heap[_I(xi+1,yi+2,zi,n)]+heap[_I(xi+1,yi,zi,n)])};
+       
+       
+       float d3fdxdydzval[8]={0.125f*(heap[_I(xi+1,yi+1,zi+1,n)]-heap[_I(xi-1,yi+1,zi+1,n)]-heap[_I(xi+1,yi-1,zi+1,n)]+heap[_I(xi-1,yi-1,zi+1,n)]-heap[_I(xi+1,yi+1,zi-1,n)]+heap[_I(xi-1,yi+1,zi-1,n)]+heap[_I(xi+1,yi-1,zi-1,n)]-heap[_I(xi-1,yi-1,zi-1,n)]),
+               0.125f*(heap[_I(xi+2,yi+1,zi+1,n)]-heap[_I(xi,yi+1,zi+1,n)]-heap[_I(xi+2,yi-1,zi+1,n)]+heap[_I(xi,yi-1,zi+1,n)]-heap[_I(xi+2,yi+1,zi-1,n)]+heap[_I(xi,yi+1,zi-1,n)]+heap[_I(xi+2,yi-1,zi-1,n)]-heap[_I(xi,yi-1,zi-1,n)]),
+               0.125f*(heap[_I(xi+1,yi+2,zi+1,n)]-heap[_I(xi-1,yi+2,zi+1,n)]-heap[_I(xi+1,yi,zi+1,n)]+heap[_I(xi-1,yi,zi+1,n)]-heap[_I(xi+1,yi+2,zi-1,n)]+heap[_I(xi-1,yi+2,zi-1,n)]+heap[_I(xi+1,yi,zi-1,n)]-heap[_I(xi-1,yi,zi-1,n)]),
+               0.125f*(heap[_I(xi+2,yi+2,zi+1,n)]-heap[_I(xi,yi+2,zi+1,n)]-heap[_I(xi+2,yi,zi+1,n)]+heap[_I(xi,yi,zi+1,n)]-heap[_I(xi+2,yi+2,zi-1,n)]+heap[_I(xi,yi+2,zi-1,n)]+heap[_I(xi+2,yi,zi-1,n)]-heap[_I(xi,yi,zi-1,n)]),
+               0.125f*(heap[_I(xi+1,yi+1,zi+2,n)]-heap[_I(xi-1,yi+1,zi+2,n)]-heap[_I(xi+1,yi-1,zi+2,n)]+heap[_I(xi-1,yi-1,zi+2,n)]-heap[_I(xi+1,yi+1,zi,n)]+heap[_I(xi-1,yi+1,zi,n)]+heap[_I(xi+1,yi-1,zi,n)]-heap[_I(xi-1,yi-1,zi,n)]),
+               0.125f*(heap[_I(xi+2,yi+1,zi+2,n)]-heap[_I(xi,yi+1,zi+2,n)]-heap[_I(xi+2,yi-1,zi+2,n)]+heap[_I(xi,yi-1,zi+2,n)]-heap[_I(xi+2,yi+1,zi,n)]+heap[_I(xi,yi+1,zi,n)]+heap[_I(xi+2,yi-1,zi,n)]-heap[_I(xi,yi-1,zi,n)]),
+               0.125f*(heap[_I(xi+1,yi+2,zi+2,n)]-heap[_I(xi-1,yi+2,zi+2,n)]-heap[_I(xi+1,yi,zi+2,n)]+heap[_I(xi-1,yi,zi+2,n)]-heap[_I(xi+1,yi+2,zi,n)]+heap[_I(xi-1,yi+2,zi,n)]+heap[_I(xi+1,yi,zi,n)]-heap[_I(xi-1,yi,zi,n)]),
+       0.125f*(heap[_I(xi+2,yi+2,zi+2,n)]-heap[_I(xi,yi+2,zi+2,n)]-heap[_I(xi+2,yi,zi+2,n)]+heap[_I(xi,yi,zi+2,n)]-heap[_I(xi+2,yi+2,zi,n)]+heap[_I(xi,yi+2,zi,n)]+heap[_I(xi+2,yi,zi,n)]-heap[_I(xi,yi,zi,n)])};
+
+       
+       tricubic_get_coeff(a,fval,dfdxval,dfdyval,dfdzval,d2fdxdyval,d2fdxdzval,d2fdydzval,d3fdxdydzval);
+       }
+               
+       dx = xx-xi;
+       dy = yy-yi;
+       dz = zz-zi;
+       
+       return tricubic_eval(a,dx,dy,dz);
+       
+}
+
+void load_frame (FILE *fp, float *F, int size, int frame, int offset)
+{      
+       fseek(fp,frame*size*sizeof(float)+offset,0);
+       fread(F,sizeof(float),size,fp);
+}
+
+void write_voxeldata_header(struct VoxelDataHeader *h, FILE *fp)
+{
+       fwrite(h,sizeof(struct VoxelDataHeader),1,fp);
+}
+
+void read_voxeldata_header(FILE *fp, struct VoxelData *vd)
+{
+       VoxelDataHeader *h=(VoxelDataHeader *)MEM_mallocN(sizeof(VoxelDataHeader), "voxel data header");
+       
+       rewind(fp);
+       fread(h,sizeof(VoxelDataHeader),1,fp);
+       
+       vd->resolX=h->resolX;
+       vd->resolY=h->resolY;
+       vd->resolZ=h->resolZ;
+
+       MEM_freeN(h);
+}
+
+void cache_voxeldata(struct Render *re,Tex *tex)
+{      
+       VoxelData *vd = tex->vd;
+       FILE *fp;
+       int size;
+       
+       if (!vd) return;
+       
+       read_voxeldata_header(fp, vd);
+       size = (vd->resolX)*(vd->resolY)*(vd->resolZ);
+       vd->dataset = MEM_mallocN(sizeof(float)*size, "voxel dataset");
+       
+       if (!BLI_exists(vd->source_path)) return;
+       fp = fopen(vd->source_path,"rb");
+       if (!fp) return;
+       
+       //here improve the dataset loading function for more dataset types
+       if (vd->still) load_frame(fp, vd->dataset, size, vd->still_frame, sizeof(VoxelDataHeader));
+       else load_frame(fp, vd->dataset, size, re->r.cfra, sizeof(VoxelDataHeader));
+       
+       fclose(fp);
+}
+
+void make_voxeldata(struct Render *re)
+{
+    Tex *tex;
+       
+       if(re->scene->r.scemode & R_PREVIEWBUTS)
+               return;
+       
+       re->i.infostr= "Loading voxel datasets";
+       re->stats_draw(&re->i);
+       
+       for (tex= G.main->tex.first; tex; tex= tex->id.next) {
+               if(tex->id.us && tex->type==TEX_VOXELDATA) {
+                       cache_voxeldata(re, tex);
+               }
+       }
+       
+       re->i.infostr= NULL;
+       re->stats_draw(&re->i);
+       
+}
+
+static void free_voxeldata_one(Render *re, Tex *tex)
+{
+       VoxelData *vd = tex->vd;
+       
+       if (vd->dataset) {
+               MEM_freeN(vd->dataset);
+               vd->dataset = NULL;
+       }
+}
+
+
+void free_voxeldata(Render *re)
+{
+       Tex *tex;
+       
+       if(re->scene->r.scemode & R_PREVIEWBUTS)
+               return;
+       
+       for (tex= G.main->tex.first; tex; tex= tex->id.next) {
+               if(tex->id.us && tex->type==TEX_VOXELDATA) {
+                       free_voxeldata_one(re, tex);
+               }
+       }
+}
+
+int voxeldatatex(struct Tex *tex, float *texvec, struct TexResult *texres)
+{       
+    int retval = TEX_INT;
+       VoxelData *vd = tex->vd;        
+       float vec[3] = {0.0, 0.0, 0.0}; 
+       float co[3];
+       float dx, dy, dz;
+       int xi, yi, zi;
+       float xf, yf, zf;
+       int i=0, fail=0;
+       int resol[3];
+       
+       if ((!vd) || (vd->dataset==NULL)) {
+               texres->tin = 0.0f;
+               return 0;
+       }
+       
+       resol[0] = vd->resolX;
+       resol[1] = vd->resolY;
+       resol[2] = vd->resolZ;
+       
+       VECCOPY(co, texvec);    
+       
+       dx=1.0f/(resol[0]);
+       dy=1.0f/(resol[1]);
+       dz=1.0f/(resol[2]);
+       
+       xi=co[0]/dx;
+       yi=co[1]/dy;
+       zi=co[2]/dz;
+               
+       xf=co[0]/dx;
+       yf=co[1]/dy;
+       zf=co[2]/dz;
+       
+       if (xi>1 && xi<resol[0])
+       {
+               if (yi>1 && yi<resol[1])
+               {
+                       if (zi>1 && zi<resol[2])
+                       {
+                               switch (vd->interp_type)
+                               {
+                                       case TEX_VD_NEARESTNEIGHBOR:
+                                       {
+                                               texres->tin = vd->dataset[_I(xi,yi,zi,resol)];
+                                               break;  
+                                       }
+                                       case TEX_VD_LINEAR:
+                                       {
+                                               texres->tin = trilinear(vd->dataset, resol, co);
+                                               break;                                  
+                                       }
+                                       case TEX_VD_TRICUBIC:
+                                       {
+                                               texres->tin = tricubic(xf, yf, zf, vd->dataset, resol);
+                                               break;
+                                       }
+                               }                                                                  
+                       } else fail++;
+               } else fail++;
+       } else fail++;
+       
+       if (fail) texres->tin=0.0f;
+
+       texres->tin *= vd->int_multiplier;
+       
+       BRICONT;
+       
+       texres->tr = texres->tin;
+       texres->tg = texres->tin;
+       texres->tb = texres->tin;
+       texres->ta = texres->tin;
+       BRICONTRGB;
+       
+       return retval;  
+}
+
+
index ba4d02d2355f6b78aed344f9d3c8154974f92495..6d8f806d8f97e3854399cab5faa6bb0eaf5c87a0 100644 (file)
@@ -92,7 +92,7 @@ MTex mtexcopybuf;
 
 char texstr[20][12]= {"None"  , "Clouds" , "Wood", "Marble", "Magic"  , "Blend",
                                         "Stucci", "Noise"  , "Image", "Plugin", "EnvMap" , "Musgrave",
-                                        "Voronoi", "DistNoise", "", "", "", "", "", ""};
+                                        "Voronoi", "DistNoise", "", "PointDensity", "VoxelData", "", "", ""};
 /*  ---------------------------------------------------------------------- */
 
 void test_idbutton_cb(void *namev, void *arg2)
index a41f954c4d8d7bf111a0361c3fbaeef68fc4c916..3f0937f511a2a4c516cd6866a03b2e7a3127bd95 100644 (file)
@@ -3484,8 +3484,8 @@ static void object_panel_fields(Object *ob)
                                sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Curve Guide%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
                                                PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
                        else
-                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
-                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
+                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Spin%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
+                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_SPIN, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
 
                        if(pd->forcefield==PFIELD_FORCE) tipstr= "Object center attracts or repels particles (On shared object layers)";
                        else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of Object Z axis (On shared object layers)";
index a129698cce3306977e2e44066b1f714c295e76ed..2e6dc7da9e12a2bed88e40364b40a0482cb0f53a 100644 (file)
@@ -264,6 +264,19 @@ static int vergcband(const void *a1, const void *a2)
        return 0;
 }
 
+static void voxeldata_filename(char *str, void *tex_v, void *unused)   /* called from fileselect */
+{
+       Tex *tex= tex_v;
+       
+       if(tex->type!=TEX_VOXELDATA) return;
+       
+       strcpy(tex->vd->source_path, str);
+       
+       allqueue(REDRAWBUTSSHADING, 0);
+       BIF_preview_changed(ID_TE);
+       BIF_undo_push("Open voxel data source");
+}
+
 void do_texbuts(unsigned short event)
 {
        Tex *tex;
@@ -425,7 +438,25 @@ void do_texbuts(unsigned short event)
                allqueue(REDRAWBUTSSHADING, 0);
                allqueue(REDRAWIPO, 0);
                break;
+       
+       case B_VOXELDATA_LOAD:
+               if (tex->vd==NULL) {
+                       tex->vd= BKE_add_voxeldata();
+#ifdef _WIN32
+                       if (strcmp (U.textudir, "/") == 0)
+                               strcpy(str, G.sce);
+                       else
+                               strcpy(str, U.textudir);
+#else
+                       strcpy(str, U.textudir);
+#endif
+               }
+               else strcpy(str, tex->vd->source_path);
                
+               sa= closest_bigger_area();
+               areawinset(sa->win);
+               activate_fileselect_args(FILE_SPECIAL, "Open Voxel Data", str, voxeldata_filename, tex, NULL);
+               break;
        default:
                if(event>=B_PLUGBUT && event<=B_PLUGBUT+23) {
                        PluginTex *pit= tex->plugin;
@@ -438,6 +469,115 @@ void do_texbuts(unsigned short event)
        }
 }
 
+static void colorband_pos_cb(void *coba_v, void *unused_v)
+{
+       ColorBand *coba= coba_v;
+       int a;
+       
+       if(coba->tot<2) return;
+       
+       for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
+       qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
+       for(a=0; a<coba->tot; a++) {
+               if(coba->data[a].cur==coba->cur) {
+                       if(coba->cur!=a) addqueue(curarea->win, REDRAW, 0);     /* button cur */
+                       coba->cur= a;
+                       break;
+               }
+       }
+}
+
+static void colorband_add_cb(void *coba_v, void *unused_v)
+{
+       ColorBand *coba= coba_v;
+       
+       if(coba->tot < MAXCOLORBAND-1) coba->tot++;
+       coba->cur= coba->tot-1;
+       
+       colorband_pos_cb(coba, NULL);
+       BIF_undo_push("Add colorband");
+       
+}
+
+static void colorband_del_cb(void *coba_v, void *unused_v)
+{
+       ColorBand *coba= coba_v;
+       int a;
+       
+       if(coba->tot<2) return;
+       
+       for(a=coba->cur; a<coba->tot; a++) {
+               coba->data[a]= coba->data[a+1];
+       }
+       if(coba->cur) coba->cur--;
+       coba->tot--;
+       
+       BIF_undo_push("Delete colorband");
+       BIF_preview_changed(ID_TE);
+}
+
+
+/* offset aligns from bottom, standard width 300, height 115 */
+static void draw_colorband_buts(uiBlock *block, ColorBand *coba, int xoffs, int yoffs, int redraw)
+{
+       CBData *cbd;
+       uiBut *bt;
+       
+       if(coba==NULL) return;
+       
+       bt= uiDefBut(block, BUT, redraw,        "Add",          80+xoffs,95+yoffs,37,20, 0, 0, 0, 0, 0, "Adds a new color position to the colorband");
+       uiButSetFunc(bt, colorband_add_cb, coba, NULL);
+       uiDefButS(block, NUM, redraw,           "Cur:",         117+xoffs,95+yoffs,81,20, &coba->cur, 0.0, (float)(coba->tot-1), 0, 0, "Displays the active color from the colorband");
+       bt= uiDefBut(block, BUT, redraw,                "Del",          199+xoffs,95+yoffs,37,20, 0, 0, 0, 0, 0, "Deletes the active position");
+       uiButSetFunc(bt, colorband_del_cb, coba, NULL);
+       uiDefButS(block, ROW, redraw,            "E",           236+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 1.0, 0, 0, "Sets interpolation type 'Ease' (quadratic) ");
+       uiDefButS(block, ROW, redraw,           "C",            252+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 3.0, 0, 0, "Sets interpolation type Cardinal");
+       uiDefButS(block, ROW, redraw,           "L",            268+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 0.0, 0, 0, "Sets interpolation type Linear");
+       uiDefButS(block, ROW, redraw,           "S",            284+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 2.0, 0, 0, "Sets interpolation type B-Spline");
+
+       uiDefBut(block, BUT_COLORBAND, redraw, "",      xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, "");
+       
+       cbd= coba->data + coba->cur;
+       
+       uiBlockBeginAlign(block);
+       bt= uiDefButF(block, NUM, redraw, "Pos",                xoffs,40+yoffs,110,20, &cbd->pos, 0.0, 1.0, 10, 0, "Sets the position of the active color");
+       uiButSetFunc(bt, colorband_pos_cb, coba, NULL);
+       uiDefButF(block, COL, redraw,           "",             xoffs,20+yoffs,110,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "");
+       uiDefButF(block, NUMSLI, redraw,        "A ",   xoffs,yoffs,110,20, &cbd->a, 0.0, 1.0, 10, 0, "Sets the alpha value for this position");
+
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUMSLI, redraw,        "R ",   115+xoffs,40+yoffs,185,20, &cbd->r, 0.0, 1.0, B_BANDCOL, 0, "Sets the red value for the active color");
+       uiDefButF(block, NUMSLI, redraw,        "G ",   115+xoffs,20+yoffs,185,20, &cbd->g, 0.0, 1.0, B_BANDCOL, 0, "Sets the green value for the active color");
+       uiDefButF(block, NUMSLI, redraw,        "B ",   115+xoffs,yoffs,185,20, &cbd->b, 0.0, 1.0, B_BANDCOL, 0, "Sets the blue value for the active color");
+       uiBlockEndAlign(block);
+}
+
+void draw_colorband_buts_small(uiBlock *block, ColorBand *coba, rctf *butr, int event)
+{
+       CBData *cbd;
+       uiBut *bt;
+       float unit= (butr->xmax-butr->xmin)/14.0f;
+       float xs= butr->xmin;
+       
+       cbd= coba->data + coba->cur;
+       
+       uiBlockBeginAlign(block);
+       uiDefButF(block, COL, event,            "",                     xs,butr->ymin+20.0f,2.0f*unit,20,                               &(cbd->r), 0, 0, 0, B_BANDCOL, "");
+       uiDefButF(block, NUM, event,            "A:",           xs+2.0f*unit,butr->ymin+20.0f,4.0f*unit,20,     &(cbd->a), 0.0f, 1.0f, 10, 2, "");
+       bt= uiDefBut(block, BUT, event, "Add",          xs+6.0f*unit,butr->ymin+20.0f,2.0f*unit,20,     NULL, 0, 0, 0, 0, "Adds a new color position to the colorband");
+       uiButSetFunc(bt, colorband_add_cb, coba, NULL);
+       bt= uiDefBut(block, BUT, event, "Del",          xs+8.0f*unit,butr->ymin+20.0f,2.0f*unit,20,     NULL, 0, 0, 0, 0, "Deletes the active position");
+       uiButSetFunc(bt, colorband_del_cb, coba, NULL);
+       uiDefButS(block, ROW, event,            "E",            xs+10.0f*unit,butr->ymin+20.0f,unit,20,         &coba->ipotype, 5.0, 1.0, 0, 0, "Sets interpolation type 'Ease' (quadratic) ");
+       uiDefButS(block, ROW, event,            "C",            xs+11.0f*unit,butr->ymin+20.0f,unit,20,         &coba->ipotype, 5.0, 3.0, 0, 0, "Sets interpolation type Cardinal");
+       uiDefButS(block, ROW, event,            "L",            xs+12.0f*unit,butr->ymin+20.0f,unit,20,         &coba->ipotype, 5.0, 0.0, 0, 0, "Sets interpolation type Linear");
+       uiDefButS(block, ROW, event,            "S",            xs+13.0f*unit,butr->ymin+20.0f,unit,20,         &coba->ipotype, 5.0, 2.0, 0, 0, "Sets interpolation type B-Spline");
+       
+       uiDefBut(block, BUT_COLORBAND, event, "",               xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, "");
+       uiBlockEndAlign(block);
+       
+}
+
 static void texture_panel_plugin(Tex *tex)
 {
        uiBlock *block;
@@ -504,7 +644,13 @@ static void texture_panel_blend(Tex *tex)
        uiDefButS(block, ROW, B_TEXPRV, "Sphere",       85, 160, 75, 19, &tex->stype, 2.0, (float)TEX_SPHERE, 0, 0, "Use progression with the shape of a sphere");
        uiDefButS(block, ROW, B_TEXPRV, "Halo",         160, 160, 75, 19, &tex->stype, 2.0, (float)TEX_HALO, 0, 0, "Use a quadratic progression with the shape of a sphere");
        uiDefButS(block, ROW, B_TEXPRV, "Radial",       235, 160, 75, 19, &tex->stype, 2.0, (float)TEX_RAD, 0, 0, "Use a polar progression");
+       uiBlockEndAlign(block);
        
+       uiBlockBeginAlign(block);
+       uiDefButS(block, ROW, B_TEXREDR_PRV, "Extend",                  10,120,63,19, &tex->extend, 4.0, 1.0, 0, 0, "Extends the color of the edge pixels");
+       uiDefButS(block, ROW, B_TEXREDR_PRV, "Clip",                    73,120,48,19, &tex->extend, 4.0, 2.0, 0, 0, "Sets alpha 0.0 outside Image edges");
+       uiDefButS(block, ROW, B_TEXREDR_PRV, "Repeat",                  121,120,63,19, &tex->extend, 4.0, 3.0, 0, 0, "Causes Image to repeat horizontally and vertically");     
+       uiBlockEndAlign(block);
 }
 
 /* newnoise: noisebasis menu string */
@@ -742,6 +888,232 @@ static void texture_panel_voronoi(Tex *tex)
        uiDefButF(block, NUMSLI, B_TEXPRV, "W4: ", 10, 10, 150, 19, &tex->vn_w4, -2.0, 2.0, 10, 0, "Sets feature weight 4");
 }
 
+static void texture_panel_pointdensity(Tex *tex)
+{
+       uiBlock *block;
+       PointDensity *pd;
+       short yco=PANEL_YMAX;
+       
+       block= uiNewBlock(&curarea->uiblocks, "texture_panel_pointdensity", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Point Density", "Texture", PANELX, PANELY, PANELW, PANELH)==0) return;
+       uiSetButLock(tex->id.lib!=0, ERROR_LIBDATA_MESSAGE);
+       
+       if(tex->pd==NULL) {
+               tex->pd= BKE_add_pointdensity();
+               tex->pd->object= OBACT;
+       }
+       if(!tex->pd) return;
+       pd= tex->pd;
+
+       uiDefBut(block, LABEL, B_NOP, "Density estimation:",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+
+       uiDefButF(block, NUM, B_REDR, "Radius: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->radius), 0.001, 100.0, 10, 2, "Radius to look for nearby particles within");
+       
+       yco -= YSPACE;
+       
+       uiDefBut(block, LABEL, B_NOP, "Falloff:",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");     
+       uiBlockBeginAlign(block);
+       uiDefButS(block, MENU, B_REDR, "Standard %x0|Smooth %x1|Soft %x2|Constant %x3|Root %x4",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &pd->falloff_type, 0.0, 0.0, 0, 0, "Falloff type");
+       if (pd->falloff_type == TEX_PD_FALLOFF_SOFT) {
+               uiDefButF(block, NUM, B_REDR, "Softness: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->falloff_softness), 1.0, 1024.0, 10, 2, "The intensity of the falloff");
+       }
+       uiBlockEndAlign(block);
+
+       yco = PANEL_YMAX;
+       
+       uiDefBut(block, LABEL, B_NOP, "Point data source:",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+       
+       uiDefButS(block, MENU, B_TEXREDR_PRV, "Particle System %x0|Object Vertices %x1",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &pd->source, 0.0, 0.0, 0, 0, "Source");
+       
+       yco -= YSPACE;
+       
+       if (pd->source == TEX_PD_PSYS) {
+               uiBlockBeginAlign(block);
+               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_REDR, "Ob:",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(pd->object), "Object that has the particle system");
+                       
+               if (pd->object && pd->object->particlesystem.first) {
+                       uiDefButS(block, NUM, B_REDR, "PSys:", 
+                               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(pd->psysindex), 1, 10, 10, 3, "Particle system number in the object");
+               }
+               uiBlockEndAlign(block);
+               
+               yco -= YSPACE;
+               
+               uiDefBut(block, LABEL, B_NOP, "Cache particles in:",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+               uiDefButS(block, MENU, B_TEXREDR_PRV, "Emit Object Location %x0|Emit Object Space %x1|Global Space %x2",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &pd->psys_cache_space, 0.0, 0.0, 0, 0, "Co-ordinate system to cache particles in");
+       }
+       else if (pd->source == TEX_PD_OBJECT) {
+               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_REDR, "Ob:",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(pd->object), "Object to render as points");
+               
+               yco -= YSPACE;
+               
+               uiDefBut(block, LABEL, B_NOP, "Cache vertices in:",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+               uiDefButS(block, MENU, B_TEXREDR_PRV, "Object Location %x0|Object Space %x1|Global Space %x2",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &pd->ob_cache_space, 0.0, 0.0, 0, 0, "Co-ordinate system to cache vertices in");
+       }
+
+}
+
+static void texture_panel_pointdensity_modify(Tex *tex)
+{
+       uiBlock *block;
+       PointDensity *pd;
+       short yco=PANEL_YMAX, ymid;
+       
+       block= uiNewBlock(&curarea->uiblocks, "texture_panel_pointdensity_modify", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Modifiers", "Texture", PANELX, PANELY, PANELW, PANELH+20)==0) return;
+       uiSetButLock(tex->id.lib!=0, ERROR_LIBDATA_MESSAGE);
+
+       if(tex->pd==NULL) {
+               tex->pd= BKE_add_pointdensity();
+       }
+       if(!tex->pd) return;
+       pd= tex->pd;
+       
+       if (pd->source == TEX_PD_PSYS) {
+               uiDefBut(block, LABEL, B_NOP, "Color & Intensity By:",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+
+               uiBlockBeginAlign(block);
+               uiDefButS(block, MENU, B_TEXREDR_PRV, "Constant %x0|Particle Age %x1|Particle Speed %x2|Velocity -> RGB %x3|",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &pd->color_source, 0.0, 0.0, 0, 0, "Particle Life: Lifetime mapped as 0.0 - 1.0 intensity, Velocity: XYZ velocity mapped as RGB colours");
+               if (ELEM(pd->color_source, TEX_PD_COLOR_PARTSPEED, TEX_PD_COLOR_PARTVEL)) {
+                       uiDefButF(block, NUM, B_REDR, "Scale: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->speed_scale), 0.001, 100.0, 10, 2, "Multipler to bring particle speed within an acceptable range");
+               }
+               uiBlockEndAlign(block);
+               
+               yco-= 2*BUTH;
+               
+               
+               if (ELEM(pd->color_source, TEX_PD_COLOR_PARTAGE, TEX_PD_COLOR_PARTSPEED)) {
+                       rctf rect = {X2CLM1, X2CLM1+BUTW1, yco, yco};
+                       if (pd->coba == NULL) pd->coba = add_colorband(1);
+                       draw_colorband_buts_small(block, pd->coba, &rect, B_TEXREDR_PRV);
+               } else {
+                       uiDefBut(block, LABEL, B_NOP, "",
+                               X2CLM2, yco, BUTW2, BUTH*2, 0, 0, 0, 0, 0, "");
+               }
+               
+               if (!ELEM(pd->color_source, TEX_PD_COLOR_PARTSPEED, TEX_PD_COLOR_PARTVEL)) yco -= BUTH;
+       }
+       
+       ymid = yco -= YSPACE;
+       
+       uiDefButBitS(block, TOG, TEX_PD_TURBULENCE, B_REDR, "Turbulence",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->flag), 0, 0, 0, 0, "Add directed turbulence to the density estimation");
+       
+       yco -= YSPACE;
+       
+       uiBlockBeginAlign(block);
+       if (pd->flag & TEX_PD_TURBULENCE) {
+               
+               uiDefButF(block, NUM, B_REDR, "Size: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->noise_size), 0.001, 100.0, 10, 2, "Turbulence size");
+               uiDefButS(block, NUM, B_REDR, "Depth: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->noise_depth), 0.0, 100.0, 10, 2, "Turbulence depth");
+               uiDefButF(block, NUM, B_REDR, "Strength: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->noise_fac), 0.001, 100.0, 10, 2, "");
+               
+               uiBlockEndAlign(block);
+               
+               yco = ymid - BUTH - YSPACE;
+
+               uiDefBut(block, LABEL, B_NOP, "Noise Basis:",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+               uiDefButS(block, MENU, B_REDR, noisebasis_menu(),
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(pd->noise_basis), 0.0, 0.0, 0, 0, "Noise formula used for tubulence");
+               
+               uiDefBut(block, LABEL, B_NOP, "Noise Influence:",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+                       
+               if (pd->source == TEX_PD_PSYS) {
+                       uiDefButS(block, MENU, B_REDR, "Noise Influence %t|Static %x0|Velocity %x1|Particle Age %x2|Time %x3",
+                               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(pd->noise_influence), 0.0, 0.0, 0, 0, "Noise Influence");
+               } else if (pd->source == TEX_PD_OBJECT) {
+                       uiDefButS(block, MENU, B_REDR, "Noise Influence %t|Static %x0|Time %x3",
+                               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(pd->noise_influence), 0.0, 0.0, 0, 0, "Noise Influence");
+               }
+       } else {
+               uiDefBut(block, LABEL, B_NOP, "",
+                       X2CLM2, yco-=2*BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+       }
+
+}
+
+static void texture_panel_voxeldata(Tex *tex)
+{
+       uiBlock *block;
+       VoxelData *vd;
+       short yco=PANEL_YMAX;
+
+       block= uiNewBlock(&curarea->uiblocks, "texture_panel_voxeldata", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Voxel Data", "Texture", PANELX, PANELY, PANELW, PANELH+YSPACE)==0) return;
+       uiSetButLock(tex->id.lib!=0, ERROR_LIBDATA_MESSAGE);
+
+       if(tex->vd==NULL) {
+               tex->vd= BKE_add_voxeldata();
+       }
+
+       if(tex->vd) {
+               vd= tex->vd;
+               
+               uiDefBut(block, LABEL, B_NOP, "Data source:",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+                       
+               uiDefIconTextBut(block, BUT, B_VOXELDATA_LOAD, ICON_FILESEL, "Open",
+                       X4CLM1, yco-=BUTH, BUTW4, BUTH, 0, 0, 0, 0, 0, "");
+               uiDefBut(block, TEX, 0, "",
+                       X4CLM2+XSPACE, yco, BUTW2+BUTW4+2*XSPACE, BUTH, &vd->source_path, 0.0, 79.0, 0, 0, "File path to the voxel data set");
+
+               yco -= YSPACE;
+               
+               uiDefBut(block, LABEL, B_NOP, "Interpolation:",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+               uiDefButI(block, MENU, B_REDR, "None %x0|Linear %x1|Tricubic %x2",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &vd->interp_type, 0.0, 0.0, 0, 0, "Interpolation type");                
+               
+               yco -= YSPACE;
+               
+               uiDefButF(block, NUM, B_REDR, "Intensity: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(vd->int_multiplier), 0.0001, 10000.0, 0, 0, "Multiplier to scale up or down the texture's intensity");
+               
+               yco = PANEL_YMAX - 2*BUTH - 2*YSPACE;
+               
+               uiDefBut(block, LABEL, B_NOP, "Resolution:",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+               uiBlockBeginAlign(block);
+               uiDefButI(block, NUM, B_REDR, "X: ",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(vd->resolX), 1, 10000, 0, 0, "Resolution of the voxel data");
+               uiDefButI(block, NUM, B_REDR, "Y: ",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(vd->resolY), 1, 10000, 0, 0, "Resolution of the voxel data");
+               uiDefButI(block, NUM, B_REDR, "Z: ",
+                       X2CLM2, yco-= BUTH, BUTW2, BUTH, &(vd->resolZ), 1, 10000, 0, 0, "Resolution of the voxel data");
+               uiBlockEndAlign(block);
+               
+               yco -= YSPACE;
+               
+               uiBlockBeginAlign(block);
+               uiDefButI(block,TOG, B_REDR, "Still",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(vd->still), 0,1, 0, 0, "Use a still frame from the data sequence for the entire rendered animation");
+               if (vd->still) uiDefButI(block, NUM, B_REDR, "Frame: ",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(vd->still_frame), 1, 10000, 0, 0, "The frame to pause on for the entire rendered animation"); 
+               uiBlockEndAlign(block);
+               
+       }
+}
 
 static char *layer_menu(RenderResult *rr, short *curlay)
 {
@@ -1419,113 +1791,6 @@ static void texture_panel_envmap(Tex *tex)
        }
 }
 
-static void colorband_pos_cb(void *coba_v, void *unused_v)
-{
-       ColorBand *coba= coba_v;
-       int a;
-       
-       if(coba->tot<2) return;
-       
-       for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
-       qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
-       for(a=0; a<coba->tot; a++) {
-               if(coba->data[a].cur==coba->cur) {
-                       if(coba->cur!=a) addqueue(curarea->win, REDRAW, 0);     /* button cur */
-                       coba->cur= a;
-                       break;
-               }
-       }
-}
-
-static void colorband_add_cb(void *coba_v, void *unused_v)
-{
-       ColorBand *coba= coba_v;
-       
-       if(coba->tot < MAXCOLORBAND-1) coba->tot++;
-       coba->cur= coba->tot-1;
-       
-       colorband_pos_cb(coba, NULL);
-       BIF_undo_push("Add colorband");
-       
-}
-
-static void colorband_del_cb(void *coba_v, void *unused_v)
-{
-       ColorBand *coba= coba_v;
-       int a;
-       
-       if(coba->tot<2) return;
-       
-       for(a=coba->cur; a<coba->tot; a++) {
-               coba->data[a]= coba->data[a+1];
-       }
-       if(coba->cur) coba->cur--;
-       coba->tot--;
-       
-       BIF_undo_push("Delete colorband");
-       BIF_preview_changed(ID_TE);
-}
-
-
-/* offset aligns from bottom, standard width 300, height 115 */
-static void draw_colorband_buts(uiBlock *block, ColorBand *coba, int xoffs, int yoffs, int redraw)
-{
-       CBData *cbd;
-       uiBut *bt;
-       
-       if(coba==NULL) return;
-       
-       bt= uiDefBut(block, BUT, redraw,        "Add",          80+xoffs,95+yoffs,37,20, 0, 0, 0, 0, 0, "Adds a new color position to the colorband");
-       uiButSetFunc(bt, colorband_add_cb, coba, NULL);
-       uiDefButS(block, NUM, redraw,           "Cur:",         117+xoffs,95+yoffs,81,20, &coba->cur, 0.0, (float)(coba->tot-1), 0, 0, "Displays the active color from the colorband");
-       bt= uiDefBut(block, BUT, redraw,                "Del",          199+xoffs,95+yoffs,37,20, 0, 0, 0, 0, 0, "Deletes the active position");
-       uiButSetFunc(bt, colorband_del_cb, coba, NULL);
-       
-       uiDefButS(block, MENU, redraw,          "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
-               236+xoffs, 95+yoffs, 64, 20,            &coba->ipotype, 0.0, 0.0, 0, 0, "Sets interpolation type");
-
-       uiDefBut(block, BUT_COLORBAND, redraw, "",      xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, "");
-       
-       cbd= coba->data + coba->cur;
-       
-       uiBlockBeginAlign(block);
-       bt= uiDefButF(block, NUM, redraw, "Pos",                xoffs,40+yoffs,110,20, &cbd->pos, 0.0, 1.0, 10, 0, "Sets the position of the active color");
-       uiButSetFunc(bt, colorband_pos_cb, coba, NULL);
-       uiDefButF(block, COL, redraw,           "",             xoffs,20+yoffs,110,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "");
-       uiDefButF(block, NUMSLI, redraw,        "A ",   xoffs,yoffs,110,20, &cbd->a, 0.0, 1.0, 10, 0, "Sets the alpha value for this position");
-
-       uiBlockBeginAlign(block);
-       uiDefButF(block, NUMSLI, redraw,        "R ",   115+xoffs,40+yoffs,185,20, &cbd->r, 0.0, 1.0, B_BANDCOL, 0, "Sets the red value for the active color");
-       uiDefButF(block, NUMSLI, redraw,        "G ",   115+xoffs,20+yoffs,185,20, &cbd->g, 0.0, 1.0, B_BANDCOL, 0, "Sets the green value for the active color");
-       uiDefButF(block, NUMSLI, redraw,        "B ",   115+xoffs,yoffs,185,20, &cbd->b, 0.0, 1.0, B_BANDCOL, 0, "Sets the blue value for the active color");
-       uiBlockEndAlign(block);
-}
-
-void draw_colorband_buts_small(uiBlock *block, ColorBand *coba, rctf *butr, int event)
-{
-       CBData *cbd;
-       uiBut *bt;
-       float unit= (butr->xmax-butr->xmin)/14.0f;
-       float xs= butr->xmin;
-       
-       cbd= coba->data + coba->cur;
-       
-       uiBlockBeginAlign(block);
-       uiDefButF(block, COL, event,            "",                     xs,butr->ymin+20.0f,2.0f*unit,20,                               &(cbd->r), 0, 0, 0, B_BANDCOL, "");
-       uiDefButF(block, NUM, event,            "A:",           xs+2.0f*unit,butr->ymin+20.0f,4.0f*unit,20,     &(cbd->a), 0.0f, 1.0f, 10, 2, "");
-       bt= uiDefBut(block, BUT, event, "Add",          xs+6.0f*unit,butr->ymin+20.0f,2.0f*unit,20,     NULL, 0, 0, 0, 0, "Adds a new color position to the colorband");
-       uiButSetFunc(bt, colorband_add_cb, coba, NULL);
-       bt= uiDefBut(block, BUT, event, "Del",          xs+8.0f*unit,butr->ymin+20.0f,2.0f*unit,20,     NULL, 0, 0, 0, 0, "Deletes the active position");
-       uiButSetFunc(bt, colorband_del_cb, coba, NULL);
-
-       uiDefButS(block, MENU, event,           "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
-               xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20,            &coba->ipotype, 0.0, 0.0, 0, 0, "Sets interpolation type");
-
-       uiDefBut(block, BUT_COLORBAND, event, "",               xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, "");
-       uiBlockEndAlign(block);
-       
-}
-
 static void texture_panel_colors(Tex *tex)
 {
        uiBlock *block;
@@ -1700,13 +1965,12 @@ static void texture_panel_texture(MTex *actmtex, Material *ma, World *wrld, Lamp
                /* newnoise: all texture types as menu, not enough room for more buttons.
                 * Can widen panel, but looks ugly when other panels overlap it */
                if( !tex->use_nodes ) {
-                       sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE);
+                       sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d|Point Density %%x%d|Voxel Data %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE, TEX_POINTDENSITY, TEX_VOXELDATA);
                        uiDefBut(block, LABEL, 0, "Texture Type",               160, 150, 140, 20, 0, 0.0, 0.0, 0, 0, "");
                        uiDefButS(block, MENU, B_TEXTYPE, textypes,     160, 125, 140, 25, &tex->type, 0,0,0,0, "Select texture type");
                }
                
                uiDefButC(block, TOG, B_TEX_USENODES, "Nodes", 160, 100, 140, 25, &tex->use_nodes, 0.0f, 0.0f, 0, 0, "");
-
        }
        else {
                // label to avoid centering
@@ -3444,6 +3708,12 @@ static void material_panel_map_to(Object *ob, Material *ma, int from_nodes)
                uiDefButBitS(block, TOG, 1, B_MATPRV, "PAttr",          250,160,60,19, &pattr, 0, 0, 0, 0, "Display settings for particle attributes");
                uiBlockSetCol(block, TH_AUTO);
        }
+       else if (ma->material_type == MA_VOLUME) {
+               uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Density",               10,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
+               uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit",           70,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
+               uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Emit Col",         120,180,80,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
+               uiDefButBitS(block, TOG, MAP_COLMIR, B_MATPRV, "Absorb Col",            200,180,80,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
+       }
        else {
                uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Col",              10,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
                uiDefButBitS(block, TOG3, MAP_NORM, B_MATPRV, "Nor",            50,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the rendered normal");
@@ -3560,37 +3830,46 @@ static void material_panel_map_input(Object *ob, Material *ma)
        
        /* TEXCO */
        uiBlockBeginAlign(block);
-       uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Object",               675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
-       if(mtex->texco == TEXCO_UV && !(mtex->texflag & MTEX_DUPLI_MAPTO)) {
-               if(!verify_valid_uv_name(mtex->uvname))
-            uiBlockSetCol(block, TH_REDALERT);
-               but=uiDefBut(block, TEX, B_MATPRV, "UV:", 750,180,158,18, mtex->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer");
-               uiButSetCompleteFunc(but, autocomplete_uv, NULL);
-               uiBlockSetCol(block, TH_AUTO);
-       }
-       else
-               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "Ob:",750,180,158,18, &(mtex->object), "");
        
-       uiDefButS(block, ROW, B_MATPRV, "UV",                   630,160,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Orco",                 670,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object");
-       if( ob->particlesystem.first )
-               uiDefButS(block, ROW, B_MATPRV, "Strand",       725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STRAND, 0, 0, "Uses normalized strand texture coordinate (1D)");
-       else
-               uiDefButS(block, ROW, B_MATPRV, "Stick",        725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Uses mesh's sticky coordinates for the texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Win",                  775,160,45,18, &(mtex->texco), 4.0, (float)TEXCO_WINDOW, 0, 0, "Uses screen coordinates as texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Nor",                  820,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_NORM, 0, 0, "Uses normal vector as texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Refl",                 864,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_REFL, 0, 0, "Uses reflection vector as texture coordinates");
+       if (ma->material_type == MA_VOLUME) {
+               uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Object",               675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
+               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "Ob:",750,180,158,18, &(mtex->object), "");
+               uiDefButS(block, ROW, B_MATPRV, "Local",                630,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object");
        
-       uiDefButS(block, ROW, B_MATPRV, "Stress",               630,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_STRESS, 0, 0, "Uses the difference of edge lengths compared to original coordinates of the mesh");
-       uiDefButS(block, ROW, B_MATPRV, "Tangent",              700,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_TANGENT, 0, 0, "Uses the optional tangent vector as texture coordinates");
-       uiBlockEndAlign(block);
 
-       if(ELEM(mtex->texco, TEXCO_UV, TEXCO_ORCO))
-               uiDefButBitS(block, TOG, MTEX_DUPLI_MAPTO, B_MATPRV, "From Dupli",      820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent");
-       else if(mtex->texco == TEXCO_OBJECT)
-               uiDefButBitS(block, TOG, MTEX_OB_DUPLI_ORIG, B_MATPRV, "From Original", 820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's derive their object coordinates from the original objects transformation");
+       } else {
+               uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Object",               675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
+               if(mtex->texco == TEXCO_UV && !(mtex->texflag & MTEX_DUPLI_MAPTO)) {
+                       if(!verify_valid_uv_name(mtex->uvname))
+                               uiBlockSetCol(block, TH_REDALERT);
+                       but=uiDefBut(block, TEX, B_MATPRV, "UV:", 750,180,158,18, mtex->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer");
+                       uiButSetCompleteFunc(but, autocomplete_uv, NULL);
+                       uiBlockSetCol(block, TH_AUTO);
+               }
+               else
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "Ob:",750,180,158,18, &(mtex->object), "");
+               
+               uiDefButS(block, ROW, B_MATPRV, "UV",                   630,160,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Orco",                 670,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object");
+               if( ob->particlesystem.first )
+                       uiDefButS(block, ROW, B_MATPRV, "Strand",       725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STRAND, 0, 0, "Uses normalized strand texture coordinate (1D)");
+               else
+                       uiDefButS(block, ROW, B_MATPRV, "Stick",        725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Uses mesh's sticky coordinates for the texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Win",                  775,160,45,18, &(mtex->texco), 4.0, (float)TEXCO_WINDOW, 0, 0, "Uses screen coordinates as texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Nor",                  820,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_NORM, 0, 0, "Uses normal vector as texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Refl",                 864,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_REFL, 0, 0, "Uses reflection vector as texture coordinates");
+               
+               uiDefButS(block, ROW, B_MATPRV, "Stress",               630,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_STRESS, 0, 0, "Uses the difference of edge lengths compared to original coordinates of the mesh");
+               uiDefButS(block, ROW, B_MATPRV, "Tangent",              700,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_TANGENT, 0, 0, "Uses the optional tangent vector as texture coordinates");
+               uiBlockEndAlign(block);
 
+               if(ELEM(mtex->texco, TEXCO_UV, TEXCO_ORCO))
+                       uiDefButBitS(block, TOG, MTEX_DUPLI_MAPTO, B_MATPRV, "From Dupli",      820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent");
+               else if(mtex->texco == TEXCO_OBJECT)
+                       uiDefButBitS(block, TOG, MTEX_OB_DUPLI_ORIG, B_MATPRV, "From Original", 820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's derive their object coordinates from the original objects transformation");
+       }
 
        /* COORDS */
        uiBlockBeginAlign(block);
@@ -4178,7 +4457,7 @@ static uiBlock *strand_menu(void *mat_v)
 }
 
 
-static void material_panel_material(Material *ma)
+static void material_panel_material_solid(Material *ma)
 {
        uiBlock *block;
        float *colpoin = NULL;
@@ -4266,6 +4545,145 @@ static void material_panel_material(Material *ma)
 
 }
 
+static void material_panel_material_volume(Material *ma)
+{
+       uiBlock *block;
+       short yco=PANEL_YMAX;
+       
+       block= uiNewBlock(&curarea->uiblocks, "material_panel_material_volume", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Volume", "Material", PANELX, PANELY, PANELW, PANELH+40)==0) return;
+       
+       uiSetButLock(ma->id.lib!=NULL, ERROR_LIBDATA_MESSAGE);
+       
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUM, B_MATPRV, "Step Size: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_stepsize), 0.001, 100.0, 10, 2, "Ray marching step size");
+       uiDefButS(block, MENU, B_TEXREDR_PRV, "Step Size Calculation %t|Randomized %x0|Constant %x1",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &ma->vol_stepsize_type, 0.0, 0.0, 0, 0, "Step size calculation, randomized replaces banding with jittering");
+       uiDefButF(block, NUM, B_MATPRV, "Depth Cutoff: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_depth_cutoff), 0.001, 1.0, 10, 2, "Stop ray marching early if transmission drops below this luminance - higher values give speedups in dense volumes at the expense of accuracy ");
+       uiBlockEndAlign(block);
+       
+       yco -= YSPACE;
+       
+       uiDefBut(block, LABEL, B_NOP, "Self Shading:",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");     
+
+       uiBlockBeginAlign(block);
+       uiDefButS(block, MENU, B_TEXREDR_PRV, "Self Shading %t|None %x0|Single Scattering %x1|Multiple Scattering %x2|Single + Multiple %x3",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &ma->vol_shade_type, 0.0, 0.0, 0, 0, "Use absorbtion to attenuate light - Single scattering: direct lighting, Multiple scattering: internal light bouncing & diffusion");
+               
+       if (ELEM3(ma->vol_shade_type, MA_VOL_SHADE_SINGLE, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE))
+       {
+               uiDefButF(block, NUM, B_MATPRV, "Step Size: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shade_stepsize), 0.001, 100.0, 10, 2, "Step");
+       
+               uiBlockEndAlign(block);
+               
+               yco -= YSPACE;
+               
+               if (ma->vol_shade_type == MA_VOL_SHADE_SINGLE)
+               {
+                       uiBlockBeginAlign(block);
+                       uiDefButBitS(block, TOG, MA_VOL_PRECACHESHADING, B_MATPRV, "Light Cache",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Pre-cache the shading information into a voxel grid, speeds up shading at slightly less accuracy");
+                       uiDefButS(block, NUM, B_MATPRV, "Resolution: ",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_precache_resolution), 0.0, 1024.0, 10, 2, "Resolution of the voxel grid, low resolutions are faster, high resolutions use more memory (res ^3)");
+               
+               }
+               else if (ELEM(ma->vol_shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE))
+               {
+                       uiDefBut(block, LABEL, B_NOP, "Light Cache:",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");     
+                       uiDefButS(block, NUM, B_MATPRV, "Resolution: ",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_precache_resolution), 0.0, 1024.0, 10, 2, "Resolution of the voxel grid, low resolutions are faster, high resolutions use more memory (res ^3)");
+               
+               }
+
+               uiBlockEndAlign(block);
+               
+               yco -= YSPACE;
+               
+               if (ELEM(ma->vol_shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE)) {
+                       uiDefBut(block, LABEL, B_NOP, "Multiple Scattering:",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");     
+
+                       uiBlockBeginAlign(block);
+                       uiDefButF(block, NUM, B_MATPRV, "Blur: ",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_ms_diff), 0.01, 1.0, 10, 2, "Diffusion factor, the strength of the blurring effect");
+                       uiDefButI(block, NUM, B_MATPRV, "Spread: ",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_ms_steps), 1, 512.0, 10, 2, "Simulation steps, the effective distance over which the light is diffused");
+                       uiDefButF(block, NUM, B_MATPRV, "Intensity: ",
+                               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_ms_intensity), 0.00001, 1024.0, 10, 2, "Multiplier for multiple scattered light energy");
+                       uiBlockEndAlign(block);
+               }
+       }
+       uiBlockEndAlign(block);
+       
+       yco -= YSPACE;
+       
+       uiDefButBitS(block, TOG, MA_VOL_USEALPHA, B_MATPRV, "Alpha",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Generate an alpha channel (causes problems with Premul)");
+       
+       
+       /*uiDefButBitS(block, TOG, MA_VOL_RECVSHADOW, B_MATPRV, "Receive Shadows",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Receive shadows from external objects");
+       */
+       
+       yco = PANEL_YMAX;
+       
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUMSLI, B_MATPRV, "Density: ",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->alpha), 0.0, 1.0, 0, 0, "Base density value - textured density is added on top");
+       uiDefButF(block, NUM, B_MATPRV, "Density Scale: ",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_density_scale), 0.000001, 100.0, 10, 2, "Global density multiplier");
+       uiBlockEndAlign(block);
+       
+       yco -= YSPACE;
+       
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUM, B_MATPRV, "Absorption: ",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_absorption), 0.0, 100.0, 10, 0, "Amount of light absorbed by the volume");
+       uiDefButF(block, COL, B_MATPRV, "",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, ma->vol_absorption_col, 0, 0, 0, B_MATCOL, "");
+       uiBlockEndAlign(block);
+
+       yco -= YSPACE;
+       
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUMSLI, B_MATPRV, "Emit: ",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->emit), 0.0, 2.0, 0, 0, "Amount of light emitted from the volume");
+       uiDefButF(block, COL, B_MATPRV, "",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->r), 0, 0, 0, B_MATCOL, "");
+       uiBlockEndAlign(block);
+       
+       yco -= YSPACE;
+       
+       uiDefButF(block, NUM, B_MATPRV, "Scattering: ",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_scattering), 0.0, 100.0, 10, 0, "Amount of light scattered through the volume from lamps");
+       
+       yco -= YSPACE;
+       
+       uiBlockBeginAlign(block);
+       uiDefButS(block, MENU, B_TEXREDR_PRV, "Scattering Direction %t|Isotropic %x0|Mie Hazy %x1|Mie Murky %x2|Rayleigh %x3|Henyey-Greenstein %x4|Schlick %x5",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &ma->vol_phasefunc_type, 0.0, 0.0, 0, 0, "Scattering Direction (Phase Function)");
+       if (ELEM(ma->vol_phasefunc_type, MA_VOL_PH_HG, MA_VOL_PH_SCHLICK)) {
+               uiDefButF(block, NUM, B_MATPRV, "Asymmetry: ",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_phasefunc_g), -1.0, 1.0, 0, 0, "> 0 is forward scattering, < 0 is back scattering");
+               uiBlockEndAlign(block);
+       } else {
+               uiBlockEndAlign(block);
+               /* spacer */
+               uiDefBut(block, LABEL, B_NOP, "",
+                       X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+       }
+       
+       yco -= YSPACE;
+       uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_MATPRV, "GR:",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &ma->group, "Limit Lighting to Lamps in this Group"); 
+       
+}
+
 static void material_panel_nodes(Material *ma)
 {
        bNode *node;
@@ -4304,7 +4722,7 @@ static void material_panel_links(Object *ob, Material *ma)
        
        block= uiNewBlock(&curarea->uiblocks, "material_panel_links", UI_EMBOSS, UI_HELV, curarea->win);
        /* 310 makes sorting code to put it right after preview panel */
-       if(uiNewPanel(curarea, block, "Links and Pipeline", "Material", 310, 0, 318, 204)==0) return;
+       if(uiNewPanel(curarea, block, "Links and Pipeline", "Material", 310, 0, 338, 204)==0) return;
 
        /* Links from object to material/nodes */
        uiDefBut(block, ROUNDBOX, 0, "",                                        5, 90, 310, 110, NULL, 7.0, 0.0, 15 , 20, ""); 
@@ -4397,7 +4815,10 @@ static void material_panel_links(Object *ob, Material *ma)
        uiDefButBitI(block, TOG, MA_ONLYCAST, B_MATPRV,"OnlyCast",              85,10,75,19, &(ma->mode), 0, 0, 0, 0, "Makes faces cast shadows only, not rendered");
        uiDefButBitI(block, TOG, MA_TRACEBLE, B_NOP,"Traceable",        160,10,75,19, &(ma->mode), 0, 0, 0, 0, "Makes material detectable by ray tracing");
        uiDefButBitI(block, TOG, MA_SHADBUF, B_MATPRV,  "Shadbuf",              235,10,75,19, &(ma->mode), 0, 0, 0, 0, "Makes material cast shadows from shadow buffer lamps");
-                                 
+       uiBlockEndAlign(block);
+       
+       uiDefButS(block, MENU, B_MATPRV, "Material Type %t|Solid %x0|Halo %x1|Volume %x2",
+               10, -15, 300, 20, &(ma->material_type), 0.0, 0.0, 0, 0, "");
        
 }
 
@@ -4455,21 +4876,26 @@ void material_panels()
                
                ma= editnode_get_active_material(ma);
                if(ma) {
-                       material_panel_material(ma);
-                       material_panel_ramps(ma);
-                       material_panel_shading(ma);
-                       
-                       if (G.scene->r.renderer==R_INTERN)
-                               material_panel_tramir(ma);
-                       else {
-                               if(ma->YF_ar==0.f) {
-                                       ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
-                                       ma->YF_dscale = 1;
+                       if (ma->material_type == MA_SOLID) {
+                               material_panel_material_solid(ma);
+                               material_panel_ramps(ma);
+                               material_panel_shading(ma);
+                               
+                               if (G.scene->r.renderer==R_INTERN)
+                                       material_panel_tramir(ma);
+                               else {
+                                       if(ma->YF_ar==0.f) {
+                                               ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
+                                               ma->YF_dscale = 1;
+                                       }
+                                       material_panel_tramir_yafray(ma);
                                }
-                               material_panel_tramir_yafray(ma);
-                       }
 
-                       material_panel_sss(ma);
+                               material_panel_sss(ma);
+                               
+                       } else if (ma->material_type == MA_VOLUME) {
+                               material_panel_material_volume(ma);
+                       }
                        material_panel_texture(ob, ma);
                        
                        mtex= ma->mtex[ ma->texact ];
@@ -4640,6 +5066,13 @@ void texture_panels()
                        case TEX_VORONOI:
                                texture_panel_voronoi(tex);
                                break;
+                       case TEX_POINTDENSITY:
+                               texture_panel_pointdensity(tex);
+                               texture_panel_pointdensity_modify(tex);
+                               break;
+                       case TEX_VOXELDATA:
+                               texture_panel_voxeldata(tex);
+                               break;
                        }
                }
        }
index c9ee5d727bbce25d26cb2d7a53532a78ef93913d..04407b8500a1609a515a3a25690ac0fd90ee5559 100644 (file)
@@ -1569,7 +1569,7 @@ static int node_composit_buts_vecblur(uiBlock *block, bNodeTree *ntree, bNode *n
                                  &nbd->maxspeed, 0, 1024, 0, 0, "If not zero, maximum speed in pixels");
                uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "BlurFac:",
                                  butr->xmin, dy+19, dx, 19, 
-                                 &nbd->fac, 0.0f, 2.0f, 10, 2, "Scaling factor for motion vectors, actually 'shutter speed' in frames");
+                                 &nbd->fac, 0.0f, 10.0f, 10, 2, "Scaling factor for motion vectors, actually 'shutter speed' in frames");
                uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Curved",
                                  butr->xmin, dy, dx, 19, 
                                  &nbd->curved, 0.0f, 2.0f, 10, 2, "Interpolate between frames in a bezier curve, rather than linearly");
index 8dfa32d48c8049feaabbab414732d098579eed43..f29cc8e595376e2b728b04bde16110f58ae53ec6 100644 (file)
@@ -324,6 +324,8 @@ static Scene *preview_prepare_scene(RenderInfo *ri, int id_type, ID *id, int pr_
                                /* turn on raytracing if needed */
                                if(mat->mode_l & (MA_RAYTRANSP|MA_RAYMIRROR))
                                        sce->r.mode |= R_RAYTRACE;
+                               if(mat->material_type == MA_VOLUME)
+                                       sce->r.mode |= R_RAYTRACE;
                                if(mat->sss_flag & MA_DIFF_SSS)
                                        sce->r.mode |= R_SSS;
                                
index 321370f9f3fff78a9286d7e209bd236c301e4af0..ee1946d093bac38cf684f1e2e8af297b239ff58e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: KX_Dome.cpp 19618 2009-04-09 10:29:07Z ben2610 $
 -----------------------------------------------------------------------------
 
 This program is free software; you can redistribute it and/or modify it under
index de3360cd897b833939ade9bdf5a6a0c64469a129..1f3cea1881eced3c83854ee1077771ce2f13e854 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: KX_Dome.h 19599 2009-04-08 15:06:20Z ben2610 $
 -----------------------------------------------------------------------------
 
 This program is free software; you can redistribute it and/or modify it under
index dcd11b551a19a2fef2f5a1f15fc735129080761d..5f3aa39aeed41ae9175034aac19880a1e04d44d1 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: KX_PythonInitTypes.cpp 19794 2009-04-19 17:29:07Z campbellbarton $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
index 6da79be930127612e0c3414dcefb291b137428c8..890b02f6f03f5cc4f4b64623312ba878704e3e45 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: KX_PythonInitTypes.h 19709 2009-04-13 19:33:22Z gsrb3d $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
index 47fe9a9eea824e0086a99a537d9046d2647c7e86..98139cce4b5a3ce887e8335adff34f16e1ae0e73 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: PHY_IController.cpp 19709 2009-04-13 19:33:22Z gsrb3d $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
index 45e93f9d24e2cac9952fc190df2b838ffa07bd30..73e6d1ada182d096af7a3139abbdb89912bc70ff 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: PHY_IController.h 19709 2009-04-13 19:33:22Z gsrb3d $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
index 4dccecd3d290dcb6dac0ce60d0bb00b37f2a2f69..441f850a2b3af585054f4fb52b2ade745e9e9a4b 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: PHY_IGraphicController.cpp 19709 2009-04-13 19:33:22Z gsrb3d $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
index 36b8a978e874a6246ec2c9f9fcce7bab01d508a0..4e11445c33a745a29b48abe3952dae2b7873f96c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: PHY_IGraphicController.h 19709 2009-04-13 19:33:22Z gsrb3d $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *