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:
Diffstat (limited to 'source/blender/render/intern/source/pointdensity.c')
-rw-r--r--source/blender/render/intern/source/pointdensity.c268
1 files changed, 262 insertions, 6 deletions
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index ffb44cf6826..a03ea9cb896 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -45,6 +45,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
#include "DNA_texture_types.h"
#include "BKE_deform.h"
@@ -52,6 +53,7 @@
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
+#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
#include "BKE_colortools.h"
@@ -165,6 +167,149 @@ static void alloc_point_data(PointDensity *pd)
}
}
+static void pointdensity_cache_psys(Scene *scene,
+ PointDensity *pd,
+ Object *ob,
+ ParticleSystem *psys,
+ float viewmat[4][4],
+ float winmat[4][4],
+ int winx, int winy,
+ const bool use_render_params)
+{
+ DerivedMesh *dm;
+ ParticleKey state;
+ ParticleCacheKey *cache;
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL;
+ float cfra = BKE_scene_frame_get(scene);
+ int i /*, childexists*/ /* UNUSED */;
+ int total_particles;
+ int data_used;
+ float *data_vel, *data_life;
+ float partco[3];
+
+ /* init everything */
+ if (!psys || !ob || !pd) {
+ 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);
+ }
+
+ if (use_render_params) {
+ dm = mesh_create_derived_render(scene,
+ ob,
+ CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ }
+ else {
+ dm = mesh_get_derived_final(scene,
+ ob,
+ CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ }
+
+ if (!psys_check_enabled(ob, psys, use_render_params)) {
+ psys_render_restore(ob, psys);
+ return;
+ }
+
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(ob, psys);
+
+ /* in case ob->imat isn't up-to-date */
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ total_particles = psys->totpart + psys->totchild;
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
+ pd->totpoints = total_particles;
+ 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))
+ childexists = 1;
+#endif
+
+ for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
+
+ if (psys->part->type == PART_HAIR) {
+ /* hair particles */
+ if (i < psys->totpart && psys->pathcache)
+ cache = psys->pathcache[i];
+ else if (i >= psys->totpart && psys->childcache)
+ cache = psys->childcache[i - psys->totpart];
+ else
+ continue;
+
+ cache += cache->segments; /* use endpoint */
+
+ copy_v3_v3(state.co, cache->co);
+ zero_v3(state.vel);
+ state.time = 0.0f;
+ }
+ else {
+ /* emitter particles */
+ state.time = cfra;
+
+ if (!psys_get_particle_state(&sim, i, &state, 0))
+ continue;
+
+ if (data_used & POINT_DATA_LIFE) {
+ if (i < psys->totpart) {
+ state.time = (cfra - pa->time) / pa->lifetime;
+ }
+ else {
+ ChildParticle *cpa = (psys->child + i) - psys->totpart;
+ float pa_birthtime, pa_dietime;
+
+ state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
+ }
+ }
+ }
+
+ copy_v3_v3(partco, state.co);
+
+ if (pd->psys_cache_space == TEX_PD_OBJECTSPACE)
+ mul_m4_v3(ob->imat, partco);
+ else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
+ sub_v3_v3(partco, ob->loc);
+ }
+ else {
+ /* TEX_PD_WORLDSPACE */
+ }
+
+ BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
+
+ 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_life) {
+ data_life[i] = state.time;
+ }
+ }
+
+ BLI_bvhtree_balance(pd->point_tree);
+ dm->release(dm);
+
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
+
+ if (use_render_params) {
+ psys_render_restore(ob, psys);
+ }
+}
+
static void pointdensity_cache_vertex_color(PointDensity *pd, Object *UNUSED(ob), DerivedMesh *dm, float *data_color)
{
@@ -332,6 +477,9 @@ static void pointdensity_cache_object(Scene *scene,
static void cache_pointdensity_ex(Scene *scene,
PointDensity *pd,
+ float viewmat[4][4],
+ float winmat[4][4],
+ int winx, int winy,
const bool use_render_params)
{
if (pd == NULL) {
@@ -343,7 +491,28 @@ static void cache_pointdensity_ex(Scene *scene,
pd->point_tree = NULL;
}
- if (pd->source == TEX_PD_OBJECT) {
+ if (pd->source == TEX_PD_PSYS) {
+ Object *ob = pd->object;
+ ParticleSystem *psys;
+
+ if (!ob || !pd->psys) {
+ return;
+ }
+
+ psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
+ if (!psys) {
+ return;
+ }
+
+ pointdensity_cache_psys(scene,
+ pd,
+ ob,
+ psys,
+ viewmat, winmat,
+ winx, winy,
+ use_render_params);
+ }
+ else if (pd->source == TEX_PD_OBJECT) {
Object *ob = pd->object;
if (ob && ob->type == OB_MESH)
pointdensity_cache_object(scene, pd, ob, use_render_params);
@@ -352,7 +521,11 @@ static void cache_pointdensity_ex(Scene *scene,
void cache_pointdensity(Render *re, PointDensity *pd)
{
- cache_pointdensity_ex(re->scene, pd, true);
+ cache_pointdensity_ex(re->scene,
+ pd,
+ re->viewmat, re->winmat,
+ re->winx, re->winy,
+ true);
}
void free_pointdensity(PointDensity *pd)
@@ -703,20 +876,83 @@ static void sample_dummy_point_density(int resolution, float *values)
memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
}
+static void particle_system_minmax(Scene *scene,
+ Object *object,
+ ParticleSystem *psys,
+ float radius,
+ const bool use_render_params,
+ float min[3], float max[3])
+{
+ const float size[3] = {radius, radius, radius};
+ const float cfra = BKE_scene_frame_get(scene);
+ ParticleSettings *part = psys->part;
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL;
+ int i;
+ int total_particles;
+ float mat[4][4], imat[4][4];
+
+ INIT_MINMAX(min, max);
+ if (part->type == PART_HAIR) {
+ /* TOOD(sergey): Not supported currently. */
+ return;
+ }
+
+ unit_m4(mat);
+ if (use_render_params) {
+ psys_render_set(object, psys, mat, mat, 1, 1, 0);
+ }
+
+ sim.scene = scene;
+ sim.ob = object;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(object, psys);
+
+ invert_m4_m4(imat, object->obmat);
+ total_particles = psys->totpart + psys->totchild;
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
+ float co_object[3], co_min[3], co_max[3];
+ ParticleKey state;
+ state.time = cfra;
+ if (!psys_get_particle_state(&sim, i, &state, 0)) {
+ continue;
+ }
+ mul_v3_m4v3(co_object, imat, 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);
+ }
+
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
+
+ if (use_render_params) {
+ psys_render_restore(object, psys);
+ }
+}
+
void RE_point_density_cache(
Scene *scene,
PointDensity *pd,
const bool use_render_params)
{
+ float mat[4][4];
+ /* Same matricies/resolution as dupli_render_particle_set(). */
+ unit_m4(mat);
BLI_mutex_lock(&sample_mutex);
- cache_pointdensity_ex(scene, pd, use_render_params);
+ cache_pointdensity_ex(scene, pd, mat, mat, 1, 1, use_render_params);
BLI_mutex_unlock(&sample_mutex);
}
void RE_point_density_minmax(
- struct Scene *UNUSED(scene),
+ struct Scene *scene,
struct PointDensity *pd,
- const bool UNUSED(use_render_params),
+ const bool use_render_params,
float r_min[3], float r_max[3])
{
Object *object = pd->object;
@@ -725,7 +961,27 @@ void RE_point_density_minmax(
zero_v3(r_max);
return;
}
- if (pd->source == TEX_PD_OBJECT) {
+ 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;