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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2016-03-24 13:41:44 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-03-24 14:07:03 +0300
commitbdae647670817f4c09d4c871314f237dde1bfaac (patch)
tree59907fb1b268a3023e43b3b4568798a5e4c3f7e2
parent8e9a55f1e51daaadf92cd4f8236e3214b8db7c85 (diff)
Color sources for point density textures based on mesh vertices
This patch adds support for coloring point density textures based on several mesh vertex attributes. * Vertex Color: Use a vertex color layer for coloring the point density texture * Vertex Weight: Use a weights from a vertex group as intensity values. (for Blender Render engine the additional color band is used) * Vertex Normals: Use object-space vertex normals as RGB values. The vertex color source enum is stored separately from the particle color source, to avoid invalid values when switching. Note that vertex colors are technically "corner colors" (MLoop), so each vertex can have as many colors as faces it is part of. For the purpose of point density the mloop colors are simply averaged, which is physically plausible because corners can be viewed as multiple points in the same location.
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py17
-rw-r--r--source/blender/editors/space_node/drawnode.c18
-rw-r--r--source/blender/makesdna/DNA_node_types.h9
-rw-r--r--source/blender/makesdna/DNA_texture_types.h29
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c56
-rw-r--r--source/blender/makesrna/intern/rna_texture.c24
-rw-r--r--source/blender/render/intern/source/pointdensity.c451
7 files changed, 457 insertions, 147 deletions
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 1f0107f2a0e..caf19a9e469 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -830,12 +830,21 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
col.separator()
+ col.label(text="Color Source:")
if pd.point_source == 'PARTICLE_SYSTEM':
- col.label(text="Color Source:")
- col.prop(pd, "color_source", text="")
- if pd.color_source in {'PARTICLE_SPEED', 'PARTICLE_VELOCITY'}:
+ col.prop(pd, "particle_color_source", text="")
+ if pd.particle_color_source in {'PARTICLE_SPEED', 'PARTICLE_VELOCITY'}:
col.prop(pd, "speed_scale")
- if pd.color_source in {'PARTICLE_SPEED', 'PARTICLE_AGE'}:
+ if pd.particle_color_source in {'PARTICLE_SPEED', 'PARTICLE_AGE'}:
+ layout.template_color_ramp(pd, "color_ramp", expand=True)
+ else:
+ col.prop(pd, "vertex_color_source", text="")
+ if pd.vertex_color_source == 'VERTEX_COLOR':
+ if pd.object and pd.object.data:
+ col.prop_search(pd, "vertex_attribute_name", pd.object.data, "vertex_colors", text="")
+ if pd.vertex_color_source == 'VERTEX_WEIGHT':
+ if pd.object:
+ col.prop_search(pd, "vertex_attribute_name", pd.object, "vertex_groups", text="")
layout.template_color_ramp(pd, "color_ramp", expand=True)
col = split.column()
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 1460a3a35c8..b2f3306fb62 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -961,6 +961,11 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext *UNUSED
{
bNode *node = ptr->data;
NodeShaderTexPointDensity *shader_point_density = node->storage;
+ Object *ob = (Object *)node->id;
+ PointerRNA ob_ptr, obdata_ptr;
+
+ RNA_id_pointer_create((ID *)ob, &ob_ptr);
+ RNA_id_pointer_create(ob ? (ID *)ob->data : NULL, &obdata_ptr);
uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
@@ -976,7 +981,18 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext *UNUSED
uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "resolution", 0, NULL, ICON_NONE);
if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
- uiItemR(layout, ptr, "color_source", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "particle_color_source", 0, NULL, ICON_NONE);
+ }
+ else {
+ uiItemR(layout, ptr, "vertex_color_source", 0, NULL, ICON_NONE);
+ if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) {
+ if (ob_ptr.data)
+ uiItemPointerR(layout, ptr, "vertex_attribute_name", &ob_ptr, "vertex_groups", "", ICON_NONE);
+ }
+ if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTCOL) {
+ if (obdata_ptr.data)
+ uiItemPointerR(layout, ptr, "vertex_attribute_name", &obdata_ptr, "vertex_colors", "", ICON_NONE);
+ }
}
}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index cf5d2dfc815..c75a019a28e 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -807,7 +807,8 @@ typedef struct NodeShaderTexPointDensity {
short space;
short interpolation;
short color_source;
- short pad2;
+ short ob_color_source;
+ char vertex_attribute_name[64]; /* vertex attribute layer for color source, MAX_CUSTOMDATA_LAYER_NAME */
PointDensity pd;
} NodeShaderTexPointDensity;
@@ -1142,4 +1143,10 @@ enum {
SHD_POINTDENSITY_COLOR_PARTVEL = 3,
};
+enum {
+ SHD_POINTDENSITY_COLOR_VERTCOL = 0,
+ SHD_POINTDENSITY_COLOR_VERTWEIGHT = 1,
+ SHD_POINTDENSITY_COLOR_VERTNOR = 2,
+};
+
#endif
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index 2843d010c9d..995d7645dc0 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -143,15 +143,18 @@ typedef struct PointDensity {
float falloff_softness;
float radius;
short source;
- short color_source;
- int totpoints;
+ short pad0;
+
+ short color_source; /* psys_color_source */
+ short ob_color_source;
- int pdpad;
+ int totpoints;
struct Object *object; /* for 'Object' or 'Particle system' type - source object */
int psys; /* index+1 in ob.particlesystem, non-ID pointer not allowed */
short psys_cache_space; /* cache points in worldspace, object space, ... ? */
short ob_cache_space; /* cache points in worldspace, object space, ... ? */
+ char vertex_attribute_name[64]; /* vertex attribute layer for color source, MAX_CUSTOMDATA_LAYER_NAME */
void *point_tree; /* the acceleration tree containing points */
float *point_data; /* dynamically allocated extra for extra information, like particle age */
@@ -160,10 +163,10 @@ typedef struct PointDensity {
short noise_depth;
short noise_influence;
short noise_basis;
- short pdpad3[3];
+ short pad1[3];
float noise_fac;
- float speed_scale, falloff_speed_scale, pdpad2;
+ float speed_scale, falloff_speed_scale, pad2;
struct ColorBand *coba; /* for time -> color */
struct CurveMapping *falloff_curve; /* falloff density curve */
@@ -594,13 +597,21 @@ enum {
#define TEX_PD_NOISE_TIME 3
/* color_source */
-#define TEX_PD_COLOR_CONSTANT 0
-#define TEX_PD_COLOR_PARTAGE 1
-#define TEX_PD_COLOR_PARTSPEED 2
-#define TEX_PD_COLOR_PARTVEL 3
+enum {
+ TEX_PD_COLOR_CONSTANT = 0,
+ /* color_source: particles */
+ TEX_PD_COLOR_PARTAGE = 1,
+ TEX_PD_COLOR_PARTSPEED = 2,
+ TEX_PD_COLOR_PARTVEL = 3,
+ /* color_source: vertices */
+ TEX_PD_COLOR_VERTCOL = 1,
+ TEX_PD_COLOR_VERTWEIGHT = 2,
+ TEX_PD_COLOR_VERTNOR = 3,
+};
#define POINT_DATA_VEL 1
#define POINT_DATA_LIFE 2
+#define POINT_DATA_COLOR 4
/******************** Voxel Data *****************************/
/* flag */
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index a701cf6182d..ccbabb2b238 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3030,12 +3030,30 @@ static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr, PointerRNA valu
}
}
-static int point_density_color_source_from_shader(NodeShaderTexPointDensity *shader_point_density)
+static int point_density_particle_color_source_from_shader(NodeShaderTexPointDensity *shader_point_density)
{
switch (shader_point_density->color_source) {
- case SHD_POINTDENSITY_COLOR_PARTAGE: return TEX_PD_COLOR_PARTAGE;
- case SHD_POINTDENSITY_COLOR_PARTSPEED: return TEX_PD_COLOR_PARTSPEED;
- case SHD_POINTDENSITY_COLOR_PARTVEL: return TEX_PD_COLOR_PARTVEL;
+ case SHD_POINTDENSITY_COLOR_PARTAGE:
+ return TEX_PD_COLOR_PARTAGE;
+ case SHD_POINTDENSITY_COLOR_PARTSPEED:
+ return TEX_PD_COLOR_PARTSPEED;
+ case SHD_POINTDENSITY_COLOR_PARTVEL:
+ return TEX_PD_COLOR_PARTVEL;
+ default:
+ BLI_assert(!"Unknown color source");
+ return TEX_PD_COLOR_CONSTANT;
+ }
+}
+
+static int point_density_vertex_color_source_from_shader(NodeShaderTexPointDensity *shader_point_density)
+{
+ switch (shader_point_density->ob_color_source) {
+ case SHD_POINTDENSITY_COLOR_VERTCOL:
+ return TEX_PD_COLOR_VERTCOL;
+ case SHD_POINTDENSITY_COLOR_VERTWEIGHT:
+ return TEX_PD_COLOR_VERTWEIGHT;
+ case SHD_POINTDENSITY_COLOR_VERTNOR:
+ return TEX_PD_COLOR_VERTNOR;
default:
BLI_assert(!"Unknown color source");
return TEX_PD_COLOR_CONSTANT;
@@ -3064,13 +3082,17 @@ void rna_ShaderNodePointDensity_density_cache(bNode *self,
pd->source = TEX_PD_PSYS;
pd->psys = shader_point_density->particle_system;
pd->psys_cache_space = TEX_PD_OBJECTSPACE;
+ pd->color_source = point_density_particle_color_source_from_shader(shader_point_density);
}
else {
BLI_assert(shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_OBJECT);
pd->source = TEX_PD_OBJECT;
pd->ob_cache_space = TEX_PD_OBJECTSPACE;
+ pd->ob_color_source = point_density_vertex_color_source_from_shader(shader_point_density);
+ BLI_strncpy(pd->vertex_attribute_name,
+ shader_point_density->vertex_attribute_name,
+ sizeof(pd->vertex_attribute_name));
}
- pd->color_source = point_density_color_source_from_shader(shader_point_density);
/* Single-threaded sampling of the voxel domain. */
RE_point_density_cache(scene,
@@ -4002,7 +4024,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem color_source_items[] = {
+ static EnumPropertyItem particle_color_source_items[] = {
{SHD_POINTDENSITY_COLOR_PARTAGE, "PARTICLE_AGE", 0, "Particle Age",
"Lifetime mapped as 0.0 - 1.0 intensity"},
{SHD_POINTDENSITY_COLOR_PARTSPEED, "PARTICLE_SPEED", 0, "Particle Speed",
@@ -4012,6 +4034,14 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem vertex_color_source_items[] = {
+ {SHD_POINTDENSITY_COLOR_VERTCOL, "VERTEX_COLOR", 0, "Vertex Color", "Vertex color layer"},
+ {SHD_POINTDENSITY_COLOR_VERTWEIGHT, "VERTEX_WEIGHT", 0, "Vertex Weight", "Vertex group weight"},
+ {SHD_POINTDENSITY_COLOR_VERTNOR, "VERTEX_NORMAL", 0, "Vertex Normal",
+ "XYZ normal vector mapped to RGB colors"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* TODO(sergey): Use some mnemonic names for the hardcoded values here. */
static EnumPropertyItem calc_mode_items[] = {
{0, "VIEWPORT", 0, "Viewport", "Canculate density using viewport settings"},
@@ -4062,12 +4092,22 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
RNA_def_property_ui_text(prop, "Interpolation", "Texture interpolation");
RNA_def_property_update(prop, 0, "rna_Node_update");
- prop = RNA_def_property(srna, "color_source", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "particle_color_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "color_source");
- RNA_def_property_enum_items(prop, color_source_items);
+ RNA_def_property_enum_items(prop, particle_color_source_items);
RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
RNA_def_property_update(prop, 0, "rna_Node_update");
+ prop = RNA_def_property(srna, "vertex_color_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "ob_color_source");
+ RNA_def_property_enum_items(prop, vertex_color_source_items);
+ RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "vertex_attribute_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Vertex Attribute Name", "Vertex attribute to use for color");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
func = RNA_def_function(srna, "cache_point_density", "rna_ShaderNodePointDensity_density_cache");
RNA_def_function_ui_description(func, "Cache point density data for later calculation");
RNA_def_pointer(func, "scene", "Scene", "", "");
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index b44482dc2c1..ad1ca12d4ea 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -1668,7 +1668,7 @@ static void rna_def_texture_pointdensity(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem color_source_items[] = {
+ static EnumPropertyItem particle_color_source_items[] = {
{TEX_PD_COLOR_CONSTANT, "CONSTANT", 0, "Constant", ""},
{TEX_PD_COLOR_PARTAGE, "PARTICLE_AGE", 0, "Particle Age", "Lifetime mapped as 0.0 - 1.0 intensity"},
{TEX_PD_COLOR_PARTSPEED, "PARTICLE_SPEED", 0, "Particle Speed",
@@ -1677,6 +1677,14 @@ static void rna_def_texture_pointdensity(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem vertex_color_source_items[] = {
+ {TEX_PD_COLOR_CONSTANT, "CONSTANT", 0, "Constant", ""},
+ {TEX_PD_COLOR_VERTCOL, "VERTEX_COLOR", 0, "Vertex Color", "Vertex color layer"},
+ {TEX_PD_COLOR_VERTWEIGHT, "VERTEX_WEIGHT", 0, "Vertex Weight", "Vertex group weight"},
+ {TEX_PD_COLOR_VERTNOR, "VERTEX_NORMAL", 0, "Vertex Normal", "XYZ normal vector mapped to RGB colors"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
static EnumPropertyItem turbulence_influence_items[] = {
{TEX_PD_NOISE_STATIC, "STATIC", 0, "Static",
"Noise patterns will remain unchanged, faster and suitable for stills"},
@@ -1742,12 +1750,22 @@ static void rna_def_texture_pointdensity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Softness", "Softness of the 'soft' falloff option");
RNA_def_property_update(prop, 0, "rna_Texture_update");
- prop = RNA_def_property(srna, "color_source", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "particle_color_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "color_source");
- RNA_def_property_enum_items(prop, color_source_items);
+ RNA_def_property_enum_items(prop, particle_color_source_items);
RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
RNA_def_property_update(prop, 0, "rna_Texture_update");
+ prop = RNA_def_property(srna, "vertex_color_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "ob_color_source");
+ RNA_def_property_enum_items(prop, vertex_color_source_items);
+ RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
+ RNA_def_property_update(prop, 0, "rna_Texture_update");
+
+ prop = RNA_def_property(srna, "vertex_attribute_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Vertex Attribute Name", "Vertex attribute to use for color");
+ RNA_def_property_update(prop, 0, "rna_Texture_update");
+
prop = RNA_def_property(srna, "speed_scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "speed_scale");
RNA_def_property_range(prop, 0.001, 100.0);
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index 91ae29afea3..59aaad661c9 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -43,6 +43,12 @@
#include "BLT_translation.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_texture_types.h"
+
+#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
@@ -52,10 +58,6 @@
#include "BKE_texture.h"
#include "BKE_colortools.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_particle_types.h"
-
#include "render_types.h"
#include "texture.h"
#include "pointdensity.h"
@@ -89,29 +91,78 @@ static int point_data_used(PointDensity *pd)
pd_bitflag |= POINT_DATA_LIFE;
}
}
+ else if (pd->source == TEX_PD_OBJECT) {
+ if (ELEM(pd->ob_color_source, TEX_PD_COLOR_VERTCOL, TEX_PD_COLOR_VERTWEIGHT, TEX_PD_COLOR_VERTNOR)) {
+ pd_bitflag |= POINT_DATA_COLOR;
+ }
+ }
return pd_bitflag;
}
+static void point_data_pointers(PointDensity *pd,
+ float **r_data_velocity, float **r_data_life, float **r_data_color)
+{
+ const int data_used = point_data_used(pd);
+ const int totpoint = pd->totpoints;
+ float *data = pd->point_data;
+ int offset = 0;
+
+ if (data_used & POINT_DATA_VEL) {
+ if (r_data_velocity)
+ *r_data_velocity = data + offset;
+ offset += 3 * totpoint;
+ }
+ else {
+ if (r_data_velocity)
+ *r_data_velocity = NULL;
+ }
+
+ if (data_used & POINT_DATA_LIFE) {
+ if (r_data_life)
+ *r_data_life = data + offset;
+ offset += totpoint;
+ }
+ else {
+ if (r_data_life)
+ *r_data_life = NULL;
+ }
+
+ if (data_used & POINT_DATA_COLOR) {
+ if (r_data_color)
+ *r_data_color = data + offset;
+ offset += 3 * totpoint;
+ }
+ else {
+ if (r_data_color)
+ *r_data_color = NULL;
+ }
+}
/* additional data stored alongside the point density BVH,
* accessible by point index number to retrieve other information
* such as particle velocity or lifetime */
-static void alloc_point_data(PointDensity *pd, int total_particles, int point_data_used)
+static void alloc_point_data(PointDensity *pd)
{
+ const int totpoints = pd->totpoints;
+ int data_used = point_data_used(pd);
int data_size = 0;
- if (point_data_used & POINT_DATA_VEL) {
+ if (data_used & POINT_DATA_VEL) {
/* store 3 channels of velocity data */
data_size += 3;
}
- if (point_data_used & POINT_DATA_LIFE) {
+ if (data_used & POINT_DATA_LIFE) {
/* store 1 channel of lifetime data */
data_size += 1;
}
+ if (data_used & POINT_DATA_COLOR) {
+ /* store 3 channels of RGB data */
+ data_size += 3;
+ }
if (data_size) {
- pd->point_data = MEM_mallocN(sizeof(float) * data_size * total_particles,
+ pd->point_data = MEM_callocN(sizeof(float) * data_size * totpoints,
"particle point data");
}
}
@@ -132,8 +183,9 @@ static void pointdensity_cache_psys(Scene *scene,
ParticleData *pa = NULL;
float cfra = BKE_scene_frame_get(scene);
int i /*, childexists*/ /* UNUSED */;
- int total_particles, offset = 0;
- int data_used = point_data_used(pd);
+ int total_particles;
+ int data_used;
+ float *data_vel, *data_life;
float partco[3];
/* init everything */
@@ -141,6 +193,8 @@ static void pointdensity_cache_psys(Scene *scene,
return;
}
+ data_used = point_data_used(pd);
+
/* Just to create a valid rendering context for particles */
if (use_render_params) {
psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0);
@@ -174,11 +228,9 @@ static void pointdensity_cache_psys(Scene *scene,
psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
- alloc_point_data(pd, total_particles, data_used);
pd->totpoints = total_particles;
- if (data_used & POINT_DATA_VEL) {
- offset = pd->totpoints * 3;
- }
+ alloc_point_data(pd);
+ point_data_pointers(pd, &data_vel, &data_life, NULL);
#if 0 /* UNUSED */
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
@@ -235,13 +287,13 @@ static void pointdensity_cache_psys(Scene *scene,
BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
- if (data_used & POINT_DATA_VEL) {
- pd->point_data[i * 3 + 0] = state.vel[0];
- pd->point_data[i * 3 + 1] = state.vel[1];
- pd->point_data[i * 3 + 2] = state.vel[2];
+ if (data_vel) {
+ data_vel[i*3 + 0] = state.vel[0];
+ data_vel[i*3 + 1] = state.vel[1];
+ data_vel[i*3 + 2] = state.vel[2];
}
- if (data_used & POINT_DATA_LIFE) {
- pd->point_data[offset + i] = state.time;
+ if (data_life) {
+ data_life[i] = state.time;
}
}
@@ -259,39 +311,127 @@ static void pointdensity_cache_psys(Scene *scene,
}
+static void pointdensity_cache_vertex_color(PointDensity *pd, Object *UNUSED(ob), DerivedMesh *dm, float *data_color)
+{
+ const MLoop *mloop = dm->getLoopArray(dm);
+ const int totloop = dm->getNumLoops(dm);
+ const MLoopCol *mcol;
+ char layername[MAX_CUSTOMDATA_LAYER_NAME];
+ int i;
+
+ BLI_assert(data_color);
+
+ if (!CustomData_has_layer(&dm->loopData, CD_MLOOPCOL))
+ return;
+ CustomData_validate_layer_name(&dm->loopData, CD_MLOOPCOL, pd->vertex_attribute_name, layername);
+ mcol = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, layername);
+ if (!mcol)
+ return;
+
+ /* Stores the number of MLoops using the same vertex, so we can normalize colors. */
+ int *mcorners = MEM_callocN(sizeof(int) * pd->totpoints, "point density corner count");
+
+ for (i = 0; i < totloop; i++) {
+ int v = mloop[i].v;
+ rgb_uchar_to_float(&data_color[v*3], &mcol[i].r);
+ ++mcorners[v];
+ }
+
+ /* Normalize colors by averaging over mcorners.
+ * All the corners share the same vertex, ie. occupy the same point in space.
+ */
+ for (i = 0; i < pd->totpoints; i++) {
+ if (mcorners[i] > 0)
+ mul_v3_fl(&data_color[i*3], 1.0f / mcorners[i]);
+ }
+
+ MEM_freeN(mcorners);
+}
+
+static void pointdensity_cache_vertex_weight(PointDensity *pd, Object *ob, DerivedMesh *dm, float *data_color)
+{
+ const int totvert = dm->getNumVerts(dm);
+ const MDeformVert *mdef, *dv;
+ int mdef_index;
+ int i;
+
+ BLI_assert(data_color);
+
+ mdef = CustomData_get_layer(&dm->vertData, CD_MDEFORMVERT);
+ if (!mdef)
+ return;
+ mdef_index = defgroup_name_index(ob, pd->vertex_attribute_name);
+ if (mdef_index < 0)
+ mdef_index = ob->actdef - 1;
+ if (mdef_index < 0)
+ return;
+
+ for (i = 0, dv = mdef; i < totvert; ++i, ++dv, data_color += 3) {
+ MDeformWeight *dw;
+ int j;
+
+ for (j = 0, dw = dv->dw; j < dv->totweight; ++j, ++dw) {
+ if (dw->def_nr == mdef_index) {
+ copy_v3_fl(data_color, dw->weight);
+ break;
+ }
+ }
+ }
+}
+
+static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob), DerivedMesh *dm, float *data_color)
+{
+ MVert *mvert = dm->getVertArray(dm), *mv;
+ int i;
+
+ BLI_assert(data_color);
+
+ for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++, data_color += 3) {
+ normal_short_to_float_v3(data_color, mv->no);
+ }
+}
+
static void pointdensity_cache_object(Scene *scene,
PointDensity *pd,
Object *ob,
const bool use_render_params)
{
+ float *data_color;
int i;
DerivedMesh *dm;
- MVert *mvert = NULL;
+ CustomDataMask mask = CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL;
+ MVert *mvert = NULL, *mv;
+
+ switch (pd->ob_color_source) {
+ case TEX_PD_COLOR_VERTCOL:
+ mask |= CD_MASK_MLOOPCOL;
+ break;
+ case TEX_PD_COLOR_VERTWEIGHT:
+ mask |= CD_MASK_MDEFORMVERT;
+ break;
+ }
if (use_render_params) {
- dm = mesh_create_derived_render(scene,
- ob,
- CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ dm = mesh_create_derived_render(scene, ob, mask);
}
else {
- dm = mesh_get_derived_final(scene,
- ob,
- CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
-
+ dm = mesh_get_derived_final(scene, ob, mask);
}
- mvert = dm->getVertArray(dm); /* local object space */
+ mvert = dm->getVertArray(dm); /* local object space */
pd->totpoints = dm->getNumVerts(dm);
if (pd->totpoints == 0) {
return;
}
pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
+ alloc_point_data(pd);
+ point_data_pointers(pd, NULL, NULL, &data_color);
- for (i = 0; i < pd->totpoints; i++, mvert++) {
+ for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++) {
float co[3];
- copy_v3_v3(co, mvert->co);
+ copy_v3_v3(co, mv->co);
switch (pd->ob_cache_space) {
case TEX_PD_OBJECTSPACE:
@@ -308,6 +448,18 @@ static void pointdensity_cache_object(Scene *scene,
BLI_bvhtree_insert(pd->point_tree, i, co, 1);
}
+
+ switch (pd->ob_color_source) {
+ case TEX_PD_COLOR_VERTCOL:
+ pointdensity_cache_vertex_color(pd, ob, dm, data_color);
+ break;
+ case TEX_PD_COLOR_VERTWEIGHT:
+ pointdensity_cache_vertex_weight(pd, ob, dm, data_color);
+ break;
+ case TEX_PD_COLOR_VERTNOR:
+ pointdensity_cache_vertex_normal(pd, ob, dm, data_color);
+ break;
+ }
BLI_bvhtree_balance(pd->point_tree);
dm->release(dm);
@@ -423,80 +575,99 @@ void free_pointdensities(Render *re)
typedef struct PointDensityRangeData {
float *density;
float squared_radius;
- const float *point_data;
+ float *point_data_life;
+ float *point_data_velocity;
+ float *point_data_color;
float *vec;
+ float *col;
float softness;
short falloff_type;
short noise_influence;
float *age;
- int point_data_used;
- int offset;
struct CurveMapping *density_curve;
float velscale;
} PointDensityRangeData;
+static float density_falloff(PointDensityRangeData *pdr, int index, float squared_dist)
+{
+ const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
+ float density = 0.0f;
+
+ switch (pdr->falloff_type) {
+ case TEX_PD_FALLOFF_STD:
+ density = dist;
+ break;
+ case TEX_PD_FALLOFF_SMOOTH:
+ density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
+ break;
+ case TEX_PD_FALLOFF_SOFT:
+ density = pow(dist, pdr->softness);
+ break;
+ case TEX_PD_FALLOFF_CONSTANT:
+ density = pdr->squared_radius;
+ break;
+ case TEX_PD_FALLOFF_ROOT:
+ density = sqrtf(dist);
+ break;
+ case TEX_PD_FALLOFF_PARTICLE_AGE:
+ if (pdr->point_data_life)
+ density = dist * MIN2(pdr->point_data_life[index], 1.0f);
+ else
+ density = dist;
+ break;
+ case TEX_PD_FALLOFF_PARTICLE_VEL:
+ if (pdr->point_data_velocity)
+ density = dist * len_v3(&pdr->point_data_velocity[index * 3]) * pdr->velscale;
+ else
+ density = dist;
+ break;
+ }
+
+ if (pdr->density_curve && dist != 0.0f) {
+ curvemapping_initialize(pdr->density_curve);
+ density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
+ }
+
+ return density;
+}
+
static void accum_density(void *userdata, int index, const float co[3], float squared_dist)
{
PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
- const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
float density = 0.0f;
UNUSED_VARS(co);
- if (pdr->point_data_used & POINT_DATA_VEL) {
- pdr->vec[0] += pdr->point_data[index * 3 + 0]; // * density;
- pdr->vec[1] += pdr->point_data[index * 3 + 1]; // * density;
- pdr->vec[2] += pdr->point_data[index * 3 + 2]; // * density;
- }
- if (pdr->point_data_used & POINT_DATA_LIFE) {
- *pdr->age += pdr->point_data[pdr->offset + index]; // * density;
- }
-
- if (pdr->falloff_type == TEX_PD_FALLOFF_STD)
- density = dist;
- else if (pdr->falloff_type == TEX_PD_FALLOFF_SMOOTH)
- density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
- else if (pdr->falloff_type == TEX_PD_FALLOFF_SOFT)
- density = pow(dist, pdr->softness);
- else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT)
- density = pdr->squared_radius;
- else if (pdr->falloff_type == TEX_PD_FALLOFF_ROOT)
- density = sqrtf(dist);
- else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) {
- if (pdr->point_data_used & POINT_DATA_LIFE)
- density = dist * MIN2(pdr->point_data[pdr->offset + index], 1.0f);
- else
- density = dist;
+ if (pdr->point_data_velocity) {
+ pdr->vec[0] += pdr->point_data_velocity[index * 3 + 0]; // * density;
+ pdr->vec[1] += pdr->point_data_velocity[index * 3 + 1]; // * density;
+ pdr->vec[2] += pdr->point_data_velocity[index * 3 + 2]; // * density;
}
- else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) {
- if (pdr->point_data_used & POINT_DATA_VEL)
- density = dist * len_v3(pdr->point_data + index * 3) * pdr->velscale;
- else
- density = dist;
+ if (pdr->point_data_life) {
+ *pdr->age += pdr->point_data_life[index]; // * density;
}
-
- if (pdr->density_curve && dist != 0.0f) {
- curvemapping_initialize(pdr->density_curve);
- density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
+ if (pdr->point_data_color) {
+ add_v3_v3(pdr->col, &pdr->point_data_color[index * 3]); // * density;
}
+ density = density_falloff(pdr, index, squared_dist);
+
*pdr->density += density;
}
static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr,
- float *density, float *vec, float *age, struct CurveMapping *density_curve, float velscale)
+ float *density, float *vec, float *age, float *col, struct CurveMapping *density_curve, float velscale)
{
pdr->squared_radius = pd->radius * pd->radius;
pdr->density = density;
- pdr->point_data = pd->point_data;
pdr->falloff_type = pd->falloff_type;
pdr->vec = vec;
pdr->age = age;
+ pdr->col = col;
pdr->softness = pd->falloff_softness;
pdr->noise_influence = pd->noise_influence;
- pdr->point_data_used = point_data_used(pd);
- pdr->offset = (pdr->point_data_used & POINT_DATA_VEL) ? pd->totpoints * 3 : 0;
+ point_data_pointers(pd, &pdr->point_data_velocity, &pdr->point_data_life, &pdr->point_data_color);
pdr->density_curve = density_curve;
pdr->velscale = velscale;
}
@@ -505,13 +676,14 @@ static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *
static int pointdensity(PointDensity *pd,
const float texvec[3],
TexResult *texres,
+ float r_vec[3],
float *r_age,
- float r_vec[3])
+ float r_col[3])
{
int retval = TEX_INT;
PointDensityRangeData pdr;
float density = 0.0f, age = 0.0f, time = 0.0f;
- float vec[3] = {0.0f, 0.0f, 0.0f}, co[3];
+ float vec[3] = {0.0f, 0.0f, 0.0f}, col[3] = {0.0f, 0.0f, 0.0f}, co[3];
float turb, noise_fac;
int num = 0;
@@ -520,7 +692,7 @@ static int pointdensity(PointDensity *pd,
if ((!pd) || (!pd->point_tree))
return 0;
- init_pointdensityrangedata(pd, &pdr, &density, vec, &age,
+ init_pointdensityrangedata(pd, &pdr, &density, vec, &age, col,
(pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL),
pd->falloff_speed_scale * 0.001f);
noise_fac = pd->noise_fac * 0.5f; /* better default */
@@ -534,10 +706,13 @@ static int pointdensity(PointDensity *pd,
if (num > 0) {
age /= num;
mul_v3_fl(vec, 1.0f / num);
+ mul_v3_fl(col, 1.0f / num);
}
/* reset */
- density = vec[0] = vec[1] = vec[2] = 0.0f;
+ density = 0.0f;
+ zero_v3(vec);
+ zero_v3(col);
}
if (pd->flag & TEX_PD_TURBULENCE) {
@@ -570,6 +745,7 @@ static int pointdensity(PointDensity *pd,
if (num > 0) {
age /= num;
mul_v3_fl(vec, 1.0f / num);
+ mul_v3_fl(col, 1.0f / num);
}
texres->tin = density;
@@ -579,51 +755,88 @@ static int pointdensity(PointDensity *pd,
if (r_vec != NULL) {
copy_v3_v3(r_vec, vec);
}
+ if (r_col != NULL) {
+ copy_v3_v3(r_col, col);
+ }
return retval;
}
-static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3])
+static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
{
- int retval = 0;
- float col[4];
-
- retval |= TEX_RGB;
+ int retval = TEX_RGB;
- switch (pd->color_source) {
- case TEX_PD_COLOR_PARTAGE:
- if (pd->coba) {
- if (do_colorband(pd->coba, age, col)) {
- texres->talpha = true;
- copy_v3_v3(&texres->tr, col);
- texres->tin *= col[3];
- texres->ta = texres->tin;
+ if (pd->source == TEX_PD_PSYS) {
+ float rgba[4];
+
+ switch (pd->color_source) {
+ case TEX_PD_COLOR_PARTAGE:
+ if (pd->coba) {
+ if (do_colorband(pd->coba, age, rgba)) {
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, rgba);
+ texres->tin *= rgba[3];
+ texres->ta = texres->tin;
+ }
}
+ break;
+ case TEX_PD_COLOR_PARTSPEED:
+ {
+ float speed = len_v3(vec) * pd->speed_scale;
+
+ if (pd->coba) {
+ if (do_colorband(pd->coba, speed, rgba)) {
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, rgba);
+ texres->tin *= rgba[3];
+ texres->ta = texres->tin;
+ }
+ }
+ break;
}
- break;
- case TEX_PD_COLOR_PARTSPEED:
- {
- float speed = len_v3(vec) * pd->speed_scale;
-
- if (pd->coba) {
- if (do_colorband(pd->coba, speed, col)) {
- texres->talpha = true;
+ case TEX_PD_COLOR_PARTVEL:
+ texres->talpha = true;
+ mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_CONSTANT:
+ default:
+ texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
+ retval = TEX_INT;
+ break;
+ }
+ }
+ else {
+ float rgba[4];
+
+ switch (pd->ob_color_source) {
+ case TEX_PD_COLOR_VERTCOL:
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, col);
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_VERTWEIGHT:
+ texres->talpha = true;
+ if (pd->coba && do_colorband(pd->coba, col[0], rgba)) {
+ copy_v3_v3(&texres->tr, rgba);
+ texres->tin *= rgba[3];
+ }
+ else {
copy_v3_v3(&texres->tr, col);
- texres->tin *= col[3];
- texres->ta = texres->tin;
}
- }
- break;
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_VERTNOR:
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, col);
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_CONSTANT:
+ default:
+ texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
+ retval = TEX_INT;
+ break;
}
- case TEX_PD_COLOR_PARTVEL:
- texres->talpha = true;
- mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
- texres->ta = texres->tin;
- break;
- case TEX_PD_COLOR_CONSTANT:
- default:
- texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
- break;
}
return retval;
@@ -634,16 +847,12 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
PointDensity *pd = tex->pd;
float age = 0.0f;
float vec[3] = {0.0f, 0.0f, 0.0f};
- int retval = pointdensity(pd, texvec, texres, &age, vec);
+ float col[3] = {0.0f, 0.0f, 0.0f};
+ int retval = pointdensity(pd, texvec, texres, vec, &age, col);
- BRICONT;
-
- if (pd->color_source == TEX_PD_COLOR_CONSTANT)
- return retval;
-
- retval |= pointdensity_color(pd, texres, age, vec);
+ retval |= pointdensity_color(pd, texres, age, vec, col);
BRICONTRGB;
-
+
return retval;
#if 0
@@ -803,7 +1012,7 @@ static void point_density_sample_func(void *data_v, const int iter)
for (size_t x = 0; x < resolution; ++x) {
size_t index = z * resolution2 + y * resolution + x;
float texvec[3];
- float age, vec[3];
+ float age, vec[3], col[3];
TexResult texres;
copy_v3_v3(texvec, min);
@@ -811,8 +1020,8 @@ static void point_density_sample_func(void *data_v, const int iter)
texvec[1] += dim[1] * (float)y / (float)resolution;
texvec[2] += dim[2] * (float)z / (float)resolution;
- pointdensity(pd, texvec, &texres, &age, vec);
- pointdensity_color(pd, &texres, age, vec);
+ pointdensity(pd, texvec, &texres, vec, &age, col);
+ pointdensity_color(pd, &texres, age, vec, col);
copy_v3_v3(&values[index*4 + 0], &texres.tr);
values[index*4 + 3] = texres.tin;