diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_texture.py | 17 | ||||
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 18 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 9 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_texture_types.h | 29 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree.c | 56 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_texture.c | 24 | ||||
-rw-r--r-- | source/blender/render/intern/source/pointdensity.c | 451 |
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; |