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-12-28 19:30:58 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-12-28 19:30:58 +0300
commit6ecab6dd8e48d564a2b43e0e81e79d079e8b4c77 (patch)
tree618e2d24eb34a05a81f726dd52eb2b7468e9296d /source/blender/blenkernel/intern/object_dupli.c
parent605263177b8eea24c1449e4dbf0138175ec3dddf (diff)
Revert particle system and point cache removal in blender2.8 branch.
This reverts commit 5aa19be91263a249ffae75573e3b32f24269d890 and b4a721af694817fa921b119df83d33ede7d7fed0. Due to postponement of particle system rewrite it was decided to put particle code back into the 2.8 branch for the time being.
Diffstat (limited to 'source/blender/blenkernel/intern/object_dupli.c')
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c332
1 files changed, 330 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index ef3b1559d5d..e3b801b3193 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -44,7 +44,6 @@
#include "DNA_anim_types.h"
#include "DNA_group_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
@@ -58,6 +57,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
+#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_editmesh.h"
#include "BKE_anim.h"
@@ -824,6 +824,327 @@ const DupliGenerator gen_dupli_faces = {
make_duplis_faces /* make_duplis */
};
+/* OB_DUPLIPARTS */
+static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem *psys)
+{
+ Scene *scene = ctx->scene;
+ Object *par = ctx->object;
+ bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER;
+ bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
+
+ GroupObject *go;
+ Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
+ DupliObject *dob;
+ ParticleDupliWeight *dw;
+ ParticleSettings *part;
+ ParticleData *pa;
+ ChildParticle *cpa = NULL;
+ ParticleKey state;
+ ParticleCacheKey *cache;
+ float ctime, pa_time, scale = 1.0f;
+ float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0;
+ float (*obmat)[4];
+ int a, b, hair = 0;
+ int totpart, totchild, totgroup = 0 /*, pa_num */;
+ const bool dupli_type_hack = !BKE_scene_use_new_shading_nodes(scene);
+
+ int no_draw_flag = PARS_UNEXIST;
+
+ if (psys == NULL) return;
+
+ part = psys->part;
+
+ if (part == NULL)
+ return;
+
+ if (!psys_check_enabled(par, psys, (ctx->eval_ctx->mode == DAG_EVAL_RENDER)))
+ return;
+
+ if (!for_render)
+ no_draw_flag |= PARS_NO_DISP;
+
+ ctime = BKE_scene_frame_get(scene); /* NOTE: in old animsys, used parent object's timeoffset... */
+
+ totpart = psys->totpart;
+ totchild = psys->totchild;
+
+ BLI_srandom((unsigned int)(31415926 + psys->seed));
+
+ if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
+ ParticleSimulationData sim = {NULL};
+ sim.scene = scene;
+ sim.ob = par;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(par, psys);
+ /* make sure emitter imat is in global coordinates instead of render view coordinates */
+ invert_m4_m4(par->imat, par->obmat);
+
+ /* first check for loops (particle system object used as dupli object) */
+ if (part->ren_as == PART_DRAW_OB) {
+ if (ELEM(part->dup_ob, NULL, par))
+ return;
+ }
+ else { /*PART_DRAW_GR */
+ if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject))
+ return;
+
+ if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) {
+ return;
+ }
+ }
+
+ /* if we have a hair particle system, use the path cache */
+ if (part->type == PART_HAIR) {
+ if (psys->flag & PSYS_HAIR_DONE)
+ hair = (totchild == 0 || psys->childcache) && psys->pathcache;
+ if (!hair)
+ return;
+
+ /* we use cache, update totchild according to cached data */
+ totchild = psys->totchildcache;
+ totpart = psys->totcached;
+ }
+
+ psys_check_group_weights(part);
+
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ /* gather list of objects or single object */
+ if (part->ren_as == PART_DRAW_GR) {
+ if (ctx->do_update) {
+ BKE_group_handle_recalc_and_update(ctx->eval_ctx, scene, par, part->dup_group);
+ }
+
+ if (part->draw & PART_DRAW_COUNT_GR) {
+ for (dw = part->dupliweights.first; dw; dw = dw->next)
+ totgroup += dw->count;
+ }
+ else {
+ for (go = part->dup_group->gobject.first; go; go = go->next)
+ totgroup++;
+ }
+
+ /* we also copy the actual objects to restore afterwards, since
+ * BKE_object_where_is_calc_time will change the object which breaks transform */
+ oblist = MEM_callocN((size_t)totgroup * sizeof(Object *), "dupgroup object list");
+ obcopylist = MEM_callocN((size_t)totgroup * sizeof(Object), "dupgroup copy list");
+
+ if (part->draw & PART_DRAW_COUNT_GR && totgroup) {
+ dw = part->dupliweights.first;
+
+ for (a = 0; a < totgroup; dw = dw->next) {
+ for (b = 0; b < dw->count; b++, a++) {
+ oblist[a] = dw->ob;
+ obcopylist[a] = *dw->ob;
+ }
+ }
+ }
+ else {
+ go = part->dup_group->gobject.first;
+ for (a = 0; a < totgroup; a++, go = go->next) {
+ oblist[a] = go->ob;
+ obcopylist[a] = *go->ob;
+ }
+ }
+ }
+ else {
+ ob = part->dup_ob;
+ obcopy = *ob;
+ }
+
+ if (totchild == 0 || part->draw & PART_DRAW_PARENT)
+ a = 0;
+ else
+ a = totpart;
+
+ for (pa = psys->particles; a < totpart + totchild; a++, pa++) {
+ if (a < totpart) {
+ /* handle parent particle */
+ if (pa->flag & no_draw_flag)
+ continue;
+
+ /* pa_num = pa->num; */ /* UNUSED */
+ pa_time = pa->time;
+ size = pa->size;
+ }
+ else {
+ /* handle child particle */
+ cpa = &psys->child[a - totpart];
+
+ /* pa_num = a; */ /* UNUSED */
+ pa_time = psys->particles[cpa->parent].time;
+ size = psys_get_child_size(psys, cpa, ctime, NULL);
+ }
+
+ /* some hair paths might be non-existent so they can't be used for duplication */
+ if (hair && psys->pathcache &&
+ ((a < totpart && psys->pathcache[a]->segments < 0) ||
+ (a >= totpart && psys->childcache[a - totpart]->segments < 0)))
+ {
+ continue;
+ }
+
+ if (part->ren_as == PART_DRAW_GR) {
+ /* prevent divide by zero below [#28336] */
+ if (totgroup == 0)
+ continue;
+
+ /* for groups, pick the object based on settings */
+ if (part->draw & PART_DRAW_RAND_GR)
+ b = BLI_rand() % totgroup;
+ else
+ b = a % totgroup;
+
+ ob = oblist[b];
+ obmat = oblist[b]->obmat;
+ }
+ else {
+ obmat = ob->obmat;
+ }
+
+ if (hair) {
+ /* hair we handle separate and compute transform based on hair keys */
+ if (a < totpart) {
+ cache = psys->pathcache[a];
+ psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale);
+ }
+ else {
+ cache = psys->childcache[a - totpart];
+ psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale);
+ }
+
+ copy_v3_v3(pamat[3], cache->co);
+ pamat[3][3] = 1.0f;
+
+ }
+ else {
+ /* first key */
+ state.time = ctime;
+ if (psys_get_particle_state(&sim, a, &state, 0) == 0) {
+ continue;
+ }
+ else {
+ float tquat[4];
+ normalize_qt_qt(tquat, state.rot);
+ quat_to_mat4(pamat, tquat);
+ copy_v3_v3(pamat[3], state.co);
+ pamat[3][3] = 1.0f;
+ }
+ }
+
+ if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
+ for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) {
+
+ copy_m4_m4(tmat, oblist[b]->obmat);
+ /* apply particle scale */
+ mul_mat3_m4_fl(tmat, size * scale);
+ mul_v3_fl(tmat[3], size * scale);
+ /* group dupli offset, should apply after everything else */
+ if (!is_zero_v3(part->dup_group->dupli_ofs))
+ sub_v3_v3(tmat[3], part->dup_group->dupli_ofs);
+ /* individual particle transform */
+ mul_m4_m4m4(mat, pamat, tmat);
+
+ dob = make_dupli(ctx, go->ob, mat, a, false, false);
+ dob->particle_system = psys;
+ if (use_texcoords)
+ psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
+ }
+ }
+ else {
+ /* to give ipos in object correct offset */
+ BKE_object_where_is_calc_time(scene, ob, ctime - pa_time);
+
+ copy_v3_v3(vec, obmat[3]);
+ obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
+
+ /* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */
+ if ((part->draw & PART_DRAW_ROTATE_OB) == 0) {
+ float xvec[3], q[4], size_mat[4][4], original_size[3];
+
+ mat4_to_size(original_size, obmat);
+ size_to_mat4(size_mat, original_size);
+
+ xvec[0] = -1.f;
+ xvec[1] = xvec[2] = 0;
+ vec_to_quat(q, xvec, ob->trackflag, ob->upflag);
+ quat_to_mat4(obmat, q);
+ obmat[3][3] = 1.0f;
+
+ /* add scaling if requested */
+ if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0)
+ mul_m4_m4m4(obmat, obmat, size_mat);
+ }
+ else if (part->draw & PART_DRAW_NO_SCALE_OB) {
+ /* remove scaling */
+ float size_mat[4][4], original_size[3];
+
+ mat4_to_size(original_size, obmat);
+ size_to_mat4(size_mat, original_size);
+ invert_m4(size_mat);
+
+ mul_m4_m4m4(obmat, obmat, size_mat);
+ }
+
+ mul_m4_m4m4(tmat, pamat, obmat);
+ mul_mat3_m4_fl(tmat, size * scale);
+
+ copy_m4_m4(mat, tmat);
+
+ if (part->draw & PART_DRAW_GLOBAL_OB)
+ add_v3_v3v3(mat[3], mat[3], vec);
+
+ dob = make_dupli(ctx, ob, mat, a, false, false);
+ dob->particle_system = psys;
+ if (use_texcoords)
+ psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
+ /* XXX blender internal needs this to be set to dupligroup to render
+ * groups correctly, but we don't want this hack for cycles */
+ if (dupli_type_hack && ctx->group)
+ dob->type = OB_DUPLIGROUP;
+ }
+ }
+
+ /* restore objects since they were changed in BKE_object_where_is_calc_time */
+ if (part->ren_as == PART_DRAW_GR) {
+ for (a = 0; a < totgroup; a++)
+ *(oblist[a]) = obcopylist[a];
+ }
+ else
+ *ob = obcopy;
+ }
+
+ /* clean up */
+ if (oblist)
+ MEM_freeN(oblist);
+ if (obcopylist)
+ MEM_freeN(obcopylist);
+
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
+}
+
+static void make_duplis_particles(const DupliContext *ctx)
+{
+ ParticleSystem *psys;
+ int psysid;
+
+ /* particle system take up one level in id, the particles another */
+ for (psys = ctx->object->particlesystem.first, psysid = 0; psys; psys = psys->next, psysid++) {
+ /* particles create one more level for persistent psys index */
+ DupliContext pctx;
+ copy_dupli_context(&pctx, ctx, ctx->object, NULL, psysid, false);
+ make_duplis_particle_system(&pctx, psys);
+ }
+}
+
+const DupliGenerator gen_dupli_particles = {
+ OB_DUPLIPARTS, /* type */
+ make_duplis_particles /* make_duplis */
+};
+
/* ------------- */
/* select dupli generator from given context */
@@ -839,7 +1160,10 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
if (ctx->eval_ctx->mode == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW))
return NULL;
- if (transflag & OB_DUPLIVERTS) {
+ if (transflag & OB_DUPLIPARTS) {
+ return &gen_dupli_particles;
+ }
+ else if (transflag & OB_DUPLIVERTS) {
if (ctx->object->type == OB_MESH) {
return &gen_dupli_verts;
}
@@ -897,8 +1221,12 @@ int count_duplilist(Object *ob)
if (ob->transflag & OB_DUPLIVERTS) {
if (ob->type == OB_MESH) {
if (ob->transflag & OB_DUPLIVERTS) {
+ ParticleSystem *psys = ob->particlesystem.first;
int pdup = 0;
+ for (; psys; psys = psys->next)
+ pdup += psys->totpart;
+
if (pdup == 0) {
Mesh *me = ob->data;
return me->totvert;