From 2f15a1f66e3092158d330db97a33dc8d087ca053 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 18 Jul 2015 21:42:39 +0200 Subject: Point density: Add utility function to sample density outside of render pipeline Not currently used, it's a preparation for the further work. Should not be functional changes. --- .../blender/render/extern/include/RE_render_ext.h | 6 + source/blender/render/intern/source/pointdensity.c | 134 ++++++++++++++++++++- 2 files changed, 137 insertions(+), 3 deletions(-) (limited to 'source/blender/render') diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index 6adbb6d0e62..9d8a1a66771 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -59,6 +59,12 @@ void RE_free_sample_material(struct Material *mat); void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob); +/* pointdensity.c */ + +struct PointDensity; + +void RE_sample_point_density(struct Scene *scene, struct PointDensity *pd, int resolution, float *values); + void RE_init_texture_rng(void); void RE_exit_texture_rng(void); #endif /* __RE_RENDER_EXT_H__ */ diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 3a1f1fbb744..a99cc3c72a2 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -45,6 +45,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_lattice.h" #include "BKE_main.h" +#include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" #include "BKE_texture.h" @@ -58,12 +59,15 @@ #include "texture.h" #include "pointdensity.h" +#include "RE_render_ext.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 ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER; static int point_data_used(PointDensity *pd) { @@ -456,14 +460,16 @@ static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData * } -int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) +static int pointdensity(PointDensity *pd, + const float texvec[3], + TexResult *texres, + float *r_age, + float r_vec[3]) { int retval = TEX_INT; - PointDensity *pd = tex->pd; PointDensityRangeData pdr; float density = 0.0f, age = 0.0f, time = 0.0f; float vec[3] = {0.0f, 0.0f, 0.0f}, co[3]; - float col[4]; float turb, noise_fac; int num = 0; @@ -524,7 +530,26 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) mul_v3_fl(vec, 1.0f / num); } + if (r_age != NULL) { + *r_age = age; + } + if (r_vec != NULL) { + copy_v3_v3(r_vec, vec); + } + texres->tin = density; + + return retval; +} + +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[4]; + BRICONT; if (pd->color_source == TEX_PD_COLOR_CONSTANT) @@ -578,3 +603,106 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) } #endif } + +static void sample_dummy_point_density(int resolution, float *values) +{ + memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution); +} + +static void particle_system_minmax(Object *object, + ParticleSystem *psys, + float radius, + float min[3], float max[3]) +{ + ParticleSettings *part = psys->part; + float imat[4][4]; + float size[3] = {radius, radius, radius}; + PARTICLE_P; + INIT_MINMAX(min, max); + if (part->type == PART_HAIR) { + /* TOOD(sergey): Not supported currently. */ + return; + } + invert_m4_m4(imat, object->obmat); + LOOP_PARTICLES { + float co_object[3], co_min[3], co_max[3]; + mul_v3_m4v3(co_object, imat, pa->state.co); + sub_v3_v3v3(co_min, co_object, size); + add_v3_v3v3(co_max, co_object, size); + minmax_v3v3_v3(min, max, co_min); + minmax_v3v3_v3(min, max, co_max); + } +} + +void RE_sample_point_density(Scene *scene, PointDensity *pd, + int resolution, float *values) +{ + const size_t resolution2 = resolution * resolution; + Object *object = pd->object; + size_t x, y, z; + float min[3], max[3], dim[3], mat[4][4]; + + if (object == NULL) { + sample_dummy_point_density(resolution, values); + 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(object, psys, pd->radius, 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); + } + + 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); + return; + } + + /* Same matricies/resolution as dupli_render_particle_set(). */ + unit_m4(mat); + + BLI_mutex_lock(&sample_mutex); + cache_pointdensity_ex(scene, pd, mat, mat, 1, 1); + BLI_mutex_unlock(&sample_mutex); + + for (z = 0; z < resolution; ++z) { + for (y = 0; y < resolution; ++y) { + for (x = 0; x < resolution; ++x) { + size_t index = z * resolution2 + y * resolution + x; + float texvec[3]; + float age, vec[3]; + TexResult texres; + + copy_v3_v3(texvec, min); + texvec[0] += dim[0] * (float)x / (float)resolution; + texvec[1] += dim[1] * (float)y / (float)resolution; + texvec[2] += dim[2] * (float)z / (float)resolution; + + pointdensity(pd, texvec, &texres, &age, vec); + + copy_v3_v3(&values[index*4 + 0], &texres.tr); + values[index*4 + 3] = texres.tin; + } + } + } + free_pointdensity(pd); +} -- cgit v1.2.3