svn merge -r 16866:17042 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Sun, 12 Oct 2008 12:17:57 +0000 (12:17 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Sun, 12 Oct 2008 12:17:57 +0000 (12:17 +0000)
28 files changed:
source/blender/blenkernel/BKE_texture.h
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/makesdna/DNA_material_types.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/shading.h
source/blender/render/intern/include/texture.h
source/blender/render/intern/include/volumetric.h [new file with mode: 0644]
source/blender/render/intern/source/convertblender.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/shadeinput.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/texture.c
source/blender/render/intern/source/volumetric.c [new file with mode: 0644]
source/blender/src/butspace.c
source/blender/src/buttons_shading.c
source/blender/src/previewrender.c

index cfcae3c44bc5a17a8932737c9a28cd5bbb4e63db..e16ac2d369b029d3c7f4c69b06be31336d538dcd 100644 (file)
@@ -39,6 +39,7 @@ struct ColorBand;
 struct HaloRen;
 struct TexMapping;
 struct EnvMap;
+struct PointDensity;
 
 /*  in ColorBand struct */
 #define MAXCOLORBAND 32
@@ -74,6 +75,11 @@ 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);
+
 int     BKE_texture_dependsOnTime(const struct Tex *texture);
 
 #endif
index f05b84f6e90ddc8727c9af9467fbbd015feb17a5..f54c0ae7ab148166d06141f6747354378629f37e 100644 (file)
@@ -166,7 +166,13 @@ void init_material(Material *ma)
        ma->sss_texfac= 0.0f;
        ma->sss_front= 1.0f;
        ma->sss_back= 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->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR;
 
        ma->preview = NULL;
index bb726887d32770a0a43b510324e8c3136b75be27..33b824623fa23c5f26235228e68c57bd979a7cf5 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"
@@ -409,6 +410,7 @@ 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);
        BKE_previewimg_free(&tex->preview);
        BKE_icon_delete((struct ID*)tex);
        tex->id.icon_id = 0;
@@ -470,6 +472,11 @@ 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;
+       }
+
        pit = tex->plugin;
        if (pit) {
                varstr= pit->varstr;
@@ -566,6 +573,7 @@ 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(tex->preview) texn->preview = BKE_previewimg_copy(tex->preview);
 
@@ -858,6 +866,55 @@ void BKE_free_envmap(EnvMap *env)
        
 }
 
+/* ------------------------------------------------------------------------- */
+
+PointDensity *BKE_add_pointdensity(void)
+{
+       PointDensity *pd;
+       
+       pd= MEM_callocN(sizeof(PointDensity), "pointdensity");
+       pd->radius = 0.3f;
+       pd->falloff_type = TEX_PD_FALLOFF_STD;
+       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;
+       
+       return pd;
+} 
+
+PointDensity *BKE_copy_pointdensity(PointDensity *pd)
+{
+       PointDensity *pdn;
+
+       pdn= MEM_dupallocN(pd);
+       pdn->point_tree = NULL;
+       pdn->point_data = NULL;
+       
+       return pd;
+}
+
+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;
+       }
+}
+
+void BKE_free_pointdensity(PointDensity *pd)
+{
+       BKE_free_pointdensitydata(pd);
+       MEM_freeN(pd);
+}
+
 /* ------------------------------------------------------------------------- */
 int BKE_texture_dependsOnTime(const struct Tex *texture)
 {
index e2e71a2fb1a7e67cde095a0f5886eee2e2f78bd9..bc5306214037ef1f5e98bb724ddf384ac24a1baa 100644 (file)
@@ -251,6 +251,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 79517c4fde4038819f4cfd3e0035415ec5b22bb3..bf7e3473d1ff0c556514baea3c05fcb9ccc2d5ec 100644 (file)
@@ -2139,6 +2139,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;
@@ -3300,6 +3307,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 25f9e179ca901cbc1aed8775eedef452cc310b11..3cae5fe4972a44c289600d8b35497e4a35fd303f 100644 (file)
@@ -2476,6 +2476,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);
 
                        tex->id.flag -= LIB_NEEDLINK;
                }
@@ -2502,6 +2503,10 @@ 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->preview = direct_link_preview_image(fd, tex->preview);
 
        tex->iuser.ok= 1;
@@ -7689,6 +7694,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) {
@@ -7712,6 +7718,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)) {
@@ -7870,6 +7877,35 @@ 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;       
+                       }
+               }
+               
+               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;
+                       }
+               }
+               
        }
        
        /* set the curve radius interpolation to 2.47 default - easy */
@@ -7894,6 +7930,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;
index 3c2ca92f3fc3110e5f83fc86a17acd006de0d712..7249090dfa7786f997b28ff7606341bf91036f3a 100644 (file)
@@ -1335,6 +1335,7 @@ static void write_textures(WriteData *wd, ListBase *idbase)
                        if(tex->plugin) writestruct(wd, DATA, "PluginTex", 1, tex->plugin);
                        if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba);
                        if(tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env);
+                       if(tex->pd) writestruct(wd, DATA, "PointDensity", 1, tex->pd);
                        
                        write_previews(wd, tex->preview);
                }
index aa8470505810d694e47165e35c8a69582e26a14f..4e006d176822875bf6476cf2bf760dff1cda18c7 100644 (file)
@@ -62,6 +62,18 @@ typedef struct Material {
        float translucency;
        /* end synced with render_types.h */
        
+       short material_type; /* solid, halo, volumetric */
+       short pad5[3];
+       
+       /* volumetrics */
+       float vol_alphathresh;
+       float vol_stepsize, vol_shade_stepsize;
+       float vol_absorption, vol_scattering;
+       float vol_absorption_col[3];
+       short vol_shadeflag;
+       short vol_phasefunc_type;
+       float vol_phasefunc_g;
+               
        float fresnel_mir, fresnel_mir_i;
        float fresnel_tra, fresnel_tra_i;
        float filter;           /* filter added, for raytrace transparency and transmissivity */
@@ -153,6 +165,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 +302,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 +347,18 @@ typedef struct Material {
 /* sss_flag */
 #define MA_DIFF_SSS            1
 
+/* vol_shadeflag */
+#define MA_VOL_SHADED          1
+#define MA_VOL_ATTENUATED      2
+#define MA_VOL_SHADOWED                4
+
+/* 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 111dc08ee02dafe9eded41146af798b96338343a..95f61e73c791f153fc31e5b3270310dabed2604a 100644 (file)
@@ -127,6 +127,33 @@ typedef struct EnvMap {
        short recalc, lastsize;
 } EnvMap;
 
+typedef struct PointDensity {
+       short flag;
+
+       short falloff_type;
+       float radius;
+       short source;
+       short pdpad[3];
+
+       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;
+       float noise_fac;
+       float pdpad4;
+       
+} PointDensity;
+
 typedef struct Tex {
        ID id;
        
@@ -172,6 +199,7 @@ typedef struct Tex {
        struct ColorBand *coba;
        struct EnvMap *env;
        struct PreviewImage * preview;
+       struct PointDensity *pd;
        
 } Tex;
 
@@ -208,6 +236,8 @@ typedef struct TexMapping {
 #define TEX_MUSGRAVE   11
 #define TEX_VORONOI            12
 #define TEX_DISTNOISE  13
+/* predicting ocean texture for 14 */
+#define TEX_POINTDENSITY       15
 
 /* musgrave stype */
 #define TEX_MFRACTAL           0
@@ -385,5 +415,34 @@ 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_SHARP   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_ANGVEL            2
+#define TEX_PD_NOISE_TIME              3
+
 #endif
 
index 888474ffa18bd2c492563dc2212d3def7589644b..112a1e9929dd68f667fa915bc318eef026b0bd64 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..9c21cc0
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *
+ * ***** 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);
+int pointdensitytex(struct Tex *tex, float *texvec, struct TexResult *texres);
+
+#endif /* POINTDENSITY_H */
+
index 1768b052b54fc431458613d077bdbfecb0cb9f9b..b0003cadb55ba38670daa020354c412c0db4c905 100644 (file)
@@ -345,6 +345,7 @@ typedef struct HaloRen
     struct Material *mat;
 } HaloRen;
 
+
 /* ------------------------------------------------------------------------- */
 
 typedef struct StrandVert {
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 be5471e07c4d451a5b6ce0ce31d34697c0393a8d..6e1ad562c14feb3317503089b09c6311b13edebd 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);
 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);
 
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..8db3fa6
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ *
+ * ***** 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): Farsthary (Raul FHernandez), Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr);
\ No newline at end of file
index 2d229cb33878568cdbbaf1646121e06d4b08d595..4b663c6caa65e114f09372e6b63b99cbdd1b9958 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 "render_types.h"
 #include "rendercore.h"
 #include "renderdatabase.h"
@@ -921,6 +923,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 +965,10 @@ static Material *give_render_material(Render *re, Object *ob, int nr)
        if(ma->nodetree && ma->use_nodes)
                flag_render_node_material(re, ma->nodetree);
        
+       if (ma->material_type == MA_VOLUME) re->r.mode |= R_RAYTRACE;
+       
+       check_material_is_textured(ma);
+       
        return ma;
 }
 
@@ -2023,6 +2051,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)
@@ -4408,6 +4437,8 @@ void RE_Database_Free(Render *re)
        end_radio_render();
        end_render_materials();
        
+       free_pointdensities(re);
+       
        if(re->wrld.aosphere) {
                MEM_freeN(re->wrld.aosphere);
                re->wrld.aosphere= NULL;
@@ -4858,6 +4889,10 @@ 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);
                }
                
                if(!re->test_break())
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..bdfb4d3
--- /dev/null
@@ -0,0 +1,347 @@
+/* 
+ * ***** 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_main.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_particle_types.h"
+
+#include "render_types.h"
+#include "renderdatabase.h"
+#include "texture.h"
+
+static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys)
+{
+       DerivedMesh* dm;
+       ParticleKey state;
+       float cfra=bsystem_time(ob,(float)G.scene->r.cfra,0.0);
+       int i, childexists;
+       int total_particles;
+       float partco[3];
+       float obview[4][4];
+       
+       /* init crap */
+       if (!psys || !ob || !pd) return;
+       
+       Mat4MulMat4(obview, re->viewinv, ob->obmat);
+       
+       /* Just to create a valid rendering context */
+       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);
+       dm->release(dm);
+       
+       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;
+       
+       pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
+       if (pd->noise_influence != TEX_PD_NOISE_STATIC)
+               pd->point_data = MEM_mallocN(sizeof(float)*3*total_particles, "point_data");
+       
+       if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
+               childexists = 1;
+       
+       for (i = 0; i < total_particles; i++) {
+
+               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 (pd->noise_influence == TEX_PD_NOISE_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];
+                       } else if (pd->noise_influence == TEX_PD_NOISE_ANGVEL) {
+                               pd->point_data[i*3 + 0] = state.ave[0];
+                               pd->point_data[i*3 + 1] = state.ave[1];
+                               pd->point_data[i*3 + 2] = state.ave[2];
+                       }
+               }
+       }
+       
+       BLI_bvhtree_balance(pd->point_tree);
+       
+       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);
+       
+       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;
+               
+               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->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;
+       }
+}
+
+
+
+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);
+               }
+       }
+}
+
+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;
+    short falloff_type;   
+} PointDensityRangeData;
+
+void accum_density(void *userdata, int index, float squared_dist)
+{
+       PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
+       const float dist = pdr->squared_radius - squared_dist;
+       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_SHARP)
+               density = dist*dist;
+       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) {
+               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;
+       }
+       
+       *pdr->density += density;
+}
+
+#define MAX_POINTS_NEAREST     25
+int pointdensitytex(Tex *tex, float *texvec, TexResult *texres)
+{
+       int rv = TEX_INT;
+       PointDensity *pd = tex->pd;
+       PointDensityRangeData pdr;
+       float density=0.0f;
+       float vec[3] = {0.0, 0.0, 0.0};
+       float tv[3];
+       float turb;
+       
+       if ((!pd) || (!pd->point_tree)) {
+               texres->tin = 0.0f;
+               return 0;
+       }
+       
+       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;
+       
+       if (pd->flag & TEX_PD_TURBULENCE) {
+               VECCOPY(tv, texvec);
+               
+               /* find the average speed vectors, for perturbing final density lookup with */
+               BLI_bvhtree_range_query(pd->point_tree, texvec, pd->radius, accum_density, &pdr);
+               
+               density = 0.0f;
+               Normalize(vec);
+       
+               turb = BLI_turbulence(pd->noise_size, texvec[0]+vec[0], texvec[1]+vec[1], texvec[2]+vec[2], pd->noise_depth);
+               
+               turb -= 0.5f;   /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
+               
+               tv[0] = texvec[0] + pd->noise_fac * turb;
+               tv[1] = texvec[1] + pd->noise_fac * turb;
+               tv[2] = texvec[2] + pd->noise_fac * turb;
+               
+               /* do density lookup with altered coordinates */
+               BLI_bvhtree_range_query(pd->point_tree, tv, pd->radius, accum_density, &pdr);
+       }
+       else
+               BLI_bvhtree_range_query(pd->point_tree, texvec, pd->radius, accum_density, &pdr);
+
+       texres->tin = density;
+
+       //texres->tr = vec[0];
+       //texres->tg = vec[1];
+       //texres->tb = vec[2];
+       
+       return TEX_INT;
+       
+       /*
+       BRICONTRGB;
+       
+       texres->ta = 1.0;
+       
+       if (texres->nor!=NULL) {
+               texres->nor[0] = texres->nor[1] = texres->nor[2] = 0.0f;
+       }
+       */
+       
+       //BRICONT;
+       
+       //return rv;
+}
index f822d41bb85c11b11fea21cf0a294cd3f6b8061a..c431340d770a229b37b847a8eb8e3dd533ded6f1 100644 (file)
@@ -205,7 +205,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);
@@ -274,9 +274,10 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
                        ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
                        shi->mat= vlr->mat;             /* shi->mat is being set in nodetree */
                }
-               else
-                       shade_material_loop(shi, shr);
-               
+               else {
+                       if (shi->mat->material_type == MA_SOLID) shade_material_loop(shi, shr);
+                       else if (shi->mat->material_type == MA_VOLUME) shade_volume_loop(shi, shr);
+               }
                /* raytrace likes to separate the spec color */
                VECSUB(shr->diff, shr->combined, shr->spec);
        }       
index ec47df74d0428039771fd84b45d91b860dd5fd09..d14d221b099f5a805bc67288b23c93da3e066092 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 476330152ecd47dbf90f67ff1dc55fa6dd2df9a3..aa11e3d75ddaf2e23d5a9cb101f906ed3f7d3ec0 100644 (file)
@@ -135,6 +135,12 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
        }       
 }
 
+/* delivers a fully filled in ShadeResult, for all passes */
+void shade_volume_loop(ShadeInput *shi, ShadeResult *shr)
+{
+       if(R.r.mode & R_RAYTRACE) volume_trace(shi, shr);
+}
+
 
 /* do a shade, finish up some passes, apply mist */
 void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
@@ -151,7 +157,8 @@ 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) shade_volume_loop(shi, shr);
        }
        
        /* copy additional passes */
@@ -667,6 +674,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 c4fac1aeb06c2d10322590770bd8b1ca89bc5f9f..6e64479b88c0b93212d29242cd24fc3c5ff597da 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 7ce66ff6d1265388d31aa082f0d162f5e5148999..dfeb775aca6c13ffcba9379655feebe5074ed4d0 100644 (file)
@@ -62,6 +62,7 @@
 #include "BKE_ipo.h"
 
 #include "envmap.h"
+#include "pointdensity.h"
 #include "renderpipeline.h"
 #include "render_types.h"
 #include "rendercore.h"
@@ -1216,6 +1217,9 @@ 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;
        }
 
        if (tex->flag & TEX_COLORBAND) {
@@ -1451,6 +1455,163 @@ 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);  /* 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;
+                               
+                               tcol[0]=texres.tr; tcol[1]=texres.tg; tcol[2]=texres.tb;
+                               
+                               if((rgbnor & TEX_RGB)==0) {
+                                       tcol[0]= mtex->r;
+                                       tcol[1]= mtex->g;
+                                       tcol[2]= mtex->b;
+                               }
+                               else if(mtex->mapto & MAP_ALPHA) {
+                                       texres.tin= stencilTin;
+                               }
+                               else texres.tin= texres.ta;
+                               
+                               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;
+                               
+                               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/volumetric.c b/source/blender/render/intern/source/volumetric.c
new file mode 100644 (file)
index 0000000..9a67909
--- /dev/null
@@ -0,0 +1,576 @@
+/**
+ *
+ * ***** 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): Farsthary (Raul FHernandez), Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include <float.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "BLI_kdtree.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"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* 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);
+}
+
+static int vol_frontface_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);
+}
+
+static int vol_always_intersect_check(Isect *is, int ob, RayFace *face)
+{
+       return 1;
+}
+
+#define VOL_IS_BACKFACE                        1
+#define VOL_IS_SAMEMATERIAL            2
+
+
+#define VOL_BOUNDS_DEPTH       0
+#define VOL_BOUNDS_SS          1
+
+/* 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_density(struct ShadeInput *shi, float *co)
+{
+       float density = shi->mat->alpha;
+       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;
+}
+
+
+/* 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);
+}
+
+void vol_get_scattering_fac(ShadeInput *shi, float *scatter_fac, float *co, float density)
+{
+       //float col[3] = {0.0, 0.0, 0.0};
+       //do_volume_tex(shi, co, MAP_EMIT+MAP_COL, col, &emission);
+       
+       *scatter_fac = shi->mat->vol_scattering;
+}
+
+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;
+       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)
+ * can be textured with 'alpha' */
+void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, float density, float stepsize)
+{
+       /* input density = density at co */
+       float dist;
+       float absorb_col[3];
+       int s, nsteps;
+       float step_vec[3], step_sta[3], step_end[3];
+
+       vol_get_absorption(shi, absorb_col, co);
+
+       dist = VecLenf(co, endco);
+       nsteps = (int)ceil(dist / stepsize);
+       
+       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);
+       
+       VECCOPY(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;
+                       
+       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_shadeflag & MA_VOL_ATTENUATED) {
+               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);
+                       
+                       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, shi->mat->vol_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);
+       
+       
+
+}
+
+/* shadows -> trace a ray to find blocker geometry
+   - if blocker is outside the volume, use standard shadow functions
+   - if blocker is inside the volume, use raytracing
+    -- (deep shadow maps could potentially slot in here too I suppose)
+   - attenuate from current point, to blocked point or volume bounds
+*/
+
+/* single scattering only for now */
+void vol_get_scattering(ShadeInput *shi, float *scatter, float *co, float stepsize, float density)
+{
+       GroupObject *go;
+       ListBase *lights;
+       LampRen *lar;
+       float col[3] = {0.f, 0.f, 0.f};
+       
+       lights= get_lights(shi);
+       for(go=lights->first; go; go= go->next)
+       {
+               float lacol[3] = {0.f, 0.f, 0.f};
+       
+               lar= go->lampren;
+               if (lar==NULL) continue;
+               
+               vol_shade_one_lamp(shi, co, lar, lacol, stepsize, density);
+                       
+               VecMulf(lacol, density);
+               
+               VecAddf(col, col, lacol);
+       }
+       
+       VECCOPY(scatter, col);
+}
+
+static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco)
+{
+       float tr[3] = {1.0f, 1.0f, 1.0f};                       /* total transmittance */
+       float radiance[3] = {0.f, 0.f, 0.f}, d_radiance[3] = {0.f, 0.f, 0.f};
+       float stepsize = shi->mat->vol_stepsize;
+       int nsteps;
+       float vec[3], stepvec[3] = {0.0, 0.0, 0.0};
+       float tau[3], step_emit[3], step_scatter[3] = {0.0, 0.0, 0.0};
+       int s;
+       float step_sta[3], step_end[3], step_mid[3];
+       float alpha;
+       float density = vol_get_density(shi, co);
+       
+       /* 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)ceil(VecLenf(co, endco) / stepsize);
+       
+       VecSubf(vec, endco, co);
+       VECCOPY(stepvec, vec);
+       VecMulf(stepvec, 1.0f / nsteps);
+       
+       VECCOPY(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, step_emit, step_mid, density);
+                       vol_get_scattering(shi, step_scatter, step_mid, stepsize, density);
+                       
+                       VecAddf(d_radiance, step_emit, step_scatter);
+                       
+                       /*   Lv += Tr * (Lve() + Ld) */
+                       VecMulVecf(d_radiance, tr, d_radiance);
+                       VecMulf(d_radiance, stepsize);
+                       
+                       VecAddf(radiance, radiance, d_radiance);        
+               }
+
+               VECCOPY(step_sta, step_end);
+               VecAddf(step_end, step_end, stepvec);
+       }
+       
+       col[0] = radiance[0];
+       col[1] = radiance[1];
+       col[2] = radiance[2];
+       
+       alpha = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f;
+       col[3] = alpha;
+       
+       /*
+       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)
+               return 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 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;
+       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);
+               shadeSunView(col, shi->view);
+       }
+}
+
+void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr)
+{
+       float hitco[3], col[4] = {0.f,0.f,0.f,0.f};
+       Isect is;
+
+       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) {
+               /* trace behind the 1st hit point */
+               vol_trace_behind(shi, shi->vlr, shi->co, col);
+               
+               /* 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 (col[3] > 1.0f) 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 (col[3] > 1.0f) 
+               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;
+       }
+}
index 5b5c7f2d5ba9540bfb9397c4b7574ce894e6353b..f134e9a965020c2f2fa46ee55664a0e67c8b95ba 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", "", "", "", ""};
 /*  ---------------------------------------------------------------------- */
 
 void test_idbutton_cb(void *namev, void *arg2)
index 989684895c8cf0bb1406e63bf8946dcd7dd4633f..7be862b0f15b28fb99ee125fa813d8e87ebe0aa8 100644 (file)
@@ -731,6 +731,107 @@ 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) {
+               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, "");     
+               uiDefButS(block, MENU, B_REDR, "Standard %x0|Smooth %x1|Sharp %x2|Constant %x3|Root %x4",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &pd->falloff_type, 0.0, 0.0, 0, 0, "Falloff type");
+               
+               yco -= YSPACE;
+               
+               
+               uiBlockBeginAlign(block);
+               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");
+                       
+               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 -= YSPACE;
+
+                       if (pd->source == TEX_PD_PSYS) {
+                               uiDefButS(block, MENU, B_REDR, "Noise Influence %t|Static %x0|Velocity %x1|Angular Velocity %x2",
+                                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(pd->noise_influence), 0.0, 0.0, 0, 0, "Noise Influence");
+                       }
+               }
+               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 char *layer_menu(RenderResult *rr, short *curlay)
 {
@@ -1690,7 +1791,7 @@ 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 */
                
-               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", 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);
                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");
 
@@ -3419,6 +3520,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");
@@ -3535,37 +3642,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);
@@ -4147,7 +4263,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;
@@ -4235,6 +4351,71 @@ 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)==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");
+       uiBlockEndAlign(block);
+       
+       yco -= YSPACE;
+                       
+       uiBlockBeginAlign(block);
+       uiDefButBitS(block, TOG, MA_VOL_ATTENUATED, B_MATPRV, "Shading",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Uses absorption for light attenuation");
+       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;
+       
+       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",
+               X2CLM1, 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: ",
+                       X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_phasefunc_g), -1.0, 1.0, 0, 0, "> 0 is forward scattering, < 0 is back scattering");
+       }
+       uiBlockEndAlign(block);
+       
+               
+       yco = PANEL_YMAX;
+       
+       uiDefButF(block, NUMSLI, B_MATPRV, "Density: ",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->alpha), 0.0, 1.0, 0, 0, "Base opacity value");
+       
+       yco -= YSPACE;
+       
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUM, B_MATPRV, "Absorption: ",
+               X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_absorption), 0.0, 10.0, 10, 0, "Multiplier for absorption");
+       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, "Emission component");
+       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, 10.0, 10, 0, "Multiplier for scattering");
+}
+
 static void material_panel_nodes(Material *ma)
 {
        bNode *node;
@@ -4273,7 +4454,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, ""); 
@@ -4366,7 +4547,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, "");
        
 }
 
@@ -4424,21 +4608,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 ];
@@ -4609,6 +4798,9 @@ void texture_panels()
                        case TEX_VORONOI:
                                texture_panel_voronoi(tex);
                                break;
+                       case TEX_POINTDENSITY:
+                               texture_panel_pointdensity(tex);
+                               break;
                        }
                }
        }
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;