Fix T47214: Keyed Particles don't render correctly when used for point density input

The issue was caused by different AABB used by Cycles and texture sampler.

Instead of trying to keep this two functions in sync we now do have an
utility call in the point density node to query the AABB.
This commit is contained in:
Sergey Sharybin 2016-01-26 12:50:55 +01:00
parent 0095c2dad2
commit 8126b0222d
Notes: blender-bot 2023-02-14 08:17:10 +01:00
Referenced by issue #47214, Keyed Particles don't render correctly when used for point density input
6 changed files with 123 additions and 116 deletions

View File

@ -803,19 +803,11 @@ static ShaderNode *add_node(Scene *scene,
(InterpolationType)b_point_density_node.interpolation();
point_density->builtin_data = b_point_density_node.ptr.data;
/* Transformation form world space to texture space. */
BL::Object b_ob(b_point_density_node.object());
if(b_ob) {
float3 loc, size;
point_density_texture_space(b_point_density_node, loc, size);
point_density->tfm =
transform_translate(-loc) * transform_scale(size) *
transform_inverse(get_transform(b_ob.matrix_world()));
}
/* 1 - render settings, 0 - vewport settings. */
int settings = background ? 1 : 0;
/* TODO(sergey): Use more proper update flag. */
if(true) {
int settings = background ? 1 : 0; /* 1 - render settings, 0 - vewport settings. */
b_point_density_node.cache_point_density(b_scene, settings);
scene->image_manager->tag_reload_image(
point_density->filename,
@ -824,6 +816,24 @@ static ShaderNode *add_node(Scene *scene,
EXTENSION_CLIP);
}
node = point_density;
/* Transformation form world space to texture space.
*
* NOTE: Do this after the texture is cached, this is because getting
* min/max will need to access this cache.
*/
BL::Object b_ob(b_point_density_node.object());
if(b_ob) {
float3 loc, size;
point_density_texture_space(b_scene,
b_point_density_node,
settings,
loc,
size);
point_density->tfm =
transform_translate(-loc) * transform_scale(size) *
transform_inverse(get_transform(b_ob.matrix_world()));
}
}
if(node)

View File

@ -22,8 +22,8 @@ namespace {
/* Point density helpers. */
static void density_texture_space_invert(float3& loc,
float3& size)
void density_texture_space_invert(float3& loc,
float3& size)
{
if(size.x != 0.0f) size.x = 0.5f/size.x;
if(size.y != 0.0f) size.y = 0.5f/size.y;
@ -32,87 +32,28 @@ static void density_texture_space_invert(float3& loc,
loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
}
static void density_object_texture_space(BL::Object b_ob,
float radius,
float3& loc,
float3& size)
{
if(b_ob.type() == BL::Object::type_MESH) {
BL::Mesh b_mesh(b_ob.data());
loc = get_float3(b_mesh.texspace_location());
size = get_float3(b_mesh.texspace_size());
}
else {
/* TODO(sergey): Not supported currently. */
}
/* Adjust texture space to include density points on the boundaries. */
size = size + make_float3(radius, radius, radius);
density_texture_space_invert(loc, size);
}
} /* namespace */
static void density_particle_system_texture_space(
BL::Object b_ob,
BL::ParticleSystem b_particle_system,
float radius,
float3& loc,
float3& size)
void point_density_texture_space(BL::Scene b_scene,
BL::ShaderNodeTexPointDensity b_point_density_node,
int settings,
float3& loc,
float3& size)
{
if(b_particle_system.settings().type() == BL::ParticleSettings::type_HAIR) {
/* TODO(sergey): Not supported currently. */
BL::Object b_ob(b_point_density_node.object());
if(!b_ob) {
loc = make_float3(0.0f, 0.0f, 0.0f);
size = make_float3(0.0f, 0.0f, 0.0f);
return;
}
Transform tfm = get_transform(b_ob.matrix_world());
Transform itfm = transform_inverse(tfm);
float3 min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
float3 particle_size = make_float3(radius, radius, radius);
for(int i = 0; i < b_particle_system.particles.length(); ++i) {
BL::Particle particle = b_particle_system.particles[i];
if(particle.alive_state() == BL::Particle::alive_state_ALIVE) {
float3 location = get_float3(particle.location());
location = transform_point(&itfm, location);
min = ccl::min(min, location - particle_size);
max = ccl::max(max, location + particle_size);
}
}
/* Calculate texture space from the particle bounds. */
float3 min, max;
b_point_density_node.calc_point_density_minmax(b_scene,
settings,
&min[0],
&max[0]);
loc = (min + max) * 0.5f;
size = (max - min) * 0.5f;
density_texture_space_invert(loc, size);
}
} /* namespace */
void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
float3& loc,
float3& size)
{
/* Fallback values. */
loc = make_float3(0.0f, 0.0f, 0.0f);
size = make_float3(0.0f, 0.0f, 0.0f);
BL::Object b_ob(b_point_density_node.object());
if(!b_ob) {
return;
}
if(b_point_density_node.point_source() ==
BL::ShaderNodeTexPointDensity::point_source_PARTICLE_SYSTEM)
{
BL::ParticleSystem b_particle_system(
b_point_density_node.particle_system());
if(b_particle_system) {
density_particle_system_texture_space(b_ob,
b_particle_system,
b_point_density_node.radius(),
loc,
size);
}
}
else {
density_object_texture_space(b_ob,
b_point_density_node.radius(),
loc,
size);
}
}
CCL_NAMESPACE_END

View File

@ -22,7 +22,9 @@
CCL_NAMESPACE_BEGIN
void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
void point_density_texture_space(BL::Scene b_scene,
BL::ShaderNodeTexPointDensity b_point_density_node,
const int settings,
float3& loc,
float3& size);

View File

@ -3100,6 +3100,22 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
BKE_texture_pointdensity_free_data(pd);
}
void rna_ShaderNodePointDensity_density_minmax(bNode *self,
Scene *scene,
int settings,
float r_min[3],
float r_max[3])
{
NodeShaderTexPointDensity *shader_point_density = self->storage;
PointDensity *pd = &shader_point_density->pd;
if (scene == NULL) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
RE_minmac_point_density(scene, pd, settings == 1, r_min, r_max);
}
#else
static EnumPropertyItem prop_image_layer_items[] = {
@ -4054,6 +4070,19 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
prop = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
RNA_def_property_flag(prop, PROP_DYNAMIC);
RNA_def_function_output(func, prop);
func = RNA_def_function(srna, "calc_point_density_minmax", "rna_ShaderNodePointDensity_density_minmax");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "scene", "Scene", "", "");
RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
prop = RNA_def_property(func, "min", PROP_FLOAT, PROP_COORDS);
RNA_def_property_array(prop, 3);
RNA_def_property_flag(prop, PROP_THICK_WRAP);
RNA_def_function_output(func, prop);
prop = RNA_def_property(func, "max", PROP_FLOAT, PROP_COORDS);
RNA_def_property_array(prop, 3);
RNA_def_property_flag(prop, PROP_THICK_WRAP);
RNA_def_function_output(func, prop);
}
static void def_glossy(StructRNA *srna)

View File

@ -67,6 +67,12 @@ void RE_cache_point_density(struct Scene *scene,
struct PointDensity *pd,
const bool use_render_params);
void RE_minmac_point_density(struct Scene *scene,
struct PointDensity *pd,
const bool use_render_params,
float r_min[3],
float r_max[3]);
void RE_sample_point_density(struct Scene *scene,
struct PointDensity *pd,
const int resolution,

View File

@ -727,6 +727,49 @@ void RE_cache_point_density(Scene *scene,
BLI_mutex_unlock(&sample_mutex);
}
void RE_minmac_point_density(struct Scene *scene,
struct PointDensity *pd,
const bool use_render_params,
float r_min[3],
float r_max[3])
{
Object *object = pd->object;
if (object == NULL) {
zero_v3(r_min);
zero_v3(r_max);
}
if (pd->source == TEX_PD_PSYS) {
ParticleSystem *psys;
if (pd->psys == 0) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
if (psys == NULL) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
particle_system_minmax(scene,
object,
psys,
pd->radius,
use_render_params,
r_min, r_max);
}
else {
float radius[3] = {pd->radius, pd->radius, pd->radius};
float *loc, *size;
BKE_object_obdata_texspace_get(pd->object, NULL, &loc, &size, NULL);
sub_v3_v3v3(r_min, loc, size);
add_v3_v3v3(r_max, loc, size);
/* Adjust texture space to include density points on the boundaries. */
sub_v3_v3(r_min, radius);
add_v3_v3(r_max, radius);
}
}
/* NOTE 1: Requires RE_cache_point_density() to be called first.
* NOTE 2: Frees point density structure after sampling.
*/
@ -750,35 +793,11 @@ void RE_sample_point_density(Scene *scene,
return;
}
if (pd->source == TEX_PD_PSYS) {
ParticleSystem *psys;
if (pd->psys == 0) {
sample_dummy_point_density(resolution, values);
return;
}
psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
if (psys == NULL) {
sample_dummy_point_density(resolution, values);
return;
}
particle_system_minmax(scene,
object,
psys,
pd->radius,
use_render_params,
min, max);
}
else {
float radius[3] = {pd->radius, pd->radius, pd->radius};
float *loc, *size;
BKE_object_obdata_texspace_get(pd->object, NULL, &loc, &size, NULL);
sub_v3_v3v3(min, loc, size);
add_v3_v3v3(max, loc, size);
/* Adjust texture space to include density points on the boundaries. */
sub_v3_v3(min, radius);
add_v3_v3(max, radius);
}
RE_minmac_point_density(scene,
pd,
use_render_params,
min,
max);
sub_v3_v3v3(dim, max, min);
if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
sample_dummy_point_density(resolution, values);