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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_effect.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h3
-rw-r--r--source/blender/blenkernel/BKE_particle.h479
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h11
-rw-r--r--source/blender/blenkernel/BKE_sca.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt6
-rw-r--r--source/blender/blenkernel/intern/anim.c2
-rw-r--r--source/blender/blenkernel/intern/boids.c1619
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c164
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c257
-rw-r--r--source/blender/blenkernel/intern/effect.c111
-rw-r--r--source/blender/blenkernel/intern/library.c13
-rw-r--r--source/blender/blenkernel/intern/library_query.c54
-rw-r--r--source/blender/blenkernel/intern/object.c226
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c332
-rw-r--r--source/blender/blenkernel/intern/object_update.c49
-rw-r--r--source/blender/blenkernel/intern/particle.c4336
-rw-r--r--source/blender/blenkernel/intern/particle_child.c739
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c1448
-rw-r--r--source/blender/blenkernel/intern/particle_system.c4347
-rw-r--r--source/blender/blenkernel/intern/pointcache.c92
-rw-r--r--source/blender/blenkernel/intern/smoke.c257
-rw-r--r--source/blender/blenloader/intern/readfile.c167
-rw-r--r--source/blender/blenloader/intern/versioning_250.c61
-rw-r--r--source/blender/blenloader/intern/versioning_260.c33
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c166
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build_nodes.cc46
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build_relations.cc134
-rw-r--r--source/blender/editors/object/object_edit.c3
-rw-r--r--source/blender/editors/space_time/space_time.c7
-rw-r--r--source/blender/editors/transform/transform_conversions.c3
-rw-r--r--source/blender/modifiers/intern/MOD_build.c2
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c943
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c3
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c327
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c104
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c2
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c2
-rw-r--r--source/blender/render/intern/source/convertblender.c1253
-rw-r--r--source/blender/render/intern/source/pointdensity.c267
-rw-r--r--source/creator/creator.c2
45 files changed, 93 insertions, 17987 deletions
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index f8fee444d91..3ca4472ea0a 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -115,7 +115,6 @@ void pdEndEffectors(struct ListBase **effectors);
void pdPrecalculateEffectors(struct ListBase *effectors);
void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse);
-void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point);
void pd_point_from_loc(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point);
void pd_point_from_soft(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 7d6096407ff..1bb1e5fab53 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -55,10 +55,7 @@ void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struc
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches);
struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
-struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys);
-void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src);
-void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_bulletsoftbody(struct Object *ob);
void BKE_object_free_curve_cache(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
deleted file mode 100644
index e17fb9f7a02..00000000000
--- a/source/blender/blenkernel/BKE_particle.h
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Adaptive time step
- * Classical SPH
- * Copyright 2011-2012 AutoCRC
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __BKE_PARTICLE_H__
-#define __BKE_PARTICLE_H__
-
-/** \file BKE_particle.h
- * \ingroup bke
- */
-
-#include "BLI_utildefines.h"
-
-#include "DNA_particle_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_customdata.h"
-
-struct ParticleSystemModifierData;
-struct ParticleSystem;
-struct ParticleKey;
-struct ParticleSettings;
-
-struct Main;
-struct Object;
-struct Scene;
-struct DerivedMesh;
-struct ModifierData;
-struct MTFace;
-struct MCol;
-struct MFace;
-struct MVert;
-struct LatticeDeformData;
-struct LinkNode;
-struct KDTree;
-struct RNG;
-struct BVHTreeRay;
-struct BVHTreeRayHit;
-struct EdgeHash;
-
-#define PARTICLE_P ParticleData * pa; int p
-#define LOOP_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++)
-#define LOOP_EXISTING_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) if (!(pa->flag & PARS_UNEXIST))
-#define LOOP_SHOWN_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) if (!(pa->flag & (PARS_UNEXIST | PARS_NO_DISP)))
-/* OpenMP: Can only advance one variable within loop definition. */
-#define LOOP_DYNAMIC_PARTICLES for (p = 0; p < psys->totpart; p++) if ((pa = psys->particles + p)->state.time > 0.0f)
-
-/* fast but sure way to get the modifier*/
-#define PARTICLE_PSMD ParticleSystemModifierData * psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys)
-
-/* common stuff that many particle functions need */
-typedef struct ParticleSimulationData {
- struct Scene *scene;
- struct Object *ob;
- struct ParticleSystem *psys;
- struct ParticleSystemModifierData *psmd;
- struct ListBase *colliders;
- /* Courant number. This is used to implement an adaptive time step. Only the
- * maximum value per time step is important. Only sph_integrate makes use of
- * this at the moment. Other solvers could, too. */
- float courant_num;
-} ParticleSimulationData;
-
-typedef struct SPHData {
- ParticleSystem *psys[10];
- ParticleData *pa;
- float mass;
- struct EdgeHash *eh;
- float *gravity;
- float hfac;
- /* Average distance to neighbours (other particles in the support domain),
- * for calculating the Courant number (adaptive time step). */
- int pass;
- float element_size;
- float flow[3];
-
- /* Integrator callbacks. This allows different SPH implementations. */
- void (*force_cb) (void *sphdata_v, ParticleKey *state, float *force, float *impulse);
- void (*density_cb) (void *rangedata_v, int index, const float co[3], float squared_dist);
-} SPHData;
-
-typedef struct ParticleTexture {
- float ivel; /* used in reset */
- float time, life, exist, size; /* used in init */
- float damp, gravity, field; /* used in physics */
- float length, clump, kink_freq, kink_amp, effector; /* used in path caching */
- float rough1, rough2, roughe; /* used in path caching */
-} ParticleTexture;
-
-typedef struct ParticleSeam {
- float v0[3], v1[3];
- float nor[3], dir[3], tan[3];
- float length2;
-} ParticleSeam;
-
-typedef struct ParticleCacheKey {
- float co[3];
- float vel[3];
- float rot[4];
- float col[3];
- float time;
- int segments;
-} ParticleCacheKey;
-
-typedef struct ParticleThreadContext {
- /* shared */
- struct ParticleSimulationData sim;
- struct DerivedMesh *dm;
- struct Material *ma;
-
- /* distribution */
- struct KDTree *tree;
-
- struct ParticleSeam *seams;
- int totseam;
-
- float *jit, *jitoff, *weight;
- float maxweight;
- int *index, *skip, jitlevel;
-
- int cfrom, distr;
-
- struct ParticleData *tpars;
-
- /* path caching */
- int editupdate, between, segments, extra_segments;
- int totchild, totparent, parent_pass;
-
- float cfra;
-
- float *vg_length, *vg_clump, *vg_kink;
- float *vg_rough1, *vg_rough2, *vg_roughe;
- float *vg_effector;
-
- struct CurveMapping *clumpcurve;
- struct CurveMapping *roughcurve;
-} ParticleThreadContext;
-
-typedef struct ParticleTask {
- ParticleThreadContext *ctx;
- struct RNG *rng, *rng_path;
- int begin, end;
-} ParticleTask;
-
-typedef struct ParticleBillboardData {
- struct Object *ob;
- float vec[3], vel[3];
- float offset[2];
- float size[2];
- float tilt, random, time;
- int uv[3];
- int lock, num;
- int totnum;
- int lifetime;
- short align, uv_split, anim, split_offset;
-} ParticleBillboardData;
-
-typedef struct ParticleCollisionElement {
- /* pointers to original data */
- float *x[3], *v[3];
-
- /* values interpolated from original data*/
- float x0[3], x1[3], x2[3], p[3];
-
- /* results for found intersection point */
- float nor[3], vel[3], uv[2];
-
- /* count of original data (1-4) */
- int tot;
-
- /* index of the collision face */
- int index;
-
- /* flags for inversed normal / particle already inside element at start */
- short inv_nor, inside;
-} ParticleCollisionElement;
-
-/* container for moving data between deflet_particle and particle_intersect_face */
-typedef struct ParticleCollision {
- struct Object *current;
- struct Object *hit;
- struct Object *prev;
- struct Object *skip;
- struct Object *emitter;
-
- struct CollisionModifierData *md; // collision modifier for current object;
-
- float f; // time factor of previous collision, needed for substracting face velocity
- float fac1, fac2;
-
- float cfra, old_cfra;
-
- float original_ray_length; //original length of co2-co1, needed for collision time evaluation
-
- int prev_index;
-
- ParticleCollisionElement pce;
-
- /* total_time is the amount of time in this subframe
- * inv_total_time is the opposite
- * inv_timestep is the inverse of the amount of time in this frame */
- float total_time, inv_total_time, inv_timestep;
-
- float radius;
- float co1[3], co2[3];
- float ve1[3], ve2[3];
-
- float acc[3], boid_z;
-
- int boid;
-} ParticleCollision;
-
-typedef struct ParticleDrawData {
- float *vdata, *vd; /* vertice data */
- float *ndata, *nd; /* normal data */
- float *cdata, *cd; /* color data */
- float *vedata, *ved; /* velocity data */
- float *ma_col;
- int tot_vec_size, flag;
- int totpoint, totve;
-} ParticleDrawData;
-
-#define PARTICLE_DRAW_DATA_UPDATED 1
-
-#define PSYS_FRAND_COUNT 1024
-extern unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
-extern unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
-extern float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];
-
-void psys_init_rng(void);
-
-BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
-{
- /* XXX far from ideal, this simply scrambles particle random numbers a bit
- * to avoid obvious correlations.
- * Can't use previous psys->frand arrays because these require initialization
- * inside psys_check_enabled, which wreaks havok in multithreaded depgraph updates.
- */
- unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT];
- unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT];
- return PSYS_FRAND_BASE[(offset + seed * multiplier) % PSYS_FRAND_COUNT];
-}
-
-BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float vec[3])
-{
- unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT];
- unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT];
- vec[0] = PSYS_FRAND_BASE[(offset + (seed + 0) * multiplier) % PSYS_FRAND_COUNT];
- vec[1] = PSYS_FRAND_BASE[(offset + (seed + 1) * multiplier) % PSYS_FRAND_COUNT];
- vec[2] = PSYS_FRAND_BASE[(offset + (seed + 2) * multiplier) % PSYS_FRAND_COUNT];
-}
-
-/* ----------- functions needed outside particlesystem ---------------- */
-/* particle.c */
-int count_particles(struct ParticleSystem *psys);
-int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur);
-
-int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys);
-int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys);
-
-struct ParticleSystem *psys_get_current(struct Object *ob);
-/* for rna */
-short psys_get_current_num(struct Object *ob);
-void psys_set_current_num(Object *ob, int index);
-/* UNUSED */
-// struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
-
-struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
-
-bool psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
-bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
-bool psys_check_edited(struct ParticleSystem *psys);
-
-void psys_check_group_weights(struct ParticleSettings *part);
-int psys_uses_gravity(struct ParticleSimulationData *sim);
-
-/* free */
-void BKE_particlesettings_free(struct ParticleSettings *part);
-void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
-void psys_free(struct Object *ob, struct ParticleSystem *psys);
-
-void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
-void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
-bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
-
-void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
-void psys_interpolate_mcol(const struct MCol *mcol, int quad, const float w[4], struct MCol *mc);
-
-void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time);
-
-CustomDataMask psys_emitter_customdata_mask(struct ParticleSystem *psys);
-void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache,
- float fuv[4], float foffset, float vec[3], float nor[3],
- float utan[3], float vtan[3], float orco[3], float ornor[3]);
-struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys);
-
-struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name);
-void object_remove_particle_system(struct Scene *scene, struct Object *ob);
-struct ParticleSettings *psys_new_settings(const char *name, struct Main *main);
-struct ParticleSettings *BKE_particlesettings_copy(struct ParticleSettings *part);
-void BKE_particlesettings_make_local(struct ParticleSettings *part);
-
-void psys_reset(struct ParticleSystem *psys, int mode);
-
-void psys_find_parents(struct ParticleSimulationData *sim);
-
-void psys_cache_paths(struct ParticleSimulationData *sim, float cfra);
-void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra);
-void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, int editupdate);
-int do_guides(struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
-void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors);
-float psys_get_timestep(struct ParticleSimulationData *sim);
-float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
-float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time);
-void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, const bool vel);
-int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always);
-
-/* child paths */
-void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part);
-void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part);
-void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers,
- struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
- struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys, const float parent_orco[3]);
-
-void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata);
-void psys_sph_finalise(struct SPHData *sphdata);
-void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]);
-
-/* for anim.c */
-void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part,
- struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa,
- float uv[2], float orco[3]);
-void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa,
- struct ParticleCacheKey *cache, float mat[4][4], float *scale);
-
-void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim);
-void psys_thread_context_free(struct ParticleThreadContext *ctx);
-void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart, struct ParticleTask **r_tasks, int *r_numtasks);
-void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
-
-void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
-void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
-
-/* particle_system.c */
-struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
-void psys_count_keyed_targets(struct ParticleSimulationData *sim);
-void psys_update_particle_tree(struct ParticleSystem *psys, float cfra);
-void psys_changed_type(struct Object *ob, struct ParticleSystem *psys);
-
-void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
-void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra);
-
-void psys_check_boid_data(struct ParticleSystem *psys);
-
-void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
-
-void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
-
-/* Callback format for performing operations on ID-pointers for particle systems */
-typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cd_flag);
-
-void BKE_particlesystem_id_loop(struct ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata);
-
-/* ----------- functions needed only inside particlesystem ------------ */
-/* particle.c */
-void psys_disable_all(struct Object *ob);
-void psys_enable_all(struct Object *ob);
-
-void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics);
-void free_keyed_keys(struct ParticleSystem *psys);
-void psys_free_particles(struct ParticleSystem *psys);
-void psys_free_children(struct ParticleSystem *psys);
-
-void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, bool velocity);
-void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float vec[3]);
-void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
-void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
-void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
-
-float psys_get_dietime_from_cache(struct PointCache *cache, int index);
-
-void psys_free_pdd(struct ParticleSystem *psys);
-
-float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup);
-void psys_get_texture(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleTexture *ptex, int event, float cfra);
-void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface,
- float (*orcodata)[3], float w[4], float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3]);
-float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values);
-void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time);
-
-/* BLI_bvhtree_ray_cast callback */
-void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit);
-void psys_particle_on_dm(struct DerivedMesh *dm_final, int from, int index, int index_dmcache,
- const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3]);
-
-/* particle_system.c */
-void distribute_particles(struct ParticleSimulationData *sim, int from);
-void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
-void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, struct ParticleSystem *psys);
-int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes);
-
-void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra);
-
-float psys_get_current_display_percentage(struct ParticleSystem *psys);
-
-typedef struct ParticleRenderElem {
- int curchild, totchild, reduce;
- float lambda, t, scalemin, scalemax;
-} ParticleRenderElem;
-
-typedef struct ParticleRenderData {
- ChildParticle *child;
- ParticleCacheKey **pathcache;
- ParticleCacheKey **childcache;
- ListBase pathcachebufs, childcachebufs;
- int totchild, totcached, totchildcache;
- struct DerivedMesh *dm;
- int totdmvert, totdmedge, totdmface;
-
- float mat[4][4];
- float viewmat[4][4], winmat[4][4];
- int winx, winy;
-
- int do_simplify;
- int timeoffset;
- ParticleRenderElem *elems;
-
- /* ORIGINDEX */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-} ParticleRenderData;
-
-/* psys_reset */
-#define PSYS_RESET_ALL 1
-#define PSYS_RESET_DEPSGRAPH 2
-/* #define PSYS_RESET_CHILDREN 3 */ /*UNUSED*/
-#define PSYS_RESET_CACHE_MISS 4
-
-/* index_dmcache */
-#define DMCACHE_NOTFOUND -1
-#define DMCACHE_ISCHILD -2
-
-/* **** Depsgraph evaluation **** */
-
-struct EvaluationContext;
-
-void BKE_particle_system_eval(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob,
- struct ParticleSystem *psys);
-
-#endif
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 8238ea64242..42d19425896 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -62,12 +62,11 @@
/* PTCacheID types */
#define PTCACHE_TYPE_SOFTBODY 0
-#define PTCACHE_TYPE_PARTICLES 1
-#define PTCACHE_TYPE_CLOTH 2
-#define PTCACHE_TYPE_SMOKE_DOMAIN 3
-#define PTCACHE_TYPE_SMOKE_HIGHRES 4
-#define PTCACHE_TYPE_DYNAMICPAINT 5
-#define PTCACHE_TYPE_RIGIDBODY 6
+#define PTCACHE_TYPE_CLOTH 1
+#define PTCACHE_TYPE_SMOKE_DOMAIN 2
+#define PTCACHE_TYPE_SMOKE_HIGHRES 3
+#define PTCACHE_TYPE_DYNAMICPAINT 4
+#define PTCACHE_TYPE_RIGIDBODY 5
/* high bits reserved for flags that need to be stored in file */
#define PTCACHE_TYPEFLAG_COMPRESS (1 << 16)
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index fa448aa97b8..1f2bb6c3a2b 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -83,7 +83,7 @@ void BKE_sca_controllers_id_loop(struct ListBase *contlist, SCAControllerIDFunc
void BKE_sca_actuators_id_loop(struct ListBase *atclist, SCAActuatorIDFunc func, void *userdata);
-const char *sca_state_name_get(Object *ob, short bit);
+const char *sca_state_name_get(struct Object *ob, short bit);
#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 7311f330962..083c8b8f5ed 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -76,7 +76,6 @@ set(SRC
intern/autoexec.c
intern/blender.c
intern/bmfont.c
- intern/boids.c
intern/bpath.c
intern/brush.c
intern/bullet.c
@@ -145,10 +144,6 @@ set(SRC
intern/outliner_treehash.c
intern/packedFile.c
intern/paint.c
- intern/particle.c
- intern/particle_child.c
- intern/particle_distribute.c
- intern/particle_system.c
intern/pbvh.c
intern/pbvh_bmesh.c
intern/pointcache.c
@@ -258,7 +253,6 @@ set(SRC
BKE_outliner_treehash.h
BKE_packedFile.h
BKE_paint.h
- BKE_particle.h
BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index dff696863e9..440f49ffb08 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -41,6 +41,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_key_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_curve.h"
@@ -49,7 +50,6 @@
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_anim.h"
#include "BKE_report.h"
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
deleted file mode 100644
index 5270d050809..00000000000
--- a/source/blender/blenkernel/intern/boids.c
+++ /dev/null
@@ -1,1619 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2009 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/boids.c
- * \ingroup bke
- */
-
-
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_object_force.h"
-#include "DNA_scene_types.h"
-
-#include "BLI_rand.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_kdtree.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_collision.h"
-#include "BKE_effect.h"
-#include "BKE_boids.h"
-#include "BKE_particle.h"
-
-#include "BKE_modifier.h"
-
-#include "RNA_enum_types.h"
-
-typedef struct BoidValues {
- float max_speed, max_acc;
- float max_ave, min_speed;
- float personal_space, jump_speed;
-} BoidValues;
-
-static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness);
-
-static int rule_none(BoidRule *UNUSED(rule), BoidBrainData *UNUSED(data), BoidValues *UNUSED(val), ParticleData *UNUSED(pa))
-{
- return 0;
-}
-
-static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule;
- BoidSettings *boids = bbd->part->boids;
- BoidParticle *bpa = pa->boid;
- EffectedPoint epoint;
- ListBase *effectors = bbd->sim->psys->effectors;
- EffectorCache *cur, *eff = NULL;
- EffectorCache temp_eff;
- EffectorData efd, cur_efd;
- float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
- float priority = 0.0f, len = 0.0f;
- int ret = 0;
-
- int p = 0;
- efd.index = cur_efd.index = &p;
-
- pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
-
- /* first find out goal/predator with highest priority */
- if (effectors) for (cur = effectors->first; cur; cur=cur->next) {
- Object *eob = cur->ob;
- PartDeflect *pd = cur->pd;
-
- if (gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) {
- if (gabr->ob == eob) {
- /* TODO: effectors with multiple points */
- if (get_effector_data(cur, &efd, &epoint, 0)) {
- if (cur->pd && cur->pd->forcefield == PFIELD_BOID)
- priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights);
- else
- priority = 1.0;
-
- eff = cur;
- }
- break;
- }
- }
- else if (rule->type == eBoidRuleType_Goal && eob == bpa->ground) {
- /* skip current object */
- }
- else if (pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(cur, &cur_efd, &epoint, 0)) {
- float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights);
-
- if (temp == 0.0f) {
- /* do nothing */
- }
- else if (temp > priority) {
- priority = temp;
- eff = cur;
- efd = cur_efd;
- len = efd.distance;
- }
- /* choose closest object with same priority */
- else if (temp == priority && efd.distance < len) {
- eff = cur;
- efd = cur_efd;
- len = efd.distance;
- }
- }
- }
-
- /* if the object doesn't have effector data we have to fake it */
- if (eff == NULL && gabr->ob) {
- memset(&temp_eff, 0, sizeof(EffectorCache));
- temp_eff.ob = gabr->ob;
- temp_eff.scene = bbd->sim->scene;
- eff = &temp_eff;
- get_effector_data(eff, &efd, &epoint, 0);
- priority = 1.0f;
- }
-
- /* then use that effector */
- if (priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */
- Object *eob = eff->ob;
- PartDeflect *pd = eff->pd;
- float surface = (pd && pd->shape == PFIELD_SHAPE_SURFACE) ? 1.0f : 0.0f;
-
- if (gabr->options & BRULE_GOAL_AVOID_PREDICT) {
- /* estimate future location of target */
- get_effector_data(eff, &efd, &epoint, 1);
-
- mul_v3_fl(efd.vel, efd.distance / (val->max_speed * bbd->timestep));
- add_v3_v3(efd.loc, efd.vel);
- sub_v3_v3v3(efd.vec_to_point, pa->prev_state.co, efd.loc);
- efd.distance = len_v3(efd.vec_to_point);
- }
-
- if (rule->type == eBoidRuleType_Goal && boids->options & BOID_ALLOW_CLIMB && surface!=0.0f) {
- if (!bbd->goal_ob || bbd->goal_priority < priority) {
- bbd->goal_ob = eob;
- copy_v3_v3(bbd->goal_co, efd.loc);
- copy_v3_v3(bbd->goal_nor, efd.nor);
- }
- }
- else if (rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing &&
- priority > 2.0f * gabr->fear_factor) {
- /* detach from surface and try to fly away from danger */
- negate_v3_v3(efd.vec_to_point, bpa->gravity);
- }
-
- copy_v3_v3(bbd->wanted_co, efd.vec_to_point);
- mul_v3_fl(bbd->wanted_co, mul);
-
- bbd->wanted_speed = val->max_speed * priority;
-
- /* with goals factor is approach velocity factor */
- if (rule->type == eBoidRuleType_Goal && boids->landing_smoothness > 0.0f) {
- float len2 = 2.0f*len_v3(pa->prev_state.vel);
-
- surface *= pa->size * boids->height;
-
- if (len2 > 0.0f && efd.distance - surface < len2) {
- len2 = (efd.distance - surface)/len2;
- bbd->wanted_speed *= powf(len2, boids->landing_smoothness);
- }
- }
-
- ret = 1;
- }
-
- return ret;
-}
-
-static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
- BoidRuleAvoidCollision *acbr = (BoidRuleAvoidCollision*) rule;
- KDTreeNearest *ptn = NULL;
- ParticleTarget *pt;
- BoidParticle *bpa = pa->boid;
- ColliderCache *coll;
- float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
- float co1[3], vel1[3], co2[3], vel2[3];
- float len, t, inp, t_min = 2.0f;
- int n, neighbors = 0, nearest = 0;
- int ret = 0;
-
- //check deflector objects first
- if (acbr->options & BRULE_ACOLL_WITH_DEFLECTORS && bbd->sim->colliders) {
- ParticleCollision col;
- BVHTreeRayHit hit;
- float radius = val->personal_space * pa->size, ray_dir[3];
-
- memset(&col, 0, sizeof(ParticleCollision));
-
- copy_v3_v3(col.co1, pa->prev_state.co);
- add_v3_v3v3(col.co2, pa->prev_state.co, pa->prev_state.vel);
- sub_v3_v3v3(ray_dir, col.co2, col.co1);
- mul_v3_fl(ray_dir, acbr->look_ahead);
- col.f = 0.0f;
- hit.index = -1;
- hit.dist = col.original_ray_length = normalize_v3(ray_dir);
-
- /* find out closest deflector object */
- for (coll = bbd->sim->colliders->first; coll; coll=coll->next) {
- /* don't check with current ground object */
- if (coll->ob == bpa->ground)
- continue;
-
- col.current = coll->ob;
- col.md = coll->collmd;
-
- if (col.md && col.md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col.md->bvhtree, col.co1, ray_dir, radius, &hit,
- BKE_psys_collision_neartest_cb, &col, raycast_flag);
- }
- }
- /* then avoid that object */
- if (hit.index>=0) {
- t = hit.dist/col.original_ray_length;
-
- /* avoid head-on collision */
- if (dot_v3v3(col.pce.nor, pa->prev_state.ave) < -0.99f) {
- /* don't know why, but uneven range [0.0, 1.0] */
- /* works much better than even [-1.0, 1.0] */
- bbd->wanted_co[0] = BLI_rng_get_float(bbd->rng);
- bbd->wanted_co[1] = BLI_rng_get_float(bbd->rng);
- bbd->wanted_co[2] = BLI_rng_get_float(bbd->rng);
- }
- else {
- copy_v3_v3(bbd->wanted_co, col.pce.nor);
- }
-
- mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size);
-
- bbd->wanted_speed = sqrtf(t) * len_v3(pa->prev_state.vel);
- bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed);
-
- return 1;
- }
- }
-
- //check boids in own system
- if (acbr->options & BRULE_ACOLL_WITH_BOIDS) {
- neighbors = BLI_kdtree_range_search__normal(
- bbd->sim->psys->tree, pa->prev_state.co, pa->prev_state.ave,
- &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel));
- if (neighbors > 1) for (n=1; n<neighbors; n++) {
- copy_v3_v3(co1, pa->prev_state.co);
- copy_v3_v3(vel1, pa->prev_state.vel);
- copy_v3_v3(co2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.co);
- copy_v3_v3(vel2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.vel);
-
- sub_v3_v3v3(loc, co1, co2);
-
- sub_v3_v3v3(vec, vel1, vel2);
-
- inp = dot_v3v3(vec, vec);
-
- /* velocities not parallel */
- if (inp != 0.0f) {
- t = -dot_v3v3(loc, vec)/inp;
- /* cpa is not too far in the future so investigate further */
- if (t > 0.0f && t < t_min) {
- madd_v3_v3fl(co1, vel1, t);
- madd_v3_v3fl(co2, vel2, t);
-
- sub_v3_v3v3(vec, co2, co1);
-
- len = normalize_v3(vec);
-
- /* distance of cpa is close enough */
- if (len < 2.0f * val->personal_space * pa->size) {
- t_min = t;
-
- mul_v3_fl(vec, len_v3(vel1));
- mul_v3_fl(vec, (2.0f - t)/2.0f);
- sub_v3_v3v3(bbd->wanted_co, vel1, vec);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
- ret = 1;
- }
- }
- }
- }
- }
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
-
- /* check boids in other systems */
- for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
- ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
-
- if (epsys) {
- BLI_assert(epsys->tree != NULL);
- neighbors = BLI_kdtree_range_search__normal(
- epsys->tree, pa->prev_state.co, pa->prev_state.ave,
- &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel));
-
- if (neighbors > 0) for (n=0; n<neighbors; n++) {
- copy_v3_v3(co1, pa->prev_state.co);
- copy_v3_v3(vel1, pa->prev_state.vel);
- copy_v3_v3(co2, (epsys->particles + ptn[n].index)->prev_state.co);
- copy_v3_v3(vel2, (epsys->particles + ptn[n].index)->prev_state.vel);
-
- sub_v3_v3v3(loc, co1, co2);
-
- sub_v3_v3v3(vec, vel1, vel2);
-
- inp = dot_v3v3(vec, vec);
-
- /* velocities not parallel */
- if (inp != 0.0f) {
- t = -dot_v3v3(loc, vec)/inp;
- /* cpa is not too far in the future so investigate further */
- if (t > 0.0f && t < t_min) {
- madd_v3_v3fl(co1, vel1, t);
- madd_v3_v3fl(co2, vel2, t);
-
- sub_v3_v3v3(vec, co2, co1);
-
- len = normalize_v3(vec);
-
- /* distance of cpa is close enough */
- if (len < 2.0f * val->personal_space * pa->size) {
- t_min = t;
-
- mul_v3_fl(vec, len_v3(vel1));
- mul_v3_fl(vec, (2.0f - t)/2.0f);
- sub_v3_v3v3(bbd->wanted_co, vel1, vec);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
- ret = 1;
- }
- }
- }
- }
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
- }
- }
-
-
- if (ptn && nearest==0)
- MEM_freeN(ptn);
-
- return ret;
-}
-static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- KDTreeNearest *ptn = NULL;
- ParticleTarget *pt;
- float len = 2.0f * val->personal_space * pa->size + 1.0f;
- float vec[3] = {0.0f, 0.0f, 0.0f};
- int neighbors = BLI_kdtree_range_search(
- bbd->sim->psys->tree, pa->prev_state.co,
- &ptn, 2.0f * val->personal_space * pa->size);
- int ret = 0;
-
- if (neighbors > 1 && ptn[1].dist!=0.0f) {
- sub_v3_v3v3(vec, pa->prev_state.co, bbd->sim->psys->particles[ptn[1].index].state.co);
- mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[1].dist) / ptn[1].dist);
- add_v3_v3(bbd->wanted_co, vec);
- bbd->wanted_speed = val->max_speed;
- len = ptn[1].dist;
- ret = 1;
- }
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
-
- /* check other boid systems */
- for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
- ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
-
- if (epsys) {
- neighbors = BLI_kdtree_range_search(
- epsys->tree, pa->prev_state.co,
- &ptn, 2.0f * val->personal_space * pa->size);
-
- if (neighbors > 0 && ptn[0].dist < len) {
- sub_v3_v3v3(vec, pa->prev_state.co, ptn[0].co);
- mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[0].dist) / ptn[1].dist);
- add_v3_v3(bbd->wanted_co, vec);
- bbd->wanted_speed = val->max_speed;
- len = ptn[0].dist;
- ret = 1;
- }
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
- }
- }
- return ret;
-}
-static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UNUSED(val), ParticleData *pa)
-{
- KDTreeNearest ptn[11];
- float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
- int neighbors = BLI_kdtree_find_nearest_n__normal(bbd->sim->psys->tree, pa->state.co, pa->prev_state.ave, ptn, 11);
- int n;
- int ret = 0;
-
- if (neighbors > 1) {
- for (n=1; n<neighbors; n++) {
- add_v3_v3(loc, bbd->sim->psys->particles[ptn[n].index].prev_state.co);
- add_v3_v3(vec, bbd->sim->psys->particles[ptn[n].index].prev_state.vel);
- }
-
- mul_v3_fl(loc, 1.0f/((float)neighbors - 1.0f));
- mul_v3_fl(vec, 1.0f/((float)neighbors - 1.0f));
-
- sub_v3_v3(loc, pa->prev_state.co);
- sub_v3_v3(vec, pa->prev_state.vel);
-
- add_v3_v3(bbd->wanted_co, vec);
- add_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
-
- ret = 1;
- }
- return ret;
-}
-static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule;
- float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
- float mul, len;
- int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size;
- int i, ret = 0, p = pa - bbd->sim->psys->particles;
-
- if (flbr->ob) {
- float vec2[3], t;
-
- /* first check we're not blocking the leader */
- sub_v3_v3v3(vec, flbr->loc, flbr->oloc);
- mul_v3_fl(vec, 1.0f/bbd->timestep);
-
- sub_v3_v3v3(loc, pa->prev_state.co, flbr->oloc);
-
- mul = dot_v3v3(vec, vec);
-
- /* leader is not moving */
- if (mul < 0.01f) {
- len = len_v3(loc);
- /* too close to leader */
- if (len < 2.0f * val->personal_space * pa->size) {
- copy_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = val->max_speed;
- return 1;
- }
- }
- else {
- t = dot_v3v3(loc, vec)/mul;
-
- /* possible blocking of leader in near future */
- if (t > 0.0f && t < 3.0f) {
- copy_v3_v3(vec2, vec);
- mul_v3_fl(vec2, t);
-
- sub_v3_v3v3(vec2, loc, vec2);
-
- len = len_v3(vec2);
-
- if (len < 2.0f * val->personal_space * pa->size) {
- copy_v3_v3(bbd->wanted_co, vec2);
- bbd->wanted_speed = val->max_speed * (3.0f - t)/3.0f;
- return 1;
- }
- }
- }
-
- /* not blocking so try to follow leader */
- if (p && flbr->options & BRULE_LEADER_IN_LINE) {
- copy_v3_v3(vec, bbd->sim->psys->particles[p-1].prev_state.vel);
- copy_v3_v3(loc, bbd->sim->psys->particles[p-1].prev_state.co);
- }
- else {
- copy_v3_v3(loc, flbr->oloc);
- sub_v3_v3v3(vec, flbr->loc, flbr->oloc);
- mul_v3_fl(vec, 1.0f/bbd->timestep);
- }
-
- /* fac is seconds behind leader */
- madd_v3_v3fl(loc, vec, -flbr->distance);
-
- sub_v3_v3v3(bbd->wanted_co, loc, pa->prev_state.co);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
-
- ret = 1;
- }
- else if (p % n) {
- float vec2[3], t, t_min = 3.0f;
-
- /* first check we're not blocking any leaders */
- for (i = 0; i< bbd->sim->psys->totpart; i+=n) {
- copy_v3_v3(vec, bbd->sim->psys->particles[i].prev_state.vel);
-
- sub_v3_v3v3(loc, pa->prev_state.co, bbd->sim->psys->particles[i].prev_state.co);
-
- mul = dot_v3v3(vec, vec);
-
- /* leader is not moving */
- if (mul < 0.01f) {
- len = len_v3(loc);
- /* too close to leader */
- if (len < 2.0f * val->personal_space * pa->size) {
- copy_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = val->max_speed;
- return 1;
- }
- }
- else {
- t = dot_v3v3(loc, vec)/mul;
-
- /* possible blocking of leader in near future */
- if (t > 0.0f && t < t_min) {
- copy_v3_v3(vec2, vec);
- mul_v3_fl(vec2, t);
-
- sub_v3_v3v3(vec2, loc, vec2);
-
- len = len_v3(vec2);
-
- if (len < 2.0f * val->personal_space * pa->size) {
- t_min = t;
- copy_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = val->max_speed * (3.0f - t)/3.0f;
- ret = 1;
- }
- }
- }
- }
-
- if (ret) return 1;
-
- /* not blocking so try to follow leader */
- if (flbr->options & BRULE_LEADER_IN_LINE) {
- copy_v3_v3(vec, bbd->sim->psys->particles[p-1].prev_state.vel);
- copy_v3_v3(loc, bbd->sim->psys->particles[p-1].prev_state.co);
- }
- else {
- copy_v3_v3(vec, bbd->sim->psys->particles[p - p%n].prev_state.vel);
- copy_v3_v3(loc, bbd->sim->psys->particles[p - p%n].prev_state.co);
- }
-
- /* fac is seconds behind leader */
- madd_v3_v3fl(loc, vec, -flbr->distance);
-
- sub_v3_v3v3(bbd->wanted_co, loc, pa->prev_state.co);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
-
- ret = 1;
- }
-
- return ret;
-}
-static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidParticle *bpa = pa->boid;
- BoidRuleAverageSpeed *asbr = (BoidRuleAverageSpeed*)rule;
- float vec[3] = {0.0f, 0.0f, 0.0f};
-
- if (asbr->wander > 0.0f) {
- /* abuse pa->r_ave for wandering */
- bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
- bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
- bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
-
- normalize_v3(bpa->wander);
-
- copy_v3_v3(vec, bpa->wander);
-
- mul_qt_v3(pa->prev_state.rot, vec);
-
- copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);
-
- mul_v3_fl(bbd->wanted_co, 1.1f);
-
- add_v3_v3(bbd->wanted_co, vec);
-
- /* leveling */
- if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
- project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
- mul_v3_fl(vec, asbr->level);
- sub_v3_v3(bbd->wanted_co, vec);
- }
- }
- else {
- copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);
-
- /* may happen at birth */
- if (dot_v2v2(bbd->wanted_co, bbd->wanted_co)==0.0f) {
- bbd->wanted_co[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- bbd->wanted_co[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- bbd->wanted_co[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- }
-
- /* leveling */
- if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
- project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
- mul_v3_fl(vec, asbr->level);
- sub_v3_v3(bbd->wanted_co, vec);
- }
-
- }
- bbd->wanted_speed = asbr->speed * val->max_speed;
-
- return 1;
-}
-static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidRuleFight *fbr = (BoidRuleFight*)rule;
- KDTreeNearest *ptn = NULL;
- ParticleTarget *pt;
- ParticleData *epars;
- ParticleData *enemy_pa = NULL;
- BoidParticle *bpa;
- /* friends & enemies */
- float closest_enemy[3] = {0.0f, 0.0f, 0.0f};
- float closest_dist = fbr->distance + 1.0f;
- float f_strength = 0.0f, e_strength = 0.0f;
- float health = 0.0f;
- int n, ret = 0;
-
- /* calculate own group strength */
- int neighbors = BLI_kdtree_range_search(
- bbd->sim->psys->tree, pa->prev_state.co,
- &ptn, fbr->distance);
- for (n=0; n<neighbors; n++) {
- bpa = bbd->sim->psys->particles[ptn[n].index].boid;
- health += bpa->data.health;
- }
-
- f_strength += bbd->part->boids->strength * health;
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
-
- /* add other friendlies and calculate enemy strength and find closest enemy */
- for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
- ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
- if (epsys) {
- epars = epsys->particles;
-
- neighbors = BLI_kdtree_range_search(
- epsys->tree, pa->prev_state.co,
- &ptn, fbr->distance);
-
- health = 0.0f;
-
- for (n=0; n<neighbors; n++) {
- bpa = epars[ptn[n].index].boid;
- health += bpa->data.health;
-
- if (n==0 && pt->mode==PTARGET_MODE_ENEMY && ptn[n].dist < closest_dist) {
- copy_v3_v3(closest_enemy, ptn[n].co);
- closest_dist = ptn[n].dist;
- enemy_pa = epars + ptn[n].index;
- }
- }
- if (pt->mode==PTARGET_MODE_ENEMY)
- e_strength += epsys->part->boids->strength * health;
- else if (pt->mode==PTARGET_MODE_FRIEND)
- f_strength += epsys->part->boids->strength * health;
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
- }
- }
- /* decide action if enemy presence found */
- if (e_strength > 0.0f) {
- sub_v3_v3v3(bbd->wanted_co, closest_enemy, pa->prev_state.co);
-
- /* attack if in range */
- if (closest_dist <= bbd->part->boids->range + pa->size + enemy_pa->size) {
- float damage = BLI_rng_get_float(bbd->rng);
- float enemy_dir[3];
-
- normalize_v3_v3(enemy_dir, bbd->wanted_co);
-
- /* fight mode */
- bbd->wanted_speed = 0.0f;
-
- /* must face enemy to fight */
- if (dot_v3v3(pa->prev_state.ave, enemy_dir)>0.5f) {
- bpa = enemy_pa->boid;
- bpa->data.health -= bbd->part->boids->strength * bbd->timestep * ((1.0f-bbd->part->boids->accuracy)*damage + bbd->part->boids->accuracy);
- }
- }
- else {
- /* approach mode */
- bbd->wanted_speed = val->max_speed;
- }
-
- /* check if boid doesn't want to fight */
- bpa = pa->boid;
- if (bpa->data.health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) {
- /* decide to flee */
- if (closest_dist < fbr->flee_distance * fbr->distance) {
- negate_v3(bbd->wanted_co);
- bbd->wanted_speed = val->max_speed;
- }
- else { /* wait for better odds */
- bbd->wanted_speed = 0.0f;
- }
- }
-
- ret = 1;
- }
-
- return ret;
-}
-
-typedef int (*boid_rule_cb)(BoidRule *rule, BoidBrainData *data, BoidValues *val, ParticleData *pa);
-
-static boid_rule_cb boid_rules[] = {
- rule_none,
- rule_goal_avoid,
- rule_goal_avoid,
- rule_avoid_collision,
- rule_separate,
- rule_flock,
- rule_follow_leader,
- rule_average_speed,
- rule_fight,
- //rule_help,
- //rule_protect,
- //rule_hide,
- //rule_follow_path,
- //rule_follow_wall
-};
-
-static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *pa)
-{
- BoidParticle *bpa = pa->boid;
-
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
- val->max_speed = boids->land_max_speed * bpa->data.health/boids->health;
- val->max_acc = boids->land_max_acc * val->max_speed;
- val->max_ave = boids->land_max_ave * (float)M_PI * bpa->data.health/boids->health;
- val->min_speed = 0.0f; /* no minimum speed on land */
- val->personal_space = boids->land_personal_space;
- val->jump_speed = boids->land_jump_speed * bpa->data.health/boids->health;
- }
- else {
- val->max_speed = boids->air_max_speed * bpa->data.health/boids->health;
- val->max_acc = boids->air_max_acc * val->max_speed;
- val->max_ave = boids->air_max_ave * (float)M_PI * bpa->data.health/boids->health;
- val->min_speed = boids->air_min_speed * boids->air_max_speed;
- val->personal_space = boids->air_personal_space;
- val->jump_speed = 0.0f; /* no jumping in air */
- }
-}
-
-static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float ground_co[3], float ground_nor[3])
-{
- const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
- BoidParticle *bpa = pa->boid;
-
- if (bpa->data.mode == eBoidMode_Climbing) {
- SurfaceModifierData *surmd = NULL;
- float x[3], v[3];
-
- surmd = (SurfaceModifierData *)modifiers_findByType(bpa->ground, eModifierType_Surface );
-
- /* take surface velocity into account */
- closest_point_on_surface(surmd, pa->state.co, x, NULL, v);
- add_v3_v3(x, v);
-
- /* get actual position on surface */
- closest_point_on_surface(surmd, x, ground_co, ground_nor, NULL);
-
- return bpa->ground;
- }
- else {
- float zvec[3] = {0.0f, 0.0f, 2000.0f};
- ParticleCollision col;
- ColliderCache *coll;
- BVHTreeRayHit hit;
- float radius = 0.0f, t, ray_dir[3];
-
- if (!bbd->sim->colliders)
- return NULL;
-
- memset(&col, 0, sizeof(ParticleCollision));
-
- /* first try to find below boid */
- copy_v3_v3(col.co1, pa->state.co);
- sub_v3_v3v3(col.co2, pa->state.co, zvec);
- sub_v3_v3v3(ray_dir, col.co2, col.co1);
- col.f = 0.0f;
- hit.index = -1;
- hit.dist = col.original_ray_length = normalize_v3(ray_dir);
- col.pce.inside = 0;
-
- for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
- col.current = coll->ob;
- col.md = coll->collmd;
- col.fac1 = col.fac2 = 0.f;
-
- if (col.md && col.md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col.md->bvhtree, col.co1, ray_dir, radius, &hit,
- BKE_psys_collision_neartest_cb, &col, raycast_flag);
- }
- }
- /* then use that object */
- if (hit.index>=0) {
- t = hit.dist/col.original_ray_length;
- interp_v3_v3v3(ground_co, col.co1, col.co2, t);
- normalize_v3_v3(ground_nor, col.pce.nor);
- return col.hit;
- }
-
- /* couldn't find below, so find upmost deflector object */
- add_v3_v3v3(col.co1, pa->state.co, zvec);
- sub_v3_v3v3(col.co2, pa->state.co, zvec);
- sub_v3_v3(col.co2, zvec);
- sub_v3_v3v3(ray_dir, col.co2, col.co1);
- col.f = 0.0f;
- hit.index = -1;
- hit.dist = col.original_ray_length = normalize_v3(ray_dir);
-
- for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
- col.current = coll->ob;
- col.md = coll->collmd;
-
- if (col.md && col.md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col.md->bvhtree, col.co1, ray_dir, radius, &hit,
- BKE_psys_collision_neartest_cb, &col, raycast_flag);
- }
- }
- /* then use that object */
- if (hit.index>=0) {
- t = hit.dist/col.original_ray_length;
- interp_v3_v3v3(ground_co, col.co1, col.co2, t);
- normalize_v3_v3(ground_nor, col.pce.nor);
- return col.hit;
- }
-
- /* default to z=0 */
- copy_v3_v3(ground_co, pa->state.co);
- ground_co[2] = 0;
- ground_nor[0] = ground_nor[1] = 0.0f;
- ground_nor[2] = 1.0f;
- return NULL;
- }
-}
-static int boid_rule_applies(ParticleData *pa, BoidSettings *UNUSED(boids), BoidRule *rule)
-{
- BoidParticle *bpa = pa->boid;
-
- if (rule==NULL)
- return 0;
-
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing) && rule->flag & BOIDRULE_ON_LAND)
- return 1;
-
- if (bpa->data.mode==eBoidMode_InAir && rule->flag & BOIDRULE_IN_AIR)
- return 1;
-
- return 0;
-}
-void boids_precalc_rules(ParticleSettings *part, float cfra)
-{
- BoidState *state = part->boids->states.first;
- BoidRule *rule;
- for (; state; state=state->next) {
- for (rule = state->rules.first; rule; rule=rule->next) {
- if (rule->type==eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule;
-
- if (flbr->ob && flbr->cfra != cfra) {
- /* save object locations for velocity calculations */
- copy_v3_v3(flbr->oloc, flbr->loc);
- copy_v3_v3(flbr->loc, flbr->ob->obmat[3]);
- flbr->cfra = cfra;
- }
- }
- }
- }
-}
-static void boid_climb(BoidSettings *boids, ParticleData *pa, float *surface_co, float *surface_nor)
-{
- BoidParticle *bpa = pa->boid;
- float nor[3], vel[3];
- copy_v3_v3(nor, surface_nor);
-
- /* gather apparent gravity */
- madd_v3_v3fl(bpa->gravity, surface_nor, -1.0f);
- normalize_v3(bpa->gravity);
-
- /* raise boid it's size from surface */
- mul_v3_fl(nor, pa->size * boids->height);
- add_v3_v3v3(pa->state.co, surface_co, nor);
-
- /* remove normal component from velocity */
- project_v3_v3v3(vel, pa->state.vel, surface_nor);
- sub_v3_v3v3(pa->state.vel, pa->state.vel, vel);
-}
-static float boid_goal_signed_dist(float *boid_co, float *goal_co, float *goal_nor)
-{
- float vec[3];
-
- sub_v3_v3v3(vec, boid_co, goal_co);
-
- return dot_v3v3(vec, goal_nor);
-}
-/* wanted_co is relative to boid location */
-static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness)
-{
- if (rule==NULL)
- return 0;
-
- if (boid_rule_applies(pa, bbd->part->boids, rule)==0)
- return 0;
-
- if (boid_rules[rule->type](rule, bbd, val, pa)==0)
- return 0;
-
- if (fuzziness < 0.0f || compare_len_v3v3(bbd->wanted_co, pa->prev_state.vel, fuzziness * len_v3(pa->prev_state.vel))==0)
- return 1;
- else
- return 0;
-}
-static BoidState *get_boid_state(BoidSettings *boids, ParticleData *pa)
-{
- BoidState *state = boids->states.first;
- BoidParticle *bpa = pa->boid;
-
- for (; state; state=state->next) {
- if (state->id==bpa->data.state_id)
- return state;
- }
-
- /* for some reason particle isn't at a valid state */
- state = boids->states.first;
- if (state)
- bpa->data.state_id = state->id;
-
- return state;
-}
-//static int boid_condition_is_true(BoidCondition *cond)
-//{
-// /* TODO */
-// return 0;
-//}
-
-/* determines the velocity the boid wants to have */
-void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
-{
- BoidRule *rule;
- BoidSettings *boids = bbd->part->boids;
- BoidValues val;
- BoidState *state = get_boid_state(boids, pa);
- BoidParticle *bpa = pa->boid;
- ParticleSystem *psys = bbd->sim->psys;
- int rand;
- //BoidCondition *cond;
-
- if (bpa->data.health <= 0.0f) {
- pa->alive = PARS_DYING;
- pa->dietime = bbd->cfra;
- return;
- }
-
- //planned for near future
- //cond = state->conditions.first;
- //for (; cond; cond=cond->next) {
- // if (boid_condition_is_true(cond)) {
- // pa->boid->state_id = cond->state_id;
- // state = get_boid_state(boids, pa);
- // break; /* only first true condition is used */
- // }
- //}
-
- zero_v3(bbd->wanted_co);
- bbd->wanted_speed = 0.0f;
-
- /* create random seed for every particle & frame */
- rand = (int)(psys_frand(psys, psys->seed + p) * 1000);
- rand = (int)(psys_frand(psys, (int)bbd->cfra + rand) * 1000);
-
- set_boid_values(&val, bbd->part->boids, pa);
-
- /* go through rules */
- switch (state->ruleset_type) {
- case eBoidRulesetType_Fuzzy:
- {
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (apply_boid_rule(bbd, rule, &val, pa, state->rule_fuzziness))
- break; /* only first nonzero rule that comes through fuzzy rule is applied */
- }
- break;
- }
- case eBoidRulesetType_Random:
- {
- /* use random rule for each particle (always same for same particle though) */
- const int n = BLI_listbase_count(&state->rules);
- if (n) {
- rule = BLI_findlink(&state->rules, rand % n);
- apply_boid_rule(bbd, rule, &val, pa, -1.0);
- }
- break;
- }
- case eBoidRulesetType_Average:
- {
- float wanted_co[3] = {0.0f, 0.0f, 0.0f}, wanted_speed = 0.0f;
- int n = 0;
- for (rule = state->rules.first; rule; rule=rule->next) {
- if (apply_boid_rule(bbd, rule, &val, pa, -1.0f)) {
- add_v3_v3(wanted_co, bbd->wanted_co);
- wanted_speed += bbd->wanted_speed;
- n++;
- zero_v3(bbd->wanted_co);
- bbd->wanted_speed = 0.0f;
- }
- }
-
- if (n > 1) {
- mul_v3_fl(wanted_co, 1.0f/(float)n);
- wanted_speed /= (float)n;
- }
-
- copy_v3_v3(bbd->wanted_co, wanted_co);
- bbd->wanted_speed = wanted_speed;
- break;
- }
-
- }
-
- /* decide on jumping & liftoff */
- if (bpa->data.mode == eBoidMode_OnLand) {
- /* fuzziness makes boids capable of misjudgement */
- float mul = 1.0f + state->rule_fuzziness;
-
- if (boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f) {
- float cvel[3], dir[3];
-
- copy_v3_v3(dir, pa->prev_state.ave);
- normalize_v2(dir);
-
- copy_v3_v3(cvel, bbd->wanted_co);
- normalize_v2(cvel);
-
- if (dot_v2v2(cvel, dir) > 0.95f / mul)
- bpa->data.mode = eBoidMode_Liftoff;
- }
- else if (val.jump_speed > 0.0f) {
- float jump_v[3];
- int jump = 0;
-
- /* jump to get to a location */
- if (bbd->wanted_co[2] > 0.0f) {
- float cvel[3], dir[3];
- float z_v, ground_v, cur_v;
- float len;
-
- copy_v3_v3(dir, pa->prev_state.ave);
- normalize_v2(dir);
-
- copy_v3_v3(cvel, bbd->wanted_co);
- normalize_v2(cvel);
-
- len = len_v2(pa->prev_state.vel);
-
- /* first of all, are we going in a suitable direction? */
- /* or at a suitably slow speed */
- if (dot_v2v2(cvel, dir) > 0.95f / mul || len <= state->rule_fuzziness) {
- /* try to reach goal at highest point of the parabolic path */
- cur_v = len_v2(pa->prev_state.vel);
- z_v = sasqrt(-2.0f * bbd->sim->scene->physics_settings.gravity[2] * bbd->wanted_co[2]);
- ground_v = len_v2(bbd->wanted_co)*sasqrt(-0.5f * bbd->sim->scene->physics_settings.gravity[2] / bbd->wanted_co[2]);
-
- len = sasqrt((ground_v-cur_v)*(ground_v-cur_v) + z_v*z_v);
-
- if (len < val.jump_speed * mul || bbd->part->boids->options & BOID_ALLOW_FLIGHT) {
- jump = 1;
-
- len = MIN2(len, val.jump_speed);
-
- copy_v3_v3(jump_v, dir);
- jump_v[2] = z_v;
- mul_v3_fl(jump_v, ground_v);
-
- normalize_v3(jump_v);
- mul_v3_fl(jump_v, len);
- add_v2_v2v2(jump_v, jump_v, pa->prev_state.vel);
- }
- }
- }
-
- /* jump to go faster */
- if (jump == 0 && val.jump_speed > val.max_speed && bbd->wanted_speed > val.max_speed) {
-
- }
-
- if (jump) {
- copy_v3_v3(pa->prev_state.vel, jump_v);
- bpa->data.mode = eBoidMode_Falling;
- }
- }
- }
-}
-/* tries to realize the wanted velocity taking all constraints into account */
-void boid_body(BoidBrainData *bbd, ParticleData *pa)
-{
- BoidSettings *boids = bbd->part->boids;
- BoidParticle *bpa = pa->boid;
- BoidValues val;
- EffectedPoint epoint;
- float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3];
- float dvec[3], bvec[3];
- float new_dir[3], new_speed;
- float old_dir[3], old_speed;
- float wanted_dir[3];
- float q[4], mat[3][3]; /* rotation */
- float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f};
- float force[3] = {0.0f, 0.0f, 0.0f};
- float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep;
-
- set_boid_values(&val, boids, pa);
-
- /* make sure there's something in new velocity, location & rotation */
- copy_particle_key(&pa->state, &pa->prev_state, 0);
-
- if (bbd->part->flag & PART_SIZEMASS)
- pa_mass*=pa->size;
-
- /* if boids can't fly they fall to the ground */
- if ((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && psys_uses_gravity(bbd->sim))
- bpa->data.mode = eBoidMode_Falling;
-
- if (bpa->data.mode == eBoidMode_Falling) {
- /* Falling boids are only effected by gravity. */
- acc[2] = bbd->sim->scene->physics_settings.gravity[2];
- }
- else {
- /* figure out acceleration */
- float landing_level = 2.0f;
- float level = landing_level + 1.0f;
- float new_vel[3];
-
- if (bpa->data.mode == eBoidMode_Liftoff) {
- bpa->data.mode = eBoidMode_InAir;
- bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
- }
- else if (bpa->data.mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) {
- /* auto-leveling & landing if close to ground */
-
- bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
-
- /* level = how many particle sizes above ground */
- level = (pa->prev_state.co[2] - ground_co[2])/(2.0f * pa->size) - 0.5f;
-
- landing_level = - boids->landing_smoothness * pa->prev_state.vel[2] * pa_mass;
-
- if (pa->prev_state.vel[2] < 0.0f) {
- if (level < 1.0f) {
- bbd->wanted_co[0] = bbd->wanted_co[1] = bbd->wanted_co[2] = 0.0f;
- bbd->wanted_speed = 0.0f;
- bpa->data.mode = eBoidMode_Falling;
- }
- else if (level < landing_level) {
- bbd->wanted_speed *= (level - 1.0f)/landing_level;
- bbd->wanted_co[2] *= (level - 1.0f)/landing_level;
- }
- }
- }
-
- copy_v3_v3(old_dir, pa->prev_state.ave);
- new_speed = normalize_v3_v3(wanted_dir, bbd->wanted_co);
-
- /* first check if we have valid direction we want to go towards */
- if (new_speed == 0.0f) {
- copy_v3_v3(new_dir, old_dir);
- }
- else {
- float old_dir2[2], wanted_dir2[2], nor[3], angle;
- copy_v2_v2(old_dir2, old_dir);
- normalize_v2(old_dir2);
- copy_v2_v2(wanted_dir2, wanted_dir);
- normalize_v2(wanted_dir2);
-
- /* choose random direction to turn if wanted velocity */
- /* is directly behind regardless of z-coordinate */
- if (dot_v2v2(old_dir2, wanted_dir2) < -0.99f) {
- wanted_dir[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- wanted_dir[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- wanted_dir[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- normalize_v3(wanted_dir);
- }
-
- /* constrain direction with maximum angular velocity */
- angle = saacos(dot_v3v3(old_dir, wanted_dir));
- angle = min_ff(angle, val.max_ave);
-
- cross_v3_v3v3(nor, old_dir, wanted_dir);
- axis_angle_to_quat(q, nor, angle);
- copy_v3_v3(new_dir, old_dir);
- mul_qt_v3(q, new_dir);
- normalize_v3(new_dir);
-
- /* save direction in case resulting velocity too small */
- axis_angle_to_quat(q, nor, angle*dtime);
- copy_v3_v3(pa->state.ave, old_dir);
- mul_qt_v3(q, pa->state.ave);
- normalize_v3(pa->state.ave);
- }
-
- /* constrain speed with maximum acceleration */
- old_speed = len_v3(pa->prev_state.vel);
-
- if (bbd->wanted_speed < old_speed)
- new_speed = MAX2(bbd->wanted_speed, old_speed - val.max_acc);
- else
- new_speed = MIN2(bbd->wanted_speed, old_speed + val.max_acc);
-
- /* combine direction and speed */
- copy_v3_v3(new_vel, new_dir);
- mul_v3_fl(new_vel, new_speed);
-
- /* maintain minimum flying velocity if not landing */
- if (level >= landing_level) {
- float len2 = dot_v2v2(new_vel, new_vel);
- float root;
-
- len2 = MAX2(len2, val.min_speed*val.min_speed);
- root = sasqrt(new_speed*new_speed - len2);
-
- new_vel[2] = new_vel[2] < 0.0f ? -root : root;
-
- normalize_v2(new_vel);
- mul_v2_fl(new_vel, sasqrt(len2));
- }
-
- /* finally constrain speed to max speed */
- new_speed = normalize_v3(new_vel);
- mul_v3_fl(new_vel, MIN2(new_speed, val.max_speed));
-
- /* get acceleration from difference of velocities */
- sub_v3_v3v3(acc, new_vel, pa->prev_state.vel);
-
- /* break acceleration to components */
- project_v3_v3v3(tan_acc, acc, pa->prev_state.ave);
- sub_v3_v3v3(nor_acc, acc, tan_acc);
- }
-
- /* account for effectors */
- pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
- pdDoEffectors(bbd->sim->psys->effectors, bbd->sim->colliders, bbd->part->effector_weights, &epoint, force, NULL);
-
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
- float length = normalize_v3(force);
-
- length = MAX2(0.0f, length - boids->land_stick_force);
-
- mul_v3_fl(force, length);
- }
-
- add_v3_v3(acc, force);
-
- /* store smoothed acceleration for nice banking etc. */
- madd_v3_v3fl(bpa->data.acc, acc, dtime);
- mul_v3_fl(bpa->data.acc, 1.0f / (1.0f + dtime));
-
- /* integrate new location & velocity */
-
- /* by regarding the acceleration as a force at this stage we*/
- /* can get better control allthough it's a bit unphysical */
- mul_v3_fl(acc, 1.0f/pa_mass);
-
- copy_v3_v3(dvec, acc);
- mul_v3_fl(dvec, dtime*dtime*0.5f);
-
- copy_v3_v3(bvec, pa->prev_state.vel);
- mul_v3_fl(bvec, dtime);
- add_v3_v3(dvec, bvec);
- add_v3_v3(pa->state.co, dvec);
-
- madd_v3_v3fl(pa->state.vel, acc, dtime);
-
- //if (bpa->data.mode != eBoidMode_InAir)
- bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
-
- /* change modes, constrain movement & keep track of down vector */
- switch (bpa->data.mode) {
- case eBoidMode_InAir:
- {
- float grav[3];
-
- grav[0] = 0.0f;
- grav[1] = 0.0f;
- grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
-
- /* don't take forward acceleration into account (better banking) */
- if (dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) {
- project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
- sub_v3_v3v3(dvec, bpa->data.acc, dvec);
- }
- else {
- copy_v3_v3(dvec, bpa->data.acc);
- }
-
- /* gather apparent gravity */
- madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
- normalize_v3(bpa->gravity);
-
- /* stick boid on goal when close enough */
- if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
- bpa->data.mode = eBoidMode_Climbing;
- bpa->ground = bbd->goal_ob;
- boid_find_ground(bbd, pa, ground_co, ground_nor);
- boid_climb(boids, pa, ground_co, ground_nor);
- }
- else if (pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
- /* land boid when below ground */
- if (boids->options & BOID_ALLOW_LAND) {
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- bpa->data.mode = eBoidMode_OnLand;
- }
- /* fly above ground */
- else if (bpa->ground) {
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- }
- }
- break;
- }
- case eBoidMode_Falling:
- {
- float grav[3];
-
- grav[0] = 0.0f;
- grav[1] = 0.0f;
- grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
-
-
- /* gather apparent gravity */
- madd_v3_v3fl(bpa->gravity, grav, dtime);
- normalize_v3(bpa->gravity);
-
- if (boids->options & BOID_ALLOW_LAND) {
- /* stick boid on goal when close enough */
- if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
- bpa->data.mode = eBoidMode_Climbing;
- bpa->ground = bbd->goal_ob;
- boid_find_ground(bbd, pa, ground_co, ground_nor);
- boid_climb(boids, pa, ground_co, ground_nor);
- }
- /* land boid when really near ground */
- else if (pa->state.co[2] <= ground_co[2] + 1.01f * pa->size * boids->height) {
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- bpa->data.mode = eBoidMode_OnLand;
- }
- /* if we're falling, can fly and want to go upwards lets fly */
- else if (boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f)
- bpa->data.mode = eBoidMode_InAir;
- }
- else
- bpa->data.mode = eBoidMode_InAir;
- break;
- }
- case eBoidMode_Climbing:
- {
- boid_climb(boids, pa, ground_co, ground_nor);
- //float nor[3];
- //copy_v3_v3(nor, ground_nor);
-
- ///* gather apparent gravity to r_ve */
- //madd_v3_v3fl(pa->r_ve, ground_nor, -1.0);
- //normalize_v3(pa->r_ve);
-
- ///* raise boid it's size from surface */
- //mul_v3_fl(nor, pa->size * boids->height);
- //add_v3_v3v3(pa->state.co, ground_co, nor);
-
- ///* remove normal component from velocity */
- //project_v3_v3v3(v, pa->state.vel, ground_nor);
- //sub_v3_v3v3(pa->state.vel, pa->state.vel, v);
- break;
- }
- case eBoidMode_OnLand:
- {
- /* stick boid on goal when close enough */
- if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
- bpa->data.mode = eBoidMode_Climbing;
- bpa->ground = bbd->goal_ob;
- boid_find_ground(bbd, pa, ground_co, ground_nor);
- boid_climb(boids, pa, ground_co, ground_nor);
- }
- /* ground is too far away so boid falls */
- else if (pa->state.co[2]-ground_co[2] > 1.1f * pa->size * boids->height)
- bpa->data.mode = eBoidMode_Falling;
- else {
- /* constrain to surface */
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- }
-
- if (boids->banking > 0.0f) {
- float grav[3];
- /* Don't take gravity's strength in to account, */
- /* otherwise amount of banking is hard to control. */
- negate_v3_v3(grav, ground_nor);
-
- project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
- sub_v3_v3v3(dvec, bpa->data.acc, dvec);
-
- /* gather apparent gravity */
- madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
- normalize_v3(bpa->gravity);
- }
- else {
- /* gather negative surface normal */
- madd_v3_v3fl(bpa->gravity, ground_nor, -1.0f);
- normalize_v3(bpa->gravity);
- }
- break;
- }
- }
-
- /* save direction to state.ave unless the boid is falling */
- /* (boids can't effect their direction when falling) */
- if (bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1f*pa->size) {
- copy_v3_v3(pa->state.ave, pa->state.vel);
- pa->state.ave[2] *= bbd->part->boids->pitch;
- normalize_v3(pa->state.ave);
- }
-
- /* apply damping */
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing))
- mul_v3_fl(pa->state.vel, 1.0f - 0.2f*bbd->part->dampfac);
-
- /* calculate rotation matrix based on forward & down vectors */
- if (bpa->data.mode == eBoidMode_InAir) {
- copy_v3_v3(mat[0], pa->state.ave);
-
- project_v3_v3v3(dvec, bpa->gravity, pa->state.ave);
- sub_v3_v3v3(mat[2], bpa->gravity, dvec);
- normalize_v3(mat[2]);
- }
- else {
- project_v3_v3v3(dvec, pa->state.ave, bpa->gravity);
- sub_v3_v3v3(mat[0], pa->state.ave, dvec);
- normalize_v3(mat[0]);
-
- copy_v3_v3(mat[2], bpa->gravity);
- }
- negate_v3(mat[2]);
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
-
- /* apply rotation */
- mat3_to_quat_is_ok(q, mat);
- copy_qt_qt(pa->state.rot, q);
-}
-
-BoidRule *boid_new_rule(int type)
-{
- BoidRule *rule = NULL;
- if (type <= 0)
- return NULL;
-
- switch (type) {
- case eBoidRuleType_Goal:
- case eBoidRuleType_Avoid:
- rule = MEM_callocN(sizeof(BoidRuleGoalAvoid), "BoidRuleGoalAvoid");
- break;
- case eBoidRuleType_AvoidCollision:
- rule = MEM_callocN(sizeof(BoidRuleAvoidCollision), "BoidRuleAvoidCollision");
- ((BoidRuleAvoidCollision*)rule)->look_ahead = 2.0f;
- break;
- case eBoidRuleType_FollowLeader:
- rule = MEM_callocN(sizeof(BoidRuleFollowLeader), "BoidRuleFollowLeader");
- ((BoidRuleFollowLeader*)rule)->distance = 1.0f;
- break;
- case eBoidRuleType_AverageSpeed:
- rule = MEM_callocN(sizeof(BoidRuleAverageSpeed), "BoidRuleAverageSpeed");
- ((BoidRuleAverageSpeed*)rule)->speed = 0.5f;
- break;
- case eBoidRuleType_Fight:
- rule = MEM_callocN(sizeof(BoidRuleFight), "BoidRuleFight");
- ((BoidRuleFight*)rule)->distance = 100.0f;
- ((BoidRuleFight*)rule)->flee_distance = 100.0f;
- break;
- default:
- rule = MEM_callocN(sizeof(BoidRule), "BoidRule");
- break;
- }
-
- rule->type = type;
- rule->flag |= BOIDRULE_IN_AIR|BOIDRULE_ON_LAND;
-// BLI_strncpy(rule->name, rna_enum_boidrule_type_items[type-1].name, sizeof(rule->name));
- rule->name[0] = '\0';
-
- return rule;
-}
-void boid_default_settings(BoidSettings *boids)
-{
- boids->air_max_speed = 10.0f;
- boids->air_max_acc = 0.5f;
- boids->air_max_ave = 0.5f;
- boids->air_personal_space = 1.0f;
-
- boids->land_max_speed = 5.0f;
- boids->land_max_acc = 0.5f;
- boids->land_max_ave = 0.5f;
- boids->land_personal_space = 1.0f;
-
- boids->options = BOID_ALLOW_FLIGHT;
-
- boids->landing_smoothness = 3.0f;
- boids->banking = 1.0f;
- boids->pitch = 1.0f;
- boids->height = 1.0f;
-
- boids->health = 1.0f;
- boids->accuracy = 1.0f;
- boids->aggression = 2.0f;
- boids->range = 1.0f;
- boids->strength = 0.1f;
-}
-
-BoidState *boid_new_state(BoidSettings *boids)
-{
- BoidState *state = MEM_callocN(sizeof(BoidState), "BoidState");
-
- state->id = boids->last_state_id++;
- if (state->id)
- BLI_snprintf(state->name, sizeof(state->name), "State %i", state->id);
- else
- strcpy(state->name, "State");
-
- state->rule_fuzziness = 0.5;
- state->volume = 1.0f;
- state->channels |= ~0;
-
- return state;
-}
-
-BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state)
-{
- BoidState *staten = MEM_dupallocN(state);
-
- BLI_duplicatelist(&staten->rules, &state->rules);
- BLI_duplicatelist(&staten->conditions, &state->conditions);
- BLI_duplicatelist(&staten->actions, &state->actions);
-
- staten->id = boids->last_state_id++;
-
- return staten;
-}
-void boid_free_settings(BoidSettings *boids)
-{
- if (boids) {
- BoidState *state = boids->states.first;
-
- for (; state; state=state->next) {
- BLI_freelistN(&state->rules);
- BLI_freelistN(&state->conditions);
- BLI_freelistN(&state->actions);
- }
-
- BLI_freelistN(&boids->states);
-
- MEM_freeN(boids);
- }
-}
-BoidSettings *boid_copy_settings(BoidSettings *boids)
-{
- BoidSettings *nboids = NULL;
-
- if (boids) {
- BoidState *state;
- BoidState *nstate;
-
- nboids = MEM_dupallocN(boids);
-
- BLI_duplicatelist(&nboids->states, &boids->states);
-
- state = boids->states.first;
- nstate = nboids->states.first;
- for (; state; state=state->next, nstate=nstate->next) {
- BLI_duplicatelist(&nstate->rules, &state->rules);
- BLI_duplicatelist(&nstate->conditions, &state->conditions);
- BLI_duplicatelist(&nstate->actions, &state->actions);
- }
- }
-
- return nboids;
-}
-BoidState *boid_get_current_state(BoidSettings *boids)
-{
- BoidState *state = boids->states.first;
-
- for (; state; state=state->next) {
- if (state->flag & BOIDSTATE_CURRENT)
- break;
- }
-
- return state;
-}
-
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index a029c8c7748..c2f64011e2e 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -53,6 +53,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
@@ -76,7 +77,6 @@
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -462,26 +462,6 @@ static void check_and_create_collision_relation(DagForest *dag, Object *ob, DagN
static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield, bool no_collision)
{
Base *base;
- ParticleSystem *particle_system;
-
- for (particle_system = ob->particlesystem.first;
- particle_system;
- particle_system = particle_system->next)
- {
- EffectorWeights *effector_weights = particle_system->part->effector_weights;
- if (effector_weights->group) {
- GroupObject *group_object;
-
- for (group_object = effector_weights->group->gobject.first;
- group_object;
- group_object = group_object->next)
- {
- if ((group_object->ob->lay & ob->lay)) {
- check_and_create_collision_relation(dag, ob, node, group_object->ob, skip_forcefield, no_collision);
- }
- }
- }
- }
/* would be nice to have a list of colliders here
* so for now walk all objects in scene check 'same layer rule' */
@@ -500,7 +480,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
DagNode *node2;
DagNode *node3;
Key *key;
- ParticleSystem *psys;
int addtoroot = 1;
node = dag_get_node(dag, ob);
@@ -752,87 +731,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
dag_add_lamp_driver_relations(dag, node, ob->data);
}
- /* particles */
- psys = ob->particlesystem.first;
- if (psys) {
- GroupObject *go;
-
- for (; psys; psys = psys->next) {
- BoidRule *rule = NULL;
- BoidState *state = NULL;
- ParticleSettings *part = psys->part;
- ListBase *effectors = NULL;
- EffectorCache *eff;
-
- if (part->adt) {
- dag_add_driver_relation(part->adt, dag, node, 1);
- }
-
- dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
-
- if (!psys_check_enabled(ob, psys))
- continue;
-
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt = pt->next) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-
- effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false);
-
- if (effectors) {
- for (eff = effectors->first; eff; eff = eff->next) {
- if (eff->psys) {
- node2 = dag_get_node(dag, eff->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Field");
- }
- }
- }
-
- pdEndEffectors(&effectors);
-
- if (part->boids) {
- for (state = part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
- if (ruleob) {
- node2 = dag_get_node(dag, ruleob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
- }
- }
- }
- }
- }
- }
-
/* object constraints */
for (con = ob->constraints.first; con; con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@@ -2249,17 +2147,6 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
ob->recalc |= OB_RECALC_DATA;
adt->recalc |= ADT_RECALC_ANIM;
}
-
- if (ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
- if (psys_check_enabled(ob, psys)) {
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
- }
- }
}
if (ob->recalc & OB_RECALC_OB)
@@ -2610,30 +2497,6 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
obt->recalc |= OB_RECALC_DATA;
lib_id_recalc_data_tag(bmain, &obt->id);
}
-
- /* particle settings can use the texture as well */
- if (obt->particlesystem.first) {
- ParticleSystem *psys = obt->particlesystem.first;
- MTex **mtexp, *mtex;
- int a;
- for (; psys; psys = psys->next) {
- mtexp = psys->part->mtex;
- for (a = 0; a < MAX_MTEX; a++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex == (Tex *)id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
-
- if (mtex->mapto & PAMAP_INIT)
- psys->recalc |= PSYS_RECALC_RESET;
- if (mtex->mapto & PAMAP_CHILD)
- psys->recalc |= PSYS_RECALC_CHILD;
-
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- }
}
}
@@ -2650,15 +2513,6 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
}
}
- /* set flags based on particle settings */
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (obt = bmain->object.first; obt; obt = obt->id.next)
- for (psys = obt->particlesystem.first; psys; psys = psys->next)
- if (&psys->part->id == id)
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
-
if (ELEM(idtype, ID_MA, ID_TE)) {
obt = sce->basact ? sce->basact->object : NULL;
if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
@@ -2934,7 +2788,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
if (flag) {
if (flag & OB_RECALC_OB)
lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
+ if (flag & OB_RECALC_DATA)
lib_id_recalc_data_tag(bmain, id);
}
else
@@ -2950,20 +2804,6 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
ob = (Object *)id;
ob->recalc |= (flag & OB_RECALC_ALL);
}
- else if (idtype == ID_PA) {
- ParticleSystem *psys;
- /* this is weak still, should be done delayed as well */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (&psys->part->id == id) {
- ob->recalc |= (flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- lib_id_recalc_tag(bmain, &ob->id);
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
- }
- }
else {
/* disable because this is called on various ID types automatically.
* where printing warning is not useful. for now just ignore */
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index dbf095d3832..b968f78077b 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -66,7 +66,6 @@
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
@@ -566,7 +565,7 @@ static int boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, float dist)
}
/* check whether bounds intersects a point with given radius */
-static int boundIntersectPoint(Bounds3D *b, float point[3], float radius)
+static int UNUSED_FUNCTION(boundIntersectPoint)(Bounds3D *b, float point[3], float radius)
{
int i = 2;
if (!b->valid) return 0;
@@ -3532,252 +3531,6 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
return 1;
}
-/*
- * Paint a particle system to the surface
- */
-static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
- ParticleSystem *psys,
- DynamicPaintBrushSettings *brush,
- float timescale)
-{
- ParticleSettings *part = psys->part;
- PaintSurfaceData *sData = surface->data;
- PaintBakeData *bData = sData->bData;
- VolumeGrid *grid = bData->grid;
-
- KDTree *tree;
- int particlesAdded = 0;
- int invalidParticles = 0;
- int p = 0;
-
- float solidradius = surface->radius_scale * ((brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius);
- float smooth = brush->particle_smooth * surface->radius_scale;
-
- float range = solidradius + smooth;
- float particle_timestep = 0.04f * part->timetweak;
-
- Bounds3D part_bb = {0};
-
- if (psys->totpart < 1) return 1;
-
- /*
- * Build a kd-tree to optimize distance search
- */
- tree = BLI_kdtree_new(psys->totpart);
-
- /* loop through particles and insert valid ones to the tree */
- p = 0;
- for (ParticleData *pa = psys->particles; p < psys->totpart; p++, pa++) {
-
- /* Proceed only if particle is active */
- if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) continue;
- else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) continue;
- else if (pa->flag & PARS_UNEXIST) continue;
-
- /* for debug purposes check if any NAN particle proceeds
- * For some reason they get past activity check, this should rule most of them out */
- if (isnan(pa->state.co[0]) || isnan(pa->state.co[1]) || isnan(pa->state.co[2])) { invalidParticles++; continue; }
-
- /* make sure particle is close enough to canvas */
- if (!boundIntersectPoint(&grid->grid_bounds, pa->state.co, range)) continue;
-
- BLI_kdtree_insert(tree, p, pa->state.co);
-
- /* calc particle system bounds */
- boundInsert(&part_bb, pa->state.co);
-
- particlesAdded++;
- }
- if (invalidParticles)
- printf("Warning: Invalid particle(s) found!\n");
-
- /* If no suitable particles were found, exit */
- if (particlesAdded < 1) {
- BLI_kdtree_free(tree);
- return 1;
- }
-
- /* begin thread safe malloc */
- BLI_begin_threaded_malloc();
-
- /* only continue if particle bb is close enough to canvas bb */
- if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) {
- int c_index;
- int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
-
- /* balance tree */
- BLI_kdtree_balance(tree);
-
- /* loop through space partitioning grid */
- for (c_index = 0; c_index < total_cells; c_index++) {
- int id;
-
- /* check cell bounding box */
- if (!grid->s_num[c_index] ||
- !boundsIntersectDist(&grid->bounds[c_index], &part_bb, range))
- {
- continue;
- }
-
- /* loop through cell points */
-#pragma omp parallel for schedule(static)
- for (id = 0; id < grid->s_num[c_index]; id++) {
- int index = grid->t_index[grid->s_pos[c_index] + id];
- float disp_intersect = 0.0f;
- float radius = 0.0f;
- float strength = 0.0f;
- float velocity_val = 0.0f;
- int part_index = -1;
-
- /*
- * With predefined radius, there is no variation between particles.
- * It's enough to just find the nearest one.
- */
- {
- KDTreeNearest nearest;
- float smooth_range, part_solidradius;
-
- /* Find nearest particle and get distance to it */
- BLI_kdtree_find_nearest(tree, bData->realCoord[bData->s_pos[index]].v, &nearest);
- /* if outside maximum range, no other particle can influence either */
- if (nearest.dist > range) continue;
-
- if (brush->flags & MOD_DPAINT_PART_RAD) {
- /* use particles individual size */
- ParticleData *pa = psys->particles + nearest.index;
- part_solidradius = pa->size;
- }
- else {
- part_solidradius = solidradius;
- }
- radius = part_solidradius + smooth;
- if (nearest.dist < radius) {
- /* distances inside solid radius has maximum influence -> dist = 0 */
- smooth_range = (nearest.dist - part_solidradius);
- if (smooth_range < 0.0f) smooth_range = 0.0f;
- /* do smoothness if enabled */
- if (smooth) smooth_range /= smooth;
-
- strength = 1.0f - smooth_range;
- disp_intersect = radius - nearest.dist;
- part_index = nearest.index;
- }
- }
- /* If using random per particle radius and closest particle didn't give max influence */
- if (brush->flags & MOD_DPAINT_PART_RAD && strength < 1.0f && psys->part->randsize > 0.0f) {
- /*
- * If we use per particle radius, we have to sample all particles
- * within max radius range
- */
- KDTreeNearest *nearest;
-
- int n, particles;
- float smooth_range = smooth * (1.0f - strength), dist;
- /* calculate max range that can have particles with higher influence than the nearest one */
- float max_range = smooth - strength * smooth + solidradius;
- /* Make gcc happy! */
- dist = max_range;
-
- particles = BLI_kdtree_range_search(tree, bData->realCoord[bData->s_pos[index]].v,
- &nearest, max_range);
-
- /* Find particle that produces highest influence */
- for (n = 0; n < particles; n++) {
- ParticleData *pa = psys->particles + nearest[n].index;
- float s_range;
-
- /* skip if out of range */
- if (nearest[n].dist > (pa->size + smooth))
- continue;
-
- /* update hit data */
- s_range = nearest[n].dist - pa->size;
- /* skip if higher influence is already found */
- if (smooth_range < s_range)
- continue;
-
- /* update hit data */
- smooth_range = s_range;
- dist = nearest[n].dist;
- part_index = nearest[n].index;
-
- /* If inside solid range and no disp depth required, no need to seek further */
- if ( (s_range < 0.0f) &&
- (surface->type != MOD_DPAINT_SURFACE_T_DISPLACE) &&
- (surface->type != MOD_DPAINT_SURFACE_T_WAVE))
- {
- break;
- }
- }
-
- if (nearest) MEM_freeN(nearest);
-
- /* now calculate influence for this particle */
- {
- float rad = radius + smooth, str;
- if ((rad - dist) > disp_intersect) {
- disp_intersect = radius - dist;
- radius = rad;
- }
-
- /* do smoothness if enabled */
- if (smooth_range < 0.0f) smooth_range = 0.0f;
- if (smooth) smooth_range /= smooth;
- str = 1.0f - smooth_range;
- /* if influence is greater, use this one */
- if (str > strength) strength = str;
- }
- }
-
- if (strength > 0.001f) {
- float paintColor[4] = {0.0f};
- float depth = 0.0f;
-
- /* apply velocity */
- if ((brush->flags & MOD_DPAINT_USES_VELOCITY) && (part_index != -1)) {
- float velocity[3];
- ParticleData *pa = psys->particles + part_index;
- mul_v3_v3fl(velocity, pa->state.vel, particle_timestep);
-
- /* substract canvas point velocity */
- if (bData->velocity) {
- sub_v3_v3(velocity, bData->velocity[index].v);
- }
- velocity_val = len_v3(velocity);
-
- /* store brush velocity for smudge */
- if ( (surface->type == MOD_DPAINT_SURFACE_T_PAINT) &&
- (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity))
- {
- copy_v3_v3(&bData->brush_velocity[index * 4], velocity);
- mul_v3_fl(&bData->brush_velocity[index * 4], 1.0f / velocity_val);
- bData->brush_velocity[index * 4 + 3] = velocity_val;
- }
- }
-
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- copy_v3_v3(paintColor, &brush->r);
- }
- else if ( (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) ||
- (surface->type == MOD_DPAINT_SURFACE_T_WAVE))
- {
- /* get displace depth */
- disp_intersect = (1.0f - sqrtf(disp_intersect / radius)) * radius;
- depth = (radius - disp_intersect) / bData->bNormal[index].normal_scale;
- if (depth < 0.0f) depth = 0.0f;
- }
-
- dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
- }
- }
- }
- }
- BLI_end_threaded_malloc();
- BLI_kdtree_free(tree);
-
- return 1;
-}
-
/* paint a single point of defined proximity radius to the surface */
static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
@@ -4869,14 +4622,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* Apply brush on the surface depending on it's collision type */
/* Particle brush: */
if (brush->collision == MOD_DPAINT_COL_PSYS) {
- if (brush->psys && brush->psys->part && ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) &&
- psys_check_enabled(brushObj, brush->psys))
- {
-
- /* Paint a particle system */
- BKE_animsys_evaluate_animdata(scene, &brush->psys->part->id, brush->psys->part->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
- dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
- }
}
/* Object center distance: */
else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 12bce70594b..c845bb57ff9 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -67,7 +67,6 @@
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_smoke.h"
@@ -178,33 +177,9 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector
BLI_addtail(*effectors, eff);
}
-static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src)
-{
- ParticleSettings *part= psys->part;
-
- if ( !psys_check_enabled(ob, psys) )
- return;
-
- if ( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0)
- return;
-
- if ( part->pd && part->pd->forcefield && weights->weight[part->pd->forcefield] != 0.0f) {
- if (*effectors == NULL)
- *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
-
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd));
- }
-
- if (part->pd2 && part->pd2->forcefield && weights->weight[part->pd2->forcefield] != 0.0f) {
- if (*effectors == NULL)
- *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
-
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2));
- }
-}
/* returns ListBase handle with objects taking part in the effecting */
-ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
+ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *UNUSED(psys_src),
EffectorWeights *weights, bool precalc)
{
Base *base;
@@ -218,13 +193,6 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
if ( (go->ob->lay & layer) ) {
if ( go->ob->pd && go->ob->pd->forcefield )
add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src);
-
- if ( go->ob->particlesystem.first ) {
- ParticleSystem *psys= go->ob->particlesystem.first;
-
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src);
- }
}
}
}
@@ -233,13 +201,6 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
if ( (base->lay & layer) ) {
if ( base->object->pd && base->object->pd->forcefield )
add_object_to_effectors(&effectors, scene, weights, base->object, ob_src);
-
- if ( base->object->particlesystem.first ) {
- ParticleSystem *psys= base->object->particlesystem.first;
-
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src);
- }
}
}
}
@@ -292,8 +253,6 @@ static void precalculate_effector(EffectorCache *eff)
if (eff->ob->type == OB_CURVE)
eff->flag |= PE_USE_NORMAL_DATA;
}
- else if (eff->psys)
- psys_update_particle_tree(eff->psys, eff->scene->r.cfra);
/* Store object velocity */
if (eff->ob) {
@@ -316,36 +275,6 @@ void pdPrecalculateEffectors(ListBase *effectors)
}
-void pd_point_from_particle(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, EffectedPoint *point)
-{
- ParticleSettings *part = sim->psys->part;
- point->loc = state->co;
- point->vel = state->vel;
- point->index = pa - sim->psys->particles;
- point->size = pa->size;
- point->charge = 0.0f;
-
- if (part->pd && part->pd->forcefield == PFIELD_CHARGE)
- point->charge += part->pd->f_strength;
-
- if (part->pd2 && part->pd2->forcefield == PFIELD_CHARGE)
- point->charge += part->pd2->f_strength;
-
- point->vel_to_sec = 1.0f;
- point->vel_to_frame = psys_get_timestep(sim);
-
- point->flag = 0;
-
- if (sim->psys->part->flag & PART_ROT_DYN) {
- point->ave = state->ave;
- point->rot = state->rot;
- }
- else
- point->ave = point->rot = NULL;
-
- point->psys = sim->psys;
-}
-
void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
{
point->loc = loc;
@@ -563,7 +492,6 @@ int closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], floa
}
int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int real_velocity)
{
- float cfra = eff->scene->r.cfra;
int ret = 0;
if (eff->pd && eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) {
@@ -598,43 +526,6 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
ret = 1;
}
}
- else if (eff->psys) {
- ParticleData *pa = eff->psys->particles + *efd->index;
- ParticleKey state;
-
- /* exclude the particle itself for self effecting particles */
- if (eff->psys == point->psys && *efd->index == point->index) {
- /* pass */
- }
- else {
- ParticleSimulationData sim= {NULL};
- sim.scene= eff->scene;
- sim.ob= eff->ob;
- sim.psys= eff->psys;
-
- /* TODO: time from actual previous calculated frame (step might not be 1) */
- state.time = cfra - 1.0f;
- ret = psys_get_particle_state(&sim, *efd->index, &state, 0);
-
- /* TODO */
- //if (eff->pd->forcefiled == PFIELD_HARMONIC && ret==0) {
- // if (pa->dietime < eff->psys->cfra)
- // eff->flag |= PE_VELOCITY_TO_IMPULSE;
- //}
-
- copy_v3_v3(efd->loc, state.co);
-
- /* rather than use the velocity use rotated x-axis (defaults to velocity) */
- efd->nor[0] = 1.f;
- efd->nor[1] = efd->nor[2] = 0.f;
- mul_qt_v3(state.rot, efd->nor);
-
- if (real_velocity)
- copy_v3_v3(efd->vel, state.vel);
-
- efd->size = pa->size;
- }
- }
else {
/* use center of object for distance calculus */
const Object *ob = eff->ob;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 895d215ca91..be04b97bb47 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -108,7 +108,6 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_packedFile.h"
#include "BKE_speaker.h"
#include "BKE_sound.h"
@@ -348,9 +347,6 @@ bool id_make_local(ID *id, bool test)
case ID_BR:
if (!test) BKE_brush_make_local((Brush *)id);
return true;
- case ID_PA:
- if (!test) BKE_particlesettings_make_local((ParticleSettings *)id);
- return true;
case ID_WM:
return false; /* can't be linked */
case ID_GD:
@@ -443,9 +439,6 @@ bool id_copy(ID *id, ID **newid, bool test)
case ID_BR:
if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id);
return true;
- case ID_PA:
- if (!test) *newid = (ID *)BKE_particlesettings_copy((ParticleSettings *)id);
- return true;
case ID_WM:
return false; /* can't be copied from here */
case ID_GD:
@@ -840,9 +833,6 @@ void *BKE_libblock_alloc_notest(short type)
case ID_BR:
id = MEM_callocN(sizeof(Brush), "brush");
break;
- case ID_PA:
- id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings");
- break;
case ID_WM:
id = MEM_callocN(sizeof(wmWindowManager), "Window manager");
break;
@@ -1261,9 +1251,6 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
case ID_BR:
BKE_brush_free((Brush *)id);
break;
- case ID_PA:
- BKE_particlesettings_free((ParticleSettings *)id);
- break;
case ID_WM:
if (free_windowmanager_cb)
free_windowmanager_cb(NULL, (wmWindowManager *)id);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index d29d2191602..2b81f899719 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -49,6 +49,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_force.h"
+#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sensor_types.h"
@@ -70,7 +71,6 @@
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sca.h"
#include "BKE_sequencer.h"
@@ -162,15 +162,6 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID
FOREACH_FINALIZE_VOID;
}
-static void library_foreach_particlesystemsObjectLooper(
- ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cd_flag)
-{
- LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
-
- FOREACH_FINALIZE_VOID;
-}
-
static void library_foreach_sensorsObjectLooper(
bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cd_flag)
{
@@ -367,7 +358,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_OB:
{
Object *object = (Object *) id;
- ParticleSystem *psys;
/* object data special case */
if (object->type == OB_EMPTY) {
@@ -422,10 +412,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data);
BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, &data);
- for (psys = object->particlesystem.first; psys; psys = psys->next) {
- BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data);
- }
-
BKE_sca_sensors_id_loop(&object->sensors, library_foreach_sensorsObjectLooper, &data);
BKE_sca_controllers_id_loop(&object->controllers, library_foreach_controllersObjectLooper, &data);
BKE_sca_actuators_id_loop(&object->actuators, library_foreach_actuatorsObjectLooper, &data);
@@ -591,44 +577,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
break;
}
- case ID_PA:
- {
- ParticleSettings *psett = (ParticleSettings *) id;
- CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP);
- CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP);
- CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP);
-
- for (i = 0; i < MAX_MTEX; i++) {
- if (psett->mtex[i]) {
- library_foreach_mtex(&data, psett->mtex[i]);
- }
- }
-
- if (psett->effector_weights) {
- CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP);
- }
-
- if (psett->boids) {
- BoidState *state;
- BoidRule *rule;
-
- for (state = psett->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->type == eBoidRuleType_Avoid) {
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- CALLBACK_INVOKE(gabr->ob, IDWALK_NOP);
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- CALLBACK_INVOKE(flbr->ob, IDWALK_NOP);
- }
- }
- }
- }
-
- break;
- }
-
case ID_MC:
{
MovieClip *clip = (MovieClip *) id;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 1ba4852623c..599d6134fd9 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -102,7 +102,6 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_property.h"
#include "BKE_rigidbody.h"
@@ -159,15 +158,6 @@ void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
}
}
-void BKE_object_free_particlesystems(Object *ob)
-{
- ParticleSystem *psys;
-
- while ((psys = BLI_pophead(&ob->particlesystem))) {
- psys_free(ob, psys);
- }
-}
-
void BKE_object_free_softbody(Object *ob)
{
if (ob->soft) {
@@ -206,9 +196,6 @@ void BKE_object_free_modifiers(Object *ob)
modifier_free(md);
}
- /* particle modifiers were freed, so free the particlesystems as well */
- BKE_object_free_particlesystems(ob);
-
/* same for softbody */
BKE_object_free_softbody(ob);
@@ -300,8 +287,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
modifier_unique_name(&ob_dst->modifiers, nmd);
}
- BKE_object_copy_particlesystems(ob_dst, ob_src);
-
/* TODO: smoke?, cloth? */
}
@@ -345,40 +330,8 @@ void BKE_object_free_derived_caches(Object *ob)
void BKE_object_free_caches(Object *object)
{
- ModifierData *md;
short update_flag = 0;
- /* Free particle system caches holding paths. */
- if (object->particlesystem.first) {
- ParticleSystem *psys;
- for (psys = object->particlesystem.first;
- psys != NULL;
- psys = psys->next)
- {
- psys_free_path_cache(psys, psys->edit);
- update_flag |= PSYS_RECALC_REDO;
- }
- }
-
- /* Free memory used by cached derived meshes in the particle system modifiers. */
- for (md = object->modifiers.first; md != NULL; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- if (psmd->dm_final != NULL) {
- psmd->dm_final->needsFree = 1;
- psmd->dm_final->release(psmd->dm_final);
- psmd->dm_final = NULL;
- if (psmd->dm_deformed != NULL) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
- psmd->flag |= eParticleSystemFlag_file_loaded;
- update_flag |= OB_RECALC_DATA;
- }
- }
- }
-
/* Tag object for update, so once memory critical operation is over and
* scene update routines are back to it's business the object will be
* guaranteed to be in a known state.
@@ -631,65 +584,6 @@ void BKE_object_unlink(Main *bmain, Object *ob)
}
#endif // XXX old animation system
- /* particle systems */
- if (obt->particlesystem.first) {
- ParticleSystem *tpsys = obt->particlesystem.first;
- for (; tpsys; tpsys = tpsys->next) {
- BoidState *state = NULL;
- BoidRule *rule = NULL;
-
- ParticleTarget *pt = tpsys->targets.first;
- for (; pt; pt = pt->next) {
- if (pt->ob == ob) {
- pt->ob = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- break;
- }
- }
-
- if (tpsys->target_ob == ob) {
- tpsys->target_ob = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
-
- if (tpsys->part->dup_ob == ob)
- tpsys->part->dup_ob = NULL;
-
- if (tpsys->part->phystype == PART_PHYS_BOIDS) {
- ParticleData *pa;
- BoidParticle *bpa;
- int p;
-
- for (p = 0, pa = tpsys->particles; p < tpsys->totpart; p++, pa++) {
- bpa = pa->boid;
- if (bpa->ground == ob)
- bpa->ground = NULL;
- }
- }
- if (tpsys->part->boids) {
- for (state = tpsys->part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->type == eBoidRuleType_Avoid) {
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- if (gabr->ob == ob)
- gabr->ob = NULL;
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- if (flbr->ob == ob)
- flbr->ob = NULL;
- }
- }
- }
- }
-
- if (tpsys->parent == ob)
- tpsys->parent = NULL;
- }
- if (ob->pd)
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
-
/* levels of detail */
for (lod = obt->lodlevels.first; lod; lod = lod->next) {
if (lod->source == ob)
@@ -1287,119 +1181,6 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
return bsbn;
}
-ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
-{
- ParticleSystem *psysn;
- ParticleData *pa;
- int p;
-
- psysn = MEM_dupallocN(psys);
- psysn->particles = MEM_dupallocN(psys->particles);
- psysn->child = MEM_dupallocN(psys->child);
-
- if (psys->part->type == PART_HAIR) {
- for (p = 0, pa = psysn->particles; p < psysn->totpart; p++, pa++)
- pa->hair = MEM_dupallocN(pa->hair);
- }
-
- if (psysn->particles && (psysn->particles->keys || psysn->particles->boid)) {
- ParticleKey *key = psysn->particles->keys;
- BoidParticle *boid = psysn->particles->boid;
-
- if (key)
- key = MEM_dupallocN(key);
-
- if (boid)
- boid = MEM_dupallocN(boid);
-
- for (p = 0, pa = psysn->particles; p < psysn->totpart; p++, pa++) {
- if (boid)
- pa->boid = boid++;
- if (key) {
- pa->keys = key;
- key += pa->totkey;
- }
- }
- }
-
- if (psys->clmd) {
- psysn->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth);
- modifier_copyData((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd);
- psys->hair_in_dm = psys->hair_out_dm = NULL;
- }
-
- BLI_duplicatelist(&psysn->targets, &psys->targets);
-
- psysn->pathcache = NULL;
- psysn->childcache = NULL;
- psysn->edit = NULL;
- psysn->pdd = NULL;
- psysn->effectors = NULL;
- psysn->tree = NULL;
- psysn->bvhtree = NULL;
-
- BLI_listbase_clear(&psysn->pathcachebufs);
- BLI_listbase_clear(&psysn->childcachebufs);
- psysn->renderdata = NULL;
-
- psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, false);
-
- /* XXX - from reading existing code this seems correct but intended usage of
- * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
- if (psysn->clmd) {
- psysn->clmd->point_cache = psysn->pointcache;
- }
-
- id_us_plus((ID *)psysn->part);
-
- return psysn;
-}
-
-void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src)
-{
- ParticleSystem *psys, *npsys;
- ModifierData *md;
-
- if (ob_dst->type != OB_MESH) {
- /* currently only mesh objects can have soft body */
- return;
- }
-
- BLI_listbase_clear(&ob_dst->particlesystem);
- for (psys = ob_src->particlesystem.first; psys; psys = psys->next) {
- npsys = BKE_object_copy_particlesystem(psys);
-
- BLI_addtail(&ob_dst->particlesystem, npsys);
-
- /* need to update particle modifiers too */
- for (md = ob_dst->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
- if (psmd->psys == psys)
- psmd->psys = npsys;
- }
- else if (md->type == eModifierType_DynamicPaint) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->brush) {
- if (pmd->brush->psys == psys) {
- pmd->brush->psys = npsys;
- }
- }
- }
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *) md;
-
- if (smd->type == MOD_SMOKE_TYPE_FLOW) {
- if (smd->flow) {
- if (smd->flow->psys == psys)
- smd->flow->psys = npsys;
- }
- }
- }
- }
- }
-}
-
void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src)
{
if (ob_src->soft) {
@@ -1558,8 +1339,6 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
obn->rigidbody_object = BKE_rigidbody_copy_object(ob);
obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob);
- BKE_object_copy_particlesystems(obn, ob);
-
obn->derivedDeform = NULL;
obn->derivedFinal = NULL;
@@ -1603,8 +1382,6 @@ static void extern_local_object__modifiersForeachIDLink(
static void extern_local_object(Object *ob)
{
- ParticleSystem *psys;
-
id_lib_extern((ID *)ob->data);
id_lib_extern((ID *)ob->dup_group);
id_lib_extern((ID *)ob->poselib);
@@ -1612,9 +1389,6 @@ static void extern_local_object(Object *ob)
extern_local_matarar(ob->mat, ob->totcol);
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- id_lib_extern((ID *)psys->part);
-
modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL);
ob->preview = NULL;
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 7f742dee73c..f4666fe4f5e 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -44,6 +44,7 @@
#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"
@@ -57,7 +58,6 @@
#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"
@@ -818,327 +818,6 @@ 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))
- 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 */
@@ -1154,10 +833,7 @@ 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_DUPLIPARTS) {
- return &gen_dupli_particles;
- }
- else if (transflag & OB_DUPLIVERTS) {
+ if (transflag & OB_DUPLIVERTS) {
if (ctx->object->type == OB_MESH) {
return &gen_dupli_verts;
}
@@ -1215,12 +891,8 @@ 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;
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 03348adeabc..2eeb9793c4e 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -32,6 +32,7 @@
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
@@ -53,7 +54,6 @@
#include "BKE_lattice.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_material.h"
#include "BKE_image.h"
@@ -257,53 +257,6 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
else if (ob->type == OB_LAMP)
lamp_drivers_update(scene, ob->data, ctime);
- /* particles */
- if (ob != scene->obedit && ob->particlesystem.first) {
- ParticleSystem *tpsys, *psys;
- DerivedMesh *dm;
- ob->transflag &= ~OB_DUPLIPARTS;
- psys = ob->particlesystem.first;
- while (psys) {
- /* ensure this update always happens even if psys is disabled */
- if (psys->recalc & PSYS_RECALC_TYPE) {
- psys_changed_type(ob, psys);
- }
-
- if (psys_check_enabled(ob, psys)) {
- /* check use of dupli objects here */
- if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) &&
- ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
- (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
- {
- ob->transflag |= OB_DUPLIPARTS;
- }
-
- particle_system_update(scene, ob, psys);
- psys = psys->next;
- }
- else if (psys->flag & PSYS_DELETE) {
- tpsys = psys->next;
- BLI_remlink(&ob->particlesystem, psys);
- psys_free(ob, psys);
- psys = tpsys;
- }
- else
- psys = psys->next;
- }
-
- if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL;
- dm = mesh_create_derived_render(scene, ob, data_mask);
- dm->release(dm);
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
-
/* quick cache removed */
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
deleted file mode 100644
index 098700495a0..00000000000
--- a/source/blender/blenkernel/intern/particle.c
+++ /dev/null
@@ -1,4336 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle.c
- * \ingroup bke
- */
-
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_curve_types.h"
-#include "DNA_group_types.h"
-#include "DNA_key_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_smoke_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_dynamicpaint_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_noise.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_kdtree.h"
-#include "BLI_rand.h"
-#include "BLI_task.h"
-#include "BLI_threads.h"
-#include "BLI_linklist.h"
-
-#include "BLT_translation.h"
-
-#include "BKE_anim.h"
-#include "BKE_animsys.h"
-
-#include "BKE_boids.h"
-#include "BKE_cloth.h"
-#include "BKE_colortools.h"
-#include "BKE_effect.h"
-#include "BKE_global.h"
-#include "BKE_group.h"
-#include "BKE_main.h"
-#include "BKE_lattice.h"
-
-#include "BKE_displist.h"
-#include "BKE_particle.h"
-#include "BKE_material.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_depsgraph.h"
-#include "BKE_modifier.h"
-#include "BKE_mesh.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_pointcache.h"
-#include "BKE_scene.h"
-#include "BKE_deform.h"
-
-#include "RE_render_ext.h"
-
-unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
-unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
-float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];
-
-void psys_init_rng(void)
-{
- int i;
- BLI_srandom(5831); /* arbitrary */
- for (i = 0; i < PSYS_FRAND_COUNT; ++i) {
- PSYS_FRAND_BASE[i] = BLI_frand();
- PSYS_FRAND_SEED_OFFSET[i] = (unsigned int)BLI_rand();
- PSYS_FRAND_SEED_MULTIPLIER[i] = (unsigned int)BLI_rand();
- }
-}
-
-static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
- ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
-static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par,
- int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra);
-extern void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
-
-/* few helpers for countall etc. */
-int count_particles(ParticleSystem *psys)
-{
- ParticleSettings *part = psys->part;
- PARTICLE_P;
- int tot = 0;
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {}
- else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {}
- else tot++;
- }
- return tot;
-}
-int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
-{
- ParticleSettings *part = psys->part;
- PARTICLE_P;
- int tot = 0;
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {}
- else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {}
- else if (p % totgr == cur) tot++;
- }
- return tot;
-}
-/* we allocate path cache memory in chunks instead of a big contiguous
- * chunk, windows' memory allocater fails to find big blocks of memory often */
-
-#define PATH_CACHE_BUF_SIZE 1024
-
-static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int totkeys)
-{
- LinkData *buf;
- ParticleCacheKey **cache;
- int i, totkey, totbufkey;
-
- tot = MAX2(tot, 1);
- totkey = 0;
- cache = MEM_callocN(tot * sizeof(void *), "PathCacheArray");
-
- while (totkey < tot) {
- totbufkey = MIN2(tot - totkey, PATH_CACHE_BUF_SIZE);
- buf = MEM_callocN(sizeof(LinkData), "PathCacheLinkData");
- buf->data = MEM_callocN(sizeof(ParticleCacheKey) * totbufkey * totkeys, "ParticleCacheKey");
-
- for (i = 0; i < totbufkey; i++)
- cache[totkey + i] = ((ParticleCacheKey *)buf->data) + i * totkeys;
-
- totkey += totbufkey;
- BLI_addtail(bufs, buf);
- }
-
- return cache;
-}
-
-static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *bufs)
-{
- LinkData *buf;
-
- if (cache)
- MEM_freeN(cache);
-
- for (buf = bufs->first; buf; buf = buf->next)
- MEM_freeN(buf->data);
- BLI_freelistN(bufs);
-}
-
-/************************************************/
-/* Getting stuff */
-/************************************************/
-/* get object's active particle system safely */
-ParticleSystem *psys_get_current(Object *ob)
-{
- ParticleSystem *psys;
- if (ob == NULL) return NULL;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys->flag & PSYS_CURRENT)
- return psys;
- }
-
- return NULL;
-}
-short psys_get_current_num(Object *ob)
-{
- ParticleSystem *psys;
- short i;
-
- if (ob == NULL) return 0;
-
- for (psys = ob->particlesystem.first, i = 0; psys; psys = psys->next, i++)
- if (psys->flag & PSYS_CURRENT)
- return i;
-
- return i;
-}
-void psys_set_current_num(Object *ob, int index)
-{
- ParticleSystem *psys;
- short i;
-
- if (ob == NULL) return;
-
- for (psys = ob->particlesystem.first, i = 0; psys; psys = psys->next, i++) {
- if (i == index)
- psys->flag |= PSYS_CURRENT;
- else
- psys->flag &= ~PSYS_CURRENT;
- }
-}
-
-#if 0 /* UNUSED */
-Object *psys_find_object(Scene *scene, ParticleSystem *psys)
-{
- Base *base;
- ParticleSystem *tpsys;
-
- for (base = scene->base.first; base; base = base->next) {
- for (tpsys = base->object->particlesystem.first; psys; psys = psys->next) {
- if (tpsys == psys)
- return base->object;
- }
- }
-
- return NULL;
-}
-#endif
-
-struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim)
-{
- struct LatticeDeformData *lattice_deform_data = NULL;
-
- if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
- Object *lattice = NULL;
- ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
-
- for (; md; md = md->next) {
- if (md->type == eModifierType_Lattice) {
- LatticeModifierData *lmd = (LatticeModifierData *)md;
- lattice = lmd->object;
- break;
- }
- }
- if (lattice)
- lattice_deform_data = init_latt_deform(lattice, NULL);
- }
-
- return lattice_deform_data;
-}
-void psys_disable_all(Object *ob)
-{
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next)
- psys->flag |= PSYS_DISABLED;
-}
-void psys_enable_all(Object *ob)
-{
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next)
- psys->flag &= ~PSYS_DISABLED;
-}
-bool psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
-{
- return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys == psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit) && !psys->renderdata);
-}
-bool psys_check_enabled(Object *ob, ParticleSystem *psys)
-{
- ParticleSystemModifierData *psmd;
-
- if (psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part)
- return 0;
-
- psmd = psys_get_modifier(ob, psys);
- if (psys->renderdata || G.is_rendering) {
- if (!(psmd->modifier.mode & eModifierMode_Render))
- return 0;
- }
- else if (!(psmd->modifier.mode & eModifierMode_Realtime))
- return 0;
-
- return 1;
-}
-
-bool psys_check_edited(ParticleSystem *psys)
-{
- if (psys->part && psys->part->type == PART_HAIR)
- return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited));
- else
- return (psys->pointcache->edit && psys->pointcache->edit->edited);
-}
-
-void psys_check_group_weights(ParticleSettings *part)
-{
- ParticleDupliWeight *dw, *tdw;
- GroupObject *go;
- int current = 0;
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) {
- /* first remove all weights that don't have an object in the group */
- dw = part->dupliweights.first;
- while (dw) {
- if (!BKE_group_object_exists(part->dup_group, dw->ob)) {
- tdw = dw->next;
- BLI_freelinkN(&part->dupliweights, dw);
- dw = tdw;
- }
- else
- dw = dw->next;
- }
-
- /* then add objects in the group to new list */
- go = part->dup_group->gobject.first;
- while (go) {
- dw = part->dupliweights.first;
- while (dw && dw->ob != go->ob)
- dw = dw->next;
-
- if (!dw) {
- dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
- dw->ob = go->ob;
- dw->count = 1;
- BLI_addtail(&part->dupliweights, dw);
- }
-
- go = go->next;
- }
-
- dw = part->dupliweights.first;
- for (; dw; dw = dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT) {
- current = 1;
- break;
- }
- }
-
- if (!current) {
- dw = part->dupliweights.first;
- if (dw)
- dw->flag |= PART_DUPLIW_CURRENT;
- }
- }
- else {
- BLI_freelistN(&part->dupliweights);
- }
-}
-int psys_uses_gravity(ParticleSimulationData *sim)
-{
- return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part && sim->psys->part->effector_weights->global_gravity != 0.0f;
-}
-/************************************************/
-/* Freeing stuff */
-/************************************************/
-static void fluid_free_settings(SPHFluidSettings *fluid)
-{
- if (fluid)
- MEM_freeN(fluid);
-}
-
-void BKE_particlesettings_free(ParticleSettings *part)
-{
- MTex *mtex;
- int a;
- BKE_animdata_free(&part->id);
-
- if (part->clumpcurve)
- curvemapping_free(part->clumpcurve);
- if (part->roughcurve)
- curvemapping_free(part->roughcurve);
-
- free_partdeflect(part->pd);
- free_partdeflect(part->pd2);
-
- if (part->effector_weights)
- MEM_freeN(part->effector_weights);
-
- BLI_freelistN(&part->dupliweights);
-
- boid_free_settings(part->boids);
- fluid_free_settings(part->fluid);
-
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = part->mtex[a];
- if (mtex && mtex->tex)
- id_us_min(&mtex->tex->id);
- if (mtex)
- MEM_freeN(mtex);
- }
-}
-
-void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics)
-{
- PARTICLE_P;
-
- LOOP_PARTICLES {
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair = NULL;
- pa->totkey = 0;
- }
-
- psys->flag &= ~PSYS_HAIR_DONE;
-
- if (psys->clmd) {
- if (dynamics) {
- BKE_ptcache_free_list(&psys->ptcaches);
- psys->pointcache = NULL;
-
- modifier_free((ModifierData *)psys->clmd);
-
- psys->clmd = NULL;
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- }
- else {
- cloth_free_modifier(psys->clmd);
- }
- }
-
- if (psys->hair_in_dm)
- psys->hair_in_dm->release(psys->hair_in_dm);
- psys->hair_in_dm = NULL;
-
- if (psys->hair_out_dm)
- psys->hair_out_dm->release(psys->hair_out_dm);
- psys->hair_out_dm = NULL;
-}
-void free_keyed_keys(ParticleSystem *psys)
-{
- PARTICLE_P;
-
- if (psys->part->type == PART_HAIR)
- return;
-
- if (psys->particles && psys->particles->keys) {
- MEM_freeN(psys->particles->keys);
-
- LOOP_PARTICLES {
- if (pa->keys) {
- pa->keys = NULL;
- pa->totkey = 0;
- }
- }
- }
-}
-static void free_child_path_cache(ParticleSystem *psys)
-{
- psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs);
- psys->childcache = NULL;
- psys->totchildcache = 0;
-}
-void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit)
-{
- if (edit) {
- psys_free_path_cache_buffers(edit->pathcache, &edit->pathcachebufs);
- edit->pathcache = NULL;
- edit->totcached = 0;
- }
- if (psys) {
- psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs);
- psys->pathcache = NULL;
- psys->totcached = 0;
-
- free_child_path_cache(psys);
- }
-}
-void psys_free_children(ParticleSystem *psys)
-{
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = NULL;
- psys->totchild = 0;
- }
-
- free_child_path_cache(psys);
-}
-void psys_free_particles(ParticleSystem *psys)
-{
- PARTICLE_P;
-
- if (psys->particles) {
- if (psys->part->type == PART_HAIR) {
- LOOP_PARTICLES {
- if (pa->hair)
- MEM_freeN(pa->hair);
- }
- }
-
- if (psys->particles->keys)
- MEM_freeN(psys->particles->keys);
-
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
-
- MEM_freeN(psys->particles);
- psys->particles = NULL;
- psys->totpart = 0;
- }
-}
-void psys_free_pdd(ParticleSystem *psys)
-{
- if (psys->pdd) {
- if (psys->pdd->cdata)
- MEM_freeN(psys->pdd->cdata);
- psys->pdd->cdata = NULL;
-
- if (psys->pdd->vdata)
- MEM_freeN(psys->pdd->vdata);
- psys->pdd->vdata = NULL;
-
- if (psys->pdd->ndata)
- MEM_freeN(psys->pdd->ndata);
- psys->pdd->ndata = NULL;
-
- if (psys->pdd->vedata)
- MEM_freeN(psys->pdd->vedata);
- psys->pdd->vedata = NULL;
-
- psys->pdd->totpoint = 0;
- psys->pdd->tot_vec_size = 0;
- }
-}
-/* free everything */
-void psys_free(Object *ob, ParticleSystem *psys)
-{
- if (psys) {
- int nr = 0;
- ParticleSystem *tpsys;
-
- psys_free_path_cache(psys, NULL);
-
- free_hair(ob, psys, 1);
-
- psys_free_particles(psys);
-
- if (psys->edit && psys->free_edit)
- psys->free_edit(psys->edit);
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = NULL;
- psys->totchild = 0;
- }
-
- /* check if we are last non-visible particle system */
- for (tpsys = ob->particlesystem.first; tpsys; tpsys = tpsys->next) {
- if (tpsys->part) {
- if (ELEM(tpsys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- nr++;
- break;
- }
- }
- }
- /* clear do-not-draw-flag */
- if (!nr)
- ob->transflag &= ~OB_DUPLIPARTS;
-
- if (psys->part) {
- id_us_min(&psys->part->id);
- psys->part = NULL;
- }
-
- BKE_ptcache_free_list(&psys->ptcaches);
- psys->pointcache = NULL;
-
- BLI_freelistN(&psys->targets);
-
- BLI_bvhtree_free(psys->bvhtree);
- BLI_kdtree_free(psys->tree);
-
- if (psys->fluid_springs)
- MEM_freeN(psys->fluid_springs);
-
- pdEndEffectors(&psys->effectors);
-
- if (psys->pdd) {
- psys_free_pdd(psys);
- MEM_freeN(psys->pdd);
- }
-
- MEM_freeN(psys);
- }
-}
-
-/************************************************/
-/* Rendering */
-/************************************************/
-/* these functions move away particle data and bring it back after
- * rendering, to make different render settings possible without
- * removing the previous data. this should be solved properly once */
-
-void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
-
- if (psys->renderdata)
- return;
-
- data = MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
-
- data->child = psys->child;
- data->totchild = psys->totchild;
- data->pathcache = psys->pathcache;
- data->pathcachebufs.first = psys->pathcachebufs.first;
- data->pathcachebufs.last = psys->pathcachebufs.last;
- data->totcached = psys->totcached;
- data->childcache = psys->childcache;
- data->childcachebufs.first = psys->childcachebufs.first;
- data->childcachebufs.last = psys->childcachebufs.last;
- data->totchildcache = psys->totchildcache;
-
- if (psmd->dm_final)
- data->dm = CDDM_copy(psmd->dm_final);
- data->totdmvert = psmd->totdmvert;
- data->totdmedge = psmd->totdmedge;
- data->totdmface = psmd->totdmface;
-
- psys->child = NULL;
- psys->pathcache = NULL;
- psys->childcache = NULL;
- psys->totchild = psys->totcached = psys->totchildcache = 0;
- BLI_listbase_clear(&psys->pathcachebufs);
- BLI_listbase_clear(&psys->childcachebufs);
-
- copy_m4_m4(data->winmat, winmat);
- mul_m4_m4m4(data->viewmat, viewmat, ob->obmat);
- mul_m4_m4m4(data->mat, winmat, data->viewmat);
- data->winx = winx;
- data->winy = winy;
-
- data->timeoffset = timeoffset;
-
- psys->renderdata = data;
-
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (psys->part->disp != 100 && psys->part->type == PART_HAIR)
- psys->recalc |= PSYS_RECALC_RESET;
-}
-
-void psys_render_restore(Object *ob, ParticleSystem *psys)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- float render_disp = psys_get_current_display_percentage(psys);
- float disp;
-
- data = psys->renderdata;
- if (!data)
- return;
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- if (psmd->dm_final) {
- psmd->dm_final->needsFree = 1;
- psmd->dm_final->release(psmd->dm_final);
- }
- if (psmd->dm_deformed) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
-
- psys_free_path_cache(psys, NULL);
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = 0;
- psys->totchild = 0;
- }
-
- psys->child = data->child;
- psys->totchild = data->totchild;
- psys->pathcache = data->pathcache;
- psys->pathcachebufs.first = data->pathcachebufs.first;
- psys->pathcachebufs.last = data->pathcachebufs.last;
- psys->totcached = data->totcached;
- psys->childcache = data->childcache;
- psys->childcachebufs.first = data->childcachebufs.first;
- psys->childcachebufs.last = data->childcachebufs.last;
- psys->totchildcache = data->totchildcache;
-
- psmd->dm_final = data->dm;
- psmd->totdmvert = data->totdmvert;
- psmd->totdmedge = data->totdmedge;
- psmd->totdmface = data->totdmface;
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
-
- if (psmd->dm_final) {
- if (!psmd->dm_final->deformedOnly) {
- if (ob->derivedDeform) {
- psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
- }
- else {
- psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
- }
- DM_ensure_tessface(psmd->dm_deformed);
- }
- psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys);
- }
-
- MEM_freeN(data);
- psys->renderdata = NULL;
-
- /* restore particle display percentage */
- disp = psys_get_current_display_percentage(psys);
-
- if (disp != render_disp) {
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (psys->part->type == PART_HAIR) {
- psys->recalc |= PSYS_RECALC_RESET;
- }
- else {
- PARTICLE_P;
-
- LOOP_PARTICLES {
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
- }
- }
-}
-
-bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
-{
- ParticleRenderData *data;
- ParticleRenderElem *elem;
- float x, w, scale, alpha, lambda, t, scalemin, scalemax;
- int b;
-
- if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
- return false;
-
- data = psys->renderdata;
- if (!data->do_simplify)
- return false;
- b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num;
- if (b == ORIGINDEX_NONE) {
- return false;
- }
-
- elem = &data->elems[b];
-
- lambda = elem->lambda;
- t = elem->t;
- scalemin = elem->scalemin;
- scalemax = elem->scalemax;
-
- if (!elem->reduce) {
- scale = scalemin;
- alpha = 1.0f;
- }
- else {
- x = (elem->curchild + 0.5f) / elem->totchild;
- if (x < lambda - t) {
- scale = scalemax;
- alpha = 1.0f;
- }
- else if (x >= lambda + t) {
- scale = scalemin;
- alpha = 0.0f;
- }
- else {
- w = (lambda + t - x) / (2.0f * t);
- scale = scalemin + (scalemax - scalemin) * w;
- alpha = w;
- }
- }
-
- params[0] = scale;
- params[1] = alpha;
-
- elem->curchild++;
-
- return 1;
-}
-
-/************************************************/
-/* Interpolation */
-/************************************************/
-static float interpolate_particle_value(float v1, float v2, float v3, float v4, const float w[4], int four)
-{
- float value;
-
- value = w[0] * v1 + w[1] * v2 + w[2] * v3;
- if (four)
- value += w[3] * v4;
-
- CLAMP(value, 0.f, 1.f);
-
- return value;
-}
-
-void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity)
-{
- float t[4];
-
- if (type < 0) {
- interp_cubic_v3(result->co, result->vel, keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt);
- }
- else {
- key_curve_position_weights(dt, t, type);
-
- interp_v3_v3v3v3v3(result->co, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
-
- if (velocity) {
- float temp[3];
-
- if (dt > 0.999f) {
- key_curve_position_weights(dt - 0.001f, t, type);
- interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
- sub_v3_v3v3(result->vel, result->co, temp);
- }
- else {
- key_curve_position_weights(dt + 0.001f, t, type);
- interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
- sub_v3_v3v3(result->vel, temp, result->co);
- }
- }
- }
-}
-
-
-typedef struct ParticleInterpolationData {
- HairKey *hkey[2];
-
- DerivedMesh *dm;
- MVert *mvert[2];
-
- int keyed;
- ParticleKey *kkey[2];
-
- PointCache *cache;
- PTCacheMem *pm;
-
- PTCacheEditPoint *epoint;
- PTCacheEditKey *ekey[2];
-
- float birthtime, dietime;
- int bspline;
-} ParticleInterpolationData;
-/* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */
-/* It uses ParticleInterpolationData->pm to store the current memory cache frame so it's thread safe. */
-static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2)
-{
- static PTCacheMem *pm = NULL;
- int index1, index2;
-
- if (index < 0) { /* initialize */
- *cur = cache->mem_cache.first;
-
- if (*cur)
- *cur = (*cur)->next;
- }
- else {
- if (*cur) {
- while (*cur && (*cur)->next && (float)(*cur)->frame < t)
- *cur = (*cur)->next;
-
- pm = *cur;
-
- index2 = BKE_ptcache_mem_index_find(pm, index);
- index1 = BKE_ptcache_mem_index_find(pm->prev, index);
-
- BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
- if (index1 < 0)
- copy_particle_key(key1, key2, 1);
- else
- BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame);
- }
- else if (cache->mem_cache.first) {
- pm = cache->mem_cache.first;
- index2 = BKE_ptcache_mem_index_find(pm, index);
- BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
- copy_particle_key(key1, key2, 1);
- }
- }
-}
-static int get_pointcache_times_for_particle(PointCache *cache, int index, float *start, float *end)
-{
- PTCacheMem *pm;
- int ret = 0;
-
- for (pm = cache->mem_cache.first; pm; pm = pm->next) {
- if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
- *start = pm->frame;
- ret++;
- break;
- }
- }
-
- for (pm = cache->mem_cache.last; pm; pm = pm->prev) {
- if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
- *end = pm->frame;
- ret++;
- break;
- }
- }
-
- return ret == 2;
-}
-
-float psys_get_dietime_from_cache(PointCache *cache, int index)
-{
- PTCacheMem *pm;
- int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
-
- for (pm = cache->mem_cache.last; pm; pm = pm->prev) {
- if (BKE_ptcache_mem_index_find(pm, index) >= 0)
- return (float)pm->frame;
- }
-
- return (float)dietime;
-}
-
-static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind)
-{
-
- if (pind->epoint) {
- PTCacheEditPoint *point = pind->epoint;
-
- pind->ekey[0] = point->keys;
- pind->ekey[1] = point->totkey > 1 ? point->keys + 1 : NULL;
-
- pind->birthtime = *(point->keys->time);
- pind->dietime = *((point->keys + point->totkey - 1)->time);
- }
- else if (pind->keyed) {
- ParticleKey *key = pa->keys;
- pind->kkey[0] = key;
- pind->kkey[1] = pa->totkey > 1 ? key + 1 : NULL;
-
- pind->birthtime = key->time;
- pind->dietime = (key + pa->totkey - 1)->time;
- }
- else if (pind->cache) {
- float start = 0.0f, end = 0.0f;
- get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL);
- pind->birthtime = pa ? pa->time : pind->cache->startframe;
- pind->dietime = pa ? pa->dietime : pind->cache->endframe;
-
- if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &end)) {
- pind->birthtime = MAX2(pind->birthtime, start);
- pind->dietime = MIN2(pind->dietime, end);
- }
- }
- else {
- HairKey *key = pa->hair;
- pind->hkey[0] = key;
- pind->hkey[1] = key + 1;
-
- pind->birthtime = key->time;
- pind->dietime = (key + pa->totkey - 1)->time;
-
- if (pind->dm) {
- pind->mvert[0] = CDDM_get_vert(pind->dm, pa->hair_index);
- pind->mvert[1] = pind->mvert[0] + 1;
- }
- }
-}
-static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey)
-{
- copy_v3_v3(key->co, ekey->co);
- if (ekey->vel) {
- copy_v3_v3(key->vel, ekey->vel);
- }
- key->time = *(ekey->time);
-}
-static void hair_to_particle(ParticleKey *key, HairKey *hkey)
-{
- copy_v3_v3(key->co, hkey->co);
- key->time = hkey->time;
-}
-
-static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey)
-{
- copy_v3_v3(key->co, mvert->co);
- key->time = hkey->time;
-}
-
-static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, ParticleInterpolationData *pind, ParticleKey *result)
-{
- PTCacheEditPoint *point = pind->epoint;
- ParticleKey keys[4];
- int point_vel = (point && point->keys->vel);
- float real_t, dfra, keytime, invdt = 1.f;
-
- /* billboards wont fill in all of these, so start cleared */
- memset(keys, 0, sizeof(keys));
-
- /* interpret timing and find keys */
- if (point) {
- if (result->time < 0.0f)
- real_t = -result->time;
- else
- real_t = *(pind->ekey[0]->time) + t * (*(pind->ekey[0][point->totkey - 1].time) - *(pind->ekey[0]->time));
-
- while (*(pind->ekey[1]->time) < real_t)
- pind->ekey[1]++;
-
- pind->ekey[0] = pind->ekey[1] - 1;
- }
- else if (pind->keyed) {
- /* we have only one key, so let's use that */
- if (pind->kkey[1] == NULL) {
- copy_particle_key(result, pind->kkey[0], 1);
- return;
- }
-
- if (result->time < 0.0f)
- real_t = -result->time;
- else
- real_t = pind->kkey[0]->time + t * (pind->kkey[0][pa->totkey - 1].time - pind->kkey[0]->time);
-
- if (psys->part->phystype == PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) {
- ParticleTarget *pt = psys->targets.first;
-
- pt = pt->next;
-
- while (pt && pa->time + pt->time < real_t)
- pt = pt->next;
-
- if (pt) {
- pt = pt->prev;
-
- if (pa->time + pt->time + pt->duration > real_t)
- real_t = pa->time + pt->time;
- }
- else
- real_t = pa->time + ((ParticleTarget *)psys->targets.last)->time;
- }
-
- CLAMP(real_t, pa->time, pa->dietime);
-
- while (pind->kkey[1]->time < real_t)
- pind->kkey[1]++;
-
- pind->kkey[0] = pind->kkey[1] - 1;
- }
- else if (pind->cache) {
- if (result->time < 0.0f) /* flag for time in frames */
- real_t = -result->time;
- else
- real_t = pa->time + t * (pa->dietime - pa->time);
- }
- else {
- if (result->time < 0.0f)
- real_t = -result->time;
- else
- real_t = pind->hkey[0]->time + t * (pind->hkey[0][pa->totkey - 1].time - pind->hkey[0]->time);
-
- while (pind->hkey[1]->time < real_t) {
- pind->hkey[1]++;
- pind->mvert[1]++;
- }
-
- pind->hkey[0] = pind->hkey[1] - 1;
- }
-
- /* set actual interpolation keys */
- if (point) {
- edit_to_particle(keys + 1, pind->ekey[0]);
- edit_to_particle(keys + 2, pind->ekey[1]);
- }
- else if (pind->dm) {
- pind->mvert[0] = pind->mvert[1] - 1;
- mvert_to_particle(keys + 1, pind->mvert[0], pind->hkey[0]);
- mvert_to_particle(keys + 2, pind->mvert[1], pind->hkey[1]);
- }
- else if (pind->keyed) {
- memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey));
- memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey));
- }
- else if (pind->cache) {
- get_pointcache_keys_for_time(NULL, pind->cache, &pind->pm, p, real_t, keys + 1, keys + 2);
- }
- else {
- hair_to_particle(keys + 1, pind->hkey[0]);
- hair_to_particle(keys + 2, pind->hkey[1]);
- }
-
- /* set secondary interpolation keys for hair */
- if (!pind->keyed && !pind->cache && !point_vel) {
- if (point) {
- if (pind->ekey[0] != point->keys)
- edit_to_particle(keys, pind->ekey[0] - 1);
- else
- edit_to_particle(keys, pind->ekey[0]);
- }
- else if (pind->dm) {
- if (pind->hkey[0] != pa->hair)
- mvert_to_particle(keys, pind->mvert[0] - 1, pind->hkey[0] - 1);
- else
- mvert_to_particle(keys, pind->mvert[0], pind->hkey[0]);
- }
- else {
- if (pind->hkey[0] != pa->hair)
- hair_to_particle(keys, pind->hkey[0] - 1);
- else
- hair_to_particle(keys, pind->hkey[0]);
- }
-
- if (point) {
- if (pind->ekey[1] != point->keys + point->totkey - 1)
- edit_to_particle(keys + 3, pind->ekey[1] + 1);
- else
- edit_to_particle(keys + 3, pind->ekey[1]);
- }
- else if (pind->dm) {
- if (pind->hkey[1] != pa->hair + pa->totkey - 1)
- mvert_to_particle(keys + 3, pind->mvert[1] + 1, pind->hkey[1] + 1);
- else
- mvert_to_particle(keys + 3, pind->mvert[1], pind->hkey[1]);
- }
- else {
- if (pind->hkey[1] != pa->hair + pa->totkey - 1)
- hair_to_particle(keys + 3, pind->hkey[1] + 1);
- else
- hair_to_particle(keys + 3, pind->hkey[1]);
- }
- }
-
- dfra = keys[2].time - keys[1].time;
- keytime = (real_t - keys[1].time) / dfra;
-
- /* convert velocity to timestep size */
- if (pind->keyed || pind->cache || point_vel) {
- invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f);
- mul_v3_fl(keys[1].vel, invdt);
- mul_v3_fl(keys[2].vel, invdt);
- interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime);
- }
-
- /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0, 1]->[k2, k3] (k1 & k4 used for cardinal & bspline interpolation)*/
- psys_interpolate_particle((pind->keyed || pind->cache || point_vel) ? -1 /* signal for cubic interpolation */
- : (pind->bspline ? KEY_BSPLINE : KEY_CARDINAL),
- keys, keytime, result, 1);
-
- /* the velocity needs to be converted back from cubic interpolation */
- if (pind->keyed || pind->cache || point_vel)
- mul_v3_fl(result->vel, 1.f / invdt);
-}
-
-static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCacheKey *result)
-{
- int i = 0;
- ParticleCacheKey *cur = first;
-
- /* scale the requested time to fit the entire path even if the path is cut early */
- t *= (first + first->segments)->time;
-
- while (i < first->segments && cur->time < t)
- cur++;
-
- if (cur->time == t)
- *result = *cur;
- else {
- float dt = (t - (cur - 1)->time) / (cur->time - (cur - 1)->time);
- interp_v3_v3v3(result->co, (cur - 1)->co, cur->co, dt);
- interp_v3_v3v3(result->vel, (cur - 1)->vel, cur->vel, dt);
- interp_qt_qtqt(result->rot, (cur - 1)->rot, cur->rot, dt);
- result->time = t;
- }
-
- /* first is actual base rotation, others are incremental from first */
- if (cur == first || cur - 1 == first)
- copy_qt_qt(result->rot, first->rot);
- else
- mul_qt_qtqt(result->rot, first->rot, result->rot);
-}
-
-/************************************************/
-/* Particles on a dm */
-/************************************************/
-/* interpolate a location on a face based on face coordinates */
-void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3],
- float w[4], float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- float *v1 = 0, *v2 = 0, *v3 = 0, *v4 = 0;
- float e1[3], e2[3], s1, s2, t1, t2;
- float *uv1, *uv2, *uv3, *uv4;
- float n1[3], n2[3], n3[3], n4[3];
- float tuv[4][2];
- float *o1, *o2, *o3, *o4;
-
- v1 = mvert[mface->v1].co;
- v2 = mvert[mface->v2].co;
- v3 = mvert[mface->v3].co;
-
- normal_short_to_float_v3(n1, mvert[mface->v1].no);
- normal_short_to_float_v3(n2, mvert[mface->v2].no);
- normal_short_to_float_v3(n3, mvert[mface->v3].no);
-
- if (mface->v4) {
- v4 = mvert[mface->v4].co;
- normal_short_to_float_v3(n4, mvert[mface->v4].no);
-
- interp_v3_v3v3v3v3(vec, v1, v2, v3, v4, w);
-
- if (nor) {
- if (mface->flag & ME_SMOOTH)
- interp_v3_v3v3v3v3(nor, n1, n2, n3, n4, w);
- else
- normal_quad_v3(nor, v1, v2, v3, v4);
- }
- }
- else {
- interp_v3_v3v3v3(vec, v1, v2, v3, w);
-
- if (nor) {
- if (mface->flag & ME_SMOOTH)
- interp_v3_v3v3v3(nor, n1, n2, n3, w);
- else
- normal_tri_v3(nor, v1, v2, v3);
- }
- }
-
- /* calculate tangent vectors */
- if (utan && vtan) {
- if (tface) {
- uv1 = tface->uv[0];
- uv2 = tface->uv[1];
- uv3 = tface->uv[2];
- uv4 = tface->uv[3];
- }
- else {
- uv1 = tuv[0]; uv2 = tuv[1]; uv3 = tuv[2]; uv4 = tuv[3];
- map_to_sphere(uv1, uv1 + 1, v1[0], v1[1], v1[2]);
- map_to_sphere(uv2, uv2 + 1, v2[0], v2[1], v2[2]);
- map_to_sphere(uv3, uv3 + 1, v3[0], v3[1], v3[2]);
- if (v4)
- map_to_sphere(uv4, uv4 + 1, v4[0], v4[1], v4[2]);
- }
-
- if (v4) {
- s1 = uv3[0] - uv1[0];
- s2 = uv4[0] - uv1[0];
-
- t1 = uv3[1] - uv1[1];
- t2 = uv4[1] - uv1[1];
-
- sub_v3_v3v3(e1, v3, v1);
- sub_v3_v3v3(e2, v4, v1);
- }
- else {
- s1 = uv2[0] - uv1[0];
- s2 = uv3[0] - uv1[0];
-
- t1 = uv2[1] - uv1[1];
- t2 = uv3[1] - uv1[1];
-
- sub_v3_v3v3(e1, v2, v1);
- sub_v3_v3v3(e2, v3, v1);
- }
-
- vtan[0] = (s1 * e2[0] - s2 * e1[0]);
- vtan[1] = (s1 * e2[1] - s2 * e1[1]);
- vtan[2] = (s1 * e2[2] - s2 * e1[2]);
-
- utan[0] = (t1 * e2[0] - t2 * e1[0]);
- utan[1] = (t1 * e2[1] - t2 * e1[1]);
- utan[2] = (t1 * e2[2] - t2 * e1[2]);
- }
-
- if (orco) {
- if (orcodata) {
- o1 = orcodata[mface->v1];
- o2 = orcodata[mface->v2];
- o3 = orcodata[mface->v3];
-
- if (mface->v4) {
- o4 = orcodata[mface->v4];
-
- interp_v3_v3v3v3v3(orco, o1, o2, o3, o4, w);
-
- if (ornor)
- normal_quad_v3(ornor, o1, o2, o3, o4);
- }
- else {
- interp_v3_v3v3v3(orco, o1, o2, o3, w);
-
- if (ornor)
- normal_tri_v3(ornor, o1, o2, o3);
- }
- }
- else {
- copy_v3_v3(orco, vec);
- if (ornor && nor)
- copy_v3_v3(ornor, nor);
- }
- }
-}
-void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float uvco[2])
-{
- float v10 = tface->uv[0][0];
- float v11 = tface->uv[0][1];
- float v20 = tface->uv[1][0];
- float v21 = tface->uv[1][1];
- float v30 = tface->uv[2][0];
- float v31 = tface->uv[2][1];
- float v40, v41;
-
- if (quad) {
- v40 = tface->uv[3][0];
- v41 = tface->uv[3][1];
-
- uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30 + w[3] * v40;
- uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31 + w[3] * v41;
- }
- else {
- uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30;
- uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31;
- }
-}
-
-void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
-{
- const char *cp1, *cp2, *cp3, *cp4;
- char *cp;
-
- cp = (char *)mc;
- cp1 = (const char *)&mcol[0];
- cp2 = (const char *)&mcol[1];
- cp3 = (const char *)&mcol[2];
-
- if (quad) {
- cp4 = (char *)&mcol[3];
-
- cp[0] = (int)(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0] + w[3] * cp4[0]);
- cp[1] = (int)(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1] + w[3] * cp4[1]);
- cp[2] = (int)(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2] + w[3] * cp4[2]);
- cp[3] = (int)(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3] + w[3] * cp4[3]);
- }
- else {
- cp[0] = (int)(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0]);
- cp[1] = (int)(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1]);
- cp[2] = (int)(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2]);
- cp[3] = (int)(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3]);
- }
-}
-
-static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, const float fw[4], const float *values)
-{
- if (values == 0 || index == -1)
- return 0.0;
-
- switch (from) {
- case PART_FROM_VERT:
- return values[index];
- case PART_FROM_FACE:
- case PART_FROM_VOLUME:
- {
- MFace *mf = dm->getTessFaceData(dm, index, CD_MFACE);
- return interpolate_particle_value(values[mf->v1], values[mf->v2], values[mf->v3], values[mf->v4], fw, mf->v4);
- }
-
- }
- return 0.0f;
-}
-
-/* conversion of pa->fw to origspace layer coordinates */
-static void psys_w_to_origspace(const float w[4], float uv[2])
-{
- uv[0] = w[1] + w[2];
- uv[1] = w[2] + w[3];
-}
-
-/* conversion of pa->fw to weights in face from origspace */
-static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4], float neww[4])
-{
- float v[4][3], co[3];
-
- v[0][0] = osface->uv[0][0]; v[0][1] = osface->uv[0][1]; v[0][2] = 0.0f;
- v[1][0] = osface->uv[1][0]; v[1][1] = osface->uv[1][1]; v[1][2] = 0.0f;
- v[2][0] = osface->uv[2][0]; v[2][1] = osface->uv[2][1]; v[2][2] = 0.0f;
-
- psys_w_to_origspace(w, co);
- co[2] = 0.0f;
-
- if (quad) {
- v[3][0] = osface->uv[3][0]; v[3][1] = osface->uv[3][1]; v[3][2] = 0.0f;
- interp_weights_poly_v3(neww, v, 4, co);
- }
- else {
- interp_weights_poly_v3(neww, v, 3, co);
- neww[3] = 0.0f;
- }
-}
-
-/**
- * Find the final derived mesh tessface for a particle, from its original tessface index.
- * This is slow and can be optimized but only for many lookups.
- *
- * \param dm_final final DM, it may not have the same topology as original mesh.
- * \param dm_deformed deformed-only DM, it has the exact same topology as original mesh.
- * \param findex_orig the input tessface index.
- * \param fw face weights (position of the particle inside the \a findex_orig tessface).
- * \param poly_nodes may be NULL, otherwise an array of linked list, one for each final DM polygon, containing all
- * its tessfaces indices.
- * \return the DM tessface index.
- */
-int psys_particle_dm_face_lookup(
- DerivedMesh *dm_final, DerivedMesh *dm_deformed,
- int findex_orig, const float fw[4], struct LinkNode **poly_nodes)
-{
- MFace *mtessface_final;
- OrigSpaceFace *osface_final;
- int pindex_orig;
- float uv[2], (*faceuv)[2];
-
- const int *index_mf_to_mpoly_deformed = NULL;
- const int *index_mf_to_mpoly = NULL;
- const int *index_mp_to_orig = NULL;
-
- const int totface_final = dm_final->getNumTessFaces(dm_final);
- const int totface_deformed = dm_deformed ? dm_deformed->getNumTessFaces(dm_deformed) : totface_final;
-
- if (ELEM(0, totface_final, totface_deformed)) {
- return DMCACHE_NOTFOUND;
- }
-
- index_mf_to_mpoly = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
- index_mp_to_orig = dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
- BLI_assert(index_mf_to_mpoly);
-
- if (dm_deformed) {
- index_mf_to_mpoly_deformed = dm_deformed->getTessFaceDataArray(dm_deformed, CD_ORIGINDEX);
- }
- else {
- BLI_assert(dm_final->deformedOnly);
- index_mf_to_mpoly_deformed = index_mf_to_mpoly;
- }
- BLI_assert(index_mf_to_mpoly_deformed);
-
- pindex_orig = index_mf_to_mpoly_deformed[findex_orig];
-
- if (dm_deformed == NULL) {
- dm_deformed = dm_final;
- }
-
- index_mf_to_mpoly_deformed = NULL;
-
- mtessface_final = dm_final->getTessFaceArray(dm_final);
- osface_final = dm_final->getTessFaceDataArray(dm_final, CD_ORIGSPACE);
-
- if (osface_final == NULL) {
- /* Assume we don't need osface_final data, and we get a direct 1-1 mapping... */
- if (findex_orig < totface_final) {
- //printf("\tNO CD_ORIGSPACE, assuming not needed\n");
- return findex_orig;
- }
- else {
- printf("\tNO CD_ORIGSPACE, error out of range\n");
- return DMCACHE_NOTFOUND;
- }
- }
- else if (findex_orig >= dm_deformed->getNumTessFaces(dm_deformed)) {
- return DMCACHE_NOTFOUND; /* index not in the original mesh */
- }
-
- psys_w_to_origspace(fw, uv);
-
- if (poly_nodes) {
- /* we can have a restricted linked list of faces to check, faster! */
- LinkNode *tessface_node = poly_nodes[pindex_orig];
-
- for (; tessface_node; tessface_node = tessface_node->next) {
- int findex_dst = GET_INT_FROM_POINTER(tessface_node->link);
- faceuv = osface_final[findex_dst].uv;
-
- /* check that this intersects - Its possible this misses :/ -
- * could also check its not between */
- if (mtessface_final[findex_dst].v4) {
- if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
- return findex_dst;
- }
- }
- else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
- return findex_dst;
- }
- }
- }
- else { /* if we have no node, try every face */
- for (int findex_dst = 0; findex_dst < totface_final; findex_dst++) {
- /* If current tessface from 'final' DM and orig tessface (given by index) map to the same orig poly... */
- if (DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex_dst) == pindex_orig) {
- faceuv = osface_final[findex_dst].uv;
-
- /* check that this intersects - Its possible this misses :/ -
- * could also check its not between */
- if (mtessface_final[findex_dst].v4) {
- if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
- return findex_dst;
- }
- }
- else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
- return findex_dst;
- }
- }
- }
- }
-
- return DMCACHE_NOTFOUND;
-}
-
-static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, const float fw[4], float UNUSED(foffset), int *mapindex, float mapfw[4])
-{
- if (index < 0)
- return 0;
-
- if (dm->deformedOnly || index_dmcache == DMCACHE_ISCHILD) {
- /* for meshes that are either only deformed or for child particles, the
- * index and fw do not require any mapping, so we can directly use it */
- if (from == PART_FROM_VERT) {
- if (index >= dm->getNumVerts(dm))
- return 0;
-
- *mapindex = index;
- }
- else { /* FROM_FACE/FROM_VOLUME */
- if (index >= dm->getNumTessFaces(dm))
- return 0;
-
- *mapindex = index;
- copy_v4_v4(mapfw, fw);
- }
- }
- else {
- /* for other meshes that have been modified, we try to map the particle
- * to their new location, which means a different index, and for faces
- * also a new face interpolation weights */
- if (from == PART_FROM_VERT) {
- if (index_dmcache == DMCACHE_NOTFOUND || index_dmcache > dm->getNumVerts(dm))
- return 0;
-
- *mapindex = index_dmcache;
- }
- else { /* FROM_FACE/FROM_VOLUME */
- /* find a face on the derived mesh that uses this face */
- MFace *mface;
- OrigSpaceFace *osface;
- int i;
-
- i = index_dmcache;
-
- if (i == DMCACHE_NOTFOUND || i >= dm->getNumTessFaces(dm))
- return 0;
-
- *mapindex = i;
-
- /* modify the original weights to become
- * weights for the derived mesh face */
- osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
- mface = dm->getTessFaceData(dm, i, CD_MFACE);
-
- if (osface == NULL)
- mapfw[0] = mapfw[1] = mapfw[2] = mapfw[3] = 0.0f;
- else
- psys_origspace_to_w(&osface[i], mface->v4, fw, mapfw);
- }
- }
-
- return 1;
-}
-
-/* interprets particle data to get a point on a mesh in object space */
-void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_dmcache,
- const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- float tmpnor[3], mapfw[4];
- float (*orcodata)[3];
- int mapindex;
-
- if (!psys_map_index_on_dm(dm_final, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
- if (vec) { vec[0] = vec[1] = vec[2] = 0.0; }
- if (nor) { nor[0] = nor[1] = 0.0; nor[2] = 1.0; }
- if (orco) { orco[0] = orco[1] = orco[2] = 0.0; }
- if (ornor) { ornor[0] = ornor[1] = 0.0; ornor[2] = 1.0; }
- if (utan) { utan[0] = utan[1] = utan[2] = 0.0; }
- if (vtan) { vtan[0] = vtan[1] = vtan[2] = 0.0; }
-
- return;
- }
-
- orcodata = dm_final->getVertDataArray(dm_final, CD_ORCO);
-
- if (from == PART_FROM_VERT) {
- dm_final->getVertCo(dm_final, mapindex, vec);
-
- if (nor) {
- dm_final->getVertNo(dm_final, mapindex, nor);
- normalize_v3(nor);
- }
-
- if (orco) {
- if (orcodata) {
- copy_v3_v3(orco, orcodata[mapindex]);
- }
- else {
- copy_v3_v3(orco, vec);
- }
- }
-
- if (ornor) {
- dm_final->getVertNo(dm_final, mapindex, ornor);
- normalize_v3(ornor);
- }
-
- if (utan && vtan) {
- utan[0] = utan[1] = utan[2] = 0.0f;
- vtan[0] = vtan[1] = vtan[2] = 0.0f;
- }
- }
- else { /* PART_FROM_FACE / PART_FROM_VOLUME */
- MFace *mface;
- MTFace *mtface;
- MVert *mvert;
-
- mface = dm_final->getTessFaceData(dm_final, mapindex, CD_MFACE);
- mvert = dm_final->getVertDataArray(dm_final, CD_MVERT);
- mtface = CustomData_get_layer(&dm_final->faceData, CD_MTFACE);
-
- if (mtface)
- mtface += mapindex;
-
- if (from == PART_FROM_VOLUME) {
- psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, tmpnor, utan, vtan, orco, ornor);
- if (nor)
- copy_v3_v3(nor, tmpnor);
-
- normalize_v3(tmpnor); /* XXX Why not normalize tmpnor before copying it into nor??? -- mont29 */
- mul_v3_fl(tmpnor, -foffset);
- add_v3_v3(vec, tmpnor);
- }
- else
- psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, nor, utan, vtan, orco, ornor);
- }
-}
-
-float psys_particle_value_from_verts(DerivedMesh *dm, short from, ParticleData *pa, float *values)
-{
- float mapfw[4];
- int mapindex;
-
- if (!psys_map_index_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, &mapindex, mapfw))
- return 0.0f;
-
- return psys_interpolate_value_from_verts(dm, from, mapindex, mapfw, values);
-}
-
-ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys)
-{
- ModifierData *md;
- ParticleSystemModifierData *psmd;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- psmd = (ParticleSystemModifierData *) md;
- if (psmd->psys == psys) {
- return psmd;
- }
- }
- }
- return NULL;
-}
-/************************************************/
-/* Particles on a shape */
-/************************************************/
-/* ready for future use */
-static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index),
- float *UNUSED(fuv), float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- /* TODO */
- float zerovec[3] = {0.0f, 0.0f, 0.0f};
- if (vec) {
- copy_v3_v3(vec, zerovec);
- }
- if (nor) {
- copy_v3_v3(nor, zerovec);
- }
- if (utan) {
- copy_v3_v3(utan, zerovec);
- }
- if (vtan) {
- copy_v3_v3(vtan, zerovec);
- }
- if (orco) {
- copy_v3_v3(orco, zerovec);
- }
- if (ornor) {
- copy_v3_v3(ornor, zerovec);
- }
-}
-/************************************************/
-/* Particles on emitter */
-/************************************************/
-
-CustomDataMask psys_emitter_customdata_mask(ParticleSystem *psys)
-{
- CustomDataMask dataMask = 0;
- MTex *mtex;
- int i;
-
- if (!psys->part)
- return 0;
-
- for (i = 0; i < MAX_MTEX; i++) {
- mtex = psys->part->mtex[i];
- if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV))
- dataMask |= CD_MASK_MTFACE;
- }
-
- if (psys->part->tanfac != 0.0f)
- dataMask |= CD_MASK_MTFACE;
-
- /* ask for vertexgroups if we need them */
- for (i = 0; i < PSYS_TOT_VG; i++) {
- if (psys->vgroup[i]) {
- dataMask |= CD_MASK_MDEFORMVERT;
- break;
- }
- }
-
- /* particles only need this if they are after a non deform modifier, and
- * the modifier stack will only create them in that case. */
- dataMask |= CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORIGINDEX;
-
- dataMask |= CD_MASK_ORCO;
-
- return dataMask;
-}
-
-void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache,
- float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- if (psmd && psmd->dm_final) {
- if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) {
- if (vec)
- copy_v3_v3(vec, fuv);
-
- if (orco)
- copy_v3_v3(orco, fuv);
- return;
- }
- /* we cant use the num_dmcache */
- psys_particle_on_dm(psmd->dm_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco, ornor);
- }
- else
- psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco, ornor);
-
-}
-/************************************************/
-/* Path Cache */
-/************************************************/
-
-extern void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-extern float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-
-void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
-{
- EffectedPoint point;
- ParticleKey state;
- EffectorData efd;
- EffectorCache *eff;
- ParticleSystem *psys = sim->psys;
- EffectorWeights *weights = sim->psys->part->effector_weights;
- GuideEffectorData *data;
- PARTICLE_P;
-
- if (!effectors)
- return;
-
- LOOP_PARTICLES {
- psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, state.co, 0, 0, 0, 0, 0);
-
- mul_m4_v3(sim->ob->obmat, state.co);
- mul_mat3_m4_v3(sim->ob->obmat, state.vel);
-
- pd_point_from_particle(sim, pa, &state, &point);
-
- for (eff = effectors->first; eff; eff = eff->next) {
- if (eff->pd->forcefield != PFIELD_GUIDE)
- continue;
-
- if (!eff->guide_data)
- eff->guide_data = MEM_callocN(sizeof(GuideEffectorData) * psys->totpart, "GuideEffectorData");
-
- data = eff->guide_data + p;
-
- sub_v3_v3v3(efd.vec_to_point, state.co, eff->guide_loc);
- copy_v3_v3(efd.nor, eff->guide_dir);
- efd.distance = len_v3(efd.vec_to_point);
-
- copy_v3_v3(data->vec_to_point, efd.vec_to_point);
- data->strength = effector_falloff(eff, &efd, &point, weights);
- }
- }
-}
-
-int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
-{
- CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve : NULL;
- CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve : NULL;
- EffectorCache *eff;
- PartDeflect *pd;
- Curve *cu;
- GuideEffectorData *data;
-
- float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
- float guidevec[4], guidedir[3], rot2[4], temp[3];
- float guidetime, radius, weight, angle, totstrength = 0.0f;
- float vec_to_point[3];
-
- if (effectors) for (eff = effectors->first; eff; eff = eff->next) {
- pd = eff->pd;
-
- if (pd->forcefield != PFIELD_GUIDE)
- continue;
-
- data = eff->guide_data + index;
-
- if (data->strength <= 0.0f)
- continue;
-
- guidetime = time / (1.0f - pd->free_end);
-
- if (guidetime > 1.0f)
- continue;
-
- cu = (Curve *)eff->ob->data;
-
- if (pd->flag & PFIELD_GUIDE_PATH_ADD) {
- if (where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
- return 0;
- }
- else {
- if (where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
- return 0;
- }
-
- mul_m4_v3(eff->ob->obmat, guidevec);
- mul_mat3_m4_v3(eff->ob->obmat, guidedir);
-
- normalize_v3(guidedir);
-
- copy_v3_v3(vec_to_point, data->vec_to_point);
-
- if (guidetime != 0.0f) {
- /* curve direction */
- cross_v3_v3v3(temp, eff->guide_dir, guidedir);
- angle = dot_v3v3(eff->guide_dir, guidedir) / (len_v3(eff->guide_dir));
- angle = saacos(angle);
- axis_angle_to_quat(rot2, temp, angle);
- mul_qt_v3(rot2, vec_to_point);
-
- /* curve tilt */
- axis_angle_to_quat(rot2, guidedir, guidevec[3] - eff->guide_loc[3]);
- mul_qt_v3(rot2, vec_to_point);
- }
-
- /* curve taper */
- if (cu->taperobj)
- mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
-
- else { /* curve size*/
- if (cu->flag & CU_PATH_RADIUS) {
- mul_v3_fl(vec_to_point, radius);
- }
- }
-
- if (clumpcurve)
- curvemapping_changed_all(clumpcurve);
- if (roughcurve)
- curvemapping_changed_all(roughcurve);
-
- {
- ParticleKey key;
- float par_co[3] = {0.0f, 0.0f, 0.0f};
- float par_vel[3] = {0.0f, 0.0f, 0.0f};
- float par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- float orco_offset[3] = {0.0f, 0.0f, 0.0f};
-
- copy_v3_v3(key.co, vec_to_point);
- do_kink(&key, par_co, par_vel, par_rot, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, 0.f, pd->kink, pd->kink_axis, 0, 0);
- do_clump(&key, par_co, guidetime, orco_offset, pd->clump_fac, pd->clump_pow, 1.0f,
- part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
- copy_v3_v3(vec_to_point, key.co);
- }
-
- add_v3_v3(vec_to_point, guidevec);
-
- //sub_v3_v3v3(pa_loc, pa_loc, pa_zero);
- madd_v3_v3fl(effect, vec_to_point, data->strength);
- madd_v3_v3fl(veffect, guidedir, data->strength);
- totstrength += data->strength;
-
- if (pd->flag & PFIELD_GUIDE_PATH_WEIGHT)
- totstrength *= weight;
- }
-
- if (totstrength != 0.0f) {
- if (totstrength > 1.0f)
- mul_v3_fl(effect, 1.0f / totstrength);
- CLAMP(totstrength, 0.0f, 1.0f);
- //add_v3_v3(effect, pa_zero);
- interp_v3_v3v3(state->co, state->co, effect, totstrength);
-
- normalize_v3(veffect);
- mul_v3_fl(veffect, len_v3(state->vel));
- copy_v3_v3(state->vel, veffect);
- return 1;
- }
- return 0;
-}
-
-static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *UNUSED(rootco), float effector, float UNUSED(dfra), float UNUSED(cfra), float *length, float *vec)
-{
- float force[3] = {0.0f, 0.0f, 0.0f};
- ParticleKey eff_key;
- EffectedPoint epoint;
-
- /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */
- if (sim->psys->flag & PSYS_HAIR_DYNAMICS)
- return;
-
- copy_v3_v3(eff_key.co, (ca - 1)->co);
- copy_v3_v3(eff_key.vel, (ca - 1)->vel);
- copy_qt_qt(eff_key.rot, (ca - 1)->rot);
-
- pd_point_from_particle(sim, sim->psys->particles + i, &eff_key, &epoint);
- pdDoEffectors(sim->psys->effectors, sim->colliders, sim->psys->part->effector_weights, &epoint, force, NULL);
-
- mul_v3_fl(force, effector * powf((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps);
-
- add_v3_v3(force, vec);
-
- normalize_v3(force);
-
- if (k < steps)
- sub_v3_v3v3(vec, (ca + 1)->co, ca->co);
-
- madd_v3_v3v3fl(ca->co, (ca - 1)->co, force, *length);
-
- if (k < steps)
- *length = len_v3(vec);
-}
-static void offset_child(ChildParticle *cpa, ParticleKey *par, float *par_rot, ParticleKey *child, float flat, float radius)
-{
- copy_v3_v3(child->co, cpa->fuv);
- mul_v3_fl(child->co, radius);
-
- child->co[0] *= flat;
-
- copy_v3_v3(child->vel, par->vel);
-
- if (par_rot) {
- mul_qt_v3(par_rot, child->co);
- copy_qt_qt(child->rot, par_rot);
- }
- else
- unit_qt(child->rot);
-
- add_v3_v3(child->co, par->co);
-}
-float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup)
-{
- float *vg = 0;
-
- if (vgroup < 0) {
- /* hair dynamics pinning vgroup */
-
- }
- else if (psys->vgroup[vgroup]) {
- MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- if (dvert) {
- int totvert = dm->getNumVerts(dm), i;
- vg = MEM_callocN(sizeof(float) * totvert, "vg_cache");
- if (psys->vg_neg & (1 << vgroup)) {
- for (i = 0; i < totvert; i++)
- vg[i] = 1.0f - defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
- }
- else {
- for (i = 0; i < totvert; i++)
- vg[i] = defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
- }
- }
- }
- return vg;
-}
-void psys_find_parents(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = sim->psys->part;
- KDTree *tree;
- ChildParticle *cpa;
- ParticleTexture ptex;
- int p, totparent, totchild = sim->psys->totchild;
- float co[3], orco[3];
- int from = PART_FROM_FACE;
- totparent = (int)(totchild * part->parents * 0.3f);
-
- if ((sim->psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr)
- totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
-
- /* hard limit, workaround for it being ignored above */
- if (sim->psys->totpart < totparent) {
- totparent = sim->psys->totpart;
- }
-
- tree = BLI_kdtree_new(totparent);
-
- for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) {
- psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0);
-
- /* Check if particle doesn't exist because of texture influence. Insert only existing particles into kdtree. */
- get_cpa_texture(sim->psmd->dm_final, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
-
- if (ptex.exist >= psys_frand(psys, p + 24)) {
- BLI_kdtree_insert(tree, p, orco);
- }
- }
-
- BLI_kdtree_balance(tree);
-
- for (; p < totchild; p++, cpa++) {
- psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0);
- cpa->parent = BLI_kdtree_find_nearest(tree, orco, NULL);
- }
-
- BLI_kdtree_free(tree);
-}
-
-static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSimulationData *sim, Scene *scene, float cfra, int editupdate)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- int totparent = 0, between = 0;
- int segments = 1 << part->draw_step;
- int totchild = psys->totchild;
-
- psys_thread_context_init(ctx, sim);
-
- /*---start figuring out what is actually wanted---*/
- if (psys_in_edit_mode(scene, psys)) {
- ParticleEditSettings *pset = &scene->toolsettings->particle;
-
- if ((psys->renderdata == 0 && G.is_rendering == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
- totchild = 0;
-
- segments = 1 << pset->draw_step;
- }
-
- if (totchild && part->childtype == PART_CHILD_FACES) {
- totparent = (int)(totchild * part->parents * 0.3f);
-
- if ((psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr)
- totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
-
- /* part->parents could still be 0 so we can't test with totparent */
- between = 1;
- }
-
- if (psys->renderdata || G.is_rendering)
- segments = 1 << part->ren_step;
- else {
- totchild = (int)((float)totchild * (float)part->disp / 100.0f);
- totparent = MIN2(totparent, totchild);
- }
-
- if (totchild == 0)
- return false;
-
- /* fill context values */
- ctx->between = between;
- ctx->segments = segments;
- if (ELEM(part->kink, PART_KINK_SPIRAL))
- ctx->extra_segments = max_ii(part->kink_extra_steps, 1);
- else
- ctx->extra_segments = 0;
- ctx->totchild = totchild;
- ctx->totparent = totparent;
- ctx->parent_pass = 0;
- ctx->cfra = cfra;
- ctx->editupdate = editupdate;
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim);
-
- /* cache all relevant vertex groups if they exist */
- ctx->vg_length = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_LENGTH);
- ctx->vg_clump = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_CLUMP);
- ctx->vg_kink = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_KINK);
- ctx->vg_rough1 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH1);
- ctx->vg_rough2 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH2);
- ctx->vg_roughe = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGHE);
- if (psys->part->flag & PART_CHILD_EFFECT)
- ctx->vg_effector = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_EFFECTOR);
-
- /* prepare curvemapping tables */
- if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve) {
- ctx->clumpcurve = curvemapping_copy(part->clumpcurve);
- curvemapping_changed_all(ctx->clumpcurve);
- }
- else {
- ctx->clumpcurve = NULL;
- }
- if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve) {
- ctx->roughcurve = curvemapping_copy(part->roughcurve);
- curvemapping_changed_all(ctx->roughcurve);
- }
- else {
- ctx->roughcurve = NULL;
- }
-
- return true;
-}
-
-static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim)
-{
- /* init random number generator */
- int seed = 31415926 + sim->psys->seed;
-
- task->rng_path = BLI_rng_new(seed);
-}
-
-/* note: this function must be thread safe, except for branching! */
-static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
-{
- ParticleThreadContext *ctx = task->ctx;
- Object *ob = ctx->sim.ob;
- ParticleSystem *psys = ctx->sim.psys;
- ParticleSettings *part = psys->part;
- ParticleCacheKey **cache = psys->childcache;
- ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.scene, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
- ParticleCacheKey *child, *key[4];
- ParticleTexture ptex;
- float *cpa_fuv = 0, *par_rot = 0, rot[4];
- float orco[3], ornor[3], hairmat[4][4], dvec[3], off1[4][3], off2[4][3];
- float eff_length, eff_vec[3], weight[4];
- int k, cpa_num;
- short cpa_from;
-
- if (!pcache)
- return;
-
- if (ctx->between) {
- ParticleData *pa = psys->particles + cpa->pa[0];
- int w, needupdate;
- float foffset, wsum = 0.f;
- float co[3];
- float p_min = part->parting_min;
- float p_max = part->parting_max;
- /* Virtual parents don't work nicely with parting. */
- float p_fac = part->parents > 0.f ? 0.f : part->parting_fac;
-
- if (ctx->editupdate) {
- needupdate = 0;
- w = 0;
- while (w < 4 && cpa->pa[w] >= 0) {
- if (psys->edit->points[cpa->pa[w]].flag & PEP_EDIT_RECALC) {
- needupdate = 1;
- break;
- }
- w++;
- }
-
- if (!needupdate)
- return;
- else
- memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
- }
-
- /* get parent paths */
- for (w = 0; w < 4; w++) {
- if (cpa->pa[w] >= 0) {
- key[w] = pcache[cpa->pa[w]];
- weight[w] = cpa->w[w];
- }
- else {
- key[w] = pcache[0];
- weight[w] = 0.f;
- }
- }
-
- /* modify weights to create parting */
- if (p_fac > 0.f) {
- for (w = 0; w < 4; w++) {
- if (w && weight[w] > 0.f) {
- float d;
- if (part->flag & PART_CHILD_LONG_HAIR) {
- /* For long hair use tip distance/root distance as parting factor instead of root to tip angle. */
- float d1 = len_v3v3(key[0]->co, key[w]->co);
- float d2 = len_v3v3((key[0] + key[0]->segments - 1)->co, (key[w] + key[w]->segments - 1)->co);
-
- d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f;
- }
- else {
- float v1[3], v2[3];
- sub_v3_v3v3(v1, (key[0] + key[0]->segments - 1)->co, key[0]->co);
- sub_v3_v3v3(v2, (key[w] + key[w]->segments - 1)->co, key[w]->co);
- normalize_v3(v1);
- normalize_v3(v2);
-
- d = RAD2DEGF(saacos(dot_v3v3(v1, v2)));
- }
-
- if (p_max > p_min)
- d = (d - p_min) / (p_max - p_min);
- else
- d = (d - p_min) <= 0.f ? 0.f : 1.f;
-
- CLAMP(d, 0.f, 1.f);
-
- if (d > 0.f)
- weight[w] *= (1.f - d);
- }
- wsum += weight[w];
- }
- for (w = 0; w < 4; w++)
- weight[w] /= wsum;
-
- interp_v4_v4v4(weight, cpa->w, weight, p_fac);
- }
-
- /* get the original coordinates (orco) for texture usage */
- cpa_num = cpa->num;
-
- foffset = cpa->foffset;
- cpa_fuv = cpa->fuv;
- cpa_from = PART_FROM_FACE;
-
- psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, ornor, 0, 0, orco, 0);
-
- mul_m4_v3(ob->obmat, co);
-
- for (w = 0; w < 4; w++)
- sub_v3_v3v3(off1[w], co, key[w]->co);
-
- psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
- }
- else {
- ParticleData *pa = psys->particles + cpa->parent;
- float co[3];
- if (ctx->editupdate) {
- if (!(psys->edit->points[cpa->parent].flag & PEP_EDIT_RECALC))
- return;
-
- memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
- }
-
- /* get the parent path */
- key[0] = pcache[cpa->parent];
-
- /* get the original coordinates (orco) for texture usage */
- cpa_from = part->from;
- cpa_num = pa->num;
- /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
- if (cpa_num > ctx->sim.psmd->dm_final->getNumTessFaces(ctx->sim.psmd->dm_final))
- cpa_num = 0;
- cpa_fuv = pa->fuv;
-
- psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, ornor, 0, 0, orco, 0);
-
- psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
- }
-
- child_keys->segments = ctx->segments;
-
- /* get different child parameters from textures & vgroups */
- get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
-
- if (ptex.exist < psys_frand(psys, i + 24)) {
- child_keys->segments = -1;
- return;
- }
-
- /* create the child path */
- for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
- if (ctx->between) {
- int w = 0;
-
- zero_v3(child->co);
- zero_v3(child->vel);
- unit_qt(child->rot);
-
- for (w = 0; w < 4; w++) {
- copy_v3_v3(off2[w], off1[w]);
-
- if (part->flag & PART_CHILD_LONG_HAIR) {
- /* Use parent rotation (in addition to emission location) to determine child offset. */
- if (k)
- mul_qt_v3((key[w] + k)->rot, off2[w]);
-
- /* Fade the effect of rotation for even lengths in the end */
- project_v3_v3v3(dvec, off2[w], (key[w] + k)->vel);
- madd_v3_v3fl(off2[w], dvec, -(float)k / (float)ctx->segments);
- }
-
- add_v3_v3(off2[w], (key[w] + k)->co);
- }
-
- /* child position is the weighted sum of parent positions */
- interp_v3_v3v3v3v3(child->co, off2[0], off2[1], off2[2], off2[3], weight);
- interp_v3_v3v3v3v3(child->vel, (key[0] + k)->vel, (key[1] + k)->vel, (key[2] + k)->vel, (key[3] + k)->vel, weight);
-
- copy_qt_qt(child->rot, (key[0] + k)->rot);
- }
- else {
- if (k) {
- mul_qt_qtqt(rot, (key[0] + k)->rot, key[0]->rot);
- par_rot = rot;
- }
- else {
- par_rot = key[0]->rot;
- }
- /* offset the child from the parent position */
- offset_child(cpa, (ParticleKey *)(key[0] + k), par_rot, (ParticleKey *)child, part->childflat, part->childrad);
- }
-
- child->time = (float)k / (float)ctx->segments;
- }
-
- /* apply effectors */
- if (part->flag & PART_CHILD_EFFECT) {
- for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
- if (k) {
- do_path_effectors(&ctx->sim, cpa->pa[0], child, k, ctx->segments, child_keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
- }
- else {
- sub_v3_v3v3(eff_vec, (child + 1)->co, child->co);
- eff_length = len_v3(eff_vec);
- }
- }
- }
-
- {
- ParticleData *pa = NULL;
- ParticleCacheKey *par = NULL;
- float par_co[3];
- float par_orco[3];
-
- if (ctx->totparent) {
- if (i >= ctx->totparent) {
- pa = &psys->particles[cpa->parent];
- /* this is now threadsafe, virtual parents are calculated before rest of children */
- BLI_assert(cpa->parent < psys->totchildcache);
- par = cache[cpa->parent];
- }
- }
- else if (cpa->parent >= 0) {
- pa = &psys->particles[cpa->parent];
- par = pcache[cpa->parent];
-
- /* If particle is unexisting, try to pick a viable parent from particles used for interpolation. */
- for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) {
- if (cpa->pa[k] >= 0) {
- pa = &psys->particles[cpa->pa[k]];
- par = pcache[cpa->pa[k]];
- }
- }
-
- if (pa->flag & PARS_UNEXIST) pa = NULL;
- }
-
- if (pa) {
- ListBase modifiers;
- BLI_listbase_clear(&modifiers);
-
- psys_particle_on_emitter(ctx->sim.psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset,
- par_co, NULL, NULL, NULL, par_orco, NULL);
-
- psys_apply_child_modifiers(ctx, &modifiers, cpa, &ptex, orco, ornor, hairmat, child_keys, par, par_orco);
- }
- else
- zero_v3(par_orco);
- }
-
- /* Hide virtual parents */
- if (i < ctx->totparent)
- child_keys->segments = -1;
-}
-
-static void exec_child_path_cache(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- ParticleTask *task = taskdata;
- ParticleThreadContext *ctx = task->ctx;
- ParticleSystem *psys = ctx->sim.psys;
- ParticleCacheKey **cache = psys->childcache;
- ChildParticle *cpa;
- int i;
-
- cpa = psys->child + task->begin;
- for (i = task->begin; i < task->end; ++i, ++cpa) {
- BLI_assert(i < psys->totchildcache);
- psys_thread_create_path(task, cpa, cache[i], i);
- }
-}
-
-void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate)
-{
- TaskScheduler *task_scheduler;
- TaskPool *task_pool;
- ParticleThreadContext ctx;
- ParticleTask *tasks_parent, *tasks_child;
- int numtasks_parent, numtasks_child;
- int i, totchild, totparent;
-
- if (sim->psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- /* create a task pool for child path tasks */
- if (!psys_thread_context_init_path(&ctx, sim, sim->scene, cfra, editupdate))
- return;
-
- task_scheduler = BLI_task_scheduler_get();
- task_pool = BLI_task_pool_create(task_scheduler, &ctx);
- totchild = ctx.totchild;
- totparent = ctx.totparent;
-
- if (editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
- ; /* just overwrite the existing cache */
- }
- else {
- /* clear out old and create new empty path cache */
- free_child_path_cache(sim->psys);
-
- sim->psys->childcache = psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx.segments + ctx.extra_segments + 1);
- sim->psys->totchildcache = totchild;
- }
-
- /* cache parent paths */
- ctx.parent_pass = 1;
- psys_tasks_create(&ctx, 0, totparent, &tasks_parent, &numtasks_parent);
- for (i = 0; i < numtasks_parent; ++i) {
- ParticleTask *task = &tasks_parent[i];
-
- psys_task_init_path(task, sim);
- BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
- }
- BLI_task_pool_work_and_wait(task_pool);
-
- /* cache child paths */
- ctx.parent_pass = 0;
- psys_tasks_create(&ctx, totparent, totchild, &tasks_child, &numtasks_child);
- for (i = 0; i < numtasks_child; ++i) {
- ParticleTask *task = &tasks_child[i];
-
- psys_task_init_path(task, sim);
- BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
- }
- BLI_task_pool_work_and_wait(task_pool);
-
- BLI_task_pool_free(task_pool);
-
- psys_tasks_free(tasks_parent, numtasks_parent);
- psys_tasks_free(tasks_child, numtasks_child);
-
- psys_thread_context_free(&ctx);
-}
-
-/* figure out incremental rotations along path starting from unit quat */
-static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i)
-{
- float cosangle, angle, tangent[3], normal[3], q[4];
-
- switch (i) {
- case 0:
- /* start from second key */
- break;
- case 1:
- /* calculate initial tangent for incremental rotations */
- sub_v3_v3v3(prev_tangent, key0->co, key1->co);
- normalize_v3(prev_tangent);
- unit_qt(key1->rot);
- break;
- default:
- sub_v3_v3v3(tangent, key0->co, key1->co);
- normalize_v3(tangent);
-
- cosangle = dot_v3v3(tangent, prev_tangent);
-
- /* note we do the comparison on cosangle instead of
- * angle, since floating point accuracy makes it give
- * different results across platforms */
- if (cosangle > 0.999999f) {
- copy_v4_v4(key1->rot, key2->rot);
- }
- else {
- angle = saacos(cosangle);
- cross_v3_v3v3(normal, prev_tangent, tangent);
- axis_angle_to_quat(q, normal, angle);
- mul_qt_qtqt(key1->rot, q, key2->rot);
- }
-
- copy_v3_v3(prev_tangent, tangent);
- }
-}
-
-/**
- * Calculates paths ready for drawing/rendering
- * - Useful for making use of opengl vertex arrays for super fast strand drawing.
- * - Makes child strands possible and creates them too into the cache.
- * - Cached path data is also used to determine cut position for the editmode tool. */
-void psys_cache_paths(ParticleSimulationData *sim, float cfra)
-{
- PARTICLE_PSMD;
- ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleCacheKey *ca, **cache;
-
- DerivedMesh *hair_dm = (psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) ? psys->hair_out_dm : NULL;
-
- ParticleKey result;
-
- Material *ma;
- ParticleInterpolationData pind;
- ParticleTexture ptex;
-
- PARTICLE_P;
-
- float birthtime = 0.0, dietime = 0.0;
- float t, time = 0.0, dfra = 1.0 /* , frs_sec = sim->scene->r.frs_sec*/ /*UNUSED*/;
- float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
- float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
- float rotmat[3][3];
- int k;
- int segments = (int)pow(2.0, (double)((psys->renderdata || G.is_rendering) ? part->ren_step : part->draw_step));
- int totpart = psys->totpart;
- float length, vec[3];
- float *vg_effector = NULL;
- float *vg_length = NULL, pa_length = 1.0f;
- int keyed, baked;
-
- /* we don't have anything valid to create paths from so let's quit here */
- if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0)
- return;
-
- if (psys_in_edit_mode(sim->scene, psys))
- if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
- return;
-
- keyed = psys->flag & PSYS_KEYED;
- baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
-
- /* clear out old and create new empty path cache */
- psys_free_path_cache(psys, psys->edit);
- cache = psys->pathcache = psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, segments + 1);
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
- ma = give_current_material(sim->ob, psys->part->omat);
- if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT))
- copy_v3_v3(col, &ma->r);
-
- if ((psys->flag & PSYS_GLOBAL_HAIR) == 0) {
- if ((psys->part->flag & PART_CHILD_EFFECT) == 0)
- vg_effector = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_EFFECTOR);
-
- if (!psys->totchild)
- vg_length = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_LENGTH);
- }
-
- /* ensure we have tessfaces to be used for mapping */
- if (part->from != PART_FROM_VERT) {
- DM_ensure_tessface(psmd->dm_final);
- }
-
- /*---first main loop: create all actual particles' paths---*/
- LOOP_PARTICLES {
- if (!psys->totchild) {
- psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
- pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
- if (vg_length)
- pa_length *= psys_particle_value_from_verts(psmd->dm_final, part->from, pa, vg_length);
- }
-
- pind.keyed = keyed;
- pind.cache = baked ? psys->pointcache : NULL;
- pind.epoint = NULL;
- pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
- pind.dm = hair_dm;
-
- memset(cache[p], 0, sizeof(*cache[p]) * (segments + 1));
-
- cache[p]->segments = segments;
-
- /*--get the first data points--*/
- init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
-
- /* hairmat is needed for for non-hair particle too so we get proper rotations */
- psys_mat_hair_to_global(sim->ob, psmd->dm_final, psys->part->from, pa, hairmat);
- copy_v3_v3(rotmat[0], hairmat[2]);
- copy_v3_v3(rotmat[1], hairmat[1]);
- copy_v3_v3(rotmat[2], hairmat[0]);
-
- if (part->draw & PART_ABS_PATH_TIME) {
- birthtime = MAX2(pind.birthtime, part->path_start);
- dietime = MIN2(pind.dietime, part->path_end);
- }
- else {
- float tb = pind.birthtime;
- birthtime = tb + part->path_start * (pind.dietime - tb);
- dietime = tb + part->path_end * (pind.dietime - tb);
- }
-
- if (birthtime >= dietime) {
- cache[p]->segments = -1;
- continue;
- }
-
- dietime = birthtime + pa_length * (dietime - birthtime);
-
- /*--interpolate actual path from data points--*/
- for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
- time = (float)k / (float)segments;
- t = birthtime + time * (dietime - birthtime);
- result.time = -t;
- do_particle_interpolation(psys, p, pa, t, &pind, &result);
- copy_v3_v3(ca->co, result.co);
-
- /* dynamic hair is in object space */
- /* keyed and baked are already in global space */
- if (hair_dm)
- mul_m4_v3(sim->ob->obmat, ca->co);
- else if (!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR))
- mul_m4_v3(hairmat, ca->co);
-
- copy_v3_v3(ca->col, col);
- }
-
- if (part->type == PART_HAIR) {
- HairKey *hkey;
-
- for (k = 0, hkey = pa->hair; k < pa->totkey; ++k, ++hkey) {
- mul_v3_m4v3(hkey->world_co, hairmat, hkey->co);
- }
- }
-
- /*--modify paths and calculate rotation & velocity--*/
-
- if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
- /* apply effectors */
- if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
- float effector = 1.0f;
- if (vg_effector)
- effector *= psys_particle_value_from_verts(psmd->dm_final, psys->part->from, pa, vg_effector);
-
- sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
- length = len_v3(vec);
-
- for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++)
- do_path_effectors(sim, p, ca, k, segments, cache[p]->co, effector, dfra, cfra, &length, vec);
- }
-
- /* apply guide curves to path data */
- if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) {
- for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
- /* ca is safe to cast, since only co and vel are used */
- do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments);
- }
-
- /* lattices have to be calculated separately to avoid mixups between effector calculations */
- if (psys->lattice_deform_data) {
- for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
- calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f);
- }
- }
-
- /* finally do rotation & velocity */
- for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++) {
- cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
-
- if (k == segments)
- copy_qt_qt(ca->rot, (ca - 1)->rot);
-
- /* set velocity */
- sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
-
- if (k == 1)
- copy_v3_v3((ca - 1)->vel, ca->vel);
-
- ca->time = (float)k / (float)segments;
- }
- /* First rotation is based on emitting face orientation.
- * This is way better than having flipping rotations resulting
- * from using a global axis as a rotation pole (vec_to_quat()).
- * It's not an ideal solution though since it disregards the
- * initial tangent, but taking that in to account will allow
- * the possibility of flipping again. -jahka
- */
- mat3_to_quat_is_ok(cache[p]->rot, rotmat);
- }
-
- psys->totcached = totpart;
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (vg_effector)
- MEM_freeN(vg_effector);
-
- if (vg_length)
- MEM_freeN(vg_length);
-}
-void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cfra)
-{
- ParticleCacheKey *ca, **cache = edit->pathcache;
- ParticleEditSettings *pset = &scene->toolsettings->particle;
-
- PTCacheEditPoint *point = NULL;
- PTCacheEditKey *ekey = NULL;
-
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- ParticleData *pa = psys ? psys->particles : NULL;
-
- ParticleInterpolationData pind;
- ParticleKey result;
-
- float birthtime = 0.0f, dietime = 0.0f;
- float t, time = 0.0f, keytime = 0.0f /*, frs_sec */;
- float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f};
- int k, i;
- int segments = 1 << pset->draw_step;
- int totpart = edit->totpoint, recalc_set = 0;
- float sel_col[3];
- float nosel_col[3];
-
- segments = MAX2(segments, 4);
-
- if (!cache || edit->totpoint != edit->totcached) {
- /* clear out old and create new empty path cache */
- psys_free_path_cache(edit->psys, edit);
- cache = edit->pathcache = psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, segments + 1);
-
- /* set flag for update (child particles check this too) */
- for (i = 0, point = edit->points; i < totpart; i++, point++)
- point->flag |= PEP_EDIT_RECALC;
- recalc_set = 1;
- }
-
- /* frs_sec = (psys || edit->pid.flag & PTCACHE_VEL_PER_SEC) ? 25.0f : 1.0f; */ /* UNUSED */
-
- if (pset->brushtype == PE_BRUSH_WEIGHT) {
- ; /* use weight painting colors now... */
- }
- else {
- sel_col[0] = (float)edit->sel_col[0] / 255.0f;
- sel_col[1] = (float)edit->sel_col[1] / 255.0f;
- sel_col[2] = (float)edit->sel_col[2] / 255.0f;
- nosel_col[0] = (float)edit->nosel_col[0] / 255.0f;
- nosel_col[1] = (float)edit->nosel_col[1] / 255.0f;
- nosel_col[2] = (float)edit->nosel_col[2] / 255.0f;
- }
-
- /*---first main loop: create all actual particles' paths---*/
- for (i = 0, point = edit->points; i < totpart; i++, pa += pa ? 1 : 0, point++) {
- if (edit->totcached && !(point->flag & PEP_EDIT_RECALC))
- continue;
-
- if (point->totkey == 0)
- continue;
-
- ekey = point->keys;
-
- pind.keyed = 0;
- pind.cache = NULL;
- pind.epoint = point;
- pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0;
- pind.dm = NULL;
-
-
- /* should init_particle_interpolation set this ? */
- if (pset->brushtype == PE_BRUSH_WEIGHT) {
- pind.hkey[0] = NULL;
- /* pa != NULL since the weight brush is only available for hair */
- pind.hkey[1] = pa->hair;
- }
-
-
- memset(cache[i], 0, sizeof(*cache[i]) * (segments + 1));
-
- cache[i]->segments = segments;
-
- /*--get the first data points--*/
- init_particle_interpolation(ob, psys, pa, &pind);
-
- if (psys) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
- copy_v3_v3(rotmat[0], hairmat[2]);
- copy_v3_v3(rotmat[1], hairmat[1]);
- copy_v3_v3(rotmat[2], hairmat[0]);
- }
-
- birthtime = pind.birthtime;
- dietime = pind.dietime;
-
- if (birthtime >= dietime) {
- cache[i]->segments = -1;
- continue;
- }
-
- /*--interpolate actual path from data points--*/
- for (k = 0, ca = cache[i]; k <= segments; k++, ca++) {
- time = (float)k / (float)segments;
- t = birthtime + time * (dietime - birthtime);
- result.time = -t;
- do_particle_interpolation(psys, i, pa, t, &pind, &result);
- copy_v3_v3(ca->co, result.co);
-
- /* non-hair points are already in global space */
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- mul_m4_v3(hairmat, ca->co);
-
- if (k) {
- cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
-
- if (k == segments)
- copy_qt_qt(ca->rot, (ca - 1)->rot);
-
- /* set velocity */
- sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
-
- if (k == 1)
- copy_v3_v3((ca - 1)->vel, ca->vel);
- }
- }
- else {
- ca->vel[0] = ca->vel[1] = 0.0f;
- ca->vel[2] = 1.0f;
- }
-
- /* selection coloring in edit mode */
- if (pset->brushtype == PE_BRUSH_WEIGHT) {
- float t2;
-
- if (k == 0) {
- weight_to_rgb(ca->col, pind.hkey[1]->weight);
- }
- else {
- float w1[3], w2[3];
- keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
-
- weight_to_rgb(w1, pind.hkey[0]->weight);
- weight_to_rgb(w2, pind.hkey[1]->weight);
-
- interp_v3_v3v3(ca->col, w1, w2, keytime);
- }
-
- /* at the moment this is only used for weight painting.
- * will need to move out of this check if its used elsewhere. */
- t2 = birthtime + ((float)k / (float)segments) * (dietime - birthtime);
-
- while (pind.hkey[1]->time < t2) pind.hkey[1]++;
- pind.hkey[0] = pind.hkey[1] - 1;
- }
- else {
- if ((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT) {
- if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
- copy_v3_v3(ca->col, sel_col);
- }
- else {
- keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
- interp_v3_v3v3(ca->col, sel_col, nosel_col, keytime);
- }
- }
- else {
- if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
- keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
- interp_v3_v3v3(ca->col, nosel_col, sel_col, keytime);
- }
- else {
- copy_v3_v3(ca->col, nosel_col);
- }
- }
- }
-
- ca->time = t;
- }
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- /* First rotation is based on emitting face orientation.
- * This is way better than having flipping rotations resulting
- * from using a global axis as a rotation pole (vec_to_quat()).
- * It's not an ideal solution though since it disregards the
- * initial tangent, but taking that in to account will allow
- * the possibility of flipping again. -jahka
- */
- mat3_to_quat_is_ok(cache[i]->rot, rotmat);
- }
- }
-
- edit->totcached = totpart;
-
- if (psys) {
- ParticleSimulationData sim = {0};
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- psys_cache_child_paths(&sim, cfra, 1);
- }
-
- /* clear recalc flag if set here */
- if (recalc_set) {
- for (i = 0, point = edit->points; i < totpart; i++, point++)
- point->flag &= ~PEP_EDIT_RECALC;
- }
-}
-/************************************************/
-/* Particle Key handling */
-/************************************************/
-void copy_particle_key(ParticleKey *to, ParticleKey *from, int time)
-{
- if (time) {
- memcpy(to, from, sizeof(ParticleKey));
- }
- else {
- float to_time = to->time;
- memcpy(to, from, sizeof(ParticleKey));
- to->time = to_time;
- }
-}
-void psys_get_from_key(ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time)
-{
- if (loc) copy_v3_v3(loc, key->co);
- if (vel) copy_v3_v3(vel, key->vel);
- if (rot) copy_qt_qt(rot, key->rot);
- if (time) *time = key->time;
-}
-/*-------changing particle keys from space to another-------*/
-#if 0
-static void key_from_object(Object *ob, ParticleKey *key)
-{
- float q[4];
-
- add_v3_v3(key->vel, key->co);
-
- mul_m4_v3(ob->obmat, key->co);
- mul_m4_v3(ob->obmat, key->vel);
- mat4_to_quat(q, ob->obmat);
-
- sub_v3_v3v3(key->vel, key->vel, key->co);
- mul_qt_qtqt(key->rot, q, key->rot);
-}
-#endif
-
-static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[4][4])
-{
- float det, w1, w2, d1[2], d2[2];
-
- memset(mat, 0, sizeof(float) * 4 * 4);
- mat[3][3] = 1.0f;
-
- /* first axis is the normal */
- normal_tri_v3(mat[2], v1, v2, v3);
-
- /* second axis along (1, 0) in uv space */
- if (uv) {
- d1[0] = uv[1][0] - uv[0][0];
- d1[1] = uv[1][1] - uv[0][1];
- d2[0] = uv[2][0] - uv[0][0];
- d2[1] = uv[2][1] - uv[0][1];
-
- det = d2[0] * d1[1] - d2[1] * d1[0];
-
- if (det != 0.0f) {
- det = 1.0f / det;
- w1 = -d2[1] * det;
- w2 = d1[1] * det;
-
- mat[1][0] = w1 * (v2[0] - v1[0]) + w2 * (v3[0] - v1[0]);
- mat[1][1] = w1 * (v2[1] - v1[1]) + w2 * (v3[1] - v1[1]);
- mat[1][2] = w1 * (v2[2] - v1[2]) + w2 * (v3[2] - v1[2]);
- normalize_v3(mat[1]);
- }
- else
- mat[1][0] = mat[1][1] = mat[1][2] = 0.0f;
- }
- else {
- sub_v3_v3v3(mat[1], v2, v1);
- normalize_v3(mat[1]);
- }
-
- /* third as a cross product */
- cross_v3_v3v3(mat[0], mat[1], mat[2]);
-}
-
-static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float mat[4][4], int orco)
-{
- float v[3][3];
- MFace *mface;
- OrigSpaceFace *osface;
- float (*orcodata)[3];
-
- int i = (ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? pa->num : pa->num_dmcache;
- if (i == -1 || i >= dm->getNumTessFaces(dm)) { unit_m4(mat); return; }
-
- mface = dm->getTessFaceData(dm, i, CD_MFACE);
- osface = dm->getTessFaceData(dm, i, CD_ORIGSPACE);
-
- if (orco && (orcodata = dm->getVertDataArray(dm, CD_ORCO))) {
- copy_v3_v3(v[0], orcodata[mface->v1]);
- copy_v3_v3(v[1], orcodata[mface->v2]);
- copy_v3_v3(v[2], orcodata[mface->v3]);
-
- /* ugly hack to use non-transformed orcos, since only those
- * give symmetric results for mirroring in particle mode */
- if (DM_get_vert_data_layer(dm, CD_ORIGINDEX))
- BKE_mesh_orco_verts_transform(ob->data, v, 3, 1);
- }
- else {
- dm->getVertCo(dm, mface->v1, v[0]);
- dm->getVertCo(dm, mface->v2, v[1]);
- dm->getVertCo(dm, mface->v3, v[2]);
- }
-
- triatomat(v[0], v[1], v[2], (osface) ? osface->uv : NULL, mat);
-}
-
-void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
-{
- float vec[3];
-
- /* can happen when called from a different object's modifier */
- if (!dm) {
- unit_m4(hairmat);
- return;
- }
-
- psys_face_mat(0, dm, pa, hairmat, 0);
- psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0, 0);
- copy_v3_v3(hairmat[3], vec);
-}
-
-void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
-{
- float vec[3], orco[3];
-
- psys_face_mat(ob, dm, pa, hairmat, 1);
- psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco, 0);
-
- /* see psys_face_mat for why this function is called */
- if (DM_get_vert_data_layer(dm, CD_ORIGINDEX))
- BKE_mesh_orco_verts_transform(ob->data, &orco, 1, 1);
- copy_v3_v3(hairmat[3], orco);
-}
-
-void psys_vec_rot_to_face(DerivedMesh *dm, ParticleData *pa, float vec[3])
-{
- float mat[4][4];
-
- psys_face_mat(0, dm, pa, mat, 0);
- transpose_m4(mat); /* cheap inverse for rotation matrix */
- mul_mat3_m4_v3(mat, vec);
-}
-
-void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
-{
- float facemat[4][4];
-
- psys_mat_hair_to_object(ob, dm, from, pa, facemat);
-
- mul_m4_m4m4(hairmat, ob->obmat, facemat);
-}
-
-/************************************************/
-/* ParticleSettings handling */
-/************************************************/
-ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *name)
-{
- ParticleSystem *psys;
- ModifierData *md;
- ParticleSystemModifierData *psmd;
-
- if (!ob || ob->type != OB_MESH)
- return NULL;
-
- psys = ob->particlesystem.first;
- for (; psys; psys = psys->next)
- psys->flag &= ~PSYS_CURRENT;
-
- psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- BLI_addtail(&ob->particlesystem, psys);
-
- psys->part = psys_new_settings(DATA_("ParticleSettings"), NULL);
-
- if (BLI_listbase_count_ex(&ob->particlesystem, 2) > 1)
- BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
- else
- BLI_strncpy(psys->name, DATA_("ParticleSystem"), sizeof(psys->name));
-
- md = modifier_new(eModifierType_ParticleSystem);
-
- if (name)
- BLI_strncpy_utf8(md->name, name, sizeof(md->name));
- else
- BLI_snprintf(md->name, sizeof(md->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
- modifier_unique_name(&ob->modifiers, md);
-
- psmd = (ParticleSystemModifierData *) md;
- psmd->psys = psys;
- BLI_addtail(&ob->modifiers, md);
-
- psys->totpart = 0;
- psys->flag = PSYS_CURRENT;
- psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1);
-
- DAG_relations_tag_update(G.main);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- return md;
-}
-void object_remove_particle_system(Scene *UNUSED(scene), Object *ob)
-{
- ParticleSystem *psys = psys_get_current(ob);
- ParticleSystemModifierData *psmd;
- ModifierData *md;
-
- if (!psys)
- return;
-
- /* clear all other appearances of this pointer (like on smoke flow modifier) */
- if ((md = modifiers_findByType(ob, eModifierType_Smoke))) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type == MOD_SMOKE_TYPE_FLOW) && smd->flow && smd->flow->psys)
- if (smd->flow->psys == psys)
- smd->flow->psys = NULL;
- }
-
- if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint))) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->brush && pmd->brush->psys)
- if (pmd->brush->psys == psys)
- pmd->brush->psys = NULL;
- }
-
- /* clear modifier */
- psmd = psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
-
- /* clear particle system */
- BLI_remlink(&ob->particlesystem, psys);
- psys_free(ob, psys);
-
- if (ob->particlesystem.first)
- ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT;
- else
- ob->mode &= ~OB_MODE_PARTICLE_EDIT;
-
- DAG_relations_tag_update(G.main);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-}
-
-static void default_particle_settings(ParticleSettings *part)
-{
- part->type = PART_EMITTER;
- part->distr = PART_DISTR_JIT;
- part->draw_as = PART_DRAW_REND;
- part->ren_as = PART_DRAW_HALO;
- part->bb_uv_split = 1;
- part->bb_align = PART_BB_VIEW;
- part->bb_split_offset = PART_BB_OFF_LINEAR;
- part->flag = PART_EDISTR | PART_TRAND | PART_HIDE_ADVANCED_HAIR;
-
- part->sta = 1.0;
- part->end = 200.0;
- part->lifetime = 50.0;
- part->jitfac = 1.0;
- part->totpart = 1000;
- part->grid_res = 10;
- part->timetweak = 1.0;
- part->courant_target = 0.2;
-
- part->integrator = PART_INT_MIDPOINT;
- part->phystype = PART_PHYS_NEWTON;
- part->hair_step = 5;
- part->keys_step = 5;
- part->draw_step = 2;
- part->ren_step = 3;
- part->adapt_angle = 5;
- part->adapt_pix = 3;
- part->kink_axis = 2;
- part->kink_amp_clump = 1.f;
- part->kink_extra_steps = 4;
- part->clump_noise_size = 1.0f;
- part->reactevent = PART_EVENT_DEATH;
- part->disp = 100;
- part->from = PART_FROM_FACE;
-
- part->normfac = 1.0f;
-
- part->mass = 1.0;
- part->size = 0.05;
- part->childsize = 1.0;
-
- part->rotmode = PART_ROT_VEL;
- part->avemode = PART_AVE_VELOCITY;
-
- part->child_nbr = 10;
- part->ren_child_nbr = 100;
- part->childrad = 0.2f;
- part->childflat = 0.0f;
- part->clumppow = 0.0f;
- part->kink_amp = 0.2f;
- part->kink_freq = 2.0;
-
- part->rough1_size = 1.0;
- part->rough2_size = 1.0;
- part->rough_end_shape = 1.0;
-
- part->clength = 1.0f;
- part->clength_thres = 0.0f;
-
- part->draw = PART_DRAW_EMITTER;
- part->draw_line[0] = 0.5;
- part->path_start = 0.0f;
- part->path_end = 1.0f;
-
- part->bb_size[0] = part->bb_size[1] = 1.0f;
-
- part->keyed_loops = 1;
-
- part->color_vec_max = 1.f;
- part->draw_col = PART_DRAW_COL_MAT;
-
- part->simplify_refsize = 1920;
- part->simplify_rate = 1.0f;
- part->simplify_transition = 0.1f;
- part->simplify_viewport = 0.8;
-
- if (!part->effector_weights)
- part->effector_weights = BKE_add_effector_weights(NULL);
-
- part->omat = 1;
- part->use_modifier_stack = false;
-}
-
-
-ParticleSettings *psys_new_settings(const char *name, Main *main)
-{
- ParticleSettings *part;
-
- if (main == NULL)
- main = G.main;
-
- part = BKE_libblock_alloc(main, ID_PA, name);
-
- default_particle_settings(part);
-
- return part;
-}
-
-void BKE_particlesettings_clump_curve_init(ParticleSettings *part)
-{
- CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
-
- cumap->cm[0].curve[0].x = 0.0f;
- cumap->cm[0].curve[0].y = 1.0f;
- cumap->cm[0].curve[1].x = 1.0f;
- cumap->cm[0].curve[1].y = 1.0f;
-
- part->clumpcurve = cumap;
-}
-
-void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
-{
- CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
-
- cumap->cm[0].curve[0].x = 0.0f;
- cumap->cm[0].curve[0].y = 1.0f;
- cumap->cm[0].curve[1].x = 1.0f;
- cumap->cm[0].curve[1].y = 1.0f;
-
- part->roughcurve = cumap;
-}
-
-ParticleSettings *BKE_particlesettings_copy(ParticleSettings *part)
-{
- ParticleSettings *partn;
- int a;
-
- partn = BKE_libblock_copy(&part->id);
- partn->pd = MEM_dupallocN(part->pd);
- partn->pd2 = MEM_dupallocN(part->pd2);
- partn->effector_weights = MEM_dupallocN(part->effector_weights);
- partn->fluid = MEM_dupallocN(part->fluid);
-
- if (part->clumpcurve)
- partn->clumpcurve = curvemapping_copy(part->clumpcurve);
- if (part->roughcurve)
- partn->roughcurve = curvemapping_copy(part->roughcurve);
-
- partn->boids = boid_copy_settings(part->boids);
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- partn->mtex[a] = MEM_mallocN(sizeof(MTex), "psys_copy_tex");
- memcpy(partn->mtex[a], part->mtex[a], sizeof(MTex));
- id_us_plus((ID *)partn->mtex[a]->tex);
- }
- }
-
- BLI_duplicatelist(&partn->dupliweights, &part->dupliweights);
-
- if (part->id.lib) {
- BKE_id_lib_local_paths(G.main, part->id.lib, &partn->id);
- }
-
- return partn;
-}
-
-static void expand_local_particlesettings(ParticleSettings *part)
-{
- int i;
- id_lib_extern((ID *)part->dup_group);
-
- for (i = 0; i < MAX_MTEX; i++) {
- if (part->mtex[i]) id_lib_extern((ID *)part->mtex[i]->tex);
- }
-}
-
-void BKE_particlesettings_make_local(ParticleSettings *part)
-{
- Main *bmain = G.main;
- Object *ob;
- bool is_local = false, is_lib = false;
-
- /* - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
- */
-
- if (part->id.lib == 0) return;
- if (part->id.us == 1) {
- id_clear_lib_data(bmain, &part->id);
- expand_local_particlesettings(part);
- return;
- }
-
- /* test objects */
- for (ob = bmain->object.first; ob && ELEM(false, is_lib, is_local); ob = ob->id.next) {
- ParticleSystem *psys = ob->particlesystem.first;
- for (; psys; psys = psys->next) {
- if (psys->part == part) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &part->id);
- expand_local_particlesettings(part);
- }
- else if (is_local && is_lib) {
- ParticleSettings *part_new = BKE_particlesettings_copy(part);
- part_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, part->id.lib, &part_new->id);
-
- /* do objects */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- ParticleSystem *psys;
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys->part == part && ob->id.lib == 0) {
- psys->part = part_new;
- id_us_plus(&part_new->id);
- id_us_min(&part->id);
- }
- }
- }
- }
-}
-
-/************************************************/
-/* Textures */
-/************************************************/
-
-static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, const float fuv[4], char *name, float *texco)
-{
- MFace *mf;
- MTFace *tf;
- int i;
-
- tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, name);
-
- if (tf == NULL)
- tf = CustomData_get_layer(&dm->faceData, CD_MTFACE);
-
- if (tf == NULL)
- return 0;
-
- if (pa) {
- i = ELEM(pa->num_dmcache, DMCACHE_NOTFOUND, DMCACHE_ISCHILD) ? pa->num : pa->num_dmcache;
- if (i >= dm->getNumTessFaces(dm))
- i = -1;
- }
- else
- i = face_index;
-
- if (i == -1) {
- texco[0] = 0.0f;
- texco[1] = 0.0f;
- texco[2] = 0.0f;
- }
- else {
- mf = dm->getTessFaceData(dm, i, CD_MFACE);
-
- psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
-
- texco[0] = texco[0] * 2.0f - 1.0f;
- texco[1] = texco[1] * 2.0f - 1.0f;
- texco[2] = 0.0f;
- }
-
- return 1;
-}
-
-#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \
- if ((event & mtex->mapto) & type) { \
- pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \
- } (void)0
-
-#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \
- if (event & type) { \
- CLAMP(pvalue, 0.0f, 1.0f); \
- } (void)0
-
-#define CLAMP_WARP_PARTICLE_TEXTURE_POS(type, pvalue) \
- if (event & type) { \
- if (pvalue < 0.0f) \
- pvalue = 1.0f + pvalue; \
- CLAMP(pvalue, 0.0f, 1.0f); \
- } (void)0
-
-#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \
- if (event & type) { \
- CLAMP(pvalue, -1.0f, 1.0f); \
- } (void)0
-
-static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra)
-{
- MTex *mtex, **mtexp = part->mtex;
- int m;
- float value, rgba[4], texvec[3];
-
- ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
- ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp =
- ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
-
- ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26);
- ptex->length *= part->clength_thres < psys_frand(psys, child_index + 27) ? part->clength : 1.0f;
-
- for (m = 0; m < MAX_MTEX; m++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex && mtex->mapto) {
- float def = mtex->def_var;
- short blend = mtex->blendtype;
- short texco = mtex->texco;
-
- if (ELEM(texco, TEXCO_UV, TEXCO_ORCO) && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
- texco = TEXCO_GLOB;
-
- switch (texco) {
- case TEXCO_GLOB:
- copy_v3_v3(texvec, par->state.co);
- break;
- case TEXCO_OBJECT:
- copy_v3_v3(texvec, par->state.co);
- if (mtex->object)
- mul_m4_v3(mtex->object->imat, texvec);
- break;
- case TEXCO_UV:
- if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec))
- break;
- /* no break, failed to get uv's, so let's try orco's */
- case TEXCO_ORCO:
- copy_v3_v3(texvec, orco);
- break;
- case TEXCO_PARTICLE:
- /* texture coordinates in range [-1, 1] */
- texvec[0] = 2.f * (cfra - par->time) / (par->dietime - par->time) - 1.f;
- texvec[1] = 0.f;
- texvec[2] = 0.f;
- break;
- }
-
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false);
-
- if ((event & mtex->mapto) & PAMAP_ROUGH)
- ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(def, ptex->rough1, value, mtex->roughfac, blend);
-
- SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
- SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac);
- SET_PARTICLE_TEXTURE(PAMAP_KINK_AMP, ptex->kink_amp, mtex->kinkampfac);
- SET_PARTICLE_TEXTURE(PAMAP_KINK_FREQ, ptex->kink_freq, mtex->kinkfac);
- SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
- }
- }
-
- CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_KINK_AMP, ptex->kink_amp);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_KINK_FREQ, ptex->kink_freq);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
-}
-void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra)
-{
- Object *ob = sim->ob;
- Mesh *me = (Mesh *)ob->data;
- ParticleSettings *part = sim->psys->part;
- MTex **mtexp = part->mtex;
- MTex *mtex;
- int m;
- float value, rgba[4], co[3], texvec[3];
- int setvars = 0;
-
- /* initialize ptex */
- ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
- ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp =
- ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
-
- ptex->time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
-
- for (m = 0; m < MAX_MTEX; m++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex && mtex->mapto) {
- float def = mtex->def_var;
- short blend = mtex->blendtype;
- short texco = mtex->texco;
-
- if (texco == TEXCO_UV && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
- texco = TEXCO_GLOB;
-
- switch (texco) {
- case TEXCO_GLOB:
- copy_v3_v3(texvec, pa->state.co);
- break;
- case TEXCO_OBJECT:
- copy_v3_v3(texvec, pa->state.co);
- if (mtex->object)
- mul_m4_v3(mtex->object->imat, texvec);
- break;
- case TEXCO_UV:
- if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec))
- break;
- /* no break, failed to get uv's, so let's try orco's */
- case TEXCO_ORCO:
- psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, 0, 0, 0, texvec, 0);
-
- if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_mesh_texspace_calc(me);
- }
- sub_v3_v3(texvec, me->loc);
- if (me->size[0] != 0.0f) texvec[0] /= me->size[0];
- if (me->size[1] != 0.0f) texvec[1] /= me->size[1];
- if (me->size[2] != 0.0f) texvec[2] /= me->size[2];
- break;
- case TEXCO_PARTICLE:
- /* texture coordinates in range [-1, 1] */
- texvec[0] = 2.f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.f;
- if (sim->psys->totpart > 0)
- texvec[1] = 2.f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - 1.f;
- else
- texvec[1] = 0.0f;
- texvec[2] = 0.f;
- break;
- }
-
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false);
-
- if ((event & mtex->mapto) & PAMAP_TIME) {
- /* the first time has to set the base value for time regardless of blend mode */
- if ((setvars & MAP_PA_TIME) == 0) {
- int flip = (mtex->timefac < 0.0f);
- float timefac = fabsf(mtex->timefac);
- ptex->time *= 1.0f - timefac;
- ptex->time += timefac * ((flip) ? 1.0f - value : value);
- setvars |= MAP_PA_TIME;
- }
- else
- ptex->time = texture_value_blend(def, ptex->time, value, mtex->timefac, blend);
- }
- SET_PARTICLE_TEXTURE(PAMAP_LIFE, ptex->life, mtex->lifefac);
- SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
- SET_PARTICLE_TEXTURE(PAMAP_SIZE, ptex->size, mtex->sizefac);
- SET_PARTICLE_TEXTURE(PAMAP_IVEL, ptex->ivel, mtex->ivelfac);
- SET_PARTICLE_TEXTURE(PAMAP_FIELD, ptex->field, mtex->fieldfac);
- SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac);
- SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac);
- SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
- }
- }
-
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_TIME, ptex->time);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_LIFE, ptex->life);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
- CLAMP_PARTICLE_TEXTURE_POS(PAMAP_SIZE, ptex->size);
- CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_IVEL, ptex->ivel);
- CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_FIELD, ptex->field);
- CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_GRAVITY, ptex->gravity);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp);
- CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
-}
-/************************************************/
-/* Particle State */
-/************************************************/
-float psys_get_timestep(ParticleSimulationData *sim)
-{
- return 0.04f * sim->psys->part->timetweak;
-}
-float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
-{
- ParticleSettings *part = psys->part;
- float time, life;
-
- if (part->childtype == PART_CHILD_FACES) {
- int w = 0;
- time = 0.0;
- while (w < 4 && cpa->pa[w] >= 0) {
- time += cpa->w[w] * (psys->particles + cpa->pa[w])->time;
- w++;
- }
-
- life = part->lifetime * (1.0f - part->randlife * psys_frand(psys, cpa - psys->child + 25));
- }
- else {
- ParticleData *pa = psys->particles + cpa->parent;
-
- time = pa->time;
- life = pa->lifetime;
- }
-
- if (birthtime)
- *birthtime = time;
- if (dietime)
- *dietime = time + life;
-
- return (cfra - time) / life;
-}
-float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED(cfra), float *UNUSED(pa_time))
-{
- ParticleSettings *part = psys->part;
- float size; // time XXX
-
- if (part->childtype == PART_CHILD_FACES)
- size = part->size;
- else
- size = psys->particles[cpa->parent].size;
-
- size *= part->childsize;
-
- if (part->childrandsize != 0.0f)
- size *= 1.0f - part->childrandsize * psys_frand(psys, cpa - psys->child + 26);
-
- return size;
-}
-static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
-{
- ParticleSystem *psys = ctx->sim.psys;
- int i = cpa - psys->child;
-
- get_cpa_texture(ctx->dm, psys, part, psys->particles + cpa->pa[0], i, cpa_num, cpa_fuv, orco, ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
-
-
- if (ptex->exist < psys_frand(psys, i + 24))
- return;
-
- if (ctx->vg_length)
- ptex->length *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_length);
- if (ctx->vg_clump)
- ptex->clump *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_clump);
- if (ctx->vg_kink)
- ptex->kink_freq *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_kink);
- if (ctx->vg_rough1)
- ptex->rough1 *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough1);
- if (ctx->vg_rough2)
- ptex->rough2 *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough2);
- if (ctx->vg_roughe)
- ptex->roughe *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_roughe);
- if (ctx->vg_effector)
- ptex->effector *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector);
-}
-/* get's hair (or keyed) particles state at the "path time" specified in state->time */
-void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, const bool vel)
-{
- PARTICLE_PSMD;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = sim->psys->part;
- Material *ma = give_current_material(sim->ob, part->omat);
- ParticleData *pa;
- ChildParticle *cpa;
- ParticleTexture ptex;
- ParticleKey *par = 0, keys[4], tstate;
- ParticleThreadContext ctx; /* fake thread context for child modifiers */
- ParticleInterpolationData pind;
-
- float t;
- float co[3], orco[3];
- float hairmat[4][4];
- int totpart = psys->totpart;
- int totchild = psys->totchild;
- short between = 0, edit = 0;
-
- int keyed = part->phystype & PART_PHYS_KEYED && psys->flag & PSYS_KEYED;
- int cached = !keyed && part->type != PART_HAIR;
-
- float *cpa_fuv; int cpa_num; short cpa_from;
-
- /* initialize keys to zero */
- memset(keys, 0, 4 * sizeof(ParticleKey));
-
- t = state->time;
- CLAMP(t, 0.0f, 1.0f);
-
- if (p < totpart) {
- /* interpolate pathcache directly if it exist */
- if (psys->pathcache) {
- ParticleCacheKey result;
- interpolate_pathcache(psys->pathcache[p], t, &result);
- copy_v3_v3(state->co, result.co);
- copy_v3_v3(state->vel, result.vel);
- copy_qt_qt(state->rot, result.rot);
- }
- /* otherwise interpolate with other means */
- else {
- pa = psys->particles + p;
-
- pind.keyed = keyed;
- pind.cache = cached ? psys->pointcache : NULL;
- pind.epoint = NULL;
- pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
- /* pind.dm disabled in editmode means we don't get effectors taken into
- * account when subdividing for instance */
- pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
- init_particle_interpolation(sim->ob, psys, pa, &pind);
- do_particle_interpolation(psys, p, pa, t, &pind, state);
-
- if (pind.dm) {
- mul_m4_v3(sim->ob->obmat, state->co);
- mul_mat3_m4_v3(sim->ob->obmat, state->vel);
- }
- else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- if ((pa->flag & PARS_REKEY) == 0) {
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, part->from, pa, hairmat);
- mul_m4_v3(hairmat, state->co);
- mul_mat3_m4_v3(hairmat, state->vel);
-
- if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) {
- do_guides(sim->psys->part, sim->psys->effectors, state, p, state->time);
- /* TODO: proper velocity handling */
- }
-
- if (psys->lattice_deform_data && edit == 0)
- calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
- }
- }
- }
- }
- else if (totchild) {
- //invert_m4_m4(imat, ob->obmat);
-
- /* interpolate childcache directly if it exists */
- if (psys->childcache) {
- ParticleCacheKey result;
- interpolate_pathcache(psys->childcache[p - totpart], t, &result);
- copy_v3_v3(state->co, result.co);
- copy_v3_v3(state->vel, result.vel);
- copy_qt_qt(state->rot, result.rot);
- }
- else {
- float par_co[3], par_orco[3];
-
- cpa = psys->child + p - totpart;
-
- if (state->time < 0.0f)
- t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
-
- if (totchild && part->childtype == PART_CHILD_FACES) {
- /* part->parents could still be 0 so we can't test with totparent */
- between = 1;
- }
- if (between) {
- int w = 0;
- float foffset;
-
- /* get parent states */
- while (w < 4 && cpa->pa[w] >= 0) {
- keys[w].time = state->time;
- psys_get_particle_on_path(sim, cpa->pa[w], keys + w, 1);
- w++;
- }
-
- /* get the original coordinates (orco) for texture usage */
- cpa_num = cpa->num;
-
- foffset = cpa->foffset;
- cpa_fuv = cpa->fuv;
- cpa_from = PART_FROM_FACE;
-
- psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco, 0);
-
- /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
- //copy_v3_v3(cpa_1st, co);
-
- //mul_m4_v3(ob->obmat, cpa_1st);
-
- pa = psys->particles + cpa->parent;
-
- psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
- if (part->type == PART_HAIR)
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
- else
- unit_m4(hairmat);
-
- pa = 0;
- }
- else {
- /* get the parent state */
- keys->time = state->time;
- psys_get_particle_on_path(sim, cpa->parent, keys, 1);
-
- /* get the original coordinates (orco) for texture usage */
- pa = psys->particles + cpa->parent;
-
- cpa_from = part->from;
- cpa_num = pa->num;
- cpa_fuv = pa->fuv;
-
- psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
- if (part->type == PART_HAIR) {
- psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco, 0);
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
- }
- else {
- copy_v3_v3(orco, cpa->fuv);
- unit_m4(hairmat);
- }
- }
-
- /* correct child ipo timing */
-#if 0 // XXX old animation system
- if ((part->flag & PART_ABS_TIME) == 0 && part->ipo) {
- calc_ipo(part->ipo, 100.0f * t);
- execute_ipo((ID *)part, part->ipo);
- }
-#endif // XXX old animation system
-
- /* get different child parameters from textures & vgroups */
- memset(&ctx, 0, sizeof(ParticleThreadContext));
- ctx.sim = *sim;
- ctx.dm = psmd->dm_final;
- ctx.ma = ma;
- /* TODO: assign vertex groups */
- get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
-
- if (between) {
- int w = 0;
-
- state->co[0] = state->co[1] = state->co[2] = 0.0f;
- state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
-
- /* child position is the weighted sum of parent positions */
- while (w < 4 && cpa->pa[w] >= 0) {
- state->co[0] += cpa->w[w] * keys[w].co[0];
- state->co[1] += cpa->w[w] * keys[w].co[1];
- state->co[2] += cpa->w[w] * keys[w].co[2];
-
- state->vel[0] += cpa->w[w] * keys[w].vel[0];
- state->vel[1] += cpa->w[w] * keys[w].vel[1];
- state->vel[2] += cpa->w[w] * keys[w].vel[2];
- w++;
- }
- /* apply offset for correct positioning */
- //add_v3_v3(state->co, cpa_1st);
- }
- else {
- /* offset the child from the parent position */
- offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
- }
-
- par = keys;
-
- if (vel)
- copy_particle_key(&tstate, state, 1);
-
- /* apply different deformations to the child path */
- do_child_modifiers(NULL, sim, &ptex, par->co, par->vel, par->rot, par_orco, cpa, orco, hairmat, state, t);
-
- /* try to estimate correct velocity */
- if (vel) {
- ParticleKey tstate_tmp;
- float length = len_v3(state->vel);
-
- if (t >= 0.001f) {
- tstate_tmp.time = t - 0.001f;
- psys_get_particle_on_path(sim, p, &tstate_tmp, 0);
- sub_v3_v3v3(state->vel, state->co, tstate_tmp.co);
- normalize_v3(state->vel);
- }
- else {
- tstate_tmp.time = t + 0.001f;
- psys_get_particle_on_path(sim, p, &tstate_tmp, 0);
- sub_v3_v3v3(state->vel, tstate_tmp.co, state->co);
- normalize_v3(state->vel);
- }
-
- mul_v3_fl(state->vel, length);
- }
- }
- }
-}
-/* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
-int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleData *pa = NULL;
- ChildParticle *cpa = NULL;
- float cfra;
- int totpart = psys->totpart;
- float timestep = psys_get_timestep(sim);
-
- /* negative time means "use current time" */
- cfra = state->time > 0 ? state->time : BKE_scene_frame_get(sim->scene);
-
- if (p >= totpart) {
- if (!psys->totchild)
- return 0;
-
- if (part->childtype == PART_CHILD_FACES) {
- if (!(psys->flag & PSYS_KEYED))
- return 0;
-
- cpa = psys->child + p - totpart;
-
- state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL);
-
- if (!always) {
- if ((state->time < 0.0f && !(part->flag & PART_UNBORN)) ||
- (state->time > 1.0f && !(part->flag & PART_DIED)))
- {
- return 0;
- }
- }
-
- state->time = (cfra - (part->sta + (part->end - part->sta) * psys_frand(psys, p + 23))) / (part->lifetime * psys_frand(psys, p + 24));
-
- psys_get_particle_on_path(sim, p, state, 1);
- return 1;
- }
- else {
- cpa = sim->psys->child + p - totpart;
- pa = sim->psys->particles + cpa->parent;
- }
- }
- else {
- pa = sim->psys->particles + p;
- }
-
- if (pa) {
- if (!always) {
- if ((cfra < pa->time && (part->flag & PART_UNBORN) == 0) ||
- (cfra >= pa->dietime && (part->flag & PART_DIED) == 0))
- {
- return 0;
- }
- }
-
- cfra = MIN2(cfra, pa->dietime);
- }
-
- if (sim->psys->flag & PSYS_KEYED) {
- state->time = -cfra;
- psys_get_particle_on_path(sim, p, state, 1);
- return 1;
- }
- else {
- if (cpa) {
- float mat[4][4];
- ParticleKey *key1;
- float t = (cfra - pa->time) / pa->lifetime;
- float par_orco[3] = {0.0f, 0.0f, 0.0f};
-
- key1 = &pa->state;
- offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad);
-
- CLAMP(t, 0.0f, 1.0f);
-
- unit_m4(mat);
- do_child_modifiers(NULL, sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t);
-
- if (psys->lattice_deform_data)
- calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
- }
- else {
- if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
- copy_particle_key(state, &pa->state, 1);
- else if (pa->prev_state.time == cfra)
- copy_particle_key(state, &pa->prev_state, 1);
- else {
- float dfra, frs_sec = sim->scene->r.frs_sec;
- /* let's interpolate to try to be as accurate as possible */
- if (pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) {
- if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) {
- /* prev_state is wrong so let's not use it, this can happen at frames 1, 0 or particle birth */
- dfra = state->time - pa->state.time;
-
- copy_particle_key(state, &pa->state, 1);
-
- madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
- }
- else {
- ParticleKey keys[4];
- float keytime;
-
- copy_particle_key(keys + 1, &pa->prev_state, 1);
- copy_particle_key(keys + 2, &pa->state, 1);
-
- dfra = keys[2].time - keys[1].time;
-
- keytime = (state->time - keys[1].time) / dfra;
-
- /* convert velocity to timestep size */
- mul_v3_fl(keys[1].vel, dfra * timestep);
- mul_v3_fl(keys[2].vel, dfra * timestep);
-
- psys_interpolate_particle(-1, keys, keytime, state, 1);
-
- /* convert back to real velocity */
- mul_v3_fl(state->vel, 1.f / (dfra * timestep));
-
- interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime);
- interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime);
- }
- }
- else if (pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) {
- /* linear interpolation using only pa->state */
-
- dfra = state->time - pa->state.time;
-
- copy_particle_key(state, &pa->state, 1);
-
- madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
- }
- else {
- /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */
- copy_particle_key(state, &pa->state, 0);
- }
- }
-
- if (sim->psys->lattice_deform_data)
- calc_latt_deform(sim->psys->lattice_deform_data, state->co, 1.0f);
- }
-
- return 1;
- }
-}
-
-void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part,
- ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa,
- float uv[2], float orco[3])
-{
- MFace *mface;
- MTFace *mtface;
- float loc[3];
- int num;
-
- /* XXX: on checking '(psmd->dm != NULL)'
- * This is incorrect but needed for metaball evaluation.
- * Ideally this would be calculated via the depsgraph, however with metaballs,
- * the entire scenes dupli's are scanned, which also looks into uncalculated data.
- *
- * For now just include this workaround as an alternative to crashing,
- * but longer term metaballs should behave in a more manageable way, see: T46622. */
-
- uv[0] = uv[1] = 0.f;
-
- if (cpa) {
- if ((part->childtype == PART_CHILD_FACES) && (psmd->dm_final != NULL)) {
- CustomData *mtf_data = psmd->dm_final->getTessFaceDataLayout(psmd->dm_final);
- const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
- mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
-
- if (mtface) {
- mface = psmd->dm_final->getTessFaceData(psmd->dm_final, cpa->num, CD_MFACE);
- mtface += cpa->num;
- psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
- }
-
- psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, 0, 0, 0, orco, 0);
- return;
- }
- else {
- pa = psys->particles + cpa->pa[0];
- }
- }
-
- if ((part->from == PART_FROM_FACE) && (psmd->dm_final != NULL)) {
- CustomData *mtf_data = psmd->dm_final->getTessFaceDataLayout(psmd->dm_final);
- const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
- mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
-
- num = pa->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- num = pa->num;
-
- if (num >= psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
- /* happens when simplify is enabled
- * gives invalid coords but would crash otherwise */
- num = DMCACHE_NOTFOUND;
- }
-
- if (mtface && !ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
- mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
- mtface += num;
- psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
- }
- }
-
- psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, 0, 0, 0, orco, 0);
-}
-
-void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[4][4], float *scale)
-{
- Object *ob = sim->ob;
- ParticleSystem *psys = sim->psys;
- ParticleSystemModifierData *psmd = sim->psmd;
- float loc[3], nor[3], vec[3], side[3], len;
- float xvec[3] = {-1.0, 0.0, 0.0}, nmat[3][3];
-
- sub_v3_v3v3(vec, (cache + cache->segments)->co, cache->co);
- len = normalize_v3(vec);
-
- if (pa == NULL && psys->part->childflat != PART_CHILD_FACES)
- pa = psys->particles + cpa->pa[0];
-
- if (pa)
- psys_particle_on_emitter(psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, nor, 0, 0, 0, 0);
- else
- psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, nor, 0, 0, 0, 0);
-
- if (psys->part->rotmode == PART_ROT_VEL) {
- transpose_m3_m4(nmat, ob->imat);
- mul_m3_v3(nmat, nor);
- normalize_v3(nor);
-
- /* make sure that we get a proper side vector */
- if (fabsf(dot_v3v3(nor, vec)) > 0.999999f) {
- if (fabsf(dot_v3v3(nor, xvec)) > 0.999999f) {
- nor[0] = 0.0f;
- nor[1] = 1.0f;
- nor[2] = 0.0f;
- }
- else {
- nor[0] = 1.0f;
- nor[1] = 0.0f;
- nor[2] = 0.0f;
- }
- }
- cross_v3_v3v3(side, nor, vec);
- normalize_v3(side);
-
- /* rotate side vector around vec */
- if (psys->part->phasefac != 0) {
- float q_phase[4];
- float phasefac = psys->part->phasefac;
- if (psys->part->randphasefac != 0.0f)
- phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20);
- axis_angle_to_quat(q_phase, vec, phasefac * (float)M_PI);
-
- mul_qt_v3(q_phase, side);
- }
-
- cross_v3_v3v3(nor, vec, side);
-
- unit_m4(mat);
- copy_v3_v3(mat[0], vec);
- copy_v3_v3(mat[1], side);
- copy_v3_v3(mat[2], nor);
- }
- else {
- quat_to_mat4(mat, pa->state.rot);
- }
-
- *scale = len;
-}
-
-void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3])
-{
- float onevec[3] = {0.0f, 0.0f, 0.0f}, tvec[3], tvec2[3];
-
- xvec[0] = 1.0f; xvec[1] = 0.0f; xvec[2] = 0.0f;
- yvec[0] = 0.0f; yvec[1] = 1.0f; yvec[2] = 0.0f;
-
- /* can happen with bad pointcache or physics calculation
- * since this becomes geometry, nan's and inf's crash raytrace code.
- * better not allow this. */
- if ((!finite(bb->vec[0])) || (!finite(bb->vec[1])) || (!finite(bb->vec[2])) ||
- (!finite(bb->vel[0])) || (!finite(bb->vel[1])) || (!finite(bb->vel[2])) )
- {
- zero_v3(bb->vec);
- zero_v3(bb->vel);
-
- zero_v3(xvec);
- zero_v3(yvec);
- zero_v3(zvec);
- zero_v3(center);
-
- return;
- }
-
- if (bb->align < PART_BB_VIEW)
- onevec[bb->align] = 1.0f;
-
- if (bb->lock && (bb->align == PART_BB_VIEW)) {
- normalize_v3_v3(xvec, bb->ob->obmat[0]);
- normalize_v3_v3(yvec, bb->ob->obmat[1]);
- normalize_v3_v3(zvec, bb->ob->obmat[2]);
- }
- else if (bb->align == PART_BB_VEL) {
- float temp[3];
-
- normalize_v3_v3(temp, bb->vel);
-
- sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
-
- if (bb->lock) {
- float fac = -dot_v3v3(zvec, temp);
-
- madd_v3_v3fl(zvec, temp, fac);
- }
- normalize_v3(zvec);
-
- cross_v3_v3v3(xvec, temp, zvec);
- normalize_v3(xvec);
-
- cross_v3_v3v3(yvec, zvec, xvec);
- }
- else {
- sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
- if (bb->lock)
- zvec[bb->align] = 0.0f;
- normalize_v3(zvec);
-
- if (bb->align < PART_BB_VIEW)
- cross_v3_v3v3(xvec, onevec, zvec);
- else
- cross_v3_v3v3(xvec, bb->ob->obmat[1], zvec);
- normalize_v3(xvec);
-
- cross_v3_v3v3(yvec, zvec, xvec);
- }
-
- copy_v3_v3(tvec, xvec);
- copy_v3_v3(tvec2, yvec);
-
- mul_v3_fl(xvec, cosf(bb->tilt * (float)M_PI));
- mul_v3_fl(tvec2, sinf(bb->tilt * (float)M_PI));
- add_v3_v3(xvec, tvec2);
-
- mul_v3_fl(yvec, cosf(bb->tilt * (float)M_PI));
- mul_v3_fl(tvec, -sinf(bb->tilt * (float)M_PI));
- add_v3_v3(yvec, tvec);
-
- mul_v3_fl(xvec, bb->size[0]);
- mul_v3_fl(yvec, bb->size[1]);
-
- madd_v3_v3v3fl(center, bb->vec, xvec, bb->offset[0]);
- madd_v3_v3fl(center, yvec, bb->offset[1]);
-}
-
-void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
-{
- ParticleSimulationData sim = {0};
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- if (psys->lattice_deform_data) {
- ParticleData *pa = psys->particles;
- HairKey *hkey;
- int p, h;
- float hairmat[4][4], imat[4][4];
-
- for (p = 0; p < psys->totpart; p++, pa++) {
- psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
-
- hkey = pa->hair;
- for (h = 0; h < pa->totkey; h++, hkey++) {
- mul_m4_v3(hairmat, hkey->co);
- calc_latt_deform(psys->lattice_deform_data, hkey->co, 1.0f);
- mul_m4_v3(imat, hkey->co);
- }
- }
-
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
-
- /* protect the applied shape */
- psys->flag |= PSYS_EDITED;
- }
-}
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
deleted file mode 100644
index ec5f73f87ce..00000000000
--- a/source/blender/blenkernel/intern/particle_child.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Lukas Toenne
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle_child.c
- * \ingroup bke
- */
-
-#include "BLI_math.h"
-#include "BLI_noise.h"
-
-#include "DNA_material_types.h"
-
-#include "BKE_colortools.h"
-#include "BKE_particle.h"
-
-struct Material;
-
-void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
-
-static void get_strand_normal(Material *ma, const float surfnor[3], float surfdist, float nor[3])
-{
- float cross[3], nstrand[3], vnor[3], blend;
-
- if (!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f)))
- return;
-
- if (ma->mode & MA_STR_SURFDIFF) {
- cross_v3_v3v3(cross, surfnor, nor);
- cross_v3_v3v3(nstrand, nor, cross);
-
- blend = dot_v3v3(nstrand, surfnor);
- CLAMP(blend, 0.0f, 1.0f);
-
- interp_v3_v3v3(vnor, nstrand, surfnor, blend);
- normalize_v3(vnor);
- }
- else {
- copy_v3_v3(vnor, nor);
- }
-
- if (ma->strand_surfnor > 0.0f) {
- if (ma->strand_surfnor > surfdist) {
- blend = (ma->strand_surfnor - surfdist) / ma->strand_surfnor;
- interp_v3_v3v3(vnor, vnor, surfnor, blend);
- normalize_v3(vnor);
- }
- }
-
- copy_v3_v3(nor, vnor);
-}
-
-/* ------------------------------------------------------------------------- */
-
-typedef struct ParticlePathIterator {
- ParticleCacheKey *key;
- int index;
- float time;
-
- ParticleCacheKey *parent_key;
- float parent_rotation[4];
-} ParticlePathIterator;
-
-static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *keys, int totkeys,
- ParticleCacheKey *parent, int index)
-{
- BLI_assert(index >= 0 && index < totkeys);
-
- iter->key = keys + index;
- iter->index = index;
- iter->time = (float)index / (float)(totkeys - 1);
-
- if (parent) {
- iter->parent_key = parent + index;
- if (index > 0)
- mul_qt_qtqt(iter->parent_rotation, iter->parent_key->rot, parent->rot);
- else
- copy_qt_qt(iter->parent_rotation, parent->rot);
- }
- else {
- iter->parent_key = NULL;
- unit_qt(iter->parent_rotation);
- }
-}
-
-typedef struct ParticlePathModifier {
- struct ParticlePathModifier *next, *prev;
-
- void (*apply)(ParticleCacheKey *keys, int totkeys, ParticleCacheKey *parent_keys);
-} ParticlePathModifier;
-
-/* ------------------------------------------------------------------------- */
-
-static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const float kink[3],
- float time, float freq, float shape, float amplitude,
- const float spiral_start[3])
-{
- float result[3];
-
- CLAMP(time, 0.f, 1.f);
-
- copy_v3_v3(result, state->co);
-
- {
- /* Creates a logarithmic spiral:
- * r(theta) = a * exp(b * theta)
- *
- * The "density" parameter b is defined by the shape parameter
- * and goes up to the Golden Spiral for 1.0
- * http://en.wikipedia.org/wiki/Golden_spiral
- */
- const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f;
- /* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
- const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) :
- (float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);
-
- float spiral_axis[3], rot[3][3];
- float vec[3];
-
- float theta = freq * time * 2.0f * (float)M_PI;
- float radius = amplitude * expf(b * theta);
-
- /* a bit more intuitive than using negative frequency for this */
- if (amplitude < 0.0f)
- theta = -theta;
-
- cross_v3_v3v3(spiral_axis, dir, kink);
- normalize_v3(spiral_axis);
-
- mul_v3_v3fl(vec, kink, -radius);
-
- axis_angle_normalized_to_mat3(rot, spiral_axis, theta);
- mul_m3_v3(rot, vec);
-
- madd_v3_v3fl(vec, kink, amplitude);
-
- axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle);
- mul_m3_v3(rot, vec);
-
- add_v3_v3v3(result, spiral_start, vec);
- }
-
- copy_v3_v3(state->co, result);
-}
-
-static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, const float parent_orco[3],
- ChildParticle *cpa, const float orco[3], float hairmat[4][4],
- ParticleCacheKey *keys, ParticleCacheKey *parent_keys, int *r_totkeys, float *r_max_length)
-{
- struct ParticleSettings *part = ctx->sim.psys->part;
- const int seed = ctx->sim.psys->child_seed + (int)(cpa - ctx->sim.psys->child);
- const int totkeys = ctx->segments + 1;
- const int extrakeys = ctx->extra_segments;
-
- float kink_amp_random = part->kink_amp_random;
- float kink_amp = part->kink_amp * (1.0f - kink_amp_random * psys_frand(ctx->sim.psys, 93541 + seed));
- float kink_freq = part->kink_freq;
- float kink_shape = part->kink_shape;
- float kink_axis_random = part->kink_axis_random;
- float rough1 = part->rough1;
- float rough2 = part->rough2;
- float rough_end = part->rough_end;
-
- ParticlePathIterator iter;
- ParticleCacheKey *key;
- int k;
-
- float dir[3];
- float spiral_start[3] = {0.0f, 0.0f, 0.0f};
- float spiral_start_time = 0.0f;
- float spiral_par_co[3] = {0.0f, 0.0f, 0.0f};
- float spiral_par_vel[3] = {0.0f, 0.0f, 0.0f};
- float spiral_par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- float totlen;
- float cut_time;
- int start_index = 0, end_index = 0;
- float kink_base[3];
-
- if (ptex) {
- kink_amp *= ptex->kink_amp;
- kink_freq *= ptex->kink_freq;
- rough1 *= ptex->rough1;
- rough2 *= ptex->rough2;
- rough_end *= ptex->roughe;
- }
-
- cut_time = (totkeys - 1) * ptex->length;
- zero_v3(spiral_start);
-
- for (k = 0, key = keys; k < totkeys-1; k++, key++) {
- if ((float)(k + 1) >= cut_time) {
- float fac = cut_time - (float)k;
- ParticleCacheKey *par = parent_keys + k;
-
- start_index = k + 1;
- end_index = start_index + extrakeys;
-
- spiral_start_time = ((float)k + fac) / (float)(totkeys - 1);
- interp_v3_v3v3(spiral_start, key->co, (key+1)->co, fac);
-
- interp_v3_v3v3(spiral_par_co, par->co, (par+1)->co, fac);
- interp_v3_v3v3(spiral_par_vel, par->vel, (par+1)->vel, fac);
- interp_qt_qtqt(spiral_par_rot, par->rot, (par+1)->rot, fac);
-
- break;
- }
- }
-
- zero_v3(dir);
-
- zero_v3(kink_base);
- kink_base[part->kink_axis] = 1.0f;
- mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base);
-
- for (k = 0, key = keys; k < end_index; k++, key++) {
- float par_time;
- float *par_co, *par_vel, *par_rot;
-
- psys_path_iter_get(&iter, keys, end_index, NULL, k);
- if (k < start_index) {
- sub_v3_v3v3(dir, (key+1)->co, key->co);
- normalize_v3(dir);
-
- par_time = (float)k / (float)(totkeys - 1);
- par_co = parent_keys[k].co;
- par_vel = parent_keys[k].vel;
- par_rot = parent_keys[k].rot;
- }
- else {
- float spiral_time = (float)(k - start_index) / (float)(extrakeys-1);
- float kink[3], tmp[3];
-
- /* use same time value for every point on the spiral */
- par_time = spiral_start_time;
- par_co = spiral_par_co;
- par_vel = spiral_par_vel;
- par_rot = spiral_par_rot;
-
- project_v3_v3v3(tmp, kink_base, dir);
- sub_v3_v3v3(kink, kink_base, tmp);
- normalize_v3(kink);
-
- if (kink_axis_random > 0.0f) {
- float a = kink_axis_random * (psys_frand(ctx->sim.psys, 7112 + seed) * 2.0f - 1.0f) * (float)M_PI;
- float rot[3][3];
-
- axis_angle_normalized_to_mat3(rot, dir, a);
- mul_m3_v3(rot, kink);
- }
-
- do_kink_spiral_deform((ParticleKey *)key, dir, kink, spiral_time, kink_freq, kink_shape, kink_amp, spiral_start);
- }
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par_co, par_vel, par_rot, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, par_time);
- }
-
- totlen = 0.0f;
- for (k = 0, key = keys; k < end_index-1; k++, key++)
- totlen += len_v3v3((key+1)->co, key->co);
-
- *r_totkeys = end_index;
- *r_max_length = totlen;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static bool check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *key, float max_length, float step_length, float *cur_length, float dvec[3])
-{
- if (*cur_length + step_length > max_length) {
- sub_v3_v3v3(dvec, key->co, (key-1)->co);
- mul_v3_fl(dvec, (max_length - *cur_length) / step_length);
- add_v3_v3v3(key->co, (key-1)->co, dvec);
- keys->segments = k;
- /* something over the maximum step value */
- return false;
- }
- else {
- *cur_length += step_length;
- return true;
- }
-}
-
-void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *modifiers,
- ChildParticle *cpa, ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
- ParticleCacheKey *keys, ParticleCacheKey *parent_keys, const float parent_orco[3])
-{
- struct ParticleSettings *part = ctx->sim.psys->part;
- struct Material *ma = ctx->ma;
- const bool draw_col_ma = (part->draw_col == PART_DRAW_COL_MAT);
- const bool use_length_check = !ELEM(part->kink, PART_KINK_SPIRAL);
-
- ParticlePathModifier *mod;
- ParticleCacheKey *key;
- int totkeys, k;
- float max_length;
-
-#if 0 /* TODO for the future: use true particle modifiers that work on the whole curve */
- for (mod = modifiers->first; mod; mod = mod->next) {
- mod->apply(keys, totkeys, parent_keys);
- }
-#else
- (void)modifiers;
- (void)mod;
-
- if (part->kink == PART_KINK_SPIRAL) {
- do_kink_spiral(ctx, ptex, parent_orco, cpa, orco, hairmat, keys, parent_keys, &totkeys, &max_length);
- keys->segments = totkeys - 1;
- }
- else {
- ParticlePathIterator iter;
-
- totkeys = ctx->segments + 1;
- max_length = ptex->length;
-
- for (k = 0, key = keys; k < totkeys; k++, key++) {
- ParticleKey *par;
-
- psys_path_iter_get(&iter, keys, totkeys, parent_keys, k);
- par = (ParticleKey *)iter.parent_key;
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par->co, par->vel, iter.parent_rotation, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, iter.time);
- }
- }
-
- {
- const float step_length = 1.0f / (float)(totkeys - 1);
-
- float cur_length = 0.0f;
-
- /* we have to correct velocity because of kink & clump */
- for (k = 0, key = keys; k < totkeys; ++k, ++key) {
- if (k >= 2) {
- sub_v3_v3v3((key-1)->vel, key->co, (key-2)->co);
- mul_v3_fl((key-1)->vel, 0.5);
-
- if (ma && draw_col_ma)
- get_strand_normal(ma, ornor, cur_length, (key-1)->vel);
- }
-
- if (use_length_check && k > 1) {
- float dvec[3];
- /* check if path needs to be cut before actual end of data points */
- if (!check_path_length(k, keys, key, max_length, step_length, &cur_length, dvec)) {
- /* last key */
- sub_v3_v3v3(key->vel, key->co, (key-1)->co);
- if (ma && draw_col_ma) {
- copy_v3_v3(key->col, &ma->r);
- }
- break;
- }
- }
- if (k == totkeys-1) {
- /* last key */
- sub_v3_v3v3(key->vel, key->co, (key-1)->co);
- }
-
- if (ma && draw_col_ma) {
- copy_v3_v3(key->col, &ma->r);
- get_strand_normal(ma, ornor, cur_length, key->vel);
- }
- }
- }
-#endif
-}
-
-/* ------------------------------------------------------------------------- */
-
-void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape,
- float amplitude, float flat, short type, short axis, float obmat[4][4], int smooth_start)
-{
- float kink[3] = {1.f, 0.f, 0.f}, par_vec[3], q1[4] = {1.f, 0.f, 0.f, 0.f};
- float t, dt = 1.f, result[3];
-
- if (ELEM(type, PART_KINK_NO, PART_KINK_SPIRAL))
- return;
-
- CLAMP(time, 0.f, 1.f);
-
- if (shape != 0.0f && !ELEM(type, PART_KINK_BRAID)) {
- if (shape < 0.0f)
- time = (float)pow(time, 1.f + shape);
- else
- time = (float)pow(time, 1.f / (1.f - shape));
- }
-
- t = time * freq * (float)M_PI;
-
- if (smooth_start) {
- dt = fabsf(t);
- /* smooth the beginning of kink */
- CLAMP(dt, 0.f, (float)M_PI);
- dt = sinf(dt / 2.f);
- }
-
- if (!ELEM(type, PART_KINK_RADIAL)) {
- float temp[3];
-
- kink[axis] = 1.f;
-
- if (obmat)
- mul_mat3_m4_v3(obmat, kink);
-
- mul_qt_v3(par_rot, kink);
-
- /* make sure kink is normal to strand */
- project_v3_v3v3(temp, kink, par_vel);
- sub_v3_v3(kink, temp);
- normalize_v3(kink);
- }
-
- copy_v3_v3(result, state->co);
- sub_v3_v3v3(par_vec, par_co, state->co);
-
- switch (type) {
- case PART_KINK_CURL:
- {
- float curl_offset[3];
-
- /* rotate kink vector around strand tangent */
- mul_v3_v3fl(curl_offset, kink, amplitude);
- axis_angle_to_quat(q1, par_vel, t);
- mul_qt_v3(q1, curl_offset);
-
- interp_v3_v3v3(par_vec, state->co, par_co, flat);
- add_v3_v3v3(result, par_vec, curl_offset);
- break;
- }
- case PART_KINK_RADIAL:
- {
- if (flat > 0.f) {
- float proj[3];
- /* flatten along strand */
- project_v3_v3v3(proj, par_vec, par_vel);
- madd_v3_v3fl(result, proj, flat);
- }
-
- madd_v3_v3fl(result, par_vec, -amplitude * sinf(t));
- break;
- }
- case PART_KINK_WAVE:
- {
- madd_v3_v3fl(result, kink, amplitude * sinf(t));
-
- if (flat > 0.f) {
- float proj[3];
- /* flatten along wave */
- project_v3_v3v3(proj, par_vec, kink);
- madd_v3_v3fl(result, proj, flat);
-
- /* flatten along strand */
- project_v3_v3v3(proj, par_vec, par_vel);
- madd_v3_v3fl(result, proj, flat);
- }
- break;
- }
- case PART_KINK_BRAID:
- {
- float y_vec[3] = {0.f, 1.f, 0.f};
- float z_vec[3] = {0.f, 0.f, 1.f};
- float vec_one[3], state_co[3];
- float inp_y, inp_z, length;
-
- if (par_rot) {
- mul_qt_v3(par_rot, y_vec);
- mul_qt_v3(par_rot, z_vec);
- }
-
- negate_v3(par_vec);
- normalize_v3_v3(vec_one, par_vec);
-
- inp_y = dot_v3v3(y_vec, vec_one);
- inp_z = dot_v3v3(z_vec, vec_one);
-
- if (inp_y > 0.5f) {
- copy_v3_v3(state_co, y_vec);
-
- mul_v3_fl(y_vec, amplitude * cosf(t));
- mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t));
- }
- else if (inp_z > 0.0f) {
- mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f));
- madd_v3_v3fl(state_co, y_vec, -0.5f);
-
- mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f));
- mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f));
- }
- else {
- mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f));
- madd_v3_v3fl(state_co, y_vec, -0.5f);
-
- mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f));
- mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f));
- }
-
- mul_v3_fl(state_co, amplitude);
- add_v3_v3(state_co, par_co);
- sub_v3_v3v3(par_vec, state->co, state_co);
-
- length = normalize_v3(par_vec);
- mul_v3_fl(par_vec, MIN2(length, amplitude / 2.f));
-
- add_v3_v3v3(state_co, par_co, y_vec);
- add_v3_v3(state_co, z_vec);
- add_v3_v3(state_co, par_vec);
-
- shape = 2.f * (float)M_PI * (1.f + shape);
-
- if (t < shape) {
- shape = t / shape;
- shape = (float)sqrt((double)shape);
- interp_v3_v3v3(result, result, state_co, shape);
- }
- else {
- copy_v3_v3(result, state_co);
- }
- break;
- }
- }
-
- /* blend the start of the kink */
- if (dt < 1.f)
- interp_v3_v3v3(state->co, state->co, result, dt);
- else
- copy_v3_v3(state->co, result);
-}
-
-static float do_clump_level(float result[3], const float co[3], const float par_co[3], float time,
- float clumpfac, float clumppow, float pa_clump, CurveMapping *clumpcurve)
-{
- float clump = 0.0f;
-
- if (clumpcurve) {
- clump = pa_clump * (1.0f - CLAMPIS(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
-
- interp_v3_v3v3(result, co, par_co, clump);
- }
- else if (clumpfac != 0.0f) {
- float cpow;
-
- if (clumppow < 0.0f)
- cpow = 1.0f + clumppow;
- else
- cpow = 1.0f + 9.0f * clumppow;
-
- if (clumpfac < 0.0f) /* clump roots instead of tips */
- clump = -clumpfac * pa_clump * (float)pow(1.0 - (double)time, (double)cpow);
- else
- clump = clumpfac * pa_clump * (float)pow((double)time, (double)cpow);
-
- interp_v3_v3v3(result, co, par_co, clump);
- }
-
- return clump;
-}
-
-float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve)
-{
- float clump;
-
- if (use_clump_noise && clump_noise_size != 0.0f) {
- float center[3], noisevec[3];
- float da[4], pa[12];
-
- mul_v3_v3fl(noisevec, orco_offset, 1.0f / clump_noise_size);
- voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0);
- mul_v3_fl(&pa[0], clump_noise_size);
- add_v3_v3v3(center, par_co, &pa[0]);
-
- do_clump_level(state->co, state->co, center, time, clumpfac, clumppow, pa_clump, clumpcurve);
- }
-
- clump = do_clump_level(state->co, state->co, par_co, time, clumpfac, clumppow, pa_clump, clumpcurve);
-
- return clump;
-}
-
-static void do_rough(const float loc[3], float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state)
-{
- float rough[3];
- float rco[3];
-
- if (thres != 0.0f) {
- if (fabsf((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) {
- return;
- }
- }
-
- copy_v3_v3(rco, loc);
- mul_v3_fl(rco, t);
- rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
- rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
- rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
-
- madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
- madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
- madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
-}
-
-static void do_rough_end(const float loc[3], float mat[4][4], float t, float fac, float shape, ParticleKey *state)
-{
- float rough[2];
- float roughfac;
-
- roughfac = fac * (float)pow((double)t, shape);
- copy_v2_v2(rough, loc);
- rough[0] = -1.0f + 2.0f * rough[0];
- rough[1] = -1.0f + 2.0f * rough[1];
- mul_v2_fl(rough, roughfac);
-
- madd_v3_v3fl(state->co, mat[0], rough[0]);
- madd_v3_v3fl(state->co, mat[1], rough[1]);
-}
-
-static void do_rough_curve(const float loc[3], float mat[4][4], float time, float fac, float size, CurveMapping *roughcurve, ParticleKey *state)
-{
- float rough[3];
- float rco[3];
-
- if (!roughcurve)
- return;
-
- fac *= CLAMPIS(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
-
- copy_v3_v3(rco, loc);
- mul_v3_fl(rco, time);
- rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
- rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
- rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
-
- madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
- madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
- madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
-}
-
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, ParticleTexture *ptex,
- const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t)
-{
- ParticleSettings *part = sim->psys->part;
- CurveMapping *clumpcurve = NULL, *roughcurve = NULL;
- int i = cpa - sim->psys->child;
- int guided = 0;
-
- if (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) {
- clumpcurve = (ctx != NULL) ? ctx->clumpcurve : part->clumpcurve;
- }
- if (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) {
- roughcurve = (ctx != NULL) ? ctx->roughcurve : part->roughcurve;
- }
-
- float kink_amp = part->kink_amp;
- float kink_amp_clump = part->kink_amp_clump;
- float kink_freq = part->kink_freq;
- float rough1 = part->rough1;
- float rough2 = part->rough2;
- float rough_end = part->rough_end;
- const bool smooth_start = (sim->psys->part->childtype == PART_CHILD_FACES);
-
- if (ptex) {
- kink_amp *= ptex->kink_amp;
- kink_freq *= ptex->kink_freq;
- rough1 *= ptex->rough1;
- rough2 *= ptex->rough2;
- rough_end *= ptex->roughe;
- }
-
- if (part->flag & PART_CHILD_EFFECT)
- /* state is safe to cast, since only co and vel are used */
- guided = do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
-
- if (guided == 0) {
- float orco_offset[3];
- float clump;
-
- sub_v3_v3v3(orco_offset, orco, par_orco);
- clump = do_clump(state, par_co, t, orco_offset, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f,
- part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
-
- if (kink_freq != 0.f) {
- kink_amp *= (1.f - kink_amp_clump * clump);
-
- do_kink(state, par_co, par_vel, par_rot, t, kink_freq, part->kink_shape,
- kink_amp, part->kink_flat, part->kink, part->kink_axis,
- sim->ob->obmat, smooth_start);
- }
- }
-
- if (roughcurve) {
- do_rough_curve(orco, mat, t, rough1, part->rough1_size, roughcurve, state);
- }
- else {
- if (rough1 > 0.f)
- do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
-
- if (rough2 > 0.f) {
- float vec[3];
- psys_frand_vec(sim->psys, i + 27, vec);
- do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
- }
-
- if (rough_end > 0.f) {
- float vec[3];
- psys_frand_vec(sim->psys, i + 27, vec);
- do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state);
- }
- }
-}
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
deleted file mode 100644
index 9185c0964b9..00000000000
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ /dev/null
@@ -1,1448 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Raul Fernandez Hernandez (Farsthary),
- * Stephen Swhitehorn,
- * Lukas Toenne
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle_distribute.c
- * \ingroup bke
- */
-
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_jitter.h"
-#include "BLI_kdtree.h"
-#include "BLI_math.h"
-#include "BLI_rand.h"
-#include "BLI_sort.h"
-#include "BLI_task.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
-#include "BKE_mesh.h"
-#include "BKE_object.h"
-#include "BKE_particle.h"
-
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot);
-
-static void alloc_child_particles(ParticleSystem *psys, int tot)
-{
- if (psys->child) {
- /* only re-allocate if we have to */
- if (psys->part->childtype && psys->totchild == tot) {
- memset(psys->child, 0, tot*sizeof(ChildParticle));
- return;
- }
-
- MEM_freeN(psys->child);
- psys->child=NULL;
- psys->totchild=0;
- }
-
- if (psys->part->childtype) {
- psys->totchild= tot;
- if (psys->totchild)
- psys->child= MEM_callocN(psys->totchild*sizeof(ChildParticle), "child_particles");
- }
-}
-
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys)
-{
- ChildParticle *cpa = NULL;
- int i, p;
- int child_nbr= psys_get_child_number(scene, psys);
- int totpart= psys_get_tot_child(scene, psys);
-
- alloc_child_particles(psys, totpart);
-
- cpa = psys->child;
- for (i=0; i<child_nbr; i++) {
- for (p=0; p<psys->totpart; p++,cpa++) {
- float length=2.0;
- cpa->parent=p;
-
- /* create even spherical distribution inside unit sphere */
- while (length>=1.0f) {
- cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
- length=len_v3(cpa->fuv);
- }
-
- cpa->num=-1;
- }
- }
- /* dmcache must be updated for parent particles if children from faces is used */
- psys_calc_dmcache(ob, finaldm, deformdm, psys);
-}
-static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
-{
- ParticleData *pa=NULL;
- float min[3], max[3], delta[3], d;
- MVert *mv, *mvert = dm->getVertDataArray(dm,0);
- int totvert=dm->getNumVerts(dm), from=psys->part->from;
- int i, j, k, p, res=psys->part->grid_res, size[3], axis;
-
- /* find bounding box of dm */
- if (totvert > 0) {
- mv=mvert;
- copy_v3_v3(min, mv->co);
- copy_v3_v3(max, mv->co);
- mv++;
- for (i = 1; i < totvert; i++, mv++) {
- minmax_v3v3_v3(min, max, mv->co);
- }
- }
- else {
- zero_v3(min);
- zero_v3(max);
- }
-
- sub_v3_v3v3(delta, max, min);
-
- /* determine major axis */
- axis = axis_dominant_v3_single(delta);
-
- d = delta[axis]/(float)res;
-
- size[axis] = res;
- size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d);
- size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d);
-
- /* float errors grrr.. */
- size[(axis+1)%3] = MIN2(size[(axis+1)%3],res);
- size[(axis+2)%3] = MIN2(size[(axis+2)%3],res);
-
- size[0] = MAX2(size[0], 1);
- size[1] = MAX2(size[1], 1);
- size[2] = MAX2(size[2], 1);
-
- /* no full offset for flat/thin objects */
- min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f;
- min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f;
- min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f;
-
- for (i=0,p=0,pa=psys->particles; i<res; i++) {
- for (j=0; j<res; j++) {
- for (k=0; k<res; k++,p++,pa++) {
- pa->fuv[0] = min[0] + (float)i*d;
- pa->fuv[1] = min[1] + (float)j*d;
- pa->fuv[2] = min[2] + (float)k*d;
- pa->flag |= PARS_UNEXIST;
- pa->hair_index = 0; /* abused in volume calculation */
- }
- }
- }
-
- /* enable particles near verts/edges/faces/inside surface */
- if (from==PART_FROM_VERT) {
- float vec[3];
-
- pa=psys->particles;
-
- min[0] -= d/2.0f;
- min[1] -= d/2.0f;
- min[2] -= d/2.0f;
-
- for (i=0,mv=mvert; i<totvert; i++,mv++) {
- sub_v3_v3v3(vec,mv->co,min);
- vec[0]/=delta[0];
- vec[1]/=delta[1];
- vec[2]/=delta[2];
- pa[((int)(vec[0] * (size[0] - 1)) * res +
- (int)(vec[1] * (size[1] - 1))) * res +
- (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST;
- }
- }
- else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
- float co1[3], co2[3];
-
- MFace *mface= NULL, *mface_array;
- float v1[3], v2[3], v3[3], v4[4], lambda;
- int a, a1, a2, a0mul, a1mul, a2mul, totface;
- int amax= from==PART_FROM_FACE ? 3 : 1;
-
- totface=dm->getNumTessFaces(dm);
- mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
-
- for (a=0; a<amax; a++) {
- if (a==0) { a0mul=res*res; a1mul=res; a2mul=1; }
- else if (a==1) { a0mul=res; a1mul=1; a2mul=res*res; }
- else { a0mul=1; a1mul=res*res; a2mul=res; }
-
- for (a1=0; a1<size[(a+1)%3]; a1++) {
- for (a2=0; a2<size[(a+2)%3]; a2++) {
- mface= mface_array;
-
- pa = psys->particles + a1*a1mul + a2*a2mul;
- copy_v3_v3(co1, pa->fuv);
- co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f;
- copy_v3_v3(co2, co1);
- co2[a] += delta[a] + 0.001f*d;
- co1[a] -= 0.001f*d;
-
- /* lets intersect the faces */
- for (i=0; i<totface; i++,mface++) {
- copy_v3_v3(v1, mvert[mface->v1].co);
- copy_v3_v3(v2, mvert[mface->v2].co);
- copy_v3_v3(v3, mvert[mface->v3].co);
-
- bool intersects_tri = isect_axial_line_segment_tri_v3(a, co1, co2, v2, v3, v1, &lambda);
- if (intersects_tri) {
- if (from==PART_FROM_FACE)
- (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
- else /* store number of intersections */
- (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
- }
-
- if (mface->v4 && (!intersects_tri || from==PART_FROM_VOLUME)) {
- copy_v3_v3(v4, mvert[mface->v4].co);
-
- if (isect_axial_line_segment_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
- if (from==PART_FROM_FACE)
- (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
- else
- (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
- }
- }
- }
-
- if (from==PART_FROM_VOLUME) {
- int in=pa->hair_index%2;
- if (in) pa->hair_index++;
- for (i=0; i<size[0]; i++) {
- if (in || (pa+i*a0mul)->hair_index%2)
- (pa+i*a0mul)->flag &= ~PARS_UNEXIST;
- /* odd intersections == in->out / out->in */
- /* even intersections -> in stays same */
- in=(in + (pa+i*a0mul)->hair_index) % 2;
- }
- }
- }
- }
- }
- }
-
- if (psys->part->flag & PART_GRID_HEXAGONAL) {
- for (i=0,p=0,pa=psys->particles; i<res; i++) {
- for (j=0; j<res; j++) {
- for (k=0; k<res; k++,p++,pa++) {
- if (j%2)
- pa->fuv[0] += d/2.f;
-
- if (k%2) {
- pa->fuv[0] += d/2.f;
- pa->fuv[1] += d/2.f;
- }
- }
- }
- }
- }
-
- if (psys->part->flag & PART_GRID_INVERT) {
- for (i=0; i<size[0]; i++) {
- for (j=0; j<size[1]; j++) {
- pa=psys->particles + res*(i*res + j);
- for (k=0; k<size[2]; k++, pa++) {
- pa->flag ^= PARS_UNEXIST;
- }
- }
- }
- }
-
- if (psys->part->grid_rand > 0.f) {
- float rfac = d * psys->part->grid_rand;
- for (p=0,pa=psys->particles; p<psys->totpart; p++,pa++) {
- if (pa->flag & PARS_UNEXIST)
- continue;
-
- pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f);
- pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f);
- pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f);
- }
- }
-}
-
-/* modified copy from rayshade.c */
-static void hammersley_create(float *out, int n, int seed, float amount)
-{
- RNG *rng;
- double p, t, offs[2];
- int k, kk;
-
- rng = BLI_rng_new(31415926 + n + seed);
- offs[0] = BLI_rng_get_double(rng) + (double)amount;
- offs[1] = BLI_rng_get_double(rng) + (double)amount;
- BLI_rng_free(rng);
-
- for (k = 0; k < n; k++) {
- t = 0;
- for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1)
- if (kk & 1) /* kk mod 2 = 1 */
- t += p;
-
- out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0);
- out[2*k + 1] = fmod(t + offs[1], 1.0);
- }
-}
-
-/* almost exact copy of BLI_jitter_init */
-static void init_mv_jit(float *jit, int num, int seed2, float amount)
-{
- RNG *rng;
- float *jit2, x, rad1, rad2, rad3;
- int i, num2;
-
- if (num==0) return;
-
- rad1= (float)(1.0f/sqrtf((float)num));
- rad2= (float)(1.0f/((float)num));
- rad3= (float)sqrtf((float)num)/((float)num);
-
- rng = BLI_rng_new(31415926 + num + seed2);
- x= 0;
- num2 = 2 * num;
- for (i=0; i<num2; i+=2) {
-
- jit[i] = x + amount*rad1*(0.5f - BLI_rng_get_float(rng));
- jit[i+1] = i/(2.0f*num) + amount*rad1*(0.5f - BLI_rng_get_float(rng));
-
- jit[i]-= (float)floor(jit[i]);
- jit[i+1]-= (float)floor(jit[i+1]);
-
- x+= rad3;
- x -= (float)floor(x);
- }
-
- jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
-
- for (i=0 ; i<4 ; i++) {
- BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
- BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
- BLI_jitterate2((float (*)[2])jit, (float (*)[2])jit2, num, rad2);
- }
- MEM_freeN(jit2);
- BLI_rng_free(rng);
-}
-
-static void psys_uv_to_w(float u, float v, int quad, float *w)
-{
- float vert[4][3], co[3];
-
- if (!quad) {
- if (u+v > 1.0f)
- v= 1.0f-v;
- else
- u= 1.0f-u;
- }
-
- vert[0][0] = 0.0f; vert[0][1] = 0.0f; vert[0][2] = 0.0f;
- vert[1][0] = 1.0f; vert[1][1] = 0.0f; vert[1][2] = 0.0f;
- vert[2][0] = 1.0f; vert[2][1] = 1.0f; vert[2][2] = 0.0f;
-
- co[0] = u;
- co[1] = v;
- co[2] = 0.0f;
-
- if (quad) {
- vert[3][0] = 0.0f; vert[3][1] = 1.0f; vert[3][2] = 0.0f;
- interp_weights_poly_v3( w,vert, 4, co);
- }
- else {
- interp_weights_poly_v3( w,vert, 3, co);
- w[3] = 0.0f;
- }
-}
-
-/* Find the index in "sum" array before "value" is crossed. */
-static int distribute_binary_search(float *sum, int n, float value)
-{
- int mid, low=0, high=n;
-
- if (value == 0.f)
- return 0;
-
- while (low <= high) {
- mid= (low + high)/2;
-
- if (sum[mid] < value && value <= sum[mid+1])
- return mid;
-
- if (sum[mid] >= value)
- high= mid - 1;
- else if (sum[mid] < value)
- low= mid + 1;
- else
- return mid;
- }
-
- return low;
-}
-
-/* the max number if calls to rng_* funcs within psys_thread_distribute_particle
- * be sure to keep up to date if this changes */
-#define PSYS_RND_DIST_SKIP 2
-
-/* note: this function must be thread safe, for from == PART_FROM_CHILD */
-#define ONLY_WORKING_WITH_PA_VERTS 0
-static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
-{
- ParticleThreadContext *ctx= thread->ctx;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- /* TODO_PARTICLE - use original index */
- pa->num= ctx->index[p];
- pa->fuv[0] = 1.0f;
- pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
-
-#if ONLY_WORKING_WITH_PA_VERTS
- if (ctx->tree) {
- KDTreeNearest ptn[3];
- int w, maxw;
-
- psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
-
- for (w=0; w<maxw; w++) {
- pa->verts[w]=ptn->num;
- }
- }
-#endif
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p) {
- ParticleThreadContext *ctx= thread->ctx;
- DerivedMesh *dm= ctx->dm;
- float randu, randv;
- int distr= ctx->distr;
- int i;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- MFace *mface;
-
- pa->num = i = ctx->index[p];
- mface = dm->getTessFaceData(dm,i,CD_MFACE);
-
- switch (distr) {
- case PART_DISTR_JIT:
- if (ctx->jitlevel == 1) {
- if (mface->v4)
- psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
- else
- psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
- }
- else {
- float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
- if (!isnan(offset)) {
- psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
- }
- }
- break;
- case PART_DISTR_RAND:
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
- break;
- }
- pa->foffset= 0.0f;
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) {
- ParticleThreadContext *ctx= thread->ctx;
- DerivedMesh *dm= ctx->dm;
- float *v1, *v2, *v3, *v4, nor[3], co[3];
- float cur_d, min_d, randu, randv;
- int distr= ctx->distr;
- int i, intersect, tot;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- MFace *mface;
- MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
-
- pa->num = i = ctx->index[p];
- mface = dm->getTessFaceData(dm,i,CD_MFACE);
-
- switch (distr) {
- case PART_DISTR_JIT:
- if (ctx->jitlevel == 1) {
- if (mface->v4)
- psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
- else
- psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
- }
- else {
- float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
- if (!isnan(offset)) {
- psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
- }
- }
- break;
- case PART_DISTR_RAND:
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
- break;
- }
- pa->foffset= 0.0f;
-
- /* experimental */
- tot=dm->getNumTessFaces(dm);
-
- psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0,0);
-
- normalize_v3(nor);
- negate_v3(nor);
-
- min_d=FLT_MAX;
- intersect=0;
-
- for (i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++) {
- if (i==pa->num) continue;
-
- v1=mvert[mface->v1].co;
- v2=mvert[mface->v2].co;
- v3=mvert[mface->v3].co;
-
- if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, NULL)) {
- if (cur_d<min_d) {
- min_d=cur_d;
- pa->foffset=cur_d*0.5f; /* to the middle of volume */
- intersect=1;
- }
- }
- if (mface->v4) {
- v4=mvert[mface->v4].co;
-
- if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, NULL)) {
- if (cur_d<min_d) {
- min_d=cur_d;
- pa->foffset=cur_d*0.5f; /* to the middle of volume */
- intersect=1;
- }
- }
- }
- }
- if (intersect==0)
- pa->foffset=0.0;
- else {
- switch (distr) {
- case PART_DISTR_JIT:
- pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
- break;
- case PART_DISTR_RAND:
- pa->foffset *= BLI_frand();
- break;
- }
- }
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p) {
- ParticleThreadContext *ctx= thread->ctx;
- Object *ob= ctx->sim.ob;
- DerivedMesh *dm= ctx->dm;
- float orco1[3], co1[3], nor1[3];
- float randu, randv;
- int cfrom= ctx->cfrom;
- int i;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- MFace *mf;
-
- if (ctx->index[p] < 0) {
- cpa->num=0;
- cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f;
- cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
- return;
- }
-
- mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
-
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mf->v4, cpa->fuv);
-
- cpa->num = ctx->index[p];
-
- if (ctx->tree) {
- KDTreeNearest ptn[10];
- int w,maxw;//, do_seams;
- float maxd /*, mind,dd */, totw= 0.0f;
- int parent[10];
- float pweight[10];
-
- psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
-
- maxd=ptn[maxw-1].dist;
- /* mind=ptn[0].dist; */ /* UNUSED */
-
- /* the weights here could be done better */
- for (w=0; w<maxw; w++) {
- parent[w]=ptn[w].index;
- pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
- }
- for (;w<10; w++) {
- parent[w]=-1;
- pweight[w]=0.0f;
- }
-
- for (w=0,i=0; w<maxw && i<4; w++) {
- if (parent[w]>=0) {
- cpa->pa[i]=parent[w];
- cpa->w[i]=pweight[w];
- totw+=pweight[w];
- i++;
- }
- }
- for (;i<4; i++) {
- cpa->pa[i]=-1;
- cpa->w[i]=0.0f;
- }
-
- if (totw > 0.0f) {
- for (w = 0; w < 4; w++) {
- cpa->w[w] /= totw;
- }
- }
-
- cpa->parent=cpa->pa[0];
- }
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void exec_distribute_parent(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- ParticleTask *task = taskdata;
- ParticleSystem *psys= task->ctx->sim.psys;
- ParticleData *pa;
- int p;
-
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin);
-
- pa= psys->particles + task->begin;
- switch (psys->part->from) {
- case PART_FROM_FACE:
- for (p = task->begin; p < task->end; ++p, ++pa)
- distribute_from_faces_exec(task, pa, p);
- break;
- case PART_FROM_VOLUME:
- for (p = task->begin; p < task->end; ++p, ++pa)
- distribute_from_volume_exec(task, pa, p);
- break;
- case PART_FROM_VERT:
- for (p = task->begin; p < task->end; ++p, ++pa)
- distribute_from_verts_exec(task, pa, p);
- break;
- }
-}
-
-static void exec_distribute_child(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- ParticleTask *task = taskdata;
- ParticleSystem *psys = task->ctx->sim.psys;
- ChildParticle *cpa;
- int p;
-
- /* RNG skipping at the beginning */
- cpa = psys->child;
- for (p = 0; p < task->begin; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP);
- }
-
- for (; p < task->end; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
- distribute_children_exec(task, cpa, p);
- }
-}
-
-static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
-{
- int *orig_index = (int *) user_data;
- int index1 = orig_index[*(const int *)p1];
- int index2 = orig_index[*(const int *)p2];
-
- if (index1 < index2)
- return -1;
- else if (index1 == index2) {
- /* this pointer comparison appears to make qsort stable for glibc,
- * and apparently on solaris too, makes the renders reproducible */
- if (p1 < p2)
- return -1;
- else if (p1 == p2)
- return 0;
- else
- return 1;
- }
- else
- return 1;
-}
-
-static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
-{
- if (from == PART_FROM_CHILD) {
- ChildParticle *cpa;
- int p, totchild = psys_get_tot_child(scene, psys);
-
- if (psys->child && totchild) {
- for (p=0,cpa=psys->child; p<totchild; p++,cpa++) {
- cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3] = 0.0;
- cpa->foffset= 0.0f;
- cpa->parent=0;
- cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
- cpa->num= -1;
- }
- }
- }
- else {
- PARTICLE_P;
- LOOP_PARTICLES {
- pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
- pa->foffset= 0.0f;
- pa->num= -1;
- }
- }
-}
-
-/* Creates a distribution of coordinates on a DerivedMesh */
-/* This is to denote functionality that does not yet work with mesh - only derived mesh */
-static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
-{
- Scene *scene = sim->scene;
- DerivedMesh *finaldm = sim->psmd->dm_final;
- Object *ob = sim->ob;
- ParticleSystem *psys= sim->psys;
- ParticleData *pa=0, *tpars= 0;
- ParticleSettings *part;
- ParticleSeam *seams= 0;
- KDTree *tree=0;
- DerivedMesh *dm= NULL;
- float *jit= NULL;
- int i, p=0;
- int cfrom=0;
- int totelem=0, totpart, *particle_element=0, children=0, totseam=0;
- int jitlevel= 1, distr;
- float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
- float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
-
- if (ELEM(NULL, ob, psys, psys->part))
- return 0;
-
- part=psys->part;
- totpart=psys->totpart;
- if (totpart==0)
- return 0;
-
- if (!finaldm->deformedOnly && !finaldm->getTessFaceDataArray(finaldm, CD_ORIGINDEX)) {
- printf("Can't create particles with the current modifier stack, disable destructive modifiers\n");
-// XXX error("Can't paint with the current modifier stack, disable destructive modifiers");
- return 0;
- }
-
- /* XXX This distribution code is totally broken in case from == PART_FROM_CHILD, it's always using finaldm
- * even if use_modifier_stack is unset... But making things consistent here break all existing edited
- * hair systems, so better wait for complete rewrite.
- */
-
- psys_thread_context_init(ctx, sim);
-
- /* First handle special cases */
- if (from == PART_FROM_CHILD) {
- /* Simple children */
- if (part->childtype != PART_CHILD_FACES) {
- BLI_srandom(31415926 + psys->seed + psys->child_seed);
- distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys);
- return 0;
- }
- }
- else {
- /* Grid distribution */
- if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) {
- BLI_srandom(31415926 + psys->seed);
-
- if (psys->part->use_modifier_stack) {
- dm = finaldm;
- }
- else {
- dm = CDDM_from_mesh((Mesh*)ob->data);
- }
- DM_ensure_tessface(dm);
-
- distribute_grid(dm,psys);
-
- if (dm != finaldm) {
- dm->release(dm);
- }
-
- return 0;
- }
- }
-
- /* Create trees and original coordinates if needed */
- if (from == PART_FROM_CHILD) {
- distr=PART_DISTR_RAND;
- BLI_srandom(31415926 + psys->seed + psys->child_seed);
- dm= finaldm;
-
- /* BMESH ONLY */
- DM_ensure_tessface(dm);
-
- children=1;
-
- tree=BLI_kdtree_new(totpart);
-
- for (p=0,pa=psys->particles; p<totpart; p++,pa++) {
- psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,NULL);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco, 1, 1);
- BLI_kdtree_insert(tree, p, orco);
- }
-
- BLI_kdtree_balance(tree);
-
- totpart = psys_get_tot_child(scene, psys);
- cfrom = from = PART_FROM_FACE;
- }
- else {
- distr = part->distr;
- BLI_srandom(31415926 + psys->seed);
-
- if (psys->part->use_modifier_stack)
- dm = finaldm;
- else
- dm= CDDM_from_mesh((Mesh*)ob->data);
-
- /* BMESH ONLY, for verts we don't care about tessfaces */
- if (from != PART_FROM_VERT) {
- DM_ensure_tessface(dm);
- }
-
- /* we need orco for consistent distributions */
- if (!CustomData_has_layer(&dm->vertData, CD_ORCO))
- DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
-
- if (from == PART_FROM_VERT) {
- MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
- float (*orcodata)[3] = dm->getVertDataArray(dm, CD_ORCO);
- int totvert = dm->getNumVerts(dm);
-
- tree=BLI_kdtree_new(totvert);
-
- for (p=0; p<totvert; p++) {
- if (orcodata) {
- copy_v3_v3(co,orcodata[p]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co, 1, 1);
- }
- else
- copy_v3_v3(co,mv[p].co);
- BLI_kdtree_insert(tree, p, co);
- }
-
- BLI_kdtree_balance(tree);
- }
- }
-
- /* Get total number of emission elements and allocate needed arrays */
- totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
-
- if (totelem == 0) {
- distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
-
- if (G.debug & G_DEBUG)
- fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
-
- if (dm != finaldm) dm->release(dm);
-
- BLI_kdtree_free(tree);
-
- return 0;
- }
-
- element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
- particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
- element_sum = MEM_mallocN(sizeof(*element_sum) * totelem, "particle_distribution_sum");
- jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
-
- /* Calculate weights from face areas */
- if ((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT) {
- MVert *v1, *v2, *v3, *v4;
- float totarea=0.f, co1[3], co2[3], co3[3], co4[3];
- float (*orcodata)[3];
-
- orcodata= dm->getVertDataArray(dm, CD_ORCO);
-
- for (i=0; i<totelem; i++) {
- MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
-
- if (orcodata) {
- copy_v3_v3(co1, orcodata[mf->v1]);
- copy_v3_v3(co2, orcodata[mf->v2]);
- copy_v3_v3(co3, orcodata[mf->v3]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co1, 1, 1);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co2, 1, 1);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co3, 1, 1);
- if (mf->v4) {
- copy_v3_v3(co4, orcodata[mf->v4]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co4, 1, 1);
- }
- }
- else {
- v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT);
- v2= (MVert*)dm->getVertData(dm,mf->v2,CD_MVERT);
- v3= (MVert*)dm->getVertData(dm,mf->v3,CD_MVERT);
- copy_v3_v3(co1, v1->co);
- copy_v3_v3(co2, v2->co);
- copy_v3_v3(co3, v3->co);
- if (mf->v4) {
- v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT);
- copy_v3_v3(co4, v4->co);
- }
- }
-
- cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
-
- if (cur > maxweight)
- maxweight = cur;
-
- element_weight[i] = cur;
- totarea += cur;
- }
-
- for (i=0; i<totelem; i++)
- element_weight[i] /= totarea;
-
- maxweight /= totarea;
- }
- else {
- float min=1.0f/(float)(MIN2(totelem,totpart));
- for (i=0; i<totelem; i++)
- element_weight[i]=min;
- maxweight=min;
- }
-
- /* Calculate weights from vgroup */
- vweight = psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
-
- if (vweight) {
- if (from==PART_FROM_VERT) {
- for (i=0;i<totelem; i++)
- element_weight[i]*=vweight[i];
- }
- else { /* PART_FROM_FACE / PART_FROM_VOLUME */
- for (i=0;i<totelem; i++) {
- MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
- tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
-
- if (mf->v4) {
- tweight += vweight[mf->v4];
- tweight /= 4.0f;
- }
- else {
- tweight /= 3.0f;
- }
-
- element_weight[i]*=tweight;
- }
- }
- MEM_freeN(vweight);
- }
-
- /* Calculate total weight of all elements */
- totweight= 0.0f;
- for (i=0;i<totelem; i++)
- totweight += element_weight[i];
-
- inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f);
-
- /* Calculate cumulative weights */
- element_sum[0] = element_weight[0] * inv_totweight;
- for (i = 1; i < totelem; i++) {
- element_sum[i] = element_sum[i - 1] + element_weight[i] * inv_totweight;
- }
-
- /* Finally assign elements to particles */
- if ((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) {
- float pos;
-
- for (p=0; p<totpart; p++) {
- /* In theory element_sum[totelem] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
- pos= BLI_frand() * element_sum[totelem - 1];
- particle_element[p] = distribute_binary_search(element_sum, totelem, pos);
- particle_element[p] = MIN2(totelem-1, particle_element[p]);
- jitter_offset[particle_element[p]] = pos;
- }
- }
- else {
- double step, pos;
-
- step = (totpart < 2) ? 0.5 : 1.0 / (double)totpart;
- /* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part
- * distribution (see T47983 and its two example files). It allows us to consider pos as
- * 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not),
- * and avoid stumbling over float imprecisions in element_sum. */
- if (from == PART_FROM_VERT) {
- pos = (totpart < totelem) ? 0.5 / (double)totelem : step * 0.5; /* We choose the smaller step. */
- }
- else {
- pos = 0.0;
- }
-
- /* Avoid initial zero-weight items. */
- for (i = 0; (element_sum[i] == 0.0) && (i < totelem - 1); i++);
-
- for (p = 0; p < totpart; p++, pos += step) {
- for ( ; (pos > (double)element_sum[i]) && (i < totelem - 1); i++);
-
- particle_element[p] = i;
-
- jitter_offset[particle_element[p]] = pos;
- }
-
- /* Avoid final zero weight items. */
- BLI_assert(p == totpart);
- if (element_weight[particle_element[--p]] == 0.0f) {
- particle_element[p] = particle_element[p - 1];
- }
- }
-
- MEM_freeN(element_sum);
-
- /* For hair, sort by origindex (allows optimization's in rendering), */
- /* however with virtual parents the children need to be in random order. */
- if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) {
- int *orig_index = NULL;
-
- if (from == PART_FROM_VERT) {
- if (dm->numVertData)
- orig_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
- }
- else {
- if (dm->numTessFaceData)
- orig_index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- }
-
- if (orig_index) {
- BLI_qsort_r(particle_element, totpart, sizeof(int), distribute_compare_orig_index, orig_index);
- }
- }
-
- /* Create jittering if needed */
- if (distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
- jitlevel= part->userjit;
-
- if (jitlevel == 0) {
- jitlevel= totpart/totelem;
- if (part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */
- if (jitlevel<3) jitlevel= 3;
- }
-
- jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit");
-
- /* for small amounts of particles we use regular jitter since it looks
- * a bit better, for larger amounts we switch to hammersley sequence
- * because it is much faster */
- if (jitlevel < 25)
- init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
- else
- hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac);
- BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
- }
-
- /* Setup things for threaded distribution */
- ctx->tree= tree;
- ctx->seams= seams;
- ctx->totseam= totseam;
- ctx->sim.psys= psys;
- ctx->index= particle_element;
- ctx->jit= jit;
- ctx->jitlevel= jitlevel;
- ctx->jitoff= jitter_offset;
- ctx->weight= element_weight;
- ctx->maxweight= maxweight;
- ctx->cfrom= cfrom;
- ctx->distr= distr;
- ctx->dm= dm;
- ctx->tpars= tpars;
-
- if (children) {
- totpart= psys_render_simplify_distribution(ctx, totpart);
- alloc_child_particles(psys, totpart);
- }
-
- return 1;
-}
-
-static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData *sim)
-{
- /* init random number generator */
- int seed = 31415926 + sim->psys->seed;
-
- task->rng = BLI_rng_new(seed);
-}
-
-static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
-{
- TaskScheduler *task_scheduler;
- TaskPool *task_pool;
- ParticleThreadContext ctx;
- ParticleTask *tasks;
- DerivedMesh *finaldm = sim->psmd->dm_final;
- int i, totpart, numtasks;
-
- /* create a task pool for distribution tasks */
- if (!psys_thread_context_init_distribute(&ctx, sim, from))
- return;
-
- task_scheduler = BLI_task_scheduler_get();
- task_pool = BLI_task_pool_create(task_scheduler, &ctx);
-
- totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart);
- psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks);
- for (i = 0; i < numtasks; ++i) {
- ParticleTask *task = &tasks[i];
-
- psys_task_init_distribute(task, sim);
- if (from == PART_FROM_CHILD)
- BLI_task_pool_push(task_pool, exec_distribute_child, task, false, TASK_PRIORITY_LOW);
- else
- BLI_task_pool_push(task_pool, exec_distribute_parent, task, false, TASK_PRIORITY_LOW);
- }
- BLI_task_pool_work_and_wait(task_pool);
-
- BLI_task_pool_free(task_pool);
-
- psys_calc_dmcache(sim->ob, finaldm, sim->psmd->dm_deformed, sim->psys);
-
- if (ctx.dm != finaldm)
- ctx.dm->release(ctx.dm);
-
- psys_tasks_free(tasks, numtasks);
-
- psys_thread_context_free(&ctx);
-}
-
-/* ready for future use, to emit particles without geometry */
-static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
-{
- distribute_invalid(sim->scene, sim->psys, 0);
-
- fprintf(stderr,"Shape emission not yet possible!\n");
-}
-
-void distribute_particles(ParticleSimulationData *sim, int from)
-{
- PARTICLE_PSMD;
- int distr_error=0;
-
- if (psmd) {
- if (psmd->dm_final)
- distribute_particles_on_dm(sim, from);
- else
- distr_error=1;
- }
- else
- distribute_particles_on_shape(sim, from);
-
- if (distr_error) {
- distribute_invalid(sim->scene, sim->psys, from);
-
- fprintf(stderr,"Particle distribution error!\n");
- }
-}
-
-/* ======== Simplify ======== */
-
-static float psys_render_viewport_falloff(double rate, float dist, float width)
-{
- return pow(rate, dist / width);
-}
-
-static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
-{
- ParticleRenderData *data = psys->renderdata;
- float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
-
- /* transform to view space */
- copy_v3_v3(co, center);
- co[3] = 1.0f;
- mul_m4_v4(data->viewmat, co);
-
- /* compute two vectors orthogonal to view vector */
- normalize_v3_v3(view, co);
- ortho_basis_v3v3_v3(ortho1, ortho2, view);
-
- /* compute on screen minification */
- w = co[2] * data->winmat[2][3] + data->winmat[3][3];
- dx = data->winx * ortho2[0] * data->winmat[0][0];
- dy = data->winy * ortho2[1] * data->winmat[1][1];
- w = sqrtf(dx * dx + dy * dy) / w;
-
- /* w squared because we are working with area */
- area = area * w * w;
-
- /* viewport of the screen test */
-
- /* project point on screen */
- mul_m4_v4(data->winmat, co);
- if (co[3] != 0.0f) {
- co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]);
- co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]);
- }
-
- /* screen space radius */
- radius = sqrtf(area / (float)M_PI);
-
- /* make smaller using fallof once over screen edge */
- *viewport = 1.0f;
-
- if (co[0] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx);
- else if (co[0] - radius > data->winx)
- *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx);
-
- if (co[1] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy);
- else if (co[1] - radius > data->winy)
- *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy);
-
- return area;
-}
-
-/* BMESH_TODO, for orig face data, we need to use MPoly */
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
-{
- DerivedMesh *dm = ctx->dm;
- Mesh *me = (Mesh *)(ctx->sim.ob->data);
- MFace *mf, *mface;
- MVert *mvert;
- ParticleRenderData *data;
- ParticleRenderElem *elems, *elem;
- ParticleSettings *part = ctx->sim.psys->part;
- float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
- float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
- double vprate;
- int *facetotvert;
- int a, b, totorigface, totface, newtot, skipped;
-
- /* double lookup */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-
- if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
- return tot;
- if (!ctx->sim.psys->renderdata)
- return tot;
-
- data = ctx->sim.psys->renderdata;
- if (data->timeoffset)
- return 0;
- if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
- return tot;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
- totorigface = me->totpoly;
-
- if (totface == 0 || totorigface == 0)
- return tot;
-
- index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
-
- facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea");
- facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter");
- facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea");
- elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem");
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- data->do_simplify = true;
- data->elems = elems;
- data->index_mf_to_mpoly = index_mf_to_mpoly;
- data->index_mp_to_orig = index_mp_to_orig;
-
- /* compute number of children per original face */
- for (a = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
- if (b != ORIGINDEX_NONE) {
- elems[b].totchild++;
- }
- }
-
- /* compute areas and centers of original faces */
- for (mf = mface, a = 0; a < totface; a++, mf++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
-
- if (b != ORIGINDEX_NONE) {
- copy_v3_v3(co1, mvert[mf->v1].co);
- copy_v3_v3(co2, mvert[mf->v2].co);
- copy_v3_v3(co3, mvert[mf->v3].co);
-
- add_v3_v3(facecenter[b], co1);
- add_v3_v3(facecenter[b], co2);
- add_v3_v3(facecenter[b], co3);
-
- if (mf->v4) {
- copy_v3_v3(co4, mvert[mf->v4].co);
- add_v3_v3(facecenter[b], co4);
- facearea[b] += area_quad_v3(co1, co2, co3, co4);
- facetotvert[b] += 4;
- }
- else {
- facearea[b] += area_tri_v3(co1, co2, co3);
- facetotvert[b] += 3;
- }
- }
- }
-
- for (a = 0; a < totorigface; a++)
- if (facetotvert[a] > 0)
- mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
-
- /* for conversion from BU area / pixel area to reference screen size */
- BKE_mesh_texspace_get(me, 0, 0, size);
- fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize;
- fac = fac * fac;
-
- powrate = log(0.5f) / log(part->simplify_rate * 0.5f);
- if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
- vprate = pow(1.0f - part->simplify_viewport, 5.0);
- else
- vprate = 1.0;
-
- /* set simplification parameters per original face */
- for (a = 0, elem = elems; a < totorigface; a++, elem++) {
- area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
- arearatio = fac * area / facearea[a];
-
- if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
- /* lambda is percentage of elements to keep */
- lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
- lambda *= viewport;
-
- lambda = MAX2(lambda, 1.0f / elem->totchild);
-
- /* compute transition region */
- t = part->simplify_transition;
- elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
- elem->reduce = 1;
-
- /* scale at end and beginning of the transition region */
- elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t);
- elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t);
-
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
-
- /* clamp scaling */
- scaleclamp = (float)min_ii(elem->totchild, 10);
- elem->scalemin = MIN2(scaleclamp, elem->scalemin);
- elem->scalemax = MIN2(scaleclamp, elem->scalemax);
-
- /* extend lambda to include transition */
- lambda = lambda + elem->t;
- if (lambda > 1.0f)
- lambda = 1.0f;
- }
- else {
- lambda = arearatio;
-
- elem->scalemax = 1.0f; //sqrt(lambda);
- elem->scalemin = 1.0f; //sqrt(lambda);
- elem->reduce = 0;
- }
-
- elem->lambda = lambda;
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
- elem->curchild = 0;
- }
-
- MEM_freeN(facearea);
- MEM_freeN(facecenter);
- MEM_freeN(facetotvert);
-
- /* move indices and set random number skipping */
- ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip");
-
- skipped = 0;
- for (a = 0, newtot = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
-
- if (b != ORIGINDEX_NONE) {
- if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
- ctx->index[newtot] = ctx->index[a];
- ctx->skip[newtot] = skipped;
- skipped = 0;
- newtot++;
- }
- else skipped++;
- }
- else skipped++;
- }
-
- for (a = 0, elem = elems; a < totorigface; a++, elem++)
- elem->curchild = 0;
-
- return newtot;
-}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
deleted file mode 100644
index 1ca68f714c8..00000000000
--- a/source/blender/blenkernel/intern/particle_system.c
+++ /dev/null
@@ -1,4347 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Raul Fernandez Hernandez (Farsthary), Stephen Swhitehorn.
- *
- * Adaptive time step
- * Classical SPH
- * Copyright 2011-2012 AutoCRC
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle_system.c
- * \ingroup bke
- */
-
-
-#include <stddef.h>
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_boid_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
-#include "DNA_object_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_listBase.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_edgehash.h"
-#include "BLI_rand.h"
-#include "BLI_jitter.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_kdtree.h"
-#include "BLI_kdopbvh.h"
-#include "BLI_sort.h"
-#include "BLI_task.h"
-#include "BLI_threads.h"
-#include "BLI_linklist.h"
-
-#include "BKE_animsys.h"
-#include "BKE_boids.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_collision.h"
-#include "BKE_colortools.h"
-#include "BKE_effect.h"
-#include "BKE_library_query.h"
-#include "BKE_particle.h"
-#include "BKE_global.h"
-
-#include "BKE_DerivedMesh.h"
-#include "BKE_object.h"
-#include "BKE_material.h"
-#include "BKE_cloth.h"
-#include "BKE_lattice.h"
-#include "BKE_pointcache.h"
-#include "BKE_mesh.h"
-#include "BKE_modifier.h"
-#include "BKE_scene.h"
-#include "BKE_bvhutils.h"
-#include "BKE_depsgraph.h"
-
-#include "PIL_time.h"
-
-#include "RE_shader_ext.h"
-
-/* fluid sim particle import */
-#ifdef WITH_MOD_FLUID
-#include "DNA_object_fluidsim.h"
-#include "LBM_fluidsim.h"
-#include <zlib.h>
-#include <string.h>
-
-#endif // WITH_MOD_FLUID
-
-static ThreadRWMutex psys_bvhtree_rwlock = BLI_RWLOCK_INITIALIZER;
-
-/************************************************/
-/* Reacting to system events */
-/************************************************/
-
-static int particles_are_dynamic(ParticleSystem *psys)
-{
- if (psys->pointcache->flag & PTCACHE_BAKED)
- return 0;
-
- if (psys->part->type == PART_HAIR)
- return psys->flag & PSYS_HAIR_DYNAMICS;
- else
- return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
-}
-
-float psys_get_current_display_percentage(ParticleSystem *psys)
-{
- ParticleSettings *part=psys->part;
-
- if ((psys->renderdata && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
- (part->child_nbr && part->childtype) || /* display percentage applies to children */
- (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
- {
- return 1.0f;
- }
-
- return psys->part->disp/100.0f;
-}
-
-static int tot_particles(ParticleSystem *psys, PTCacheID *pid)
-{
- if (pid && psys->pointcache->flag & PTCACHE_EXTERNAL)
- return pid->cache->totpoint;
- else if (psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT)
- return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist;
- else
- return psys->part->totpart - psys->totunexist;
-}
-
-void psys_reset(ParticleSystem *psys, int mode)
-{
- PARTICLE_P;
-
- if (ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) {
- if (mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) {
- /* don't free if not absolutely necessary */
- if (psys->totpart != tot_particles(psys, NULL)) {
- psys_free_particles(psys);
- psys->totpart= 0;
- }
-
- psys->totkeyed= 0;
- psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED);
-
- if (psys->edit && psys->free_edit) {
- psys->free_edit(psys->edit);
- psys->edit = NULL;
- psys->free_edit = NULL;
- }
- }
- }
- else if (mode == PSYS_RESET_CACHE_MISS) {
- /* set all particles to be skipped */
- LOOP_PARTICLES
- pa->flag |= PARS_NO_DISP;
- }
-
- /* reset children */
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child= NULL;
- }
-
- psys->totchild= 0;
-
- /* reset path cache */
- psys_free_path_cache(psys, psys->edit);
-
- /* reset point cache */
- BKE_ptcache_invalidate(psys->pointcache);
-
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
-
- psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
-}
-
-static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleData *newpars = NULL;
- BoidParticle *newboids = NULL;
- PARTICLE_P;
- int totpart, totsaved = 0;
-
- if (new_totpart<0) {
- if ((part->distr == PART_DISTR_GRID) && (part->from != PART_FROM_VERT)) {
- totpart= part->grid_res;
- totpart*=totpart*totpart;
- }
- else
- totpart=part->totpart;
- }
- else
- totpart=new_totpart;
-
- if (totpart != psys->totpart) {
- if (psys->edit && psys->free_edit) {
- psys->free_edit(psys->edit);
- psys->edit = NULL;
- psys->free_edit = NULL;
- }
-
- if (totpart) {
- newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
- if (newpars == NULL)
- return;
-
- if (psys->part->phystype == PART_PHYS_BOIDS) {
- newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles");
-
- if (newboids == NULL) {
- /* allocation error! */
- if (newpars)
- MEM_freeN(newpars);
- return;
- }
- }
- }
-
- if (psys->particles) {
- totsaved=MIN2(psys->totpart,totpart);
- /*save old pars*/
- if (totsaved) {
- memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData));
-
- if (psys->particles->boid)
- memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidParticle));
- }
-
- if (psys->particles->keys)
- MEM_freeN(psys->particles->keys);
-
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
-
- for (p=0, pa=newpars; p<totsaved; p++, pa++) {
- if (pa->keys) {
- pa->keys= NULL;
- pa->totkey= 0;
- }
- }
-
- for (p=totsaved, pa=psys->particles+totsaved; p<psys->totpart; p++, pa++)
- if (pa->hair) MEM_freeN(pa->hair);
-
- MEM_freeN(psys->particles);
- psys_free_pdd(psys);
- }
-
- psys->particles=newpars;
- psys->totpart=totpart;
-
- if (newboids) {
- LOOP_PARTICLES
- pa->boid = newboids++;
- }
- }
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child=NULL;
- psys->totchild=0;
- }
-}
-
-int psys_get_child_number(Scene *scene, ParticleSystem *psys)
-{
- int nbr;
-
- if (!psys->part->childtype)
- return 0;
-
- if (psys->renderdata)
- nbr= psys->part->ren_child_nbr;
- else
- nbr= psys->part->child_nbr;
-
- return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL);
-}
-
-int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
-{
- return psys->totpart*psys_get_child_number(scene, psys);
-}
-
-/************************************************/
-/* Distribution */
-/************************************************/
-
-void psys_calc_dmcache(Object *ob, DerivedMesh *dm_final, DerivedMesh *dm_deformed, ParticleSystem *psys)
-{
- /* use for building derived mesh mapping info:
- *
- * node: the allocated links - total derived mesh element count
- * nodearray: the array of nodes aligned with the base mesh's elements, so
- * each original elements can reference its derived elements
- */
- Mesh *me= (Mesh*)ob->data;
- bool use_modifier_stack= psys->part->use_modifier_stack;
- PARTICLE_P;
-
- /* CACHE LOCATIONS */
- if (!dm_final->deformedOnly) {
- /* Will use later to speed up subsurf/derivedmesh */
- LinkNode *node, *nodedmelem, **nodearray;
- int totdmelem, totelem, i, *origindex, *origindex_poly = NULL;
-
- if (psys->part->from == PART_FROM_VERT) {
- totdmelem= dm_final->getNumVerts(dm_final);
-
- if (use_modifier_stack) {
- totelem= totdmelem;
- origindex= NULL;
- }
- else {
- totelem= me->totvert;
- origindex= dm_final->getVertDataArray(dm_final, CD_ORIGINDEX);
- }
- }
- else { /* FROM_FACE/FROM_VOLUME */
- totdmelem= dm_final->getNumTessFaces(dm_final);
-
- if (use_modifier_stack) {
- totelem= totdmelem;
- origindex= NULL;
- origindex_poly= NULL;
- }
- else {
- totelem = dm_deformed->getNumTessFaces(dm_deformed);
- origindex = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
-
- /* for face lookups we need the poly origindex too */
- origindex_poly= dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
- if (origindex_poly == NULL) {
- origindex= NULL;
- }
- }
- }
-
- nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems");
- nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array");
-
- for (i=0, node=nodedmelem; i<totdmelem; i++, node++) {
- int origindex_final;
- node->link = SET_INT_IN_POINTER(i);
-
- /* may be vertex or face origindex */
- if (use_modifier_stack) {
- origindex_final = i;
- }
- else {
- origindex_final = origindex ? origindex[i] : ORIGINDEX_NONE;
-
- /* if we have a poly source, do an index lookup */
- if (origindex_poly && origindex_final != ORIGINDEX_NONE) {
- origindex_final = origindex_poly[origindex_final];
- }
- }
-
- if (origindex_final != ORIGINDEX_NONE && origindex_final < totelem) {
- if (nodearray[origindex_final]) {
- /* prepend */
- node->next = nodearray[origindex_final];
- nodearray[origindex_final] = node;
- }
- else {
- nodearray[origindex_final] = node;
- }
- }
- }
-
- /* cache the verts/faces! */
- LOOP_PARTICLES {
- if (pa->num < 0) {
- pa->num_dmcache = DMCACHE_NOTFOUND;
- continue;
- }
-
- if (use_modifier_stack) {
- if (pa->num < totelem)
- pa->num_dmcache = DMCACHE_ISCHILD;
- else
- pa->num_dmcache = DMCACHE_NOTFOUND;
- }
- else {
- if (psys->part->from == PART_FROM_VERT) {
- if (pa->num < totelem && nodearray[pa->num])
- pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link);
- else
- pa->num_dmcache = DMCACHE_NOTFOUND;
- }
- else { /* FROM_FACE/FROM_VOLUME */
- pa->num_dmcache = psys_particle_dm_face_lookup(dm_final, dm_deformed, pa->num, pa->fuv, nodearray);
- }
- }
- }
-
- MEM_freeN(nodearray);
- MEM_freeN(nodedmelem);
- }
- else {
- /* TODO PARTICLE, make the following line unnecessary, each function
- * should know to use the num or num_dmcache, set the num_dmcache to
- * an invalid value, just in case */
-
- LOOP_PARTICLES {
- pa->num_dmcache = DMCACHE_NOTFOUND;
- }
- }
-}
-
-/* threaded child particle distribution and path caching */
-void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData *sim)
-{
- memset(ctx, 0, sizeof(ParticleThreadContext));
- ctx->sim = *sim;
- ctx->dm = ctx->sim.psmd->dm_final;
- ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
-}
-
-#define MAX_PARTICLES_PER_TASK 256 /* XXX arbitrary - maybe use at least number of points instead for better balancing? */
-
-BLI_INLINE int ceil_ii(int a, int b)
-{
- return (a + b - 1) / b;
-}
-
-void psys_tasks_create(ParticleThreadContext *ctx, int startpart, int endpart, ParticleTask **r_tasks, int *r_numtasks)
-{
- ParticleTask *tasks;
- int numtasks = ceil_ii((endpart - startpart), MAX_PARTICLES_PER_TASK);
- float particles_per_task = (float)(endpart - startpart) / (float)numtasks, p, pnext;
- int i;
-
- tasks = MEM_callocN(sizeof(ParticleTask) * numtasks, "ParticleThread");
- *r_numtasks = numtasks;
- *r_tasks = tasks;
-
- p = (float)startpart;
- for (i = 0; i < numtasks; i++, p = pnext) {
- pnext = p + particles_per_task;
-
- tasks[i].ctx = ctx;
- tasks[i].begin = (int)p;
- tasks[i].end = min_ii((int)pnext, endpart);
- }
-}
-
-void psys_tasks_free(ParticleTask *tasks, int numtasks)
-{
- int i;
-
- /* threads */
- for (i = 0; i < numtasks; ++i) {
- if (tasks[i].rng)
- BLI_rng_free(tasks[i].rng);
- if (tasks[i].rng_path)
- BLI_rng_free(tasks[i].rng_path);
- }
-
- MEM_freeN(tasks);
-}
-
-void psys_thread_context_free(ParticleThreadContext *ctx)
-{
- /* path caching */
- if (ctx->vg_length)
- MEM_freeN(ctx->vg_length);
- if (ctx->vg_clump)
- MEM_freeN(ctx->vg_clump);
- if (ctx->vg_kink)
- MEM_freeN(ctx->vg_kink);
- if (ctx->vg_rough1)
- MEM_freeN(ctx->vg_rough1);
- if (ctx->vg_rough2)
- MEM_freeN(ctx->vg_rough2);
- if (ctx->vg_roughe)
- MEM_freeN(ctx->vg_roughe);
-
- if (ctx->sim.psys->lattice_deform_data) {
- end_latt_deform(ctx->sim.psys->lattice_deform_data);
- ctx->sim.psys->lattice_deform_data = NULL;
- }
-
- /* distribution */
- if (ctx->jit) MEM_freeN(ctx->jit);
- if (ctx->jitoff) MEM_freeN(ctx->jitoff);
- if (ctx->weight) MEM_freeN(ctx->weight);
- if (ctx->index) MEM_freeN(ctx->index);
- if (ctx->skip) MEM_freeN(ctx->skip);
- if (ctx->seams) MEM_freeN(ctx->seams);
- //if (ctx->vertpart) MEM_freeN(ctx->vertpart);
- BLI_kdtree_free(ctx->tree);
-
- if (ctx->clumpcurve != NULL) {
- curvemapping_free(ctx->clumpcurve);
- }
- if (ctx->roughcurve != NULL) {
- curvemapping_free(ctx->roughcurve);
- }
-}
-
-static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleTexture ptex;
-
- psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f);
-
- switch (part->type) {
- case PART_EMITTER:
- if (ptex.exist < psys_frand(psys, p+125))
- pa->flag |= PARS_UNEXIST;
- pa->time = part->sta + (part->end - part->sta)*ptex.time;
- break;
- case PART_HAIR:
- if (ptex.exist < psys_frand(psys, p+125))
- pa->flag |= PARS_UNEXIST;
- pa->time = 0.f;
- break;
- case PART_FLUID:
- break;
- }
-}
-
-/* set particle parameters that don't change during particle's life */
-void initialize_particle(ParticleSimulationData *sim, ParticleData *pa)
-{
- ParticleSettings *part = sim->psys->part;
- float birth_time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
-
- pa->flag &= ~PARS_UNEXIST;
- pa->time = part->sta + (part->end - part->sta) * birth_time;
-
- pa->hair_index = 0;
- /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */
- /* usage other than straight after distribute has to handle this index by itself - jahka*/
- //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we don't have a derived mesh face */
-}
-
-static void initialize_all_particles(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- /* Grid distributionsets UNEXIST flag, need to take care of
- * it here because later this flag is being reset.
- *
- * We can't do it for any distribution, because it'll then
- * conflict with texture influence, which does not free
- * unexisting particles and only sets flag.
- *
- * It's not so bad, because only grid distribution sets
- * UNEXIST flag.
- */
- const bool emit_from_volume_grid = (part->distr == PART_DISTR_GRID) &&
- (!ELEM(part->from, PART_FROM_VERT, PART_FROM_CHILD));
- PARTICLE_P;
- LOOP_PARTICLES {
- if (!(emit_from_volume_grid && (pa->flag & PARS_UNEXIST) != 0)) {
- initialize_particle(sim, pa);
- }
- }
-}
-
-static void free_unexisting_particles(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- PARTICLE_P;
-
- psys->totunexist = 0;
-
- LOOP_PARTICLES {
- if (pa->flag & PARS_UNEXIST) {
- psys->totunexist++;
- }
- }
-
- if (psys->totpart && psys->totunexist == psys->totpart) {
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
-
- MEM_freeN(psys->particles);
- psys->particles = NULL;
- psys->totpart = psys->totunexist = 0;
- }
-
- if (psys->totunexist) {
- int newtotpart = psys->totpart - psys->totunexist;
- ParticleData *npa, *newpars;
-
- npa = newpars = MEM_callocN(newtotpart * sizeof(ParticleData), "particles");
-
- for (p=0, pa=psys->particles; p<newtotpart; p++, pa++, npa++) {
- while (pa->flag & PARS_UNEXIST)
- pa++;
-
- memcpy(npa, pa, sizeof(ParticleData));
- }
-
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
- MEM_freeN(psys->particles);
- psys->particles = newpars;
- psys->totpart -= psys->totunexist;
-
- if (psys->particles->boid) {
- BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles");
-
- LOOP_PARTICLES {
- pa->boid = newboids++;
- }
-
- }
- }
-}
-
-static void get_angular_velocity_vector(short avemode, ParticleKey *state, float vec[3])
-{
- switch (avemode) {
- case PART_AVE_VELOCITY:
- copy_v3_v3(vec, state->vel);
- break;
- case PART_AVE_HORIZONTAL:
- {
- float zvec[3];
- zvec[0] = zvec[1] = 0;
- zvec[2] = 1.f;
- cross_v3_v3v3(vec, state->vel, zvec);
- break;
- }
- case PART_AVE_VERTICAL:
- {
- float zvec[3], temp[3];
- zvec[0] = zvec[1] = 0;
- zvec[2] = 1.f;
- cross_v3_v3v3(temp, state->vel, zvec);
- cross_v3_v3v3(vec, temp, state->vel);
- break;
- }
- case PART_AVE_GLOBAL_X:
- vec[0] = 1.f;
- vec[1] = vec[2] = 0;
- break;
- case PART_AVE_GLOBAL_Y:
- vec[1] = 1.f;
- vec[0] = vec[2] = 0;
- break;
- case PART_AVE_GLOBAL_Z:
- vec[2] = 1.f;
- vec[0] = vec[1] = 0;
- break;
- }
-}
-
-void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
-{
- Object *ob = sim->ob;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleTexture ptex;
- float fac, phasefac, nor[3] = {0,0,0},loc[3],vel[3] = {0.0,0.0,0.0},rot[4],q2[4];
- float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3] = {0.0,0.0,0.0};
- float x_vec[3] = {1.0,0.0,0.0}, utan[3] = {0.0,1.0,0.0}, vtan[3] = {0.0,0.0,1.0}, rot_vec[3] = {0.0,0.0,0.0};
- float q_phase[4];
-
- const bool use_boids = ((part->phystype == PART_PHYS_BOIDS) &&
- (pa->boid != NULL));
- const bool use_tangents = ((use_boids == false) &&
- ((part->tanfac != 0.0f) || (part->rotmode == PART_ROT_NOR_TAN)));
-
- int p = pa - psys->particles;
-
- /* get birth location from object */
- if (use_tangents)
- psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0);
- else
- psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0);
-
- /* get possible textural influence */
- psys_get_texture(sim, pa, &ptex, PAMAP_IVEL, cfra);
-
- /* particles live in global space so */
- /* let's convert: */
- /* -location */
- mul_m4_v3(ob->obmat, loc);
-
- /* -normal */
- mul_mat3_m4_v3(ob->obmat, nor);
- normalize_v3(nor);
-
- /* -tangent */
- if (use_tangents) {
- //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f;
- float phase=0.0f;
- mul_v3_fl(vtan,-cosf((float)M_PI*(part->tanphase+phase)));
- fac= -sinf((float)M_PI*(part->tanphase+phase));
- madd_v3_v3fl(vtan, utan, fac);
-
- mul_mat3_m4_v3(ob->obmat,vtan);
-
- copy_v3_v3(utan, nor);
- mul_v3_fl(utan,dot_v3v3(vtan,nor));
- sub_v3_v3(vtan, utan);
-
- normalize_v3(vtan);
- }
-
-
- /* -velocity (boids need this even if there's no random velocity) */
- if (part->randfac != 0.0f || (part->phystype==PART_PHYS_BOIDS && pa->boid)) {
- r_vel[0] = 2.0f * (psys_frand(psys, p + 10) - 0.5f);
- r_vel[1] = 2.0f * (psys_frand(psys, p + 11) - 0.5f);
- r_vel[2] = 2.0f * (psys_frand(psys, p + 12) - 0.5f);
-
- mul_mat3_m4_v3(ob->obmat, r_vel);
- normalize_v3(r_vel);
- }
-
- /* -angular velocity */
- if (part->avemode==PART_AVE_RAND) {
- r_ave[0] = 2.0f * (psys_frand(psys, p + 13) - 0.5f);
- r_ave[1] = 2.0f * (psys_frand(psys, p + 14) - 0.5f);
- r_ave[2] = 2.0f * (psys_frand(psys, p + 15) - 0.5f);
-
- mul_mat3_m4_v3(ob->obmat,r_ave);
- normalize_v3(r_ave);
- }
-
- /* -rotation */
- if (part->randrotfac != 0.0f) {
- r_rot[0] = 2.0f * (psys_frand(psys, p + 16) - 0.5f);
- r_rot[1] = 2.0f * (psys_frand(psys, p + 17) - 0.5f);
- r_rot[2] = 2.0f * (psys_frand(psys, p + 18) - 0.5f);
- r_rot[3] = 2.0f * (psys_frand(psys, p + 19) - 0.5f);
- normalize_qt(r_rot);
-
- mat4_to_quat(rot,ob->obmat);
- mul_qt_qtqt(r_rot,r_rot,rot);
- }
-
- if (use_boids) {
- float dvec[3], q[4], mat[3][3];
-
- copy_v3_v3(state->co,loc);
-
- /* boids don't get any initial velocity */
- zero_v3(state->vel);
-
- /* boids store direction in ave */
- if (fabsf(nor[2])==1.0f) {
- sub_v3_v3v3(state->ave, loc, ob->obmat[3]);
- normalize_v3(state->ave);
- }
- else {
- copy_v3_v3(state->ave, nor);
- }
-
- /* calculate rotation matrix */
- project_v3_v3v3(dvec, r_vel, state->ave);
- sub_v3_v3v3(mat[0], state->ave, dvec);
- normalize_v3(mat[0]);
- negate_v3_v3(mat[2], r_vel);
- normalize_v3(mat[2]);
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
-
- /* apply rotation */
- mat3_to_quat_is_ok( q,mat);
- copy_qt_qt(state->rot, q);
- }
- else {
- /* conversion done so now we apply new: */
- /* -velocity from: */
-
- /* *reactions */
- if (dtime > 0.f) {
- sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel);
- }
-
- /* *emitter velocity */
- if (dtime != 0.f && part->obfac != 0.f) {
- sub_v3_v3v3(vel, loc, state->co);
- mul_v3_fl(vel, part->obfac/dtime);
- }
-
- /* *emitter normal */
- if (part->normfac != 0.f)
- madd_v3_v3fl(vel, nor, part->normfac);
-
- /* *emitter tangent */
- if (sim->psmd && part->tanfac != 0.f)
- madd_v3_v3fl(vel, vtan, part->tanfac);
-
- /* *emitter object orientation */
- if (part->ob_vel[0] != 0.f) {
- normalize_v3_v3(vec, ob->obmat[0]);
- madd_v3_v3fl(vel, vec, part->ob_vel[0]);
- }
- if (part->ob_vel[1] != 0.f) {
- normalize_v3_v3(vec, ob->obmat[1]);
- madd_v3_v3fl(vel, vec, part->ob_vel[1]);
- }
- if (part->ob_vel[2] != 0.f) {
- normalize_v3_v3(vec, ob->obmat[2]);
- madd_v3_v3fl(vel, vec, part->ob_vel[2]);
- }
-
- /* *texture */
- /* TODO */
-
- /* *random */
- if (part->randfac != 0.f)
- madd_v3_v3fl(vel, r_vel, part->randfac);
-
- /* *particle */
- if (part->partfac != 0.f)
- madd_v3_v3fl(vel, p_vel, part->partfac);
-
- mul_v3_v3fl(state->vel, vel, ptex.ivel);
-
- /* -location from emitter */
- copy_v3_v3(state->co,loc);
-
- /* -rotation */
- unit_qt(state->rot);
-
- if (part->rotmode) {
- bool use_global_space;
-
- /* create vector into which rotation is aligned */
- switch (part->rotmode) {
- case PART_ROT_NOR:
- case PART_ROT_NOR_TAN:
- copy_v3_v3(rot_vec, nor);
- use_global_space = false;
- break;
- case PART_ROT_VEL:
- copy_v3_v3(rot_vec, vel);
- use_global_space = true;
- break;
- case PART_ROT_GLOB_X:
- case PART_ROT_GLOB_Y:
- case PART_ROT_GLOB_Z:
- rot_vec[part->rotmode - PART_ROT_GLOB_X] = 1.0f;
- use_global_space = true;
- break;
- case PART_ROT_OB_X:
- case PART_ROT_OB_Y:
- case PART_ROT_OB_Z:
- copy_v3_v3(rot_vec, ob->obmat[part->rotmode - PART_ROT_OB_X]);
- use_global_space = false;
- break;
- default:
- use_global_space = true;
- break;
- }
-
- /* create rotation quat */
-
-
- if (use_global_space) {
- negate_v3(rot_vec);
- vec_to_quat(q2, rot_vec, OB_POSX, OB_POSZ);
-
- /* randomize rotation quat */
- if (part->randrotfac != 0.0f) {
- interp_qt_qtqt(rot, q2, r_rot, part->randrotfac);
- }
- else {
- copy_qt_qt(rot, q2);
- }
- }
- else {
- /* calculate rotation in local-space */
- float q_obmat[4];
- float q_imat[4];
-
- mat4_to_quat(q_obmat, ob->obmat);
- invert_qt_qt_normalized(q_imat, q_obmat);
-
-
- if (part->rotmode != PART_ROT_NOR_TAN) {
- float rot_vec_local[3];
-
- /* rot_vec */
- negate_v3(rot_vec);
- copy_v3_v3(rot_vec_local, rot_vec);
- mul_qt_v3(q_imat, rot_vec_local);
- normalize_v3(rot_vec_local);
-
- vec_to_quat(q2, rot_vec_local, OB_POSX, OB_POSZ);
- }
- else {
- /* (part->rotmode == PART_ROT_NOR_TAN) */
- float tmat[3][3];
-
- /* note: utan_local is not taken from 'utan', we calculate from rot_vec/vtan */
- /* note: it looks like rotation phase may be applied twice (once with vtan, again below)
- * however this isn't the case - campbell */
- float *rot_vec_local = tmat[0];
- float *vtan_local = tmat[1];
- float *utan_local = tmat[2];
-
- /* use tangents */
- BLI_assert(use_tangents == true);
-
- /* rot_vec */
- copy_v3_v3(rot_vec_local, rot_vec);
- mul_qt_v3(q_imat, rot_vec_local);
-
- /* vtan_local */
- copy_v3_v3(vtan_local, vtan); /* flips, cant use */
- mul_qt_v3(q_imat, vtan_local);
-
- /* ensure orthogonal matrix (rot_vec aligned) */
- cross_v3_v3v3(utan_local, vtan_local, rot_vec_local);
- cross_v3_v3v3(vtan_local, utan_local, rot_vec_local);
-
- /* note: no need to normalize */
- mat3_to_quat(q2, tmat);
- }
-
- /* randomize rotation quat */
- if (part->randrotfac != 0.0f) {
- mul_qt_qtqt(r_rot, r_rot, q_imat);
- interp_qt_qtqt(rot, q2, r_rot, part->randrotfac);
- }
- else {
- copy_qt_qt(rot, q2);
- }
-
- mul_qt_qtqt(rot, q_obmat, rot);
- }
-
- /* rotation phase */
- phasefac = part->phasefac;
- if (part->randphasefac != 0.0f)
- phasefac += part->randphasefac * psys_frand(psys, p + 20);
- axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI);
-
- /* combine base rotation & phase */
- mul_qt_qtqt(state->rot, rot, q_phase);
- }
-
- /* -angular velocity */
-
- zero_v3(state->ave);
-
- if (part->avemode) {
- if (part->avemode == PART_AVE_RAND)
- copy_v3_v3(state->ave, r_ave);
- else
- get_angular_velocity_vector(part->avemode, state, state->ave);
-
- normalize_v3(state->ave);
- mul_v3_fl(state->ave, part->avefac);
- }
- }
-}
-
-/* recursively evaluate emitter parent anim at cfra */
-static void evaluate_emitter_anim(Scene *scene, Object *ob, float cfra)
-{
- if (ob->parent)
- evaluate_emitter_anim(scene, ob->parent, cfra);
-
- /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
- BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(scene, ob, cfra);
-}
-
-/* sets particle to the emitter surface with initial velocity & rotation */
-void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part;
- ParticleTexture ptex;
- int p = pa - psys->particles;
- part=psys->part;
-
- /* get precise emitter matrix if particle is born */
- if (part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
- evaluate_emitter_anim(sim->scene, sim->ob, pa->time);
-
- psys->flag |= PSYS_OB_ANIM_RESTORE;
- }
-
- psys_get_birth_coords(sim, pa, &pa->state, dtime, cfra);
-
- /* Initialize particle settings which depends on texture.
- *
- * We could only do it now because we'll need to know coordinate
- * before sampling the texture.
- */
- initialize_particle_texture(sim, pa, p);
-
- if (part->phystype==PART_PHYS_BOIDS && pa->boid) {
- BoidParticle *bpa = pa->boid;
-
- /* and gravity in r_ve */
- bpa->gravity[0] = bpa->gravity[1] = 0.0f;
- bpa->gravity[2] = -1.0f;
- if ((sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) &&
- (sim->scene->physics_settings.gravity[2] != 0.0f))
- {
- bpa->gravity[2] = sim->scene->physics_settings.gravity[2];
- }
-
- bpa->data.health = part->boids->health;
- bpa->data.mode = eBoidMode_InAir;
- bpa->data.state_id = ((BoidState*)part->boids->states.first)->id;
- bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f;
- }
-
- if (part->type == PART_HAIR) {
- pa->lifetime = 100.0f;
- }
- else {
- /* initialize the lifetime, in case the texture coordinates
- * are from Particles/Strands, which would cause undefined values
- */
- pa->lifetime = part->lifetime * (1.0f - part->randlife * psys_frand(psys, p + 21));
- pa->dietime = pa->time + pa->lifetime;
-
- /* get possible textural influence */
- psys_get_texture(sim, pa, &ptex, PAMAP_LIFE, cfra);
-
- pa->lifetime = part->lifetime * ptex.life;
-
- if (part->randlife != 0.0f)
- pa->lifetime *= 1.0f - part->randlife * psys_frand(psys, p + 21);
- }
-
- pa->dietime = pa->time + pa->lifetime;
-
- if (sim->psys->pointcache && sim->psys->pointcache->flag & PTCACHE_BAKED &&
- sim->psys->pointcache->mem_cache.first) {
- float dietime = psys_get_dietime_from_cache(sim->psys->pointcache, p);
- pa->dietime = MIN2(pa->dietime, dietime);
- }
-
- if (pa->time > cfra)
- pa->alive = PARS_UNBORN;
- else if (pa->dietime <= cfra)
- pa->alive = PARS_DEAD;
- else
- pa->alive = PARS_ALIVE;
-
- pa->state.time = cfra;
-}
-static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from)
-{
- ParticleData *pa;
- int p, totpart=sim->psys->totpart;
-
- for (p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++)
- reset_particle(sim, pa, dtime, cfra);
-}
-/************************************************/
-/* Particle targets */
-/************************************************/
-ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt)
-{
- ParticleSystem *psys = NULL;
-
- if (pt->ob == NULL || pt->ob == ob)
- psys = BLI_findlink(&ob->particlesystem, pt->psys-1);
- else
- psys = BLI_findlink(&pt->ob->particlesystem, pt->psys-1);
-
- if (psys)
- pt->flag |= PTARGET_VALID;
- else
- pt->flag &= ~PTARGET_VALID;
-
- return psys;
-}
-/************************************************/
-/* Keyed particles */
-/************************************************/
-/* Counts valid keyed targets */
-void psys_count_keyed_targets(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys, *kpsys;
- ParticleTarget *pt = psys->targets.first;
- int keys_valid = 1;
- psys->totkeyed = 0;
-
- for (; pt; pt=pt->next) {
- kpsys = psys_get_target_system(sim->ob, pt);
-
- if (kpsys && kpsys->totpart) {
- psys->totkeyed += keys_valid;
- if (psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f)
- psys->totkeyed += 1;
- }
- else {
- keys_valid = 0;
- }
- }
-
- psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops;
-}
-
-static void set_keyed_keys(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSimulationData ksim= {0};
- ParticleTarget *pt;
- PARTICLE_P;
- ParticleKey *key;
- int totpart = psys->totpart, k, totkeys = psys->totkeyed;
- int keyed_flag = 0;
-
- ksim.scene= sim->scene;
-
- /* no proper targets so let's clear and bail out */
- if (psys->totkeyed==0) {
- free_keyed_keys(psys);
- psys->flag &= ~PSYS_KEYED;
- return;
- }
-
- if (totpart && psys->particles->totkey != totkeys) {
- free_keyed_keys(psys);
-
- key = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys");
-
- LOOP_PARTICLES {
- pa->keys = key;
- pa->totkey = totkeys;
- key += totkeys;
- }
- }
-
- psys->flag &= ~PSYS_KEYED;
-
-
- pt = psys->targets.first;
- for (k=0; k<totkeys; k++) {
- ksim.ob = pt->ob ? pt->ob : sim->ob;
- ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1);
- keyed_flag = (ksim.psys->flag & PSYS_KEYED);
- ksim.psys->flag &= ~PSYS_KEYED;
-
- LOOP_PARTICLES {
- key = pa->keys + k;
- key->time = -1.0; /* use current time */
-
- psys_get_particle_state(&ksim, p%ksim.psys->totpart, key, 1);
-
- if (psys->flag & PSYS_KEYED_TIMING) {
- key->time = pa->time + pt->time;
- if (pt->duration != 0.0f && k+1 < totkeys) {
- copy_particle_key(key+1, key, 1);
- (key+1)->time = pa->time + pt->time + pt->duration;
- }
- }
- else if (totkeys > 1)
- key->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime;
- else
- key->time = pa->time;
- }
-
- if (psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f)
- k++;
-
- ksim.psys->flag |= keyed_flag;
-
- pt = (pt->next && pt->next->flag & PTARGET_VALID) ? pt->next : psys->targets.first;
- }
-
- psys->flag |= PSYS_KEYED;
-}
-
-/************************************************/
-/* Point Cache */
-/************************************************/
-void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
-{
- PointCache *cache = psys->pointcache;
-
- if (cache->flag & PTCACHE_DISK_CACHE && BLI_listbase_is_empty(&cache->mem_cache)) {
- PTCacheID pid;
- BKE_ptcache_id_from_particles(&pid, ob, psys);
- cache->flag &= ~PTCACHE_DISK_CACHE;
- BKE_ptcache_disk_to_mem(&pid);
- cache->flag |= PTCACHE_DISK_CACHE;
- }
-}
-static void psys_clear_temp_pointcache(ParticleSystem *psys)
-{
- if (psys->pointcache->flag & PTCACHE_DISK_CACHE)
- BKE_ptcache_free_mem(&psys->pointcache->mem_cache);
-}
-void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
-{
- ParticleSettings *part = psys->part;
-
- *sfra = max_ii(1, (int)part->sta);
- *efra = min_ii((int)(part->end + part->lifetime + 1.0f), max_ii(scene->r.pefra, scene->r.efra));
-}
-
-/************************************************/
-/* Effectors */
-/************************************************/
-static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra)
-{
- if (psys) {
- PARTICLE_P;
- int totpart = 0;
- bool need_rebuild;
-
- BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_READ);
- need_rebuild = !psys->bvhtree || psys->bvhtree_frame != cfra;
- BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
-
- if (need_rebuild) {
- LOOP_SHOWN_PARTICLES {
- totpart++;
- }
-
- BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_WRITE);
-
- BLI_bvhtree_free(psys->bvhtree);
- psys->bvhtree = BLI_bvhtree_new(totpart, 0.0, 4, 6);
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_ALIVE) {
- if (pa->state.time == cfra)
- BLI_bvhtree_insert(psys->bvhtree, p, pa->prev_state.co, 1);
- else
- BLI_bvhtree_insert(psys->bvhtree, p, pa->state.co, 1);
- }
- }
- BLI_bvhtree_balance(psys->bvhtree);
-
- psys->bvhtree_frame = cfra;
-
- BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
- }
- }
-}
-void psys_update_particle_tree(ParticleSystem *psys, float cfra)
-{
- if (psys) {
- PARTICLE_P;
- int totpart = 0;
-
- if (!psys->tree || psys->tree_frame != cfra) {
- LOOP_SHOWN_PARTICLES {
- totpart++;
- }
-
- BLI_kdtree_free(psys->tree);
- psys->tree = BLI_kdtree_new(psys->totpart);
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_ALIVE) {
- if (pa->state.time == cfra)
- BLI_kdtree_insert(psys->tree, p, pa->prev_state.co);
- else
- BLI_kdtree_insert(psys->tree, p, pa->state.co);
- }
- }
- BLI_kdtree_balance(psys->tree);
-
- psys->tree_frame = cfra;
- }
- }
-}
-
-static void psys_update_effectors(ParticleSimulationData *sim)
-{
- pdEndEffectors(&sim->psys->effectors);
- sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys,
- sim->psys->part->effector_weights, true);
- precalc_guides(sim, sim->psys->effectors);
-}
-
-static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration,
- void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse),
- void *forcedata)
-{
-#define ZERO_F43 {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}
-
- ParticleKey states[5];
- float force[3], acceleration[3], impulse[3], dx[4][3] = ZERO_F43, dv[4][3] = ZERO_F43, oldpos[3];
- float pa_mass= (part->flag & PART_SIZEMASS ? part->mass * pa->size : part->mass);
- int i, steps=1;
- int integrator = part->integrator;
-
-#undef ZERO_F43
-
- copy_v3_v3(oldpos, pa->state.co);
-
- /* Verlet integration behaves strangely with moving emitters, so do first step with euler. */
- if (pa->prev_state.time < 0.f && integrator == PART_INT_VERLET)
- integrator = PART_INT_EULER;
-
- switch (integrator) {
- case PART_INT_EULER:
- steps=1;
- break;
- case PART_INT_MIDPOINT:
- steps=2;
- break;
- case PART_INT_RK4:
- steps=4;
- break;
- case PART_INT_VERLET:
- steps=1;
- break;
- }
-
- for (i=0; i<steps; i++) {
- copy_particle_key(states + i, &pa->state, 1);
- }
-
- states->time = 0.f;
-
- for (i=0; i<steps; i++) {
- zero_v3(force);
- zero_v3(impulse);
-
- force_func(forcedata, states+i, force, impulse);
-
- /* force to acceleration*/
- mul_v3_v3fl(acceleration, force, 1.0f/pa_mass);
-
- if (external_acceleration)
- add_v3_v3(acceleration, external_acceleration);
-
- /* calculate next state */
- add_v3_v3(states[i].vel, impulse);
-
- switch (integrator) {
- case PART_INT_EULER:
- madd_v3_v3v3fl(pa->state.co, states->co, states->vel, dtime);
- madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime);
- break;
- case PART_INT_MIDPOINT:
- if (i==0) {
- madd_v3_v3v3fl(states[1].co, states->co, states->vel, dtime*0.5f);
- madd_v3_v3v3fl(states[1].vel, states->vel, acceleration, dtime*0.5f);
- states[1].time = dtime*0.5f;
- /*fra=sim->psys->cfra+0.5f*dfra;*/
- }
- else {
- madd_v3_v3v3fl(pa->state.co, states->co, states[1].vel, dtime);
- madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime);
- }
- break;
- case PART_INT_RK4:
- switch (i) {
- case 0:
- copy_v3_v3(dx[0], states->vel);
- mul_v3_fl(dx[0], dtime);
- copy_v3_v3(dv[0], acceleration);
- mul_v3_fl(dv[0], dtime);
-
- madd_v3_v3v3fl(states[1].co, states->co, dx[0], 0.5f);
- madd_v3_v3v3fl(states[1].vel, states->vel, dv[0], 0.5f);
- states[1].time = dtime*0.5f;
- /*fra=sim->psys->cfra+0.5f*dfra;*/
- break;
- case 1:
- madd_v3_v3v3fl(dx[1], states->vel, dv[0], 0.5f);
- mul_v3_fl(dx[1], dtime);
- copy_v3_v3(dv[1], acceleration);
- mul_v3_fl(dv[1], dtime);
-
- madd_v3_v3v3fl(states[2].co, states->co, dx[1], 0.5f);
- madd_v3_v3v3fl(states[2].vel, states->vel, dv[1], 0.5f);
- states[2].time = dtime*0.5f;
- break;
- case 2:
- madd_v3_v3v3fl(dx[2], states->vel, dv[1], 0.5f);
- mul_v3_fl(dx[2], dtime);
- copy_v3_v3(dv[2], acceleration);
- mul_v3_fl(dv[2], dtime);
-
- add_v3_v3v3(states[3].co, states->co, dx[2]);
- add_v3_v3v3(states[3].vel, states->vel, dv[2]);
- states[3].time = dtime;
- /*fra=cfra;*/
- break;
- case 3:
- add_v3_v3v3(dx[3], states->vel, dv[2]);
- mul_v3_fl(dx[3], dtime);
- copy_v3_v3(dv[3], acceleration);
- mul_v3_fl(dv[3], dtime);
-
- madd_v3_v3v3fl(pa->state.co, states->co, dx[0], 1.0f/6.0f);
- madd_v3_v3fl(pa->state.co, dx[1], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.co, dx[2], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.co, dx[3], 1.0f/6.0f);
-
- madd_v3_v3v3fl(pa->state.vel, states->vel, dv[0], 1.0f/6.0f);
- madd_v3_v3fl(pa->state.vel, dv[1], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.vel, dv[2], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.vel, dv[3], 1.0f/6.0f);
- }
- break;
- case PART_INT_VERLET: /* Verlet integration */
- madd_v3_v3v3fl(pa->state.vel, pa->prev_state.vel, acceleration, dtime);
- madd_v3_v3v3fl(pa->state.co, pa->prev_state.co, pa->state.vel, dtime);
-
- sub_v3_v3v3(pa->state.vel, pa->state.co, oldpos);
- mul_v3_fl(pa->state.vel, 1.0f/dtime);
- break;
- }
- }
-}
-
-/*********************************************************************************************************
- * SPH fluid physics
- *
- * In theory, there could be unlimited implementation of SPH simulators
- *
- * This code uses in some parts adapted algorithms from the pseudo code as outlined in the Research paper:
- *
- * Titled: Particle-based Viscoelastic Fluid Simulation.
- * Authors: Simon Clavet, Philippe Beaudoin and Pierre Poulin
- * Website: http://www.iro.umontreal.ca/labs/infographie/papers/Clavet-2005-PVFS/
- *
- * Presented at Siggraph, (2005)
- *
- * ********************************************************************************************************/
-#define PSYS_FLUID_SPRINGS_INITIAL_SIZE 256
-static ParticleSpring *sph_spring_add(ParticleSystem *psys, ParticleSpring *spring)
-{
- /* Are more refs required? */
- if (psys->alloc_fluidsprings == 0 || psys->fluid_springs == NULL) {
- psys->alloc_fluidsprings = PSYS_FLUID_SPRINGS_INITIAL_SIZE;
- psys->fluid_springs = (ParticleSpring*)MEM_callocN(psys->alloc_fluidsprings * sizeof(ParticleSpring), "Particle Fluid Springs");
- }
- else if (psys->tot_fluidsprings == psys->alloc_fluidsprings) {
- /* Double the number of refs allocated */
- psys->alloc_fluidsprings *= 2;
- psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
- }
-
- memcpy(psys->fluid_springs + psys->tot_fluidsprings, spring, sizeof(ParticleSpring));
- psys->tot_fluidsprings++;
-
- return psys->fluid_springs + psys->tot_fluidsprings - 1;
-}
-static void sph_spring_delete(ParticleSystem *psys, int j)
-{
- if (j != psys->tot_fluidsprings - 1)
- psys->fluid_springs[j] = psys->fluid_springs[psys->tot_fluidsprings - 1];
-
- psys->tot_fluidsprings--;
-
- if (psys->tot_fluidsprings < psys->alloc_fluidsprings/2 && psys->alloc_fluidsprings > PSYS_FLUID_SPRINGS_INITIAL_SIZE) {
- psys->alloc_fluidsprings /= 2;
- psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
- }
-}
-static void sph_springs_modify(ParticleSystem *psys, float dtime)
-{
- SPHFluidSettings *fluid = psys->part->fluid;
- ParticleData *pa1, *pa2;
- ParticleSpring *spring = psys->fluid_springs;
-
- float h, d, Rij[3], rij, Lij;
- int i;
-
- float yield_ratio = fluid->yield_ratio;
- float plasticity = fluid->plasticity_constant;
- /* scale things according to dtime */
- float timefix = 25.f * dtime;
-
- if ((fluid->flag & SPH_VISCOELASTIC_SPRINGS)==0 || fluid->spring_k == 0.f)
- return;
-
- /* Loop through the springs */
- for (i=0; i<psys->tot_fluidsprings; i++, spring++) {
- pa1 = psys->particles + spring->particle_index[0];
- pa2 = psys->particles + spring->particle_index[1];
-
- sub_v3_v3v3(Rij, pa2->prev_state.co, pa1->prev_state.co);
- rij = normalize_v3(Rij);
-
- /* adjust rest length */
- Lij = spring->rest_length;
- d = yield_ratio * timefix * Lij;
-
- if (rij > Lij + d) // Stretch
- spring->rest_length += plasticity * (rij - Lij - d) * timefix;
- else if (rij < Lij - d) // Compress
- spring->rest_length -= plasticity * (Lij - d - rij) * timefix;
-
- h = 4.f*pa1->size;
-
- if (spring->rest_length > h)
- spring->delete_flag = 1;
- }
-
- /* Loop through springs backwaqrds - for efficient delete function */
- for (i=psys->tot_fluidsprings-1; i >= 0; i--) {
- if (psys->fluid_springs[i].delete_flag)
- sph_spring_delete(psys, i);
- }
-}
-static EdgeHash *sph_springhash_build(ParticleSystem *psys)
-{
- EdgeHash *springhash = NULL;
- ParticleSpring *spring;
- int i = 0;
-
- springhash = BLI_edgehash_new_ex(__func__, psys->tot_fluidsprings);
-
- for (i=0, spring=psys->fluid_springs; i<psys->tot_fluidsprings; i++, spring++)
- BLI_edgehash_insert(springhash, spring->particle_index[0], spring->particle_index[1], SET_INT_IN_POINTER(i+1));
-
- return springhash;
-}
-
-#define SPH_NEIGHBORS 512
-typedef struct SPHNeighbor {
- ParticleSystem *psys;
- int index;
-} SPHNeighbor;
-
-typedef struct SPHRangeData {
- SPHNeighbor neighbors[SPH_NEIGHBORS];
- int tot_neighbors;
-
- float* data;
-
- ParticleSystem *npsys;
- ParticleData *pa;
-
- float h;
- float mass;
- float massfac;
- int use_size;
-} SPHRangeData;
-
-static void sph_evaluate_func(BVHTree *tree, ParticleSystem **psys, float co[3], SPHRangeData *pfr, float interaction_radius, BVHTree_RangeQuery callback)
-{
- int i;
-
- pfr->tot_neighbors = 0;
-
- for (i=0; i < 10 && psys[i]; i++) {
- pfr->npsys = psys[i];
- pfr->massfac = psys[i]->part->mass / pfr->mass;
- pfr->use_size = psys[i]->part->flag & PART_SIZEMASS;
-
- if (tree) {
- BLI_bvhtree_range_query(tree, co, interaction_radius, callback, pfr);
- break;
- }
- else {
- BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_READ);
-
- BLI_bvhtree_range_query(psys[i]->bvhtree, co, interaction_radius, callback, pfr);
-
- BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
- }
- }
-}
-static void sph_density_accum_cb(void *userdata, int index, const float co[3], float squared_dist)
-{
- SPHRangeData *pfr = (SPHRangeData *)userdata;
- ParticleData *npa = pfr->npsys->particles + index;
- float q;
- float dist;
-
- UNUSED_VARS(co);
-
- if (npa == pfr->pa || squared_dist < FLT_EPSILON)
- return;
-
- /* Ugh! One particle has too many neighbors! If some aren't taken into
- * account, the forces will be biased by the tree search order. This
- * effectively adds enery to the system, and results in a churning motion.
- * But, we have to stop somewhere, and it's not the end of the world.
- * - jahka and z0r
- */
- if (pfr->tot_neighbors >= SPH_NEIGHBORS)
- return;
-
- pfr->neighbors[pfr->tot_neighbors].index = index;
- pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
- pfr->tot_neighbors++;
-
- dist = sqrtf(squared_dist);
- q = (1.f - dist/pfr->h) * pfr->massfac;
-
- if (pfr->use_size)
- q *= npa->size;
-
- pfr->data[0] += q*q;
- pfr->data[1] += q*q*q;
-}
-
-/*
- * Find the Courant number for an SPH particle (used for adaptive time step).
- */
-static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
-{
- ParticleData *pa, *npa;
- int i;
- float flow[3], offset[3], dist;
-
- zero_v3(flow);
-
- dist = 0.0f;
- if (pfr->tot_neighbors > 0) {
- pa = pfr->pa;
- for (i=0; i < pfr->tot_neighbors; i++) {
- npa = pfr->neighbors[i].psys->particles + pfr->neighbors[i].index;
- sub_v3_v3v3(offset, pa->prev_state.co, npa->prev_state.co);
- dist += len_v3(offset);
- add_v3_v3(flow, npa->prev_state.vel);
- }
- dist += sphdata->psys[0]->part->fluid->radius; // TODO: remove this? - z0r
- sphdata->element_size = dist / pfr->tot_neighbors;
- mul_v3_v3fl(sphdata->flow, flow, 1.0f / pfr->tot_neighbors);
- }
- else {
- sphdata->element_size = FLT_MAX;
- copy_v3_v3(sphdata->flow, flow);
- }
-}
-static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
-{
- SPHData *sphdata = (SPHData *)sphdata_v;
- ParticleSystem **psys = sphdata->psys;
- ParticleData *pa = sphdata->pa;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- ParticleSpring *spring = NULL;
- SPHRangeData pfr;
- SPHNeighbor *pfn;
- float *gravity = sphdata->gravity;
- EdgeHash *springhash = sphdata->eh;
-
- float q, u, rij, dv[3];
- float pressure, near_pressure;
-
- float visc = fluid->viscosity_omega;
- float stiff_visc = fluid->viscosity_beta * (fluid->flag & SPH_FAC_VISCOSITY ? fluid->viscosity_omega : 1.f);
-
- float inv_mass = 1.0f / sphdata->mass;
- float spring_constant = fluid->spring_k;
-
- /* 4.0 seems to be a pretty good value */
- float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
- float h = interaction_radius * sphdata->hfac;
- float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.f); /* 4.77 is an experimentally determined density factor */
- float rest_length = fluid->rest_length * (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.f);
-
- float stiffness = fluid->stiffness_k;
- float stiffness_near_fac = fluid->stiffness_knear * (fluid->flag & SPH_FAC_REPULSION ? fluid->stiffness_k : 1.f);
-
- ParticleData *npa;
- float vec[3];
- float vel[3];
- float co[3];
- float data[2];
- float density, near_density;
-
- int i, spring_index, index = pa - psys[0]->particles;
-
- data[0] = data[1] = 0;
- pfr.data = data;
- pfr.h = h;
- pfr.pa = pa;
- pfr.mass = sphdata->mass;
-
- sph_evaluate_func( NULL, psys, state->co, &pfr, interaction_radius, sph_density_accum_cb);
-
- density = data[0];
- near_density = data[1];
-
- pressure = stiffness * (density - rest_density);
- near_pressure = stiffness_near_fac * near_density;
-
- pfn = pfr.neighbors;
- for (i=0; i<pfr.tot_neighbors; i++, pfn++) {
- npa = pfn->psys->particles + pfn->index;
-
- madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
-
- sub_v3_v3v3(vec, co, state->co);
- rij = normalize_v3(vec);
-
- q = (1.f - rij/h) * pfn->psys->part->mass * inv_mass;
-
- if (pfn->psys->part->flag & PART_SIZEMASS)
- q *= npa->size;
-
- copy_v3_v3(vel, npa->prev_state.vel);
-
- /* Double Density Relaxation */
- madd_v3_v3fl(force, vec, -(pressure + near_pressure*q)*q);
-
- /* Viscosity */
- if (visc > 0.f || stiff_visc > 0.f) {
- sub_v3_v3v3(dv, vel, state->vel);
- u = dot_v3v3(vec, dv);
-
- if (u < 0.f && visc > 0.f)
- madd_v3_v3fl(force, vec, 0.5f * q * visc * u );
-
- if (u > 0.f && stiff_visc > 0.f)
- madd_v3_v3fl(force, vec, 0.5f * q * stiff_visc * u );
- }
-
- if (spring_constant > 0.f) {
- /* Viscoelastic spring force */
- if (pfn->psys == psys[0] && fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash) {
- /* BLI_edgehash_lookup appears to be thread-safe. - z0r */
- spring_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(springhash, index, pfn->index));
-
- if (spring_index) {
- spring = psys[0]->fluid_springs + spring_index - 1;
-
- madd_v3_v3fl(force, vec, -10.f * spring_constant * (1.f - rij/h) * (spring->rest_length - rij));
- }
- else if (fluid->spring_frames == 0 || (pa->prev_state.time-pa->time) <= fluid->spring_frames) {
- ParticleSpring temp_spring;
- temp_spring.particle_index[0] = index;
- temp_spring.particle_index[1] = pfn->index;
- temp_spring.rest_length = (fluid->flag & SPH_CURRENT_REST_LENGTH) ? rij : rest_length;
- temp_spring.delete_flag = 0;
-
- /* sph_spring_add is not thread-safe. - z0r */
- sph_spring_add(psys[0], &temp_spring);
- }
- }
- else {/* PART_SPRING_HOOKES - Hooke's spring force */
- madd_v3_v3fl(force, vec, -10.f * spring_constant * (1.f - rij/h) * (rest_length - rij));
- }
- }
- }
-
- /* Artificial buoyancy force in negative gravity direction */
- if (fluid->buoyancy > 0.f && gravity)
- madd_v3_v3fl(force, gravity, fluid->buoyancy * (density-rest_density));
-
- if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
- sph_particle_courant(sphdata, &pfr);
- sphdata->pass++;
-}
-
-static void sphclassical_density_accum_cb(void *userdata, int index, const float co[3], float UNUSED(squared_dist))
-{
- SPHRangeData *pfr = (SPHRangeData *)userdata;
- ParticleData *npa = pfr->npsys->particles + index;
- float q;
- float qfac = 21.0f / (256.f * (float)M_PI);
- float rij, rij_h;
- float vec[3];
-
- /* Exclude particles that are more than 2h away. Can't use squared_dist here
- * because it is not accurate enough. Use current state, i.e. the output of
- * basic_integrate() - z0r */
- sub_v3_v3v3(vec, npa->state.co, co);
- rij = len_v3(vec);
- rij_h = rij / pfr->h;
- if (rij_h > 2.0f)
- return;
-
- /* Smoothing factor. Utilise the Wendland kernel. gnuplot:
- * q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x)
- * plot [0:2] q1(x) */
- q = qfac / pow3f(pfr->h) * pow4f(2.0f - rij_h) * ( 1.0f + 2.0f * rij_h);
- q *= pfr->npsys->part->mass;
-
- if (pfr->use_size)
- q *= pfr->pa->size;
-
- pfr->data[0] += q;
- pfr->data[1] += q / npa->sphdensity;
-}
-
-static void sphclassical_neighbour_accum_cb(void *userdata, int index, const float co[3], float UNUSED(squared_dist))
-{
- SPHRangeData *pfr = (SPHRangeData *)userdata;
- ParticleData *npa = pfr->npsys->particles + index;
- float rij, rij_h;
- float vec[3];
-
- if (pfr->tot_neighbors >= SPH_NEIGHBORS)
- return;
-
- /* Exclude particles that are more than 2h away. Can't use squared_dist here
- * because it is not accurate enough. Use current state, i.e. the output of
- * basic_integrate() - z0r */
- sub_v3_v3v3(vec, npa->state.co, co);
- rij = len_v3(vec);
- rij_h = rij / pfr->h;
- if (rij_h > 2.0f)
- return;
-
- pfr->neighbors[pfr->tot_neighbors].index = index;
- pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
- pfr->tot_neighbors++;
-}
-static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
-{
- SPHData *sphdata = (SPHData *)sphdata_v;
- ParticleSystem **psys = sphdata->psys;
- ParticleData *pa = sphdata->pa;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- SPHRangeData pfr;
- SPHNeighbor *pfn;
- float *gravity = sphdata->gravity;
-
- float dq, u, rij, dv[3];
- float pressure, npressure;
-
- float visc = fluid->viscosity_omega;
-
- float interaction_radius;
- float h, hinv;
- /* 4.77 is an experimentally determined density factor */
- float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f);
-
- // Use speed of sound squared
- float stiffness = pow2f(fluid->stiffness_k);
-
- ParticleData *npa;
- float vec[3];
- float co[3];
- float pressureTerm;
-
- int i;
-
- float qfac2 = 42.0f / (256.0f * (float)M_PI);
- float rij_h;
-
- /* 4.0 here is to be consistent with previous formulation/interface */
- interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
- h = interaction_radius * sphdata->hfac;
- hinv = 1.0f / h;
-
- pfr.h = h;
- pfr.pa = pa;
-
- sph_evaluate_func(NULL, psys, state->co, &pfr, interaction_radius, sphclassical_neighbour_accum_cb);
- pressure = stiffness * (pow7f(pa->sphdensity / rest_density) - 1.0f);
-
- /* multiply by mass so that we return a force, not accel */
- qfac2 *= sphdata->mass / pow3f(pfr.h);
-
- pfn = pfr.neighbors;
- for (i = 0; i < pfr.tot_neighbors; i++, pfn++) {
- npa = pfn->psys->particles + pfn->index;
- if (npa == pa) {
- /* we do not contribute to ourselves */
- continue;
- }
-
- /* Find vector to neighbor. Exclude particles that are more than 2h
- * away. Can't use current state here because it may have changed on
- * another thread - so do own mini integration. Unlike basic_integrate,
- * SPH integration depends on neighboring particles. - z0r */
- madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
- sub_v3_v3v3(vec, co, state->co);
- rij = normalize_v3(vec);
- rij_h = rij / pfr.h;
- if (rij_h > 2.0f)
- continue;
-
- npressure = stiffness * (pow7f(npa->sphdensity / rest_density) - 1.0f);
-
- /* First derivative of smoothing factor. Utilise the Wendland kernel.
- * gnuplot:
- * q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x)
- * plot [0:2] q2(x)
- * Particles > 2h away are excluded above. */
- dq = qfac2 * (2.0f * pow4f(2.0f - rij_h) - 4.0f * pow3f(2.0f - rij_h) * (1.0f + 2.0f * rij_h) );
-
- if (pfn->psys->part->flag & PART_SIZEMASS)
- dq *= npa->size;
-
- pressureTerm = pressure / pow2f(pa->sphdensity) + npressure / pow2f(npa->sphdensity);
-
- /* Note that 'minus' is removed, because vec = vecBA, not vecAB.
- * This applies to the viscosity calculation below, too. */
- madd_v3_v3fl(force, vec, pressureTerm * dq);
-
- /* Viscosity */
- if (visc > 0.0f) {
- sub_v3_v3v3(dv, npa->prev_state.vel, pa->prev_state.vel);
- u = dot_v3v3(vec, dv);
- /* Apply parameters */
- u *= -dq * hinv * visc / (0.5f * npa->sphdensity + 0.5f * pa->sphdensity);
- madd_v3_v3fl(force, vec, u);
- }
- }
-
- /* Artificial buoyancy force in negative gravity direction */
- if (fluid->buoyancy > 0.f && gravity)
- madd_v3_v3fl(force, gravity, fluid->buoyancy * (pa->sphdensity - rest_density));
-
- if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
- sph_particle_courant(sphdata, &pfr);
- sphdata->pass++;
-}
-
-static void sphclassical_calc_dens(ParticleData *pa, float UNUSED(dfra), SPHData *sphdata)
-{
- ParticleSystem **psys = sphdata->psys;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- /* 4.0 seems to be a pretty good value */
- float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
- SPHRangeData pfr;
- float data[2];
-
- data[0] = 0;
- data[1] = 0;
- pfr.data = data;
- pfr.h = interaction_radius * sphdata->hfac;
- pfr.pa = pa;
- pfr.mass = sphdata->mass;
-
- sph_evaluate_func( NULL, psys, pa->state.co, &pfr, interaction_radius, sphclassical_density_accum_cb);
- pa->sphdensity = min_ff(max_ff(data[0], fluid->rest_density * 0.9f), fluid->rest_density * 1.1f);
-}
-
-void psys_sph_init(ParticleSimulationData *sim, SPHData *sphdata)
-{
- ParticleTarget *pt;
- int i;
-
- // Add other coupled particle systems.
- sphdata->psys[0] = sim->psys;
- for (i=1, pt=sim->psys->targets.first; i<10; i++, pt=(pt?pt->next:NULL))
- sphdata->psys[i] = pt ? psys_get_target_system(sim->ob, pt) : NULL;
-
- if (psys_uses_gravity(sim))
- sphdata->gravity = sim->scene->physics_settings.gravity;
- else
- sphdata->gravity = NULL;
- sphdata->eh = sph_springhash_build(sim->psys);
-
- // These per-particle values should be overridden later, but just for
- // completeness we give them default values now.
- sphdata->pa = NULL;
- sphdata->mass = 1.0f;
-
- if (sim->psys->part->fluid->solver == SPH_SOLVER_DDR) {
- sphdata->force_cb = sph_force_cb;
- sphdata->density_cb = sph_density_accum_cb;
- sphdata->hfac = 1.0f;
- }
- else {
- /* SPH_SOLVER_CLASSICAL */
- sphdata->force_cb = sphclassical_force_cb;
- sphdata->density_cb = sphclassical_density_accum_cb;
- sphdata->hfac = 0.5f;
- }
-
-}
-
-void psys_sph_finalise(SPHData *sphdata)
-{
- if (sphdata->eh) {
- BLI_edgehash_free(sphdata->eh, NULL);
- sphdata->eh = NULL;
- }
-}
-/* Sample the density field at a point in space. */
-void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2])
-{
- ParticleSystem **psys = sphdata->psys;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- /* 4.0 seems to be a pretty good value */
- float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
- SPHRangeData pfr;
- float density[2];
-
- density[0] = density[1] = 0.0f;
- pfr.data = density;
- pfr.h = interaction_radius * sphdata->hfac;
- pfr.mass = sphdata->mass;
-
- sph_evaluate_func(tree, psys, co, &pfr, interaction_radius, sphdata->density_cb);
-
- vars[0] = pfr.data[0];
- vars[1] = pfr.data[1];
-}
-
-static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, SPHData *sphdata)
-{
- ParticleSettings *part = sim->psys->part;
- // float timestep = psys_get_timestep(sim); // UNUSED
- float pa_mass = part->mass * (part->flag & PART_SIZEMASS ? pa->size : 1.f);
- float dtime = dfra*psys_get_timestep(sim);
- // int steps = 1; // UNUSED
- float effector_acceleration[3];
-
- sphdata->pa = pa;
- sphdata->mass = pa_mass;
- sphdata->pass = 0;
- //sphdata.element_size and sphdata.flow are set in the callback.
-
- /* restore previous state and treat gravity & effectors as external acceleration*/
- sub_v3_v3v3(effector_acceleration, pa->state.vel, pa->prev_state.vel);
- mul_v3_fl(effector_acceleration, 1.f/dtime);
-
- copy_particle_key(&pa->state, &pa->prev_state, 0);
-
- integrate_particle(part, pa, dtime, effector_acceleration, sphdata->force_cb, sphdata);
-}
-
-/************************************************/
-/* Basic physics */
-/************************************************/
-typedef struct EfData {
- ParticleTexture ptex;
- ParticleSimulationData *sim;
- ParticleData *pa;
-} EfData;
-static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, float *impulse)
-{
- EfData *efdata = (EfData *)efdata_v;
- ParticleSimulationData *sim = efdata->sim;
- ParticleSettings *part = sim->psys->part;
- ParticleData *pa = efdata->pa;
- EffectedPoint epoint;
-
- /* add effectors */
- pd_point_from_particle(efdata->sim, efdata->pa, state, &epoint);
- if (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)
- pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse);
-
- mul_v3_fl(force, efdata->ptex.field);
- mul_v3_fl(impulse, efdata->ptex.field);
-
- /* calculate air-particle interaction */
- if (part->dragfac != 0.0f)
- madd_v3_v3fl(force, state->vel, -part->dragfac * pa->size * pa->size * len_v3(state->vel));
-
- /* brownian force */
- if (part->brownfac != 0.0f) {
- force[0] += (BLI_frand()-0.5f) * part->brownfac;
- force[1] += (BLI_frand()-0.5f) * part->brownfac;
- force[2] += (BLI_frand()-0.5f) * part->brownfac;
- }
-
- if (part->flag & PART_ROT_DYN && epoint.ave)
- copy_v3_v3(pa->state.ave, epoint.ave);
-}
-/* gathers all forces that effect particles and calculates a new state for the particle */
-static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, float cfra)
-{
- ParticleSettings *part = sim->psys->part;
- ParticleData *pa = sim->psys->particles + p;
- ParticleKey tkey;
- float dtime=dfra*psys_get_timestep(sim), time;
- float *gravity = NULL, gr[3];
- EfData efdata;
-
- psys_get_texture(sim, pa, &efdata.ptex, PAMAP_PHYSICS, cfra);
-
- efdata.pa = pa;
- efdata.sim = sim;
-
- /* add global acceleration (gravitation) */
- if (psys_uses_gravity(sim) &&
- /* normal gravity is too strong for hair so it's disabled by default */
- (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR))
- {
- zero_v3(gr);
- madd_v3_v3fl(gr, sim->scene->physics_settings.gravity, part->effector_weights->global_gravity * efdata.ptex.gravity);
- gravity = gr;
- }
-
- /* maintain angular velocity */
- copy_v3_v3(pa->state.ave, pa->prev_state.ave);
-
- integrate_particle(part, pa, dtime, gravity, basic_force_cb, &efdata);
-
- /* damp affects final velocity */
- if (part->dampfac != 0.f)
- mul_v3_fl(pa->state.vel, 1.f - part->dampfac * efdata.ptex.damp * 25.f * dtime);
-
- //copy_v3_v3(pa->state.ave, states->ave);
-
- /* finally we do guides */
- time=(cfra-pa->time)/pa->lifetime;
- CLAMP(time, 0.0f, 1.0f);
-
- copy_v3_v3(tkey.co,pa->state.co);
- copy_v3_v3(tkey.vel,pa->state.vel);
- tkey.time=pa->state.time;
-
- if (part->type != PART_HAIR) {
- if (do_guides(sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
- copy_v3_v3(pa->state.co,tkey.co);
- /* guides don't produce valid velocity */
- sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co);
- mul_v3_fl(pa->state.vel,1.0f/dtime);
- pa->state.time=tkey.time;
- }
- }
-}
-static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, float timestep)
-{
- float rotfac, rot1[4], rot2[4] = {1.0,0.0,0.0,0.0}, dtime=dfra*timestep, extrotfac;
-
- if ((part->flag & PART_ROTATIONS) == 0) {
- unit_qt(pa->state.rot);
- return;
- }
-
- if (part->flag & PART_ROT_DYN) {
- extrotfac = len_v3(pa->state.ave);
- }
- else {
- extrotfac = 0.0f;
- }
-
- if ((part->flag & PART_ROT_DYN) && ELEM(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
- float angle;
- float len1 = len_v3(pa->prev_state.vel);
- float len2 = len_v3(pa->state.vel);
- float vec[3];
-
- if (len1 == 0.0f || len2 == 0.0f) {
- zero_v3(pa->state.ave);
- }
- else {
- cross_v3_v3v3(pa->state.ave, pa->prev_state.vel, pa->state.vel);
- normalize_v3(pa->state.ave);
- angle = dot_v3v3(pa->prev_state.vel, pa->state.vel) / (len1 * len2);
- mul_v3_fl(pa->state.ave, saacos(angle) / dtime);
- }
-
- get_angular_velocity_vector(part->avemode, &pa->state, vec);
- axis_angle_to_quat(rot2, vec, dtime*part->avefac);
- }
-
- rotfac = len_v3(pa->state.ave);
- if (rotfac == 0.0f || (part->flag & PART_ROT_DYN)==0 || extrotfac == 0.0f) {
- unit_qt(rot1);
- }
- else {
- axis_angle_to_quat(rot1,pa->state.ave,rotfac*dtime);
- }
- mul_qt_qtqt(pa->state.rot,rot1,pa->prev_state.rot);
- mul_qt_qtqt(pa->state.rot,rot2,pa->state.rot);
-
- /* keep rotation quat in good health */
- normalize_qt(pa->state.rot);
-}
-
-/************************************************
- * Collisions
- *
- * The algorithm is roughly:
- * 1. Use a BVH tree to search for faces that a particle may collide with.
- * 2. Use Newton's method to find the exact time at which the collision occurs.
- * http://en.wikipedia.org/wiki/Newton's_method
- *
- ************************************************/
-#define COLLISION_MAX_COLLISIONS 10
-#define COLLISION_MIN_RADIUS 0.001f
-#define COLLISION_MIN_DISTANCE 0.0001f
-#define COLLISION_ZERO 0.00001f
-#define COLLISION_INIT_STEP 0.00008f
-typedef float (*NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor);
-static float nr_signed_distance_to_plane(float *p, float radius, ParticleCollisionElement *pce, float *nor)
-{
- float p0[3], e1[3], e2[3], d;
-
- sub_v3_v3v3(e1, pce->x1, pce->x0);
- sub_v3_v3v3(e2, pce->x2, pce->x0);
- sub_v3_v3v3(p0, p, pce->x0);
-
- cross_v3_v3v3(nor, e1, e2);
- normalize_v3(nor);
-
- d = dot_v3v3(p0, nor);
-
- if (pce->inv_nor == -1) {
- if (d < 0.f)
- pce->inv_nor = 1;
- else
- pce->inv_nor = 0;
- }
-
- if (pce->inv_nor == 1) {
- negate_v3(nor);
- d = -d;
- }
-
- return d - radius;
-}
-static float nr_distance_to_edge(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor))
-{
- float v0[3], v1[3], v2[3], c[3];
-
- sub_v3_v3v3(v0, pce->x1, pce->x0);
- sub_v3_v3v3(v1, p, pce->x0);
- sub_v3_v3v3(v2, p, pce->x1);
-
- cross_v3_v3v3(c, v1, v2);
-
- return fabsf(len_v3(c)/len_v3(v0)) - radius;
-}
-static float nr_distance_to_vert(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor))
-{
- return len_v3v3(p, pce->x0) - radius;
-}
-static void collision_interpolate_element(ParticleCollisionElement *pce, float t, float fac, ParticleCollision *col)
-{
- /* t is the current time for newton rhapson */
- /* fac is the starting factor for current collision iteration */
- /* the col->fac's are factors for the particle subframe step start and end during collision modifier step */
- float f = fac + t*(1.f-fac);
- float mul = col->fac1 + f * (col->fac2-col->fac1);
- if (pce->tot > 0) {
- madd_v3_v3v3fl(pce->x0, pce->x[0], pce->v[0], mul);
-
- if (pce->tot > 1) {
- madd_v3_v3v3fl(pce->x1, pce->x[1], pce->v[1], mul);
-
- if (pce->tot > 2)
- madd_v3_v3v3fl(pce->x2, pce->x[2], pce->v[2], mul);
- }
- }
-}
-static void collision_point_velocity(ParticleCollisionElement *pce)
-{
- float v[3];
-
- copy_v3_v3(pce->vel, pce->v[0]);
-
- if (pce->tot > 1) {
- sub_v3_v3v3(v, pce->v[1], pce->v[0]);
- madd_v3_v3fl(pce->vel, v, pce->uv[0]);
-
- if (pce->tot > 2) {
- sub_v3_v3v3(v, pce->v[2], pce->v[0]);
- madd_v3_v3fl(pce->vel, v, pce->uv[1]);
- }
- }
-}
-static float collision_point_distance_with_normal(float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *nor)
-{
- if (fac >= 0.f)
- collision_interpolate_element(pce, 0.f, fac, col);
-
- switch (pce->tot) {
- case 1:
- {
- sub_v3_v3v3(nor, p, pce->x0);
- return normalize_v3(nor);
- }
- case 2:
- {
- float u, e[3], vec[3];
- sub_v3_v3v3(e, pce->x1, pce->x0);
- sub_v3_v3v3(vec, p, pce->x0);
- u = dot_v3v3(vec, e) / dot_v3v3(e, e);
-
- madd_v3_v3v3fl(nor, vec, e, -u);
- return normalize_v3(nor);
- }
- case 3:
- return nr_signed_distance_to_plane(p, 0.f, pce, nor);
- }
- return 0;
-}
-static void collision_point_on_surface(float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *co)
-{
- collision_interpolate_element(pce, 0.f, fac, col);
-
- switch (pce->tot) {
- case 1:
- {
- sub_v3_v3v3(co, p, pce->x0);
- normalize_v3(co);
- madd_v3_v3v3fl(co, pce->x0, co, col->radius);
- break;
- }
- case 2:
- {
- float u, e[3], vec[3], nor[3];
- sub_v3_v3v3(e, pce->x1, pce->x0);
- sub_v3_v3v3(vec, p, pce->x0);
- u = dot_v3v3(vec, e) / dot_v3v3(e, e);
-
- madd_v3_v3v3fl(nor, vec, e, -u);
- normalize_v3(nor);
-
- madd_v3_v3v3fl(co, pce->x0, e, pce->uv[0]);
- madd_v3_v3fl(co, nor, col->radius);
- break;
- }
- case 3:
- {
- float p0[3], e1[3], e2[3], nor[3];
-
- sub_v3_v3v3(e1, pce->x1, pce->x0);
- sub_v3_v3v3(e2, pce->x2, pce->x0);
- sub_v3_v3v3(p0, p, pce->x0);
-
- cross_v3_v3v3(nor, e1, e2);
- normalize_v3(nor);
-
- if (pce->inv_nor == 1)
- negate_v3(nor);
-
- madd_v3_v3v3fl(co, pce->x0, nor, col->radius);
- madd_v3_v3fl(co, e1, pce->uv[0]);
- madd_v3_v3fl(co, e2, pce->uv[1]);
- break;
- }
- }
-}
-/* find first root in range [0-1] starting from 0 */
-static float collision_newton_rhapson(ParticleCollision *col, float radius, ParticleCollisionElement *pce, NRDistanceFunc distance_func)
-{
- float t0, t1, dt_init, d0, d1, dd, n[3];
- int iter;
-
- pce->inv_nor = -1;
-
- if (col->inv_total_time > 0.0f) {
- /* Initial step size should be small, but not too small or floating point
- * precision errors will appear. - z0r */
- dt_init = COLLISION_INIT_STEP * col->inv_total_time;
- }
- else {
- dt_init = 0.001f;
- }
-
- /* start from the beginning */
- t0 = 0.f;
- collision_interpolate_element(pce, t0, col->f, col);
- d0 = distance_func(col->co1, radius, pce, n);
- t1 = dt_init;
- d1 = 0.f;
-
- for (iter=0; iter<10; iter++) {//, itersum++) {
- /* get current location */
- collision_interpolate_element(pce, t1, col->f, col);
- interp_v3_v3v3(pce->p, col->co1, col->co2, t1);
-
- d1 = distance_func(pce->p, radius, pce, n);
-
- /* particle already inside face, so report collision */
- if (iter == 0 && d0 < 0.f && d0 > -radius) {
- copy_v3_v3(pce->p, col->co1);
- copy_v3_v3(pce->nor, n);
- pce->inside = 1;
- return 0.f;
- }
-
- /* Zero gradient (no movement relative to element). Can't step from
- * here. */
- if (d1 == d0) {
- /* If first iteration, try from other end where the gradient may be
- * greater. Note: code duplicated below. */
- if (iter == 0) {
- t0 = 1.f;
- collision_interpolate_element(pce, t0, col->f, col);
- d0 = distance_func(col->co2, radius, pce, n);
- t1 = 1.0f - dt_init;
- d1 = 0.f;
- continue;
- }
- else
- return -1.f;
- }
-
- dd = (t1-t0)/(d1-d0);
-
- t0 = t1;
- d0 = d1;
-
- t1 -= d1*dd;
-
- /* Particle moving away from plane could also mean a strangely rotating
- * face, so check from end. Note: code duplicated above. */
- if (iter == 0 && t1 < 0.f) {
- t0 = 1.f;
- collision_interpolate_element(pce, t0, col->f, col);
- d0 = distance_func(col->co2, radius, pce, n);
- t1 = 1.0f - dt_init;
- d1 = 0.f;
- continue;
- }
- else if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f))
- return -1.f;
-
- if (d1 <= COLLISION_ZERO && d1 >= -COLLISION_ZERO) {
- if (t1 >= -COLLISION_ZERO && t1 <= 1.f) {
- if (distance_func == nr_signed_distance_to_plane)
- copy_v3_v3(pce->nor, n);
-
- CLAMP(t1, 0.f, 1.f);
-
- return t1;
- }
- else
- return -1.f;
- }
- }
- return -1.0;
-}
-static int collision_sphere_to_tri(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
-{
- ParticleCollisionElement *result = &col->pce;
- float ct, u, v;
-
- pce->inv_nor = -1;
- pce->inside = 0;
-
- ct = collision_newton_rhapson(col, radius, pce, nr_signed_distance_to_plane);
-
- if (ct >= 0.f && ct < *t && (result->inside==0 || pce->inside==1) ) {
- float e1[3], e2[3], p0[3];
- float e1e1, e1e2, e1p0, e2e2, e2p0, inv;
-
- sub_v3_v3v3(e1, pce->x1, pce->x0);
- sub_v3_v3v3(e2, pce->x2, pce->x0);
- /* XXX: add radius correction here? */
- sub_v3_v3v3(p0, pce->p, pce->x0);
-
- e1e1 = dot_v3v3(e1, e1);
- e1e2 = dot_v3v3(e1, e2);
- e1p0 = dot_v3v3(e1, p0);
- e2e2 = dot_v3v3(e2, e2);
- e2p0 = dot_v3v3(e2, p0);
-
- inv = 1.f/(e1e1 * e2e2 - e1e2 * e1e2);
- u = (e2e2 * e1p0 - e1e2 * e2p0) * inv;
- v = (e1e1 * e2p0 - e1e2 * e1p0) * inv;
-
- if (u>=0.f && u<=1.f && v>=0.f && u+v<=1.f) {
- *result = *pce;
-
- /* normal already calculated in pce */
-
- result->uv[0] = u;
- result->uv[1] = v;
-
- *t = ct;
- return 1;
- }
- }
- return 0;
-}
-static int collision_sphere_to_edges(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
-{
- ParticleCollisionElement edge[3], *cur = NULL, *hit = NULL;
- ParticleCollisionElement *result = &col->pce;
-
- float ct;
- int i;
-
- for (i=0; i<3; i++) {
- cur = edge+i;
- cur->x[0] = pce->x[i]; cur->x[1] = pce->x[(i+1)%3];
- cur->v[0] = pce->v[i]; cur->v[1] = pce->v[(i+1)%3];
- cur->tot = 2;
- cur->inside = 0;
-
- ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_edge);
-
- if (ct >= 0.f && ct < *t) {
- float u, e[3], vec[3];
-
- sub_v3_v3v3(e, cur->x1, cur->x0);
- sub_v3_v3v3(vec, cur->p, cur->x0);
- u = dot_v3v3(vec, e) / dot_v3v3(e, e);
-
- if (u < 0.f || u > 1.f)
- break;
-
- *result = *cur;
-
- madd_v3_v3v3fl(result->nor, vec, e, -u);
- normalize_v3(result->nor);
-
- result->uv[0] = u;
-
-
- hit = cur;
- *t = ct;
- }
-
- }
-
- return hit != NULL;
-}
-static int collision_sphere_to_verts(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
-{
- ParticleCollisionElement vert[3], *cur = NULL, *hit = NULL;
- ParticleCollisionElement *result = &col->pce;
-
- float ct;
- int i;
-
- for (i=0; i<3; i++) {
- cur = vert+i;
- cur->x[0] = pce->x[i];
- cur->v[0] = pce->v[i];
- cur->tot = 1;
- cur->inside = 0;
-
- ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_vert);
-
- if (ct >= 0.f && ct < *t) {
- *result = *cur;
-
- sub_v3_v3v3(result->nor, cur->p, cur->x0);
- normalize_v3(result->nor);
-
- hit = cur;
- *t = ct;
- }
-
- }
-
- return hit != NULL;
-}
-/* Callback for BVHTree near test */
-void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
-{
- ParticleCollision *col = (ParticleCollision *) userdata;
- ParticleCollisionElement pce;
- const MVertTri *vt = &col->md->tri[index];
- MVert *x = col->md->x;
- MVert *v = col->md->current_v;
- float t = hit->dist/col->original_ray_length;
- int collision = 0;
-
- pce.x[0] = x[vt->tri[0]].co;
- pce.x[1] = x[vt->tri[1]].co;
- pce.x[2] = x[vt->tri[2]].co;
-
- pce.v[0] = v[vt->tri[0]].co;
- pce.v[1] = v[vt->tri[1]].co;
- pce.v[2] = v[vt->tri[2]].co;
-
- pce.tot = 3;
- pce.inside = 0;
- pce.index = index;
-
- /* don't collide with same face again */
- if (col->hit == col->current && col->pce.index == index && col->pce.tot == 3)
- return;
-
- collision = collision_sphere_to_tri(col, ray->radius, &pce, &t);
- if (col->pce.inside == 0) {
- collision += collision_sphere_to_edges(col, ray->radius, &pce, &t);
- collision += collision_sphere_to_verts(col, ray->radius, &pce, &t);
- }
-
- if (collision) {
- hit->dist = col->original_ray_length * t;
- hit->index = index;
-
- collision_point_velocity(&col->pce);
-
- col->hit = col->current;
- }
-}
-static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, ListBase *colliders)
-{
- const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
- ColliderCache *coll;
- float ray_dir[3];
-
- if (BLI_listbase_is_empty(colliders))
- return 0;
-
- sub_v3_v3v3(ray_dir, col->co2, col->co1);
- hit->index = -1;
- hit->dist = col->original_ray_length = normalize_v3(ray_dir);
- col->pce.inside = 0;
-
- /* even if particle is stationary we want to check for moving colliders */
- /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */
- if (hit->dist == 0.0f)
- hit->dist = col->original_ray_length = 0.000001f;
-
- for (coll = colliders->first; coll; coll=coll->next) {
- /* for boids: don't check with current ground object */
- if (coll->ob == col->skip)
- continue;
-
- /* particles should not collide with emitter at birth */
- if (coll->ob == col->emitter && pa->time < col->cfra && pa->time >= col->old_cfra)
- continue;
-
- col->current = coll->ob;
- col->md = coll->collmd;
- col->fac1 = (col->old_cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x);
- col->fac2 = (col->cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x);
-
- if (col->md && col->md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col->md->bvhtree, col->co1, ray_dir, col->radius, hit,
- BKE_psys_collision_neartest_cb, col, raycast_flag);
- }
- }
-
- return hit->index >= 0;
-}
-static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation)
-{
- ParticleCollisionElement *pce = &col->pce;
- PartDeflect *pd = col->hit->pd;
- float co[3]; /* point of collision */
- float x = hit->dist/col->original_ray_length; /* location factor of collision between this iteration */
- float f = col->f + x * (1.0f - col->f); /* time factor of collision between timestep */
- float dt1 = (f - col->f) * col->total_time; /* time since previous collision (in seconds) */
- float dt2 = (1.0f - f) * col->total_time; /* time left after collision (in seconds) */
- int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */
-
- /* calculate exact collision location */
- interp_v3_v3v3(co, col->co1, col->co2, x);
-
- /* particle dies in collision */
- if (through == 0 && (kill || pd->flag & PDEFLE_KILL_PART)) {
- pa->alive = PARS_DYING;
- pa->dietime = col->old_cfra + (col->cfra - col->old_cfra) * f;
-
- copy_v3_v3(pa->state.co, co);
- interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f);
- interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f);
- interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f);
-
- /* particle is dead so we don't need to calculate further */
- return 0;
- }
- /* figure out velocity and other data after collision */
- else {
- float v0[3]; /* velocity directly before collision to be modified into velocity directly after collision */
- float v0_nor[3];/* normal component of v0 */
- float v0_tan[3];/* tangential component of v0 */
- float vc_tan[3];/* tangential component of collision surface velocity */
- float v0_dot, vc_dot;
- float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f);
- float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f);
- float distance, nor[3], dot;
-
- CLAMP(damp,0.0f, 1.0f);
- CLAMP(frict,0.0f, 1.0f);
-
- /* get exact velocity right before collision */
- madd_v3_v3v3fl(v0, col->ve1, col->acc, dt1);
-
- /* convert collider velocity from 1/framestep to 1/s TODO: here we assume 1 frame step for collision modifier */
- mul_v3_fl(pce->vel, col->inv_timestep);
-
- /* calculate tangential particle velocity */
- v0_dot = dot_v3v3(pce->nor, v0);
- madd_v3_v3v3fl(v0_tan, v0, pce->nor, -v0_dot);
-
- /* calculate tangential collider velocity */
- vc_dot = dot_v3v3(pce->nor, pce->vel);
- madd_v3_v3v3fl(vc_tan, pce->vel, pce->nor, -vc_dot);
-
- /* handle friction effects (tangential and angular velocity) */
- if (frict > 0.0f) {
- /* angular <-> linear velocity */
- if (dynamic_rotation) {
- float vr_tan[3], v1_tan[3], ave[3];
-
- /* linear velocity of particle surface */
- cross_v3_v3v3(vr_tan, pce->nor, pa->state.ave);
- mul_v3_fl(vr_tan, pa->size);
-
- /* change to coordinates that move with the collision plane */
- sub_v3_v3v3(v1_tan, v0_tan, vc_tan);
-
- /* The resulting velocity is a weighted average of particle cm & surface
- * velocity. This weight (related to particle's moment of inertia) could
- * be made a parameter for angular <-> linear conversion.
- */
- madd_v3_v3fl(v1_tan, vr_tan, -0.4);
- mul_v3_fl(v1_tan, 1.0f/1.4f); /* 1/(1+0.4) */
-
- /* rolling friction is around 0.01 of sliding friction (could be made a parameter) */
- mul_v3_fl(v1_tan, 1.0f - 0.01f * frict);
-
- /* surface_velocity is opposite to cm velocity */
- negate_v3_v3(vr_tan, v1_tan);
-
- /* get back to global coordinates */
- add_v3_v3(v1_tan, vc_tan);
-
- /* convert to angular velocity*/
- cross_v3_v3v3(ave, vr_tan, pce->nor);
- mul_v3_fl(ave, 1.0f/MAX2(pa->size, 0.001f));
-
- /* only friction will cause change in linear & angular velocity */
- interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict);
- interp_v3_v3v3(v0_tan, v0_tan, v1_tan, frict);
- }
- else {
- /* just basic friction (unphysical due to the friction model used in Blender) */
- interp_v3_v3v3(v0_tan, v0_tan, vc_tan, frict);
- }
- }
-
- /* stickiness was possibly added before, so cancel that before calculating new normal velocity */
- /* otherwise particles go flying out of the surface because of high reversed sticky velocity */
- if (v0_dot < 0.0f) {
- v0_dot += pd->pdef_stickness;
- if (v0_dot > 0.0f)
- v0_dot = 0.0f;
- }
-
- /* damping and flipping of velocity around normal */
- v0_dot *= 1.0f - damp;
- vc_dot *= through ? damp : 1.0f;
-
- /* calculate normal particle velocity */
- /* special case for object hitting the particle from behind */
- if (through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot)))
- mul_v3_v3fl(v0_nor, pce->nor, vc_dot);
- else if (v0_dot > 0.f)
- mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? -1.0f : 1.0f) * v0_dot);
- else
- mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot);
-
- /* combine components together again */
- add_v3_v3v3(v0, v0_nor, v0_tan);
-
- if (col->boid) {
- /* keep boids above ground */
- BoidParticle *bpa = pa->boid;
- if (bpa->data.mode == eBoidMode_OnLand || co[2] <= col->boid_z) {
- co[2] = col->boid_z;
- v0[2] = 0.0f;
- }
- }
-
- /* re-apply acceleration to final location and velocity */
- madd_v3_v3v3fl(pa->state.co, co, v0, dt2);
- madd_v3_v3fl(pa->state.co, col->acc, 0.5f*dt2*dt2);
- madd_v3_v3v3fl(pa->state.vel, v0, col->acc, dt2);
-
- /* make sure particle stays on the right side of the surface */
- if (!through) {
- distance = collision_point_distance_with_normal(co, pce, -1.f, col, nor);
-
- if (distance < col->radius + COLLISION_MIN_DISTANCE)
- madd_v3_v3fl(co, nor, col->radius + COLLISION_MIN_DISTANCE - distance);
-
- dot = dot_v3v3(nor, v0);
- if (dot < 0.f)
- madd_v3_v3fl(v0, nor, -dot);
-
- distance = collision_point_distance_with_normal(pa->state.co, pce, 1.f, col, nor);
-
- if (distance < col->radius + COLLISION_MIN_DISTANCE)
- madd_v3_v3fl(pa->state.co, nor, col->radius + COLLISION_MIN_DISTANCE - distance);
-
- dot = dot_v3v3(nor, pa->state.vel);
- if (dot < 0.f)
- madd_v3_v3fl(pa->state.vel, nor, -dot);
- }
-
- /* add stickiness to surface */
- madd_v3_v3fl(pa->state.vel, pce->nor, -pd->pdef_stickness);
-
- /* set coordinates for next iteration */
- copy_v3_v3(col->co1, co);
- copy_v3_v3(col->co2, pa->state.co);
-
- copy_v3_v3(col->ve1, v0);
- copy_v3_v3(col->ve2, pa->state.vel);
-
- col->f = f;
- }
-
- col->prev = col->hit;
- col->prev_index = hit->index;
-
- return 1;
-}
-static void collision_fail(ParticleData *pa, ParticleCollision *col)
-{
- /* final chance to prevent total failure, so stick to the surface and hope for the best */
- collision_point_on_surface(col->co1, &col->pce, 1.f, col, pa->state.co);
-
- copy_v3_v3(pa->state.vel, col->pce.vel);
- mul_v3_fl(pa->state.vel, col->inv_timestep);
-
-
- /* printf("max iterations\n"); */
-}
-
-/* Particle - Mesh collision detection and response
- * Features:
- * -friction and damping
- * -angular momentum <-> linear momentum
- * -high accuracy by re-applying particle acceleration after collision
- * -handles moving, rotating and deforming meshes
- * -uses Newton-Rhapson iteration to find the collisions
- * -handles spherical particles and (nearly) point like particles
- */
-static void collision_check(ParticleSimulationData *sim, int p, float dfra, float cfra)
-{
- ParticleSettings *part = sim->psys->part;
- ParticleData *pa = sim->psys->particles + p;
- ParticleCollision col;
- BVHTreeRayHit hit;
- int collision_count=0;
-
- float timestep = psys_get_timestep(sim);
-
- memset(&col, 0, sizeof(ParticleCollision));
-
- col.total_time = timestep * dfra;
- col.inv_total_time = 1.0f/col.total_time;
- col.inv_timestep = 1.0f/timestep;
-
- col.cfra = cfra;
- col.old_cfra = sim->psys->cfra;
-
- /* get acceleration (from gravity, forcefields etc. to be re-applied in collision response) */
- sub_v3_v3v3(col.acc, pa->state.vel, pa->prev_state.vel);
- mul_v3_fl(col.acc, 1.f/col.total_time);
-
- /* set values for first iteration */
- copy_v3_v3(col.co1, pa->prev_state.co);
- copy_v3_v3(col.co2, pa->state.co);
- copy_v3_v3(col.ve1, pa->prev_state.vel);
- copy_v3_v3(col.ve2, pa->state.vel);
- col.f = 0.0f;
-
- col.radius = ((part->flag & PART_SIZE_DEFL) || (part->phystype == PART_PHYS_BOIDS)) ? pa->size : COLLISION_MIN_RADIUS;
-
- /* override for boids */
- if (part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) {
- col.boid = 1;
- col.boid_z = pa->state.co[2];
- col.skip = pa->boid->ground;
- }
-
- /* 10 iterations to catch multiple collisions */
- while (collision_count < COLLISION_MAX_COLLISIONS) {
- if (collision_detect(pa, &col, &hit, sim->colliders)) {
-
- collision_count++;
-
- if (collision_count == COLLISION_MAX_COLLISIONS)
- collision_fail(pa, &col);
- else if (collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0)
- return;
- }
- else
- return;
- }
-}
-/************************************************/
-/* Hair */
-/************************************************/
-/* check if path cache or children need updating and do it if needed */
-static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
- Base *base;
- int distr=0, alloc=0, skip=0;
-
- if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
- alloc=1;
-
- if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT)))
- distr=1;
-
- if (distr) {
- if (alloc)
- realloc_particles(sim, sim->psys->totpart);
-
- if (psys_get_tot_child(sim->scene, psys)) {
- /* don't generate children while computing the hair keys */
- if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
- distribute_particles(sim, PART_FROM_CHILD);
-
- if (part->childtype==PART_CHILD_FACES && part->parents != 0.0f)
- psys_find_parents(sim);
- }
- }
- else
- psys_free_children(psys);
- }
-
- if ((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0)
- skip = 1; /* only hair, keyed and baked stuff can have paths */
- else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
- skip = 1; /* particle visualization must be set as path */
- else if (!psys->renderdata) {
- if (part->draw_as != PART_DRAW_REND)
- skip = 1; /* draw visualization */
- else if (psys->pointcache->flag & PTCACHE_BAKING)
- skip = 1; /* no need to cache paths while baking dynamics */
- else if (psys_in_edit_mode(sim->scene, psys)) {
- if ((pset->flag & PE_DRAW_PART)==0)
- skip = 1;
- else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
- skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */
- }
- }
-
-
- /* particle instance modifier with "path" option need cached paths even if particle system doesn't */
- for (base = sim->scene->base.first; base; base= base->next) {
- ModifierData *md = modifiers_findByType(base->object, eModifierType_ParticleInstance);
- if (md) {
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
- if (pimd->flag & eParticleInstanceFlag_Path && pimd->ob == sim->ob && pimd->psys == (psys - (ParticleSystem*)sim->ob->particlesystem.first)) {
- skip = 0;
- break;
- }
- }
- }
-
- if (!skip) {
- psys_cache_paths(sim, cfra);
-
- /* for render, child particle paths are computed on the fly */
- if (part->childtype) {
- if (!psys->totchild)
- skip = 1;
- else if (psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)==0)
- skip = 1;
-
- if (!skip)
- psys_cache_child_paths(sim, cfra, 0);
- }
- }
- else if (psys->pathcache)
- psys_free_path_cache(psys, NULL);
-}
-
-static bool psys_hair_use_simulation(ParticleData *pa, float max_length)
-{
- /* Minimum segment length relative to average length.
- * Hairs with segments below this length will be excluded from the simulation,
- * because otherwise the solver will become unstable.
- * The hair system should always make sure the hair segments have reasonable length ratios,
- * but this can happen in old files when e.g. cutting hair.
- */
- const float min_length = 0.1f * max_length;
-
- HairKey *key;
- int k;
-
- if (pa->totkey < 2)
- return false;
-
- for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
- float length = len_v3v3(key->co, (key-1)->co);
- if (length < min_length)
- return false;
- }
-
- return true;
-}
-
-static MDeformVert *hair_set_pinning(MDeformVert *dvert, float weight)
-{
- if (dvert) {
- if (!dvert->totweight) {
- dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight");
- dvert->totweight = 1;
- }
-
- dvert->dw->weight = weight;
- dvert++;
- }
- return dvert;
-}
-
-static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int totedge, DerivedMesh **r_dm, ClothHairData **r_hairdata)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- DerivedMesh *dm;
- ClothHairData *hairdata;
- MVert *mvert;
- MEdge *medge;
- MDeformVert *dvert;
- HairKey *key;
- PARTICLE_P;
- int k, hair_index;
- float hairmat[4][4];
- float max_length;
- float hair_radius;
-
- dm = *r_dm;
- if (!dm) {
- *r_dm = dm = CDDM_new(totpoint, totedge, 0, 0, 0);
- DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
- }
- mvert = CDDM_get_verts(dm);
- medge = CDDM_get_edges(dm);
- dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
-
- hairdata = *r_hairdata;
- if (!hairdata) {
- *r_hairdata = hairdata = MEM_mallocN(sizeof(ClothHairData) * totpoint, "hair data");
- }
-
- /* calculate maximum segment length */
- max_length = 0.0f;
- LOOP_PARTICLES {
- for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
- float length = len_v3v3(key->co, (key-1)->co);
- if (max_length < length)
- max_length = length;
- }
- }
-
- psys->clmd->sim_parms->vgroup_mass = 1;
-
- /* XXX placeholder for more flexible future hair settings */
- hair_radius = part->size;
-
- /* make vgroup for pin roots etc.. */
- hair_index = 1;
- LOOP_PARTICLES {
- float root_mat[4][4];
- float bending_stiffness;
- bool use_hair;
-
- pa->hair_index = hair_index;
- use_hair = psys_hair_use_simulation(pa, max_length);
-
- psys_mat_hair_to_object(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
- mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
- normalize_m4(root_mat);
-
- bending_stiffness = CLAMPIS(1.0f - part->bending_random * psys_frand(psys, p + 666), 0.0f, 1.0f);
-
- for (k=0, key=pa->hair; k<pa->totkey; k++,key++) {
- ClothHairData *hair;
- float *co, *co_next;
-
- co = key->co;
- co_next = (key+1)->co;
-
- /* create fake root before actual root to resist bending */
- if (k==0) {
- hair = &psys->clmd->hairdata[pa->hair_index - 1];
- copy_v3_v3(hair->loc, root_mat[3]);
- copy_m3_m4(hair->rot, root_mat);
-
- hair->radius = hair_radius;
- hair->bending_stiffness = bending_stiffness;
-
- add_v3_v3v3(mvert->co, co, co);
- sub_v3_v3(mvert->co, co_next);
- mul_m4_v3(hairmat, mvert->co);
-
- medge->v1 = pa->hair_index - 1;
- medge->v2 = pa->hair_index;
-
- dvert = hair_set_pinning(dvert, 1.0f);
-
- mvert++;
- medge++;
- }
-
- /* store root transform in cloth data */
- hair = &psys->clmd->hairdata[pa->hair_index + k];
- copy_v3_v3(hair->loc, root_mat[3]);
- copy_m3_m4(hair->rot, root_mat);
-
- hair->radius = hair_radius;
- hair->bending_stiffness = bending_stiffness;
-
- copy_v3_v3(mvert->co, co);
- mul_m4_v3(hairmat, mvert->co);
-
- if (k) {
- medge->v1 = pa->hair_index + k - 1;
- medge->v2 = pa->hair_index + k;
- }
-
- /* roots and disabled hairs should be 1.0, the rest can be anything from 0.0 to 1.0 */
- if (use_hair)
- dvert = hair_set_pinning(dvert, key->weight);
- else
- dvert = hair_set_pinning(dvert, 1.0f);
-
- mvert++;
- if (k)
- medge++;
- }
-
- hair_index += pa->totkey + 1;
- }
-}
-
-static void do_hair_dynamics(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- PARTICLE_P;
- EffectorWeights *clmd_effweights;
- int totpoint;
- int totedge;
- float (*deformedVerts)[3];
- bool realloc_roots;
-
- if (!psys->clmd) {
- psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
- psys->clmd->sim_parms->goalspring = 0.0f;
- psys->clmd->sim_parms->vel_damping = 1.0f;
- psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
- psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
- }
-
- /* count simulated points */
- totpoint = 0;
- totedge = 0;
- LOOP_PARTICLES {
- /* "out" dm contains all hairs */
- totedge += pa->totkey;
- totpoint += pa->totkey + 1; /* +1 for virtual root point */
- }
-
- realloc_roots = false; /* whether hair root info array has to be reallocated */
- if (psys->hair_in_dm) {
- DerivedMesh *dm = psys->hair_in_dm;
- if (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm)) {
- dm->release(dm);
- psys->hair_in_dm = NULL;
- realloc_roots = true;
- }
- }
-
- if (!psys->hair_in_dm || !psys->clmd->hairdata || realloc_roots) {
- if (psys->clmd->hairdata) {
- MEM_freeN(psys->clmd->hairdata);
- psys->clmd->hairdata = NULL;
- }
- }
-
- hair_create_input_dm(sim, totpoint, totedge, &psys->hair_in_dm, &psys->clmd->hairdata);
-
- if (psys->hair_out_dm)
- psys->hair_out_dm->release(psys->hair_out_dm);
-
- psys->clmd->point_cache = psys->pointcache;
- /* for hair sim we replace the internal cloth effector weights temporarily
- * to use the particle settings
- */
- clmd_effweights = psys->clmd->sim_parms->effector_weights;
- psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
-
- deformedVerts = MEM_mallocN(sizeof(*deformedVerts) * psys->hair_in_dm->getNumVerts(psys->hair_in_dm), "do_hair_dynamics vertexCos");
- psys->hair_out_dm = CDDM_copy(psys->hair_in_dm);
- psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts);
-
- clothModifier_do(psys->clmd, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
-
- CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts);
-
- MEM_freeN(deformedVerts);
-
- /* restore cloth effector weights */
- psys->clmd->sim_parms->effector_weights = clmd_effweights;
-}
-static void hair_step(ParticleSimulationData *sim, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
-
- LOOP_PARTICLES {
- pa->size = part->size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-
- if (psys->recalc & PSYS_RECALC_RESET) {
- /* need this for changing subsurf levels */
- psys_calc_dmcache(sim->ob, sim->psmd->dm_final, sim->psmd->dm_deformed, psys);
-
- if (psys->clmd)
- cloth_free_modifier(psys->clmd);
- }
-
- /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles [#25519] */
- if (psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS && psys->particles)
- do_hair_dynamics(sim);
-
- /* following lines were removed r29079 but cause bug [#22811], see report for details */
- psys_update_effectors(sim);
- psys_update_path_cache(sim, cfra);
-
- psys->flag |= PSYS_HAIR_UPDATED;
-}
-
-static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
-{
- Object *ob = sim->ob;
- ParticleSystem *psys = sim->psys;
- HairKey *key, *root;
- PARTICLE_P;
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- psys->lattice_deform_data= psys_create_lattice_deform_data(sim);
-
- if (psys->totpart==0) return;
-
- /* save new keys for elements if needed */
- LOOP_PARTICLES {
- /* first time alloc */
- if (pa->totkey==0 || pa->hair==NULL) {
- pa->hair = MEM_callocN((psys->part->hair_step + 1) * sizeof(HairKey), "HairKeys");
- pa->totkey = 0;
- }
-
- key = root = pa->hair;
- key += pa->totkey;
-
- /* convert from global to geometry space */
- copy_v3_v3(key->co, pa->state.co);
- mul_m4_v3(ob->imat, key->co);
-
- if (pa->totkey) {
- sub_v3_v3(key->co, root->co);
- psys_vec_rot_to_face(sim->psmd->dm_final, pa, key->co);
- }
-
- key->time = pa->state.time;
-
- key->weight = 1.0f - key->time / 100.0f;
-
- pa->totkey++;
-
- /* root is always in the origin of hair space so we set it to be so after the last key is saved*/
- if (pa->totkey == psys->part->hair_step + 1) {
- zero_v3(root->co);
- }
-
- }
-}
-
-/* Code for an adaptive time step based on the Courant-Friedrichs-Lewy
- * condition. */
-static const float MIN_TIMESTEP = 1.0f / 101.0f;
-/* Tolerance of 1.5 means the last subframe neither favors growing nor
- * shrinking (e.g if it were 1.3, the last subframe would tend to be too
- * small). */
-static const float TIMESTEP_EXPANSION_FACTOR = 0.1f;
-static const float TIMESTEP_EXPANSION_TOLERANCE = 1.5f;
-
-/* Calculate the speed of the particle relative to the local scale of the
- * simulation. This should be called once per particle during a simulation
- * step, after the velocity has been updated. element_size defines the scale of
- * the simulation, and is typically the distance to neighboring particles. */
-static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa,
- float dtime, SPHData *sphdata, SpinLock *spin)
-{
- float relative_vel[3];
-
- sub_v3_v3v3(relative_vel, pa->prev_state.vel, sphdata->flow);
-
- const float courant_num = len_v3(relative_vel) * dtime / sphdata->element_size;
- if (sim->courant_num < courant_num) {
- BLI_spin_lock(spin);
- if (sim->courant_num < courant_num) {
- sim->courant_num = courant_num;
- }
- BLI_spin_unlock(spin);
- }
-}
-static float get_base_time_step(ParticleSettings *part)
-{
- return 1.0f / (float) (part->subframes + 1);
-}
-/* Update time step size to suit current conditions. */
-static float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, float t_frac)
-{
- float dt_target;
- if (sim->courant_num == 0.0f)
- dt_target = 1.0f;
- else
- dt_target = psys->dt_frac * (psys->part->courant_target / sim->courant_num);
-
- /* Make sure the time step is reasonable. For some reason, the CLAMP macro
- * doesn't work here. The time step becomes too large. - z0r */
- if (dt_target < MIN_TIMESTEP)
- dt_target = MIN_TIMESTEP;
- else if (dt_target > get_base_time_step(psys->part))
- dt_target = get_base_time_step(psys->part);
-
- /* Decrease time step instantly, but increase slowly. */
- if (dt_target > psys->dt_frac)
- psys->dt_frac = interpf(dt_target, psys->dt_frac, TIMESTEP_EXPANSION_FACTOR);
- else
- psys->dt_frac = dt_target;
-
- /* Sync with frame end if it's close. */
- if (t_frac == 1.0f)
- return psys->dt_frac;
- else if (t_frac + (psys->dt_frac * TIMESTEP_EXPANSION_TOLERANCE) >= 1.0f)
- return 1.0f - t_frac;
- else
- return psys->dt_frac;
-}
-
-/************************************************/
-/* System Core */
-/************************************************/
-
-typedef struct DynamicStepSolverTaskData {
- ParticleSimulationData *sim;
-
- float cfra;
- float timestep;
- float dtime;
-
- SpinLock spin;
-} DynamicStepSolverTaskData;
-
-static void dynamics_step_sph_ddr_task_cb_ex(
- void *userdata, void *userdata_chunk, const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
-
- SPHData *sphdata = userdata_chunk;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- /* do global forces & effectors */
- basic_integrate(sim, p, pa->state.time, data->cfra);
-
- /* actual fluids calculations */
- sph_integrate(sim, pa, pa->state.time, sphdata);
-
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, data->cfra);
-
- /* SPH particles are not physical particles, just interpolation
- * particles, thus rotation has not a direct sense for them */
- basic_rotate(part, pa, pa->state.time, data->timestep);
-
- if (part->time_flag & PART_TIME_AUTOSF) {
- update_courant_num(sim, pa, data->dtime, sphdata, &data->spin);
- }
-}
-
-static void dynamics_step_sph_classical_basic_integrate_task_cb_ex(
- void *userdata, void *UNUSED(userdata_chunk), const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- basic_integrate(sim, p, pa->state.time, data->cfra);
-}
-
-static void dynamics_step_sph_classical_calc_density_task_cb_ex(
- void *userdata, void *userdata_chunk, const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
-
- SPHData *sphdata = userdata_chunk;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- sphclassical_calc_dens(pa, pa->state.time, sphdata);
-}
-
-static void dynamics_step_sph_classical_integrate_task_cb_ex(
- void *userdata, void *userdata_chunk, const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
-
- SPHData *sphdata = userdata_chunk;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- /* actual fluids calculations */
- sph_integrate(sim, pa, pa->state.time, sphdata);
-
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, data->cfra);
-
- /* SPH particles are not physical particles, just interpolation
- * particles, thus rotation has not a direct sense for them */
- basic_rotate(part, pa, pa->state.time, data->timestep);
-
- if (part->time_flag & PART_TIME_AUTOSF) {
- update_courant_num(sim, pa, data->dtime, sphdata, &data->spin);
- }
-}
-
-/* unbaked particles are calculated dynamically */
-static void dynamics_step(ParticleSimulationData *sim, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part=psys->part;
- RNG *rng;
- BoidBrainData bbd;
- ParticleTexture ptex;
- PARTICLE_P;
- float timestep;
- /* frame & time changes */
- float dfra, dtime;
- float birthtime, dietime;
-
- /* where have we gone in time since last time */
- dfra= cfra - psys->cfra;
-
- timestep = psys_get_timestep(sim);
- dtime= dfra*timestep;
-
- if (dfra < 0.0f) {
- LOOP_EXISTING_PARTICLES {
- psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
- pa->size = part->size*ptex.size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- reset_particle(sim, pa, dtime, cfra);
- }
- return;
- }
-
- BLI_srandom(31415926 + (int)cfra + psys->seed);
- /* for now do both, boids us 'rng' */
- rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed);
-
- psys_update_effectors(sim);
-
- if (part->type != PART_HAIR)
- sim->colliders = get_collider_cache(sim->scene, sim->ob, NULL);
-
- /* initialize physics type specific stuff */
- switch (part->phystype) {
- case PART_PHYS_BOIDS:
- {
- ParticleTarget *pt = psys->targets.first;
- bbd.sim = sim;
- bbd.part = part;
- bbd.cfra = cfra;
- bbd.dfra = dfra;
- bbd.timestep = timestep;
- bbd.rng = rng;
-
- psys_update_particle_tree(psys, cfra);
-
- boids_precalc_rules(part, cfra);
-
- for (; pt; pt=pt->next) {
- ParticleSystem *psys_target = psys_get_target_system(sim->ob, pt);
- if (psys_target && psys_target != psys) {
- psys_update_particle_tree(psys_target, cfra);
- }
- }
- break;
- }
- case PART_PHYS_FLUID:
- {
- ParticleTarget *pt = psys->targets.first;
- psys_update_particle_bvhtree(psys, cfra);
-
- for (; pt; pt=pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */
- if (pt->ob)
- psys_update_particle_bvhtree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra);
- }
- break;
- }
- }
- /* initialize all particles for dynamics */
- LOOP_SHOWN_PARTICLES {
- copy_particle_key(&pa->prev_state,&pa->state,1);
-
- psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
-
- pa->size = part->size*ptex.size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- birthtime = pa->time;
- dietime = pa->dietime;
-
- /* store this, so we can do multiple loops over particles */
- pa->state.time = dfra;
-
- if (dietime <= cfra && psys->cfra < dietime) {
- /* particle dies some time between this and last step */
- pa->state.time = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra);
- pa->alive = PARS_DYING;
- }
- else if (birthtime <= cfra && birthtime >= psys->cfra) {
- /* particle is born some time between this and last step*/
- reset_particle(sim, pa, dfra*timestep, cfra);
- pa->alive = PARS_ALIVE;
- pa->state.time = cfra - birthtime;
- }
- else if (dietime < cfra) {
- /* nothing to be done when particle is dead */
- }
-
- /* only reset unborn particles if they're shown or if the particle is born soon*/
- if (pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN || (cfra + psys->pointcache->step > pa->time))) {
- reset_particle(sim, pa, dtime, cfra);
- }
- else if (part->phystype == PART_PHYS_NO) {
- reset_particle(sim, pa, dtime, cfra);
- }
-
- if (ELEM(pa->alive, PARS_ALIVE, PARS_DYING)==0 || (pa->flag & (PARS_UNEXIST|PARS_NO_DISP)))
- pa->state.time = -1.f;
- }
-
- switch (part->phystype) {
- case PART_PHYS_NEWTON:
- {
- LOOP_DYNAMIC_PARTICLES {
- /* do global forces & effectors */
- basic_integrate(sim, p, pa->state.time, cfra);
-
- /* deflection */
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, cfra);
-
- /* rotations */
- basic_rotate(part, pa, pa->state.time, timestep);
- }
- break;
- }
- case PART_PHYS_BOIDS:
- {
- LOOP_DYNAMIC_PARTICLES {
- bbd.goal_ob = NULL;
-
- boid_brain(&bbd, p, pa);
-
- if (pa->alive != PARS_DYING) {
- boid_body(&bbd, pa);
-
- /* deflection */
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, cfra);
- }
- }
- break;
- }
- case PART_PHYS_FLUID:
- {
- SPHData sphdata;
- psys_sph_init(sim, &sphdata);
-
- DynamicStepSolverTaskData task_data = {
- .sim = sim, .cfra = cfra, .timestep = timestep, .dtime = dtime,
- };
-
- BLI_spin_init(&task_data.spin);
-
- if (part->fluid->solver == SPH_SOLVER_DDR) {
- /* Apply SPH forces using double-density relaxation algorithm
- * (Clavat et. al.) */
-
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, &sphdata, sizeof(sphdata),
- dynamics_step_sph_ddr_task_cb_ex, psys->totpart > 100, true);
-
- sph_springs_modify(psys, timestep);
- }
- else {
- /* SPH_SOLVER_CLASSICAL */
- /* Apply SPH forces using classical algorithm (due to Gingold
- * and Monaghan). Note that, unlike double-density relaxation,
- * this algorithm is separated into distinct loops. */
-
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, NULL, 0,
- dynamics_step_sph_classical_basic_integrate_task_cb_ex, psys->totpart > 100, true);
-
- /* calculate summation density */
- /* Note that we could avoid copying sphdata for each thread here (it's only read here),
- * but doubt this would gain us anything except confusion... */
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, &sphdata, sizeof(sphdata),
- dynamics_step_sph_classical_calc_density_task_cb_ex, psys->totpart > 100, true);
-
- /* do global forces & effectors */
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, &sphdata, sizeof(sphdata),
- dynamics_step_sph_classical_integrate_task_cb_ex, psys->totpart > 100, true);
- }
-
- BLI_spin_end(&task_data.spin);
-
- psys_sph_finalise(&sphdata);
- break;
- }
- }
-
- /* finalize particle state and time after dynamics */
- LOOP_DYNAMIC_PARTICLES {
- if (pa->alive == PARS_DYING) {
- pa->alive=PARS_DEAD;
- pa->state.time=pa->dietime;
- }
- else
- pa->state.time=cfra;
- }
-
- free_collider_cache(&sim->colliders);
- BLI_rng_free(rng);
-}
-static void update_children(ParticleSimulationData *sim)
-{
- if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0)
- /* don't generate children while growing hair - waste of time */
- psys_free_children(sim->psys);
- else if (sim->psys->part->childtype) {
- if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys))
- distribute_particles(sim, PART_FROM_CHILD);
- else {
- /* Children are up to date, nothing to do. */
- }
- }
- else
- psys_free_children(sim->psys);
-}
-/* updates cached particles' alive & other flags etc..*/
-static void cached_step(ParticleSimulationData *sim, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleTexture ptex;
- PARTICLE_P;
- float disp, dietime;
-
- psys_update_effectors(sim);
-
- disp= psys_get_current_display_percentage(psys);
-
- LOOP_PARTICLES {
- psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
- pa->size = part->size*ptex.size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
-
- dietime = pa->dietime;
-
- /* update alive status and push events */
- if (pa->time > cfra) {
- pa->alive = PARS_UNBORN;
- if (part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0)
- reset_particle(sim, pa, 0.0f, cfra);
- }
- else if (dietime <= cfra)
- pa->alive = PARS_DEAD;
- else
- pa->alive = PARS_ALIVE;
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-}
-
-static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra))
-{
- ParticleSystem *psys = sim->psys;
- if (psys->particles) {
- MEM_freeN(psys->particles);
- psys->particles = 0;
- psys->totpart = 0;
- }
-
- /* fluid sim particle import handling, actual loading of particles from file */
-#ifdef WITH_MOD_FLUID
- {
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim);
-
- if ( fluidmd && fluidmd->fss) {
- FluidsimSettings *fss= fluidmd->fss;
- ParticleSettings *part = psys->part;
- ParticleData *pa=NULL;
- char filename[256];
- char debugStrBuffer[256];
- int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
- int p, j, totpart;
- int readMask, activeParts = 0, fileParts = 0;
- gzFile gzf;
-
-// XXX if (ob==G.obedit) // off...
-// return;
-
- // ok, start loading
- BLI_join_dirfile(filename, sizeof(filename), fss->surfdataPath, OB_FLUIDSIM_SURF_PARTICLES_FNAME);
-
- BLI_path_abs(filename, modifier_path_relbase(sim->ob));
-
- BLI_path_frame(filename, curFrame, 0); // fixed #frame-no
-
- gzf = BLI_gzopen(filename, "rb");
- if (!gzf) {
- BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer),"readFsPartData::error - Unable to open file for reading '%s'\n", filename);
- // XXX bad level call elbeemDebugOut(debugStrBuffer);
- return;
- }
-
- gzread(gzf, &totpart, sizeof(totpart));
- totpart = (G.is_rendering)?totpart:(part->disp*totpart) / 100;
-
- part->totpart= totpart;
- part->sta=part->end = 1.0f;
- part->lifetime = sim->scene->r.efra + 1;
-
- /* allocate particles */
- realloc_particles(sim, part->totpart);
-
- // set up reading mask
- readMask = fss->typeFlags;
-
- for (p=0, pa=psys->particles; p<totpart; p++, pa++) {
- int ptype=0;
-
- gzread(gzf, &ptype, sizeof( ptype ));
- if (ptype & readMask) {
- activeParts++;
-
- gzread(gzf, &(pa->size), sizeof(float));
-
- pa->size /= 10.0f;
-
- for (j=0; j<3; j++) {
- float wrf;
- gzread(gzf, &wrf, sizeof( wrf ));
- pa->state.co[j] = wrf;
- //fprintf(stderr,"Rj%d ",j);
- }
- for (j=0; j<3; j++) {
- float wrf;
- gzread(gzf, &wrf, sizeof( wrf ));
- pa->state.vel[j] = wrf;
- }
-
- zero_v3(pa->state.ave);
- unit_qt(pa->state.rot);
-
- pa->time = 1.f;
- pa->dietime = sim->scene->r.efra + 1;
- pa->lifetime = sim->scene->r.efra;
- pa->alive = PARS_ALIVE;
- //if (a < 25) fprintf(stderr,"FSPARTICLE debug set %s, a%d = %f,%f,%f, life=%f\n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime );
- }
- else {
- // skip...
- for (j=0; j<2*3+1; j++) {
- float wrf; gzread(gzf, &wrf, sizeof( wrf ));
- }
- }
- fileParts++;
- }
- gzclose(gzf);
-
- totpart = psys->totpart = activeParts;
- BLI_snprintf(debugStrBuffer,sizeof(debugStrBuffer),"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d\n", psys->totpart,activeParts,fileParts,readMask);
- // bad level call
- // XXX elbeemDebugOut(debugStrBuffer);
-
- } // fluid sim particles done
- }
-#endif // WITH_MOD_FLUID
-}
-
-static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra))
-{
- ParticleSystem *psys = sim->psys;
- int oldtotpart = psys->totpart;
- int totpart = tot_particles(psys, pid);
-
- if (totpart != oldtotpart)
- realloc_particles(sim, totpart);
-
- return totpart - oldtotpart;
-}
-
-/* Calculates the next state for all particles of the system
- * In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)
- * 1. Emit particles
- * 2. Check cache (if used) and return if frame is cached
- * 3. Do dynamics
- * 4. Save to cache */
-static void system_step(ParticleSimulationData *sim, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- PointCache *cache = psys->pointcache;
- PTCacheID ptcacheid, *pid = NULL;
- PARTICLE_P;
- float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */
- int startframe = 0, endframe = 100, oldtotpart = 0;
-
- /* cache shouldn't be used for hair or "continue physics" */
- if (part->type != PART_HAIR) {
- psys_clear_temp_pointcache(psys);
-
- /* set suitable cache range automatically */
- if ((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0)
- psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe);
-
- pid = &ptcacheid;
- BKE_ptcache_id_from_particles(pid, sim->ob, psys);
-
- BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL);
-
- /* clear everything on start frame, or when psys needs full reset! */
- if ((cfra == startframe) || (psys->recalc & PSYS_RECALC_RESET)) {
- BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED);
- BKE_ptcache_validate(cache, startframe);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- }
-
- CLAMP(cache_cfra, startframe, endframe);
- }
-
-/* 1. emit particles and redo particles if needed */
- oldtotpart = psys->totpart;
- if (emit_particles(sim, pid, cfra) || psys->recalc & PSYS_RECALC_RESET) {
- distribute_particles(sim, part->from);
- initialize_all_particles(sim);
- /* reset only just created particles (on startframe all particles are recreated) */
- reset_all_particles(sim, 0.0, cfra, oldtotpart);
- free_unexisting_particles(sim);
-
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
-
- psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
-
- /* flag for possible explode modifiers after this system */
- sim->psmd->flag |= eParticleSystemFlag_Pars;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
- }
-
-/* 2. try to read from the cache */
- if (pid) {
- int cache_result = BKE_ptcache_read(pid, cache_cfra);
-
- if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
- cached_step(sim, cfra);
- update_children(sim);
- psys_update_path_cache(sim, cfra);
-
- BKE_ptcache_validate(cache, (int)cache_cfra);
-
- if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_write(pid, (int)cache_cfra);
-
- return;
- }
- /* Cache is supposed to be baked, but no data was found so bail out */
- else if (cache->flag & PTCACHE_BAKED) {
- psys_reset(psys, PSYS_RESET_CACHE_MISS);
- return;
- }
- else if (cache_result == PTCACHE_READ_OLD) {
- psys->cfra = (float)cache->simframe;
- cached_step(sim, psys->cfra);
- }
-
- /* if on second frame, write cache for first frame */
- if (psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write(pid, startframe);
- }
- else
- BKE_ptcache_invalidate(cache);
-
-/* 3. do dynamics */
- /* set particles to be not calculated TODO: can't work with pointcache */
- disp= psys_get_current_display_percentage(psys);
-
- LOOP_PARTICLES {
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-
- if (psys->totpart) {
- int dframe, totframesback = 0;
- float t_frac, dt_frac;
-
- /* handle negative frame start at the first frame by doing
- * all the steps before the first frame */
- if ((int)cfra == startframe && part->sta < startframe)
- totframesback = (startframe - (int)part->sta);
-
- if (!(part->time_flag & PART_TIME_AUTOSF)) {
- /* Constant time step */
- psys->dt_frac = get_base_time_step(part);
- }
- else if ((int)cfra == startframe) {
- /* Variable time step; initialise to subframes */
- psys->dt_frac = get_base_time_step(part);
- }
- else if (psys->dt_frac < MIN_TIMESTEP) {
- /* Variable time step; subsequent frames */
- psys->dt_frac = MIN_TIMESTEP;
- }
-
- for (dframe=-totframesback; dframe<=0; dframe++) {
- /* simulate each subframe */
- dt_frac = psys->dt_frac;
- for (t_frac = dt_frac; t_frac <= 1.0f; t_frac += dt_frac) {
- sim->courant_num = 0.0f;
- dynamics_step(sim, cfra+dframe+t_frac - 1.f);
- psys->cfra = cfra+dframe+t_frac - 1.f;
-#if 0
- printf("%f,%f,%f,%f\n", cfra+dframe+t_frac - 1.f, t_frac, dt_frac, sim->courant_num);
-#endif
- if (part->time_flag & PART_TIME_AUTOSF)
- dt_frac = update_timestep(psys, sim, t_frac);
- }
- }
- }
-
-/* 4. only write cache starting from second frame */
- if (pid) {
- BKE_ptcache_validate(cache, (int)cache_cfra);
- if ((int)cache_cfra != startframe)
- BKE_ptcache_write(pid, (int)cache_cfra);
- }
-
- update_children(sim);
-
-/* cleanup */
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-}
-
-/* system type has changed so set sensible defaults and clear non applicable flags */
-void psys_changed_type(Object *ob, ParticleSystem *psys)
-{
- ParticleSettings *part = psys->part;
- PTCacheID pid;
-
- BKE_ptcache_id_from_particles(&pid, ob, psys);
-
- if (part->phystype != PART_PHYS_KEYED)
- psys->flag &= ~PSYS_KEYED;
-
- if (part->type == PART_HAIR) {
- if (ELEM(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
- part->ren_as = PART_DRAW_PATH;
-
- if (part->distr == PART_DISTR_GRID)
- part->distr = PART_DISTR_JIT;
-
- if (ELEM(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
- part->draw_as = PART_DRAW_REND;
-
- CLAMP(part->path_start, 0.0f, 100.0f);
- CLAMP(part->path_end, 0.0f, 100.0f);
-
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
- }
- else {
- free_hair(ob, psys, 1);
-
- CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime));
- CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime));
- }
-
- psys_reset(psys, PSYS_RESET_ALL);
-}
-void psys_check_boid_data(ParticleSystem *psys)
-{
- BoidParticle *bpa;
- PARTICLE_P;
-
- pa = psys->particles;
-
- if (!pa)
- return;
-
- if (psys->part && psys->part->phystype==PART_PHYS_BOIDS) {
- if (!pa->boid) {
- bpa = MEM_callocN(psys->totpart * sizeof(BoidParticle), "Boid Data");
-
- LOOP_PARTICLES
- pa->boid = bpa++;
- }
- }
- else if (pa->boid) {
- MEM_freeN(pa->boid);
- LOOP_PARTICLES
- pa->boid = NULL;
- }
-}
-
-static void fluid_default_settings(ParticleSettings *part)
-{
- SPHFluidSettings *fluid = part->fluid;
-
- fluid->spring_k = 0.f;
- fluid->plasticity_constant = 0.1f;
- fluid->yield_ratio = 0.1f;
- fluid->rest_length = 1.f;
- fluid->viscosity_omega = 2.f;
- fluid->viscosity_beta = 0.1f;
- fluid->stiffness_k = 1.f;
- fluid->stiffness_knear = 1.f;
- fluid->rest_density = 1.f;
- fluid->buoyancy = 0.f;
- fluid->radius = 1.f;
- fluid->flag |= SPH_FAC_REPULSION|SPH_FAC_DENSITY|SPH_FAC_RADIUS|SPH_FAC_VISCOSITY|SPH_FAC_REST_LENGTH;
-}
-
-static void psys_prepare_physics(ParticleSimulationData *sim)
-{
- ParticleSettings *part = sim->psys->part;
-
- if (ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
- PTCacheID pid;
- BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys);
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
- }
- else {
- free_keyed_keys(sim->psys);
- sim->psys->flag &= ~PSYS_KEYED;
- }
-
- if (part->phystype == PART_PHYS_BOIDS && part->boids == NULL) {
- BoidState *state;
-
- part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings");
- boid_default_settings(part->boids);
-
- state = boid_new_state(part->boids);
- BLI_addtail(&state->rules, boid_new_rule(eBoidRuleType_Separate));
- BLI_addtail(&state->rules, boid_new_rule(eBoidRuleType_Flock));
-
- ((BoidRule*)state->rules.first)->flag |= BOIDRULE_CURRENT;
-
- state->flag |= BOIDSTATE_CURRENT;
- BLI_addtail(&part->boids->states, state);
- }
- else if (part->phystype == PART_PHYS_FLUID && part->fluid == NULL) {
- part->fluid = MEM_callocN(sizeof(SPHFluidSettings), "SPH Fluid Settings");
- fluid_default_settings(part);
- }
-
- psys_check_boid_data(sim->psys);
-}
-static int hair_needs_recalc(ParticleSystem *psys)
-{
- if (!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) &&
- ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET || (psys->part->flag & PART_HAIR_REGROW && !psys->edit)))
- {
- return 1;
- }
-
- return 0;
-}
-
-/* main particle update call, checks that things are ok on the large scale and
- * then advances in to actual particle calculations depending on particle type */
-void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
-{
- ParticleSimulationData sim= {0};
- ParticleSettings *part = psys->part;
- float cfra;
-
- /* drawdata is outdated after ANY change */
- if (psys->pdd) psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
-
- if (!psys_check_enabled(ob, psys))
- return;
-
- cfra= BKE_scene_frame_get(scene);
-
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psys_get_modifier(ob, psys);
-
- /* system was already updated from modifier stack */
- if (sim.psmd->flag & eParticleSystemFlag_psys_updated) {
- sim.psmd->flag &= ~eParticleSystemFlag_psys_updated;
- /* make sure it really was updated to cfra */
- if (psys->cfra == cfra)
- return;
- }
-
- if (!sim.psmd->dm_final)
- return;
-
- if (part->from != PART_FROM_VERT) {
- DM_ensure_tessface(sim.psmd->dm_final);
- }
-
- /* execute drivers only, as animation has already been done */
- BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, cfra, ADT_RECALC_DRIVERS);
-
- /* to verify if we need to restore object afterwards */
- psys->flag &= ~PSYS_OB_ANIM_RESTORE;
-
- if (psys->recalc & PSYS_RECALC_TYPE)
- psys_changed_type(sim.ob, sim.psys);
-
- if (psys->recalc & PSYS_RECALC_RESET)
- psys->totunexist = 0;
-
- /* setup necessary physics type dependent additional data if it doesn't yet exist */
- psys_prepare_physics(&sim);
-
- switch (part->type) {
- case PART_HAIR:
- {
- /* nothing to do so bail out early */
- if (psys->totpart == 0 && part->totpart == 0) {
- psys_free_path_cache(psys, NULL);
- free_hair(ob, psys, 0);
- psys->flag |= PSYS_HAIR_DONE;
- }
- /* (re-)create hair */
- else if (hair_needs_recalc(psys)) {
- float hcfra=0.0f;
- int i, recalc = psys->recalc;
-
- free_hair(ob, psys, 0);
-
- if (psys->edit && psys->free_edit) {
- psys->free_edit(psys->edit);
- psys->edit = NULL;
- psys->free_edit = NULL;
- }
-
- /* first step is negative so particles get killed and reset */
- psys->cfra= 1.0f;
-
- for (i=0; i<=part->hair_step; i++) {
- hcfra=100.0f*(float)i/(float)psys->part->hair_step;
- if ((part->flag & PART_HAIR_REGROW)==0)
- BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, hcfra, ADT_RECALC_ANIM);
- system_step(&sim, hcfra);
- psys->cfra = hcfra;
- psys->recalc = 0;
- save_hair(&sim, hcfra);
- }
-
- psys->flag |= PSYS_HAIR_DONE;
- psys->recalc = recalc;
- }
- else if (psys->flag & PSYS_EDITED)
- psys->flag |= PSYS_HAIR_DONE;
-
- if (psys->flag & PSYS_HAIR_DONE)
- hair_step(&sim, cfra);
- break;
- }
- case PART_FLUID:
- {
- particles_fluid_step(&sim, (int)cfra);
- break;
- }
- default:
- {
- switch (part->phystype) {
- case PART_PHYS_NO:
- case PART_PHYS_KEYED:
- {
- PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
- bool free_unexisting = false;
-
- /* Particles without dynamics haven't been reset yet because they don't use pointcache */
- if (psys->recalc & PSYS_RECALC_RESET)
- psys_reset(psys, PSYS_RESET_ALL);
-
- if (emit_particles(&sim, NULL, cfra) || (psys->recalc & PSYS_RECALC_RESET)) {
- free_keyed_keys(psys);
- distribute_particles(&sim, part->from);
- initialize_all_particles(&sim);
- free_unexisting = true;
-
- /* flag for possible explode modifiers after this system */
- sim.psmd->flag |= eParticleSystemFlag_Pars;
- }
-
- LOOP_EXISTING_PARTICLES {
- pa->size = part->size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- reset_particle(&sim, pa, 0.0, cfra);
-
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-
- /* free unexisting after reseting particles */
- if (free_unexisting)
- free_unexisting_particles(&sim);
-
- if (part->phystype == PART_PHYS_KEYED) {
- psys_count_keyed_targets(&sim);
- set_keyed_keys(&sim);
- psys_update_path_cache(&sim,(int)cfra);
- }
- break;
- }
- default:
- {
- /* the main dynamic particle system step */
- system_step(&sim, cfra);
- break;
- }
- }
- break;
- }
- }
-
- /* make sure emitter is left at correct time (particle emission can change this) */
- if (psys->flag & PSYS_OB_ANIM_RESTORE) {
- evaluate_emitter_anim(scene, ob, cfra);
- psys->flag &= ~PSYS_OB_ANIM_RESTORE;
- }
-
- psys->cfra = cfra;
- psys->recalc = 0;
-
- /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
- if (psys->renderdata==0)
- invert_m4_m4(psys->imat, ob->obmat);
-}
-
-/* ID looper */
-
-void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata)
-{
- ParticleTarget *pt;
-
- func(psys, (ID **)&psys->part, userdata, IDWALK_USER | IDWALK_NEVER_NULL);
- func(psys, (ID **)&psys->target_ob, userdata, IDWALK_NOP);
- func(psys, (ID **)&psys->parent, userdata, IDWALK_NOP);
-
- for (pt = psys->targets.first; pt; pt = pt->next) {
- func(psys, (ID **)&pt->ob, userdata, IDWALK_NOP);
- }
-
- if (psys->part->phystype == PART_PHYS_BOIDS) {
- ParticleData *pa;
- int p;
-
- for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
- func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_NOP);
- }
- }
-}
-
-/* **** Depsgraph evaluation **** */
-
-void BKE_particle_system_eval(EvaluationContext *UNUSED(eval_ctx),
- Scene *scene,
- Object *ob,
- ParticleSystem *psys)
-{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s:%s\n", __func__, ob->id.name, psys->name);
- }
- BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
-}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 448aaaa7830..36f786c5254 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -62,11 +62,11 @@
#include "BKE_blender.h"
#include "BKE_cloth.h"
#include "BKE_dynamicpaint.h"
+#include "BKE_key.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_smoke.h"
@@ -195,6 +195,36 @@ static void ptcache_softbody_read(int index, void *soft_v, void **data, float UN
PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
}
}
+
+static void interpolate_particle_keys(short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity)
+{
+ float t[4];
+
+ if (type < 0) {
+ interp_cubic_v3(result->co, result->vel, keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt);
+ }
+ else {
+ key_curve_position_weights(dt, t, type);
+
+ interp_v3_v3v3v3v3(result->co, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
+
+ if (velocity) {
+ float temp[3];
+
+ if (dt > 0.999f) {
+ key_curve_position_weights(dt - 0.001f, t, type);
+ interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
+ sub_v3_v3v3(result->vel, result->co, temp);
+ }
+ else {
+ key_curve_position_weights(dt + 0.001f, t, type);
+ interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
+ sub_v3_v3v3(result->vel, temp, result->co);
+ }
+ }
+ }
+}
+
static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
{
SoftBody *soft= soft_v;
@@ -220,7 +250,7 @@ static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, f
mul_v3_fl(keys[1].vel, dfra);
mul_v3_fl(keys[2].vel, dfra);
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
+ interpolate_particle_keys(-1, keys, (cfra - cfra1) / dfra, keys, 1);
mul_v3_fl(keys->vel, 1.0f / dfra);
@@ -402,7 +432,7 @@ static void ptcache_particle_interpolate(int index, void *psys_v, void **data, f
mul_v3_fl(keys[1].vel, dfra * timestep);
mul_v3_fl(keys[2].vel, dfra * timestep);
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
+ interpolate_particle_keys(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep));
@@ -534,7 +564,7 @@ static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, flo
mul_v3_fl(keys[1].vel, dfra);
mul_v3_fl(keys[2].vel, dfra);
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
+ interpolate_particle_keys(-1, keys, (cfra - cfra1) / dfra, keys, 1);
mul_v3_fl(keys->vel, 1.0f / dfra);
@@ -1358,7 +1388,7 @@ static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, fl
dfra = cfra2 - cfra1;
/* note: keys[0] and keys[3] unused for type < 1 (crappy) */
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true);
+ interpolate_particle_keys(-1, keys, (cfra - cfra1) / dfra, &result, true);
interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
copy_v3_v3(rbo->pos, result.co);
@@ -1424,7 +1454,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->ob= ob;
pid->calldata= psys;
- pid->type= PTCACHE_TYPE_PARTICLES;
+ pid->type= 0xdeadbeef;
pid->stack_index= psys->pointcache->index;
pid->cache= psys->pointcache;
pid->cache_ptr= &psys->pointcache;
@@ -2224,8 +2254,6 @@ static int ptcache_old_elemsize(PTCacheID *pid)
{
if (pid->type==PTCACHE_TYPE_SOFTBODY)
return 6 * sizeof(float);
- else if (pid->type==PTCACHE_TYPE_PARTICLES)
- return sizeof(ParticleKey);
else if (pid->type==PTCACHE_TYPE_CLOTH)
return 9 * sizeof(float);
@@ -3262,8 +3290,6 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
cloth_free_modifier(pid->calldata);
else if (pid->type == PTCACHE_TYPE_SOFTBODY)
sbFreeSimulation(pid->calldata);
- else if (pid->type == PTCACHE_TYPE_PARTICLES)
- psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
#if 0
else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
smokeModifier_reset(pid->calldata);
@@ -3283,38 +3309,16 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
{
PTCacheID pid;
- ParticleSystem *psys;
ModifierData *md;
- int reset, skip;
+ int reset;
reset= 0;
- skip= 0;
if (ob->soft) {
BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
reset |= BKE_ptcache_id_reset(scene, &pid, mode);
}
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- /* children or just redo can be calculated without resetting anything */
- if (psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
- skip = 1;
- /* Baked cloth hair has to be checked too, because we don't want to reset */
- /* particles or cloth in that case -jahka */
- else if (psys->clmd) {
- BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
- if (mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED)))
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- else
- skip = 1;
- }
-
- if (skip == 0 && psys->part) {
- BKE_ptcache_id_from_particles(&pid, ob, psys);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- }
- }
-
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type == eModifierType_Cloth) {
BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
@@ -3554,14 +3558,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
/* cache/bake a single object */
cache = pid->cache;
if ((cache->flag & PTCACHE_BAKED)==0) {
- if (pid->type==PTCACHE_TYPE_PARTICLES) {
- ParticleSystem *psys= pid->calldata;
-
- /* a bit confusing, could make this work better in the UI */
- if (psys->part->type == PART_EMITTER)
- psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
- }
- else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
+ if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
/* get all pids from the object and search for smoke low res */
ListBase pidlist2;
PTCacheID *pid2;
@@ -3605,15 +3602,6 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
for (pid=pidlist.first; pid; pid=pid->next) {
cache = pid->cache;
if ((cache->flag & PTCACHE_BAKED)==0) {
- if (pid->type==PTCACHE_TYPE_PARTICLES) {
- ParticleSystem *psys = (ParticleSystem*)pid->calldata;
- /* skip hair & keyed particles */
- if (psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
- continue;
-
- psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
- }
-
if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) &&
(render || bake))
{
@@ -3709,10 +3697,6 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
for (pid=pidlist.first; pid; pid=pid->next) {
- /* skip hair particles */
- if (pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
- continue;
-
cache = pid->cache;
if (baker->quick_step > 1)
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index d20994a2e39..b8fe669cab0 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -77,7 +77,6 @@
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_smoke.h"
@@ -1127,248 +1126,6 @@ static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_mult
em_freeData(&em1);
}
-typedef struct EmitFromParticlesData {
- SmokeFlowSettings *sfs;
- KDTree *tree;
- int hires_multiplier;
-
- EmissionMap *em;
- float *particle_vel;
- float hr;
-
- int *min, *max, *res;
-
- float solid;
- float smooth;
- float hr_smooth;
-} EmitFromParticlesData;
-
-static void emit_from_particles_task_cb(void *userdata, const int z)
-{
- EmitFromParticlesData *data = userdata;
- SmokeFlowSettings *sfs = data->sfs;
- EmissionMap *em = data->em;
- const int hires_multiplier = data->hires_multiplier;
-
- for (int x = data->min[0]; x < data->max[0]; x++) {
- for (int y = data->min[1]; y < data->max[1]; y++) {
- /* take low res samples where possible */
- if (hires_multiplier <= 1 || !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
- /* get low res space coordinates */
- const int lx = x / hires_multiplier;
- const int ly = y / hires_multiplier;
- const int lz = z / hires_multiplier;
-
- const int index = smoke_get_index(lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
- const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
-
- /* find particle distance from the kdtree */
- KDTreeNearest nearest;
- const float range = data->solid + data->smooth;
- BLI_kdtree_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence[index] = (nearest.dist < data->solid) ?
- 1.0f : (1.0f - (nearest.dist - data->solid) / data->smooth);
- /* Uses particle velocity as initial velocity for smoke */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (sfs->psys->part->phystype != PART_PHYS_NO)) {
- VECADDFAC(&em->velocity[index * 3], &em->velocity[index * 3],
- &data->particle_vel[nearest.index * 3], sfs->vel_multi);
- }
- }
- }
-
- /* take high res samples if required */
- if (hires_multiplier > 1) {
- /* get low res space coordinates */
- const float lx = ((float)x) * data->hr;
- const float ly = ((float)y) * data->hr;
- const float lz = ((float)z) * data->hr;
-
- const int index = smoke_get_index(
- x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
- const float ray_start[3] = {lx + 0.5f * data->hr, ly + 0.5f * data->hr, lz + 0.5f * data->hr};
-
- /* find particle distance from the kdtree */
- KDTreeNearest nearest;
- const float range = data->solid + data->hr_smooth;
- BLI_kdtree_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence_high[index] = (nearest.dist < data->solid) ?
- 1.0f : (1.0f - (nearest.dist - data->solid) / data->smooth);
- }
- }
-
- }
- }
-}
-
-static void emit_from_particles(
- Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, Scene *scene, float dt)
-{
- if (sfs && sfs->psys && sfs->psys->part && ELEM(sfs->psys->part->type, PART_EMITTER, PART_FLUID)) // is particle system selected
- {
- ParticleSimulationData sim;
- ParticleSystem *psys = sfs->psys;
- float *particle_pos;
- float *particle_vel;
- int totpart = psys->totpart, totchild;
- int p = 0;
- int valid_particles = 0;
- int bounds_margin = 1;
-
- /* radius based flow */
- const float solid = sfs->particle_size * 0.5f;
- const float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
- int hires_multiplier = 1;
- KDTree *tree = NULL;
-
- sim.scene = scene;
- sim.ob = flow_ob;
- sim.psys = psys;
-
- /* prepare curvemapping tables */
- if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve)
- curvemapping_changed_all(psys->part->clumpcurve);
- if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
- curvemapping_changed_all(psys->part->roughcurve);
-
- /* initialize particle cache */
- if (psys->part->type == PART_HAIR) {
- // TODO: PART_HAIR not supported whatsoever
- totchild = 0;
- }
- else {
- totchild = psys->totchild * psys->part->disp / 100;
- }
-
- particle_pos = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles");
- particle_vel = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles");
-
- /* setup particle radius emission if enabled */
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- tree = BLI_kdtree_new(psys->totpart + psys->totchild);
-
- /* check need for high resolution map */
- if ((sds->flags & MOD_SMOKE_HIGHRES) && (sds->highres_sampling == SM_HRES_FULLSAMPLE)) {
- hires_multiplier = sds->amplify + 1;
- }
-
- bounds_margin = (int)ceil(solid + smooth);
- }
-
- /* calculate local position for each particle */
- for (p = 0; p < totpart + totchild; p++)
- {
- ParticleKey state;
- float *pos;
- if (p < totpart) {
- if (psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST))
- continue;
- }
- else {
- /* handle child particle */
- ChildParticle *cpa = &psys->child[p - totpart];
- if (psys->particles[cpa->parent].flag & (PARS_NO_DISP | PARS_UNEXIST))
- continue;
- }
-
- state.time = BKE_scene_frame_get(scene); /* use scene time */
- if (psys_get_particle_state(&sim, p, &state, 0) == 0)
- continue;
-
- /* location */
- pos = &particle_pos[valid_particles * 3];
- copy_v3_v3(pos, state.co);
- smoke_pos_to_cell(sds, pos);
-
- /* velocity */
- copy_v3_v3(&particle_vel[valid_particles * 3], state.vel);
- mul_mat3_m4_v3(sds->imat, &particle_vel[valid_particles * 3]);
-
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- BLI_kdtree_insert(tree, valid_particles, pos);
- }
-
- /* calculate emission map bounds */
- em_boundInsert(em, pos);
- valid_particles++;
- }
-
- /* set emission map */
- clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, bounds_margin, dt);
- em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY, hires_multiplier);
-
- if (!(sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE)) {
- for (p = 0; p < valid_particles; p++)
- {
- int cell[3];
- size_t i = 0;
- size_t index = 0;
- int badcell = 0;
-
- /* 1. get corresponding cell */
- cell[0] = floor(particle_pos[p * 3]) - em->min[0];
- cell[1] = floor(particle_pos[p * 3 + 1]) - em->min[1];
- cell[2] = floor(particle_pos[p * 3 + 2]) - em->min[2];
- /* check if cell is valid (in the domain boundary) */
- for (i = 0; i < 3; i++) {
- if ((cell[i] > em->res[i] - 1) || (cell[i] < 0)) {
- badcell = 1;
- break;
- }
- }
- if (badcell)
- continue;
- /* get cell index */
- index = smoke_get_index(cell[0], em->res[0], cell[1], em->res[1], cell[2]);
- /* Add influence to emission map */
- em->influence[index] = 1.0f;
- /* Uses particle velocity as initial velocity for smoke */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
- {
- VECADDFAC(&em->velocity[index * 3], &em->velocity[index * 3], &particle_vel[p * 3], sfs->vel_multi);
- }
- } // particles loop
- }
- else if (valid_particles > 0) { // MOD_SMOKE_FLOW_USE_PART_SIZE
- int min[3], max[3], res[3];
- const float hr = 1.0f / ((float)hires_multiplier);
- /* slightly adjust high res antialias smoothness based on number of divisions
- * to allow smaller details but yet not differing too much from the low res size */
- const float hr_smooth = smooth * powf(hr, 1.0f / 3.0f);
-
- /* setup loop bounds */
- for (int i = 0; i < 3; i++) {
- min[i] = em->min[i] * hires_multiplier;
- max[i] = em->max[i] * hires_multiplier;
- res[i] = em->res[i] * hires_multiplier;
- }
-
- BLI_kdtree_balance(tree);
-
- EmitFromParticlesData data = {
- .sfs = sfs, .tree = tree, .hires_multiplier = hires_multiplier, .hr = hr,
- .em = em, .particle_vel = particle_vel, .min = min, .max = max, .res = res,
- .solid = solid, .smooth = smooth, .hr_smooth = hr_smooth,
- };
-
- BLI_task_parallel_range(min[2], max[2], &data, emit_from_particles_task_cb, true);
- }
-
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- BLI_kdtree_free(tree);
- }
-
- /* free data */
- if (particle_pos)
- MEM_freeN(particle_pos);
- if (particle_vel)
- MEM_freeN(particle_vel);
- }
-}
-
static void sample_derivedmesh(
SmokeFlowSettings *sfs,
const MVert *mvert, const MLoop *mloop, const MLoopTri *mlooptri, const MLoopUV *mloopuv,
@@ -2093,10 +1850,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
/* just sample flow directly to emission map if no subframes */
if (!subframes) {
- if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
- emit_from_particles(collob, sds, sfs, em, scene, dt);
- }
- else {
+ if (sfs->source == MOD_SMOKE_FLOW_SOURCE_MESH) {
emit_from_derivedmesh(collob, sds, sfs, em, dt);
}
}
@@ -2127,14 +1881,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
scene->r.subframe = 0.0f;
}
- if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
- /* emit_from_particles() updates timestep internally */
- emit_from_particles(collob, sds, sfs, &em_temp, scene, sdt);
- if (!(sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE)) {
- hires_multiplier = 1;
- }
- }
- else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
+ if (sfs->source == MOD_SMOKE_FLOW_SOURCE_MESH) {
/* update flow object frame */
BLI_mutex_lock(&object_update_lock);
BKE_object_modifier_update_subframe(scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index a5267175dfa..6667ae9051e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -134,7 +134,6 @@
#include "BKE_node.h" // for tree type defines
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_sca.h" // for init_actuator
@@ -4114,165 +4113,6 @@ static void direct_link_partdeflect(PartDeflect *pd)
if (pd) pd->rng = NULL;
}
-static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
-{
- int a;
-
- part->adt = newdataadr(fd, part->adt);
- part->pd = newdataadr(fd, part->pd);
- part->pd2 = newdataadr(fd, part->pd2);
-
- direct_link_animdata(fd, part->adt);
- direct_link_partdeflect(part->pd);
- direct_link_partdeflect(part->pd2);
-
- part->clumpcurve = newdataadr(fd, part->clumpcurve);
- if (part->clumpcurve)
- direct_link_curvemapping(fd, part->clumpcurve);
- part->roughcurve = newdataadr(fd, part->roughcurve);
- if (part->roughcurve)
- direct_link_curvemapping(fd, part->roughcurve);
-
- part->effector_weights = newdataadr(fd, part->effector_weights);
- if (!part->effector_weights)
- part->effector_weights = BKE_add_effector_weights(part->eff_group);
-
- link_list(fd, &part->dupliweights);
-
- part->boids = newdataadr(fd, part->boids);
- part->fluid = newdataadr(fd, part->fluid);
-
- if (part->boids) {
- BoidState *state;
- link_list(fd, &part->boids->states);
-
- for (state=part->boids->states.first; state; state=state->next) {
- link_list(fd, &state->rules);
- link_list(fd, &state->conditions);
- link_list(fd, &state->actions);
- }
- }
- for (a = 0; a < MAX_MTEX; a++) {
- part->mtex[a] = newdataadr(fd, part->mtex[a]);
- }
-}
-
-static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase *particles)
-{
- ParticleSystem *psys, *psysnext;
-
- for (psys=particles->first; psys; psys=psysnext) {
- psysnext = psys->next;
-
- psys->part = newlibadr_us(fd, id->lib, psys->part);
- if (psys->part) {
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt=pt->next)
- pt->ob=newlibadr(fd, id->lib, pt->ob);
-
- psys->parent = newlibadr(fd, id->lib, psys->parent);
- psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
-
- if (psys->clmd) {
- /* XXX - from reading existing code this seems correct but intended usage of
- * pointcache /w cloth should be added in 'ParticleSystem' - campbell */
- psys->clmd->point_cache = psys->pointcache;
- psys->clmd->ptcaches.first = psys->clmd->ptcaches.last= NULL;
- psys->clmd->coll_parms->group = newlibadr(fd, id->lib, psys->clmd->coll_parms->group);
- psys->clmd->modifier.error = NULL;
- }
- }
- else {
- /* particle modifier must be removed before particle system */
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
-
- BLI_remlink(particles, psys);
- MEM_freeN(psys);
- }
- }
-}
-static void direct_link_particlesystems(FileData *fd, ListBase *particles)
-{
- ParticleSystem *psys;
- ParticleData *pa;
- int a;
-
- for (psys=particles->first; psys; psys=psys->next) {
- psys->particles=newdataadr(fd, psys->particles);
-
- if (psys->particles && psys->particles->hair) {
- for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++)
- pa->hair=newdataadr(fd, pa->hair);
- }
-
- if (psys->particles && psys->particles->keys) {
- for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
- pa->keys= NULL;
- pa->totkey= 0;
- }
-
- psys->flag &= ~PSYS_KEYED;
- }
-
- if (psys->particles && psys->particles->boid) {
- pa = psys->particles;
- pa->boid = newdataadr(fd, pa->boid);
- for (a=1, pa++; a<psys->totpart; a++, pa++)
- pa->boid = (pa-1)->boid + 1;
- }
- else if (psys->particles) {
- for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++)
- pa->boid = NULL;
- }
-
- psys->fluid_springs = newdataadr(fd, psys->fluid_springs);
-
- psys->child = newdataadr(fd, psys->child);
- psys->effectors = NULL;
-
- link_list(fd, &psys->targets);
-
- psys->edit = NULL;
- psys->free_edit = NULL;
- psys->pathcache = NULL;
- psys->childcache = NULL;
- BLI_listbase_clear(&psys->pathcachebufs);
- BLI_listbase_clear(&psys->childcachebufs);
- psys->pdd = NULL;
- psys->renderdata = NULL;
-
- if (psys->clmd) {
- psys->clmd = newdataadr(fd, psys->clmd);
- psys->clmd->clothObject = NULL;
- psys->clmd->hairdata = NULL;
-
- psys->clmd->sim_parms= newdataadr(fd, psys->clmd->sim_parms);
- psys->clmd->coll_parms= newdataadr(fd, psys->clmd->coll_parms);
-
- if (psys->clmd->sim_parms) {
- psys->clmd->sim_parms->effector_weights = NULL;
- if (psys->clmd->sim_parms->presets > 10)
- psys->clmd->sim_parms->presets = 0;
- }
-
- psys->hair_in_dm = psys->hair_out_dm = NULL;
- psys->clmd->solver_result = NULL;
- }
-
- direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache, 0);
- if (psys->clmd) {
- psys->clmd->point_cache = psys->pointcache;
- }
-
- psys->tree = NULL;
- psys->bvhtree = NULL;
- }
- return;
-}
-
/* ************ READ MESH ***************** */
static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
@@ -4882,7 +4722,6 @@ static void lib_link_object(FileData *fd, Main *main)
if (ob->soft)
ob->soft->effector_weights->group = newlibadr(fd, ob->id.lib, ob->soft->effector_weights->group);
- lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
lib_link_modifiers(fd, ob);
if (ob->rigidbody_constraint) {
@@ -5379,9 +5218,6 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->rigidbody_constraint = newdataadr(fd, ob->rigidbody_constraint);
if (ob->rigidbody_constraint)
ob->rigidbody_constraint->physics_constraint = NULL;
-
- link_list(fd, &ob->particlesystem);
- direct_link_particlesystems(fd, &ob->particlesystem);
link_list(fd, &ob->prop);
for (prop = ob->prop.first; prop; prop = prop->next) {
@@ -8043,9 +7879,6 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_BR:
direct_link_brush(fd, (Brush*)id);
break;
- case ID_PA:
- direct_link_particlesettings(fd, (ParticleSettings*)id);
- break;
case ID_GD:
direct_link_gpencil(fd, (bGPdata *)id);
break;
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 43ebab7856c..b3ac48cf0cb 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -78,7 +78,6 @@
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
#include "BKE_multires.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
@@ -743,7 +742,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
Curve *cu;
Scene *sce;
Tex *tx;
- ParticleSettings *part;
Object *ob;
//PTCacheID *pid;
//ListBase pidlist;
@@ -874,25 +872,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
me->drawflag = ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES;
}
- /* particle draw and render types */
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->draw_as) {
- if (part->draw_as == PART_DRAW_DOT) {
- part->ren_as = PART_DRAW_HALO;
- part->draw_as = PART_DRAW_REND;
- }
- else if (part->draw_as <= PART_DRAW_AXIS) {
- part->ren_as = PART_DRAW_HALO;
- }
- else {
- part->ren_as = part->draw_as;
- part->draw_as = PART_DRAW_REND;
- }
- }
- part->path_end = 1.0f;
- part->clength = 1.0f;
- }
-
/* set old pointcaches to have disk cache flag */
for (ob = main->object.first; ob; ob = ob->id.next) {
@@ -1134,7 +1113,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
Lamp *la;
World *wo;
Tex *tex;
- ParticleSettings *part;
bool do_gravity = false;
for (sce = main->scene.first; sce; sce = sce->id.next)
@@ -1195,12 +1173,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
}
}
- /* Assign proper global gravity weights for dynamics (only z-coordinate is taken into account) */
- if (do_gravity) {
- for (part = main->particle.first; part; part = part->id.next)
- part->effector_weights->global_gravity = part->acc[2]/-9.81f;
- }
-
for (ob = main->object.first; ob; ob = ob->id.next) {
ModifierData *md;
@@ -2193,7 +2165,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 255 || (main->versionfile == 255 && main->subversionfile < 1)) {
Brush *br;
- ParticleSettings *part;
bScreen *sc;
Object *ob;
@@ -2202,14 +2173,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
br->ob_mode = OB_MODE_ALL_PAINT;
}
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->boids)
- part->boids->pitch = 1.0f;
-
- part->flag &= ~PART_HAIR_REGROW; /* this was a deprecated flag before */
- part->kink_amp_clump = 1.f; /* keep old files looking similar */
- }
-
for (sc = main->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
@@ -2427,7 +2390,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bScreen *sc;
Brush *brush;
Object *ob;
- ParticleSettings *part;
Material *mat;
int tex_nr, transp_tex;
@@ -2477,12 +2439,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
}
}
}
-
- /* particle draw color from material */
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->draw & PART_DRAW_MAT_COL)
- part->draw_col = PART_DRAW_COL_MAT;
- }
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 6)) {
@@ -2575,14 +2531,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
}
}
}
-
- {
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- /* Initialize particle billboard scale */
- part->bb_size[0] = part->bb_size[1] = 1.0f;
- }
- }
}
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 1)) {
@@ -2751,15 +2699,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 4)) {
{
- /* Adaptive time step for particle systems */
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- part->courant_target = 0.2f;
- part->time_flag &= ~PART_TIME_AUTOSF;
- }
- }
-
- {
/* set defaults for obstacle avoidance, recast data */
Scene *sce;
for (sce = main->scene.first; sce; sce = sce->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 907baab0aee..cc8939f6991 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -64,7 +64,6 @@
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_property.h" // for BKE_bproperty_object_get
#include "BKE_scene.h"
@@ -651,20 +650,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
do_versions_nodetree_image_default_alpha_output(ntree);
}
-
- {
- /* support old particle dupliobject rotation settings */
- ParticleSettings *part;
-
- for (part = main->particle.first; part; part = part->id.next) {
- if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- part->draw |= PART_DRAW_ROTATE_OB;
-
- if (part->rotmode == 0)
- part->rotmode = PART_ROT_VEL;
- }
- }
- }
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 1)) {
@@ -1141,16 +1126,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
-
-
- if (main->versionfile < 263) {
- /* Default for old files is to save particle rotations to pointcache */
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- part->flag |= PART_ROTATIONS;
- }
- }
-
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 1)) {
/* file output node paths are now stored in the file info struct instead socket name */
Scene *sce;
@@ -1444,8 +1419,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
- ParticleSettings *part;
-
FOREACH_NODETREE(main, ntree, id) {
if (ntree->type == NTREE_COMPOSIT) {
bNode *node;
@@ -1460,12 +1433,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
} FOREACH_NODETREE_END
-
- /* keep compatibility for dupliobject particle size */
- for (part = main->particle.first; part; part = part->id.next)
- if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
- if ((part->draw & PART_DRAW_ROTATE_OB) == 0)
- part->draw |= PART_DRAW_NO_SCALE_OB;
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index f2d42849bcc..cba3dd92ffa 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -88,7 +88,6 @@
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_property.h" // for BKE_bproperty_object_get
#include "BKE_scene.h"
@@ -495,27 +494,6 @@ static void do_version_ntree_242_2(bNodeTree *ntree)
}
}
-static void do_version_free_effect_245(Effect *eff)
-{
- PartEff *paf;
-
- if (eff->type == EFF_PARTICLE) {
- paf = (PartEff *)eff;
- if (paf->keys)
- MEM_freeN(paf->keys);
- }
- MEM_freeN(eff);
-}
-
-static void do_version_free_effects_245(ListBase *lb)
-{
- Effect *eff;
-
- while ((eff = BLI_pophead(lb))) {
- do_version_free_effect_245(eff);
- }
-}
-
static void do_version_constraints_245(ListBase *lb)
{
bConstraint *con;
@@ -2687,13 +2665,11 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
Image *ima;
Lamp *la;
Material *ma;
- ParticleSettings *part;
World *wrld;
Mesh *me;
bNodeTree *ntree;
Tex *tex;
ModifierData *md;
- ParticleSystem *psys;
/* unless the file was created 2.44.3 but not 2.45, update the constraints */
if (!(main->versionfile == 244 && main->subversionfile == 3) &&
@@ -2779,17 +2755,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
if (ob->soft && !ob->soft->pointcache)
ob->soft->pointcache = BKE_ptcache_add(&ob->soft->ptcaches);
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys->pointcache) {
- if (psys->pointcache->flag & PTCACHE_BAKED && (psys->pointcache->flag & PTCACHE_DISK_CACHE) == 0) {
- printf("Old memory cache isn't supported for particles, so re-bake the simulation!\n");
- psys->pointcache->flag &= ~PTCACHE_BAKED;
- }
- }
- else
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- }
-
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData*) md;
@@ -2846,18 +2811,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
ma->strand_min = 1.0f;
}
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->ren_child_nbr == 0)
- part->ren_child_nbr = part->child_nbr;
-
- if (part->simplify_refsize == 0) {
- part->simplify_refsize = 1920;
- part->simplify_rate = 1.0f;
- part->simplify_transition = 0.1f;
- part->simplify_viewport = 0.8f;
- }
- }
-
for (wrld = main->world.first; wrld; wrld = wrld->id.next) {
if (wrld->ao_approx_error == 0.0f)
wrld->ao_approx_error = 0.25f;
@@ -2999,7 +2952,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 8)) {
Scene *sce;
Object *ob;
- PartEff *paf = NULL;
for (ob = main->object.first; ob; ob = ob->id.next) {
if (ob->soft && ob->soft->keys) {
@@ -3016,124 +2968,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
sb->keys = NULL;
sb->totkey = 0;
}
-
- /* convert old particles to new system */
- if ((paf = blo_do_version_give_parteff_245(ob))) {
- ParticleSystem *psys;
- ModifierData *md;
- ParticleSystemModifierData *psmd;
- ParticleSettings *part;
-
- /* create new particle system */
- psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
-
- part = psys->part = psys_new_settings("ParticleSettings", main);
-
- /* needed for proper libdata lookup */
- blo_do_versions_oldnewmap_insert(fd->libmap, psys->part, psys->part, 0);
- part->id.lib = ob->id.lib;
-
- part->id.us--;
- part->id.tag |= (ob->id.tag & LIB_TAG_NEED_LINK);
-
- psys->totpart = 0;
- psys->flag = PSYS_CURRENT;
-
- BLI_addtail(&ob->particlesystem, psys);
-
- md = modifier_new(eModifierType_ParticleSystem);
- BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_listbase_count(&ob->particlesystem));
- psmd = (ParticleSystemModifierData*) md;
- psmd->psys = psys;
- BLI_addtail(&ob->modifiers, md);
-
- /* convert settings from old particle system */
- /* general settings */
- part->totpart = MIN2(paf->totpart, 100000);
- part->sta = paf->sta;
- part->end = paf->end;
- part->lifetime = paf->lifetime;
- part->randlife = paf->randlife;
- psys->seed = paf->seed;
- part->disp = paf->disp;
- part->omat = paf->mat[0];
- part->hair_step = paf->totkey;
-
- part->eff_group = paf->group;
-
- /* old system didn't interpolate between keypoints at render time */
- part->draw_step = part->ren_step = 0;
-
- /* physics */
- part->normfac = paf->normfac * 25.0f;
- part->obfac = paf->obfac;
- part->randfac = paf->randfac * 25.0f;
- part->dampfac = paf->damp;
- copy_v3_v3(part->acc, paf->force);
-
- /* flags */
- if (paf->stype & PAF_VECT) {
- if (paf->flag & PAF_STATIC) {
- /* new hair lifetime is always 100.0f */
- float fac = paf->lifetime / 100.0f;
-
- part->draw_as = PART_DRAW_PATH;
- part->type = PART_HAIR;
- psys->recalc |= PSYS_RECALC_REDO;
-
- part->normfac *= fac;
- part->randfac *= fac;
- }
- else {
- part->draw_as = PART_DRAW_LINE;
- part->draw |= PART_DRAW_VEL_LENGTH;
- part->draw_line[1] = 0.04f;
- }
- }
-
- part->rotmode = PART_ROT_VEL;
-
- part->flag |= (paf->flag & PAF_BSPLINE) ? PART_HAIR_BSPLINE : 0;
- part->flag |= (paf->flag & PAF_TRAND) ? PART_TRAND : 0;
- part->flag |= (paf->flag & PAF_EDISTR) ? PART_EDISTR : 0;
- part->flag |= (paf->flag & PAF_UNBORN) ? PART_UNBORN : 0;
- part->flag |= (paf->flag & PAF_DIED) ? PART_DIED : 0;
- part->from |= (paf->flag & PAF_FACE) ? PART_FROM_FACE : 0;
- part->draw |= (paf->flag & PAF_SHOWE) ? PART_DRAW_EMITTER : 0;
-
- psys->vgroup[PSYS_VG_DENSITY] = paf->vertgroup;
- psys->vgroup[PSYS_VG_VEL] = paf->vertgroup_v;
- psys->vgroup[PSYS_VG_LENGTH] = paf->vertgroup_v;
-
- /* dupliobjects */
- if (ob->transflag & OB_DUPLIVERTS) {
- Object *dup = main->object.first;
-
- for (; dup; dup = dup->id.next) {
- if (ob == blo_do_versions_newlibadr(fd, lib, dup->parent)) {
- part->dup_ob = dup;
- ob->transflag |= OB_DUPLIPARTS;
- ob->transflag &= ~OB_DUPLIVERTS;
-
- part->draw_as = PART_DRAW_OB;
-
- /* needed for proper libdata lookup */
- blo_do_versions_oldnewmap_insert(fd->libmap, dup, dup, 0);
- }
- }
- }
-
- {
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- if (fluidmd && fluidmd->fss && fluidmd->fss->type == OB_FLUIDSIM_PARTICLE)
- part->type = PART_FLUID;
- }
-
- do_version_free_effects_245(&ob->effect);
-
- printf("Old particle system converted to new system.\n");
- }
}
for (sce = main->scene.first; sce; sce = sce->id.next) {
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index a62b23bde68..09182009d8c 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -76,7 +76,6 @@ extern "C" {
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sound.h"
#include "BKE_texture.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_build.h b/source/blender/depsgraph/intern/depsgraph_build.h
index c5b04ec299c..af61ab4eb8b 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.h
+++ b/source/blender/depsgraph/intern/depsgraph_build.h
@@ -108,7 +108,6 @@ struct DepsgraphNodeBuilder {
void build_object_constraints(Scene *scene, Object *ob);
void build_pose_constraints(Object *ob, bPoseChannel *pchan);
void build_rigidbody(Scene *scene);
- void build_particles(Scene *scene, Object *ob);
void build_animdata(ID *id);
OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
void build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con);
@@ -266,7 +265,6 @@ struct DepsgraphRelationBuilder
void build_driver(ID *id, FCurve *fcurve);
void build_world(World *world);
void build_rigidbody(Scene *scene);
- void build_particles(Scene *scene, Object *ob);
void build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map);
void build_splineik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map);
void build_rig(Scene *scene, Object *ob);
diff --git a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
index 0a5235a6d11..2ac1a112eca 100644
--- a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
@@ -83,7 +83,6 @@ extern "C" {
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sound.h"
#include "BKE_texture.h"
@@ -447,11 +446,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
*/
build_animdata(&ob->id);
- /* particle systems */
- if (ob->particlesystem.first) {
- build_particles(scene, ob);
- }
-
/* grease pencil */
if (ob->gpd) {
build_gpencil(ob->gpd);
@@ -677,46 +671,6 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
}
}
-void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
-{
- /**
- * Particle Systems Nodes
- * ======================
- *
- * There are two types of nodes associated with representing
- * particle systems:
- * 1) Component (EVAL_PARTICLES) - This is the particle-system
- * evaluation context for an object. It acts as the container
- * for all the nodes associated with a particular set of particle
- * systems.
- * 2) Particle System Eval Operation - This operation node acts as a
- * blackbox evaluation step for one particle system referenced by
- * the particle systems stack. All dependencies link to this operation.
- */
-
- /* component for all particle systems */
- ComponentDepsNode *psys_comp = add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
-
- /* particle systems */
- for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) {
- ParticleSettings *part = psys->part;
-
- /* particle settings */
- // XXX: what if this is used more than once!
- build_animdata(&part->id);
-
- /* this particle system */
- // TODO: for now, this will just be a placeholder "ubereval" node
- add_operation_node(psys_comp,
- DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval, _1, scene, ob, psys),
- DEG_OPCODE_PSYS_EVAL,
- psys->name);
- }
-
- /* pointcache */
- // TODO...
-}
-
/* IK Solver Eval Steps */
void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
{
diff --git a/source/blender/depsgraph/intern/depsgraph_build_relations.cc b/source/blender/depsgraph/intern/depsgraph_build_relations.cc
index 226991e7b11..f0f1f83c264 100644
--- a/source/blender/depsgraph/intern/depsgraph_build_relations.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build_relations.cc
@@ -79,7 +79,6 @@ extern "C" {
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sound.h"
#include "BKE_texture.h"
@@ -434,11 +433,6 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
}
}
- /* particle systems */
- if (ob->particlesystem.first) {
- build_particles(scene, ob);
- }
-
/* grease pencil */
if (ob->gpd) {
build_gpencil(&ob->id, ob->gpd);
@@ -1020,134 +1014,6 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
}
}
-void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
-{
- TimeSourceKey time_src_key;
- OperationKey obdata_ubereval_key(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_UBEREVAL);
-
- /* particle systems */
- for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) {
- ParticleSettings *part = psys->part;
-
- /* particle settings */
- build_animdata(&part->id);
-
- /* this particle system */
- OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
-
- /* XXX: if particle system is later re-enabled, we must do full rebuild? */
- if (!psys_check_enabled(ob, psys))
- continue;
-
- /* TODO(sergey): Are all particle systems depends on time?
- * Hair without dynamics i.e.
- */
- add_relation(time_src_key, psys_key,
- DEPSREL_TYPE_TIME,
- "TimeSrc -> PSys");
-
- /* TODO(sergey): Currently particle update is just a placeholder,
- * hook it to the ubereval node so particle system is getting updated
- * on playback.
- */
- add_relation(psys_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_OPERATION,
- "PSys -> UberEval");
-
-#if 0
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- ParticleTarget *pt;
-
- for (pt = psys->targets.first; pt; pt = pt->next) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-#endif
-
- /* effectors */
- ListBase *effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false);
-
- if (effectors) {
- for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
- if (eff->psys) {
- // XXX: DAG_RL_DATA_DATA | DAG_RL_OB_DATA
- ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY); // xxx: particles instead?
- add_relation(eff_key, psys_key, DEPSREL_TYPE_STANDARD, "Particle Field");
- }
- }
- }
-
- pdEndEffectors(&effectors);
-
- /* boids */
- if (part->boids) {
- BoidRule *rule = NULL;
- BoidState *state = NULL;
-
- for (state = (BoidState *)part->boids->states.first; state; state = state->next) {
- for (rule = (BoidRule *)state->rules.first; rule; rule = rule->next) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
- if (ruleob) {
- ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule");
- }
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- ComponentKey dup_ob_key(&part->dup_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dup_ob_key,
- psys_key,
- DEPSREL_TYPE_TRANSFORM,
- "Particle Object Visualization");
- }
- }
-
- /* Particle depends on the object transform, so that channel is to be ready
- * first.
- *
- * TODO(sergey): This relation should be altered once real granular update
- * is implemented.
- */
- ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_GEOMETRY_EVAL,
- "Partcile Eval");
-
- /* pointcache */
- // TODO...
-}
-
/* IK Solver Eval Steps */
void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
bPoseChannel *pchan,
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 38f22beff8d..453cc0980d5 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -418,8 +418,7 @@ void ED_object_editmode_exit(bContext *C, int flag)
/* flag object caches as outdated */
BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
- pid->cache->flag |= PTCACHE_OUTDATED;
+ pid->cache->flag |= PTCACHE_OUTDATED;
}
BLI_freelistN(&pidlist);
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index fde955c24a7..d28f6e1f3e2 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -115,9 +115,6 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
case PTCACHE_TYPE_SOFTBODY:
if (!(stime->cache_display & TIME_CACHE_SOFTBODY)) continue;
break;
- case PTCACHE_TYPE_PARTICLES:
- if (!(stime->cache_display & TIME_CACHE_PARTICLES)) continue;
- break;
case PTCACHE_TYPE_CLOTH:
if (!(stime->cache_display & TIME_CACHE_CLOTH)) continue;
break;
@@ -179,10 +176,6 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
col[0] = 1.0; col[1] = 0.4; col[2] = 0.02;
col[3] = 0.1;
break;
- case PTCACHE_TYPE_PARTICLES:
- col[0] = 1.0; col[1] = 0.1; col[2] = 0.02;
- col[3] = 0.1;
- break;
case PTCACHE_TYPE_CLOTH:
col[0] = 0.1; col[1] = 0.1; col[2] = 0.75;
col[3] = 0.1;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index dd7d03b92a4..b0174b5cbca 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -6140,8 +6140,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* flag object caches as outdated */
BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR);
for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
- pid->cache->flag |= PTCACHE_OUTDATED;
+ pid->cache->flag |= PTCACHE_OUTDATED;
}
BLI_freelistN(&pidlist);
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index a364eef2974..8f3e1c24141 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -41,10 +41,10 @@
#include "BLI_ghash.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#ifdef _OPENMP
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 38ffdaa709b..97f4423b798 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -48,7 +48,6 @@
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
@@ -94,950 +93,10 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static void createFacepa(ExplodeModifierData *emd,
- ParticleSystemModifierData *psmd,
- DerivedMesh *dm)
-{
- ParticleSystem *psys = psmd->psys;
- MFace *fa = NULL, *mface = NULL;
- MVert *mvert = NULL;
- ParticleData *pa;
- KDTree *tree;
- RNG *rng;
- float center[3], co[3];
- int *facepa = NULL, *vertpa = NULL, totvert = 0, totface = 0, totpart = 0;
- int i, p, v1, v2, v3, v4 = 0;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
- totvert = dm->getNumVerts(dm);
- totpart = psmd->psys->totpart;
-
- rng = BLI_rng_new_srandom(psys->seed);
-
- if (emd->facepa)
- MEM_freeN(emd->facepa);
-
- facepa = emd->facepa = MEM_callocN(sizeof(int) * totface, "explode_facepa");
-
- vertpa = MEM_callocN(sizeof(int) * totvert, "explode_vertpa");
-
- /* initialize all faces & verts to no particle */
- for (i = 0; i < totface; i++)
- facepa[i] = totpart;
-
- for (i = 0; i < totvert; i++)
- vertpa[i] = totpart;
-
- /* set protected verts */
- if (emd->vgroup) {
- MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- if (dvert) {
- const int defgrp_index = emd->vgroup - 1;
- for (i = 0; i < totvert; i++, dvert++) {
- float val = BLI_rng_get_float(rng);
- val = (1.0f - emd->protect) * val + emd->protect * 0.5f;
- if (val < defvert_find_weight(dvert, defgrp_index))
- vertpa[i] = -1;
- }
- }
- }
-
- /* make tree of emitter locations */
- tree = BLI_kdtree_new(totpart);
- for (p = 0, pa = psys->particles; p < totpart; p++, pa++) {
- psys_particle_on_emitter(psmd, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, NULL, NULL, NULL, NULL, NULL);
- BLI_kdtree_insert(tree, p, co);
- }
- BLI_kdtree_balance(tree);
-
- /* set face-particle-indexes to nearest particle to face center */
- for (i = 0, fa = mface; i < totface; i++, fa++) {
- add_v3_v3v3(center, mvert[fa->v1].co, mvert[fa->v2].co);
- add_v3_v3(center, mvert[fa->v3].co);
- if (fa->v4) {
- add_v3_v3(center, mvert[fa->v4].co);
- mul_v3_fl(center, 0.25);
- }
- else
- mul_v3_fl(center, 1.0f / 3.0f);
-
- p = BLI_kdtree_find_nearest(tree, center, NULL);
-
- v1 = vertpa[fa->v1];
- v2 = vertpa[fa->v2];
- v3 = vertpa[fa->v3];
- if (fa->v4)
- v4 = vertpa[fa->v4];
-
- if (v1 >= 0 && v2 >= 0 && v3 >= 0 && (fa->v4 == 0 || v4 >= 0))
- facepa[i] = p;
-
- if (v1 >= 0) vertpa[fa->v1] = p;
- if (v2 >= 0) vertpa[fa->v2] = p;
- if (v3 >= 0) vertpa[fa->v3] = p;
- if (fa->v4 && v4 >= 0) vertpa[fa->v4] = p;
- }
-
- if (vertpa) MEM_freeN(vertpa);
- BLI_kdtree_free(tree);
-
- BLI_rng_free(rng);
-}
-
-static int edgecut_get(EdgeHash *edgehash, unsigned int v1, unsigned int v2)
-{
- return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2));
-}
-
-
-static const short add_faces[24] = {
- 0,
- 0, 0, 2, 0, 1, 2, 2, 0, 2, 1,
- 2, 2, 2, 2, 3, 0, 0, 0, 1, 0,
- 1, 1, 2
-};
-
-static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFace *mf)
-{
- MFace *df = CDDM_get_tessface(split, cur);
- DM_copy_tessface_data(dm, split, i, cur, 1);
- *df = *mf;
- return df;
-}
-
-#define SET_VERTS(a, b, c, d) \
- { \
- v[0] = mf->v##a; uv[0] = a - 1; \
- v[1] = mf->v##b; uv[1] = b - 1; \
- v[2] = mf->v##c; uv[2] = c - 1; \
- v[3] = mf->v##d; uv[3] = d - 1; \
- } (void)0
-
-#define GET_ES(v1, v2) edgecut_get(eh, v1, v2)
-#define INT_UV(uvf, c0, c1) mid_v2_v2v2(uvf, mf->uv[c0], mf->uv[c1])
-
-static void remap_faces_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = v3;
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = 0;
- df2->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v1];
- df3->v1 = v1;
- df3->v2 = v3;
- df3->v3 = v4;
- df3->v4 = 0;
- df3->flag &= ~ME_FACE_SEL;
-}
-
-static void remap_uvs_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2, *df3;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- df3 = df1 + 2;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c1, c2);
- copy_v2_v2(df1->uv[3], mf->uv[c2]);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
-
- copy_v2_v2(df3->uv[0], mf->uv[c0]);
- copy_v2_v2(df3->uv[1], mf->uv[c2]);
- copy_v2_v2(df3->uv[2], mf->uv[c3]);
- }
-}
-
-static void remap_faces_5_10(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = v2;
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = GET_ES(v1, v4);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v3];
- df2->v1 = GET_ES(v1, v4);
- df2->v2 = GET_ES(v2, v3);
- df2->v3 = v3;
- df2->v4 = v4;
- df2->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_5_10(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- copy_v2_v2(df1->uv[1], mf->uv[c1]);
- INT_UV(df1->uv[2], c1, c2);
- INT_UV(df1->uv[3], c0, c3);
-
- INT_UV(df2->uv[0], c0, c3);
- INT_UV(df2->uv[1], c1, c2);
- copy_v2_v2(df2->uv[2], mf->uv[c2]);
- copy_v2_v2(df2->uv[3], mf->uv[c3]);
-
- }
-}
-
-static void remap_faces_15(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
- MFace *df4 = get_dface(dm, split, cur + 3, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v1, v3);
- df1->v4 = GET_ES(v1, v4);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = GET_ES(v1, v3);
- df2->flag |= ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v3];
- df3->v1 = GET_ES(v1, v3);
- df3->v2 = GET_ES(v2, v3);
- df3->v3 = v3;
- df3->v4 = GET_ES(v3, v4);
- df3->flag |= ME_FACE_SEL;
-
- facepa[cur + 3] = vertpa[v4];
- df4->v1 = GET_ES(v1, v4);
- df4->v2 = GET_ES(v1, v3);
- df4->v3 = GET_ES(v3, v4);
- df4->v4 = v4;
- df4->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_15(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2, *df3, *df4;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- df3 = df1 + 2;
- df4 = df1 + 3;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c0, c2);
- INT_UV(df1->uv[3], c0, c3);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
- INT_UV(df2->uv[3], c0, c2);
-
- INT_UV(df3->uv[0], c0, c2);
- INT_UV(df3->uv[1], c1, c2);
- copy_v2_v2(df3->uv[2], mf->uv[c2]);
- INT_UV(df3->uv[3], c2, c3);
-
- INT_UV(df4->uv[0], c0, c3);
- INT_UV(df4->uv[1], c0, c2);
- INT_UV(df4->uv[2], c2, c3);
- copy_v2_v2(df4->uv[3], mf->uv[c3]);
- }
-}
-
-static void remap_faces_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = GET_ES(v1, v4);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = 0;
- df2->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v4];
- df3->v1 = GET_ES(v1, v4);
- df3->v2 = GET_ES(v2, v3);
- df3->v3 = v3;
- df3->v4 = v4;
- df3->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2, *df3;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- df3 = df1 + 2;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c1, c2);
- INT_UV(df1->uv[3], c0, c3);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
-
- INT_UV(df3->uv[0], c0, c3);
- INT_UV(df3->uv[1], c1, c2);
- copy_v2_v2(df3->uv[2], mf->uv[c2]);
- copy_v2_v2(df3->uv[3], mf->uv[c3]);
- }
-}
-
-static void remap_faces_19_21_22(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v1, v3);
- df1->v4 = 0;
- df1->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = v3;
- df2->v4 = GET_ES(v1, v3);
- df2->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_19_21_22(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
-{
- MTFace *mf, *df1, *df2;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c0, c2);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- copy_v2_v2(df2->uv[2], mf->uv[c2]);
- INT_UV(df2->uv[3], c0, c2);
- }
-}
-
-static void remap_faces_23(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = GET_ES(v1, v3);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = 0;
- df2->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v3];
- df3->v1 = GET_ES(v1, v3);
- df3->v2 = GET_ES(v2, v3);
- df3->v3 = v3;
- df3->v4 = 0;
- df3->flag &= ~ME_FACE_SEL;
-}
-
-static void remap_uvs_23(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
-{
- MTFace *mf, *df1, *df2;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c1, c2);
- INT_UV(df1->uv[3], c0, c2);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
-
- INT_UV(df2->uv[0], c0, c2);
- INT_UV(df2->uv[1], c1, c2);
- copy_v2_v2(df2->uv[2], mf->uv[c2]);
- }
-}
-
-static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
-{
- DerivedMesh *splitdm;
- MFace *mf = NULL, *df1 = NULL;
- MFace *mface = dm->getTessFaceArray(dm);
- MVert *dupve, *mv;
- EdgeHash *edgehash;
- EdgeHashIterator *ehi;
- int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumTessFaces(dm);
-
- int *facesplit = MEM_callocN(sizeof(int) * totface, "explode_facesplit");
- int *vertpa = MEM_callocN(sizeof(int) * totvert, "explode_vertpa2");
- int *facepa = emd->facepa;
- int *fs, totesplit = 0, totfsplit = 0, curdupface = 0;
- int i, v1, v2, v3, v4, esplit,
- v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */
- uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */
- int numlayer;
- unsigned int ed_v1, ed_v2;
-
- edgehash = BLI_edgehash_new(__func__);
-
- /* recreate vertpa from facepa calculation */
- for (i = 0, mf = mface; i < totface; i++, mf++) {
- vertpa[mf->v1] = facepa[i];
- vertpa[mf->v2] = facepa[i];
- vertpa[mf->v3] = facepa[i];
- if (mf->v4)
- vertpa[mf->v4] = facepa[i];
- }
-
- /* mark edges for splitting and how to split faces */
- for (i = 0, mf = mface, fs = facesplit; i < totface; i++, mf++, fs++) {
- v1 = vertpa[mf->v1];
- v2 = vertpa[mf->v2];
- v3 = vertpa[mf->v3];
-
- if (v1 != v2) {
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v2, NULL);
- (*fs) |= 1;
- }
-
- if (v2 != v3) {
- BLI_edgehash_reinsert(edgehash, mf->v2, mf->v3, NULL);
- (*fs) |= 2;
- }
-
- if (mf->v4) {
- v4 = vertpa[mf->v4];
-
- if (v3 != v4) {
- BLI_edgehash_reinsert(edgehash, mf->v3, mf->v4, NULL);
- (*fs) |= 4;
- }
-
- if (v1 != v4) {
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v4, NULL);
- (*fs) |= 8;
- }
-
- /* mark center vertex as a fake edge split */
- if (*fs == 15)
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
- }
- else {
- (*fs) |= 16; /* mark face as tri */
-
- if (v1 != v3) {
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
- (*fs) |= 4;
- }
- }
- }
-
- /* count splits & create indexes for new verts */
- ehi = BLI_edgehashIterator_new(edgehash);
- totesplit = totvert;
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit));
- totesplit++;
- }
- BLI_edgehashIterator_free(ehi);
-
- /* count new faces due to splitting */
- for (i = 0, fs = facesplit; i < totface; i++, fs++)
- totfsplit += add_faces[*fs];
-
- splitdm = CDDM_from_template_ex(
- dm, totesplit, 0, totface + totfsplit, 0, 0,
- CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
- numlayer = CustomData_number_of_layers(&splitdm->faceData, CD_MTFACE);
-
- /* copy new faces & verts (is it really this painful with custom data??) */
- for (i = 0; i < totvert; i++) {
- MVert source;
- MVert *dest;
- dm->getVert(dm, i, &source);
- dest = CDDM_get_vert(splitdm, i);
-
- DM_copy_vert_data(dm, splitdm, i, i, 1);
- *dest = source;
- }
-
- /* override original facepa (original pointer is saved in caller function) */
-
- /* BMESH_TODO, (totfsplit * 2) over allocation is used since the quads are
- * later interpreted as tri's, for this to work right I think we probably
- * have to stop using tessface - campbell */
-
- facepa = MEM_callocN(sizeof(int) * (totface + (totfsplit * 2)), "explode_facepa");
- //memcpy(facepa, emd->facepa, totface*sizeof(int));
- emd->facepa = facepa;
-
- /* create new verts */
- ehi = BLI_edgehashIterator_new(edgehash);
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
- esplit = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
- mv = CDDM_get_vert(splitdm, ed_v2);
- dupve = CDDM_get_vert(splitdm, esplit);
-
- DM_copy_vert_data(splitdm, splitdm, ed_v2, esplit, 1);
-
- *dupve = *mv;
-
- mv = CDDM_get_vert(splitdm, ed_v1);
-
- mid_v3_v3v3(dupve->co, dupve->co, mv->co);
- }
- BLI_edgehashIterator_free(ehi);
-
- /* create new faces */
- curdupface = 0; //=totface;
- //curdupin=totesplit;
- for (i = 0, fs = facesplit; i < totface; i++, fs++) {
- mf = dm->getTessFaceData(dm, i, CD_MFACE);
-
- switch (*fs) {
- case 3:
- case 10:
- case 11:
- case 15:
- SET_VERTS(1, 2, 3, 4);
- break;
- case 5:
- case 6:
- case 7:
- SET_VERTS(2, 3, 4, 1);
- break;
- case 9:
- case 13:
- SET_VERTS(4, 1, 2, 3);
- break;
- case 12:
- case 14:
- SET_VERTS(3, 4, 1, 2);
- break;
- case 21:
- case 23:
- SET_VERTS(1, 2, 3, 4);
- break;
- case 19:
- SET_VERTS(2, 3, 1, 4);
- break;
- case 22:
- SET_VERTS(3, 1, 2, 4);
- break;
- }
-
- switch (*fs) {
- case 3:
- case 6:
- case 9:
- case 12:
- remap_faces_3_6_9_12(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_3_6_9_12(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 5:
- case 10:
- remap_faces_5_10(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_5_10(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 15:
- remap_faces_15(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_15(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 7:
- case 11:
- case 13:
- case 14:
- remap_faces_7_11_13_14(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_7_11_13_14(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 19:
- case 21:
- case 22:
- remap_faces_19_21_22(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
- if (numlayer)
- remap_uvs_19_21_22(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
- break;
- case 23:
- remap_faces_23(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
- if (numlayer)
- remap_uvs_23(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
- break;
- case 0:
- case 16:
- df1 = get_dface(dm, splitdm, curdupface, i, mf);
- facepa[curdupface] = vertpa[mf->v1];
-
- if (df1->v4)
- df1->flag |= ME_FACE_SEL;
- else
- df1->flag &= ~ME_FACE_SEL;
- break;
- }
-
- curdupface += add_faces[*fs] + 1;
- }
-
- for (i = 0; i < curdupface; i++) {
- mf = CDDM_get_tessface(splitdm, i);
- test_index_face(mf, &splitdm->faceData, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3));
- }
-
- BLI_edgehash_free(edgehash, NULL);
- MEM_freeN(facesplit);
- MEM_freeN(vertpa);
-
- CDDM_calc_edges_tessface(splitdm);
- CDDM_tessfaces_to_faces(splitdm); /*builds ngon faces from tess (mface) faces*/
-
- return splitdm;
-}
-static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
- ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
- DerivedMesh *to_explode)
-{
- DerivedMesh *explode, *dm = to_explode;
- MFace *mf = NULL, *mface;
- /* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */
- ParticleSimulationData sim = {NULL};
- ParticleData *pa = NULL, *pars = psmd->psys->particles;
- ParticleKey state, birth;
- EdgeHash *vertpahash;
- EdgeHashIterator *ehi;
- float *vertco = NULL, imat[4][4];
- float rot[4];
- float cfra;
- /* float timestep; */
- const int *facepa = emd->facepa;
- int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
- int i, v, u;
- unsigned int ed_v1, ed_v2, mindex = 0;
- MTFace *mtface = NULL, *mtf;
-
- totface = dm->getNumTessFaces(dm);
- totvert = dm->getNumVerts(dm);
- mface = dm->getTessFaceArray(dm);
- totpart = psmd->psys->totpart;
-
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psmd->psys;
- sim.psmd = psmd;
-
- /* timestep = psys_get_timestep(&sim); */
-
- cfra = BKE_scene_frame_get(scene);
-
- /* hash table for vertice <-> particle relations */
- vertpahash = BLI_edgehash_new(__func__);
-
- for (i = 0; i < totface; i++) {
- if (facepa[i] != totpart) {
- pa = pars + facepa[i];
-
- if ((pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) ||
- (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) ||
- (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0))
- {
- delface++;
- continue;
- }
- }
-
- /* do mindex + totvert to ensure the vertex index to be the first
- * with BLI_edgehashIterator_getKey */
- if (facepa[i] == totpart || cfra < (pars + facepa[i])->time)
- mindex = totvert + totpart;
- else
- mindex = totvert + facepa[i];
-
- mf = &mface[i];
-
- /* set face vertices to exist in particle group */
- BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, NULL);
- BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL);
- BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL);
- if (mf->v4)
- BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, NULL);
- }
-
- /* make new vertice indexes & count total vertices after duplication */
- ehi = BLI_edgehashIterator_new(vertpahash);
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
- totdup++;
- }
- BLI_edgehashIterator_free(ehi);
-
- /* the final duplicated vertices */
- explode = CDDM_from_template_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
- mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
- /*dupvert = CDDM_get_verts(explode);*/
-
- /* getting back to object space */
- invert_m4_m4(imat, ob->obmat);
-
- psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- /* duplicate & displace vertices */
- ehi = BLI_edgehashIterator_new(vertpahash);
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- MVert source;
- MVert *dest;
-
- /* get particle + vertex from hash */
- BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
- ed_v2 -= totvert;
- v = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
-
- dm->getVert(dm, ed_v1, &source);
- dest = CDDM_get_vert(explode, v);
-
- DM_copy_vert_data(dm, explode, ed_v1, v, 1);
- *dest = source;
-
- if (ed_v2 != totpart) {
- /* get particle */
- pa = pars + ed_v2;
-
- psys_get_birth_coords(&sim, pa, &birth, 0, 0);
-
- state.time = cfra;
- psys_get_particle_state(&sim, ed_v2, &state, 1);
-
- vertco = CDDM_get_vert(explode, v)->co;
- mul_m4_v3(ob->obmat, vertco);
-
- sub_v3_v3(vertco, birth.co);
-
- /* apply rotation, size & location */
- sub_qt_qtqt(rot, state.rot, birth.rot);
- mul_qt_v3(rot, vertco);
-
- if (emd->flag & eExplodeFlag_PaSize)
- mul_v3_fl(vertco, pa->size);
-
- add_v3_v3(vertco, state.co);
-
- mul_m4_v3(imat, vertco);
- }
- }
- BLI_edgehashIterator_free(ehi);
-
- /*map new vertices to faces*/
- for (i = 0, u = 0; i < totface; i++) {
- MFace source;
- int orig_v4;
-
- if (facepa[i] != totpart) {
- pa = pars + facepa[i];
-
- if (pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) continue;
- if (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) continue;
- if (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0) continue;
- }
-
- dm->getTessFace(dm, i, &source);
- mf = CDDM_get_tessface(explode, u);
-
- orig_v4 = source.v4;
-
- if (facepa[i] != totpart && cfra < pa->time)
- mindex = totvert + totpart;
- else
- mindex = totvert + facepa[i];
-
- source.v1 = edgecut_get(vertpahash, source.v1, mindex);
- source.v2 = edgecut_get(vertpahash, source.v2, mindex);
- source.v3 = edgecut_get(vertpahash, source.v3, mindex);
- if (source.v4)
- source.v4 = edgecut_get(vertpahash, source.v4, mindex);
-
- DM_copy_tessface_data(dm, explode, i, u, 1);
-
- *mf = source;
-
- /* override uv channel for particle age */
- if (mtface) {
- float age = (cfra - pa->time) / pa->lifetime;
- /* Clamp to this range to avoid flipping to the other side of the coordinates. */
- CLAMP(age, 0.001f, 0.999f);
-
- mtf = mtface + u;
-
- mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age;
- mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f;
- }
-
- test_index_face(mf, &explode->faceData, u, (orig_v4 ? 4 : 3));
- u++;
- }
-
- /* cleanup */
- BLI_edgehash_free(vertpahash, NULL);
-
- /* finalization */
- CDDM_calc_edges_tessface(explode);
- CDDM_tessfaces_to_faces(explode);
- explode->dirty |= DM_DIRTY_NORMALS;
-
- if (psmd->psys->lattice_deform_data) {
- end_latt_deform(psmd->psys->lattice_deform_data);
- psmd->psys->lattice_deform_data = NULL;
- }
-
- return explode;
-}
-
-static ParticleSystemModifierData *findPrecedingParticlesystem(Object *ob, ModifierData *emd)
-{
- ModifierData *md;
- ParticleSystemModifierData *psmd = NULL;
-
- for (md = ob->modifiers.first; emd != md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem)
- psmd = (ParticleSystemModifierData *) md;
- }
- return psmd;
-}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
- DerivedMesh *dm = derivedData;
- ExplodeModifierData *emd = (ExplodeModifierData *) md;
- ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ob, md);
-
- DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-
- if (psmd) {
- ParticleSystem *psys = psmd->psys;
-
- if (psys == NULL || psys->totpart == 0) return derivedData;
- if (psys->part == NULL || psys->particles == NULL) return derivedData;
- if (psmd->dm_final == NULL) return derivedData;
-
- /* 1. find faces to be exploded if needed */
- if (emd->facepa == NULL ||
- psmd->flag & eParticleSystemFlag_Pars ||
- emd->flag & eExplodeFlag_CalcFaces ||
- MEM_allocN_len(emd->facepa) / sizeof(int) != dm->getNumTessFaces(dm))
- {
- if (psmd->flag & eParticleSystemFlag_Pars)
- psmd->flag &= ~eParticleSystemFlag_Pars;
-
- if (emd->flag & eExplodeFlag_CalcFaces)
- emd->flag &= ~eExplodeFlag_CalcFaces;
-
- createFacepa(emd, psmd, derivedData);
- }
- /* 2. create new mesh */
- if (emd->flag & eExplodeFlag_EdgeCut) {
- int *facepa = emd->facepa;
- DerivedMesh *splitdm = cutEdges(emd, dm);
- DerivedMesh *explode = explodeMesh(emd, psmd, md->scene, ob, splitdm);
-
- MEM_freeN(emd->facepa);
- emd->facepa = facepa;
- splitdm->release(splitdm);
- return explode;
- }
- else
- return explodeMesh(emd, psmd, md->scene, ob, derivedData);
- }
return derivedData;
}
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index d4f02d923d3..113c2cea33e 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -33,11 +33,12 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "DNA_object_types.h"
+
#include "MEM_guardedalloc.h"
#include "BKE_mesh_mapping.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_util.h"
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 4e78e758dc3..3c560ae5759 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -34,6 +34,7 @@
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -48,7 +49,6 @@
#include "BKE_lattice.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "depsgraph_private.h"
@@ -74,40 +74,9 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
-static bool isDisabled(ModifierData *md, int useRenderParams)
+static bool isDisabled(ModifierData *UNUSED(md), int UNUSED(useRenderParams))
{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
- ParticleSystem *psys;
- ModifierData *ob_md;
-
- if (!pimd->ob)
- return true;
-
- psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
- if (psys == NULL)
- return true;
-
- /* If the psys modifier is disabled we cannot use its data.
- * First look up the psys modifier from the object, then check if it is enabled.
- */
- for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) {
- if (ob_md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md;
- if (psmd->psys == psys) {
- int required_mode;
-
- if (useRenderParams) required_mode = eModifierMode_Render;
- else required_mode = eModifierMode_Realtime;
-
- if (!modifier_isEnabled(md->scene, ob_md, required_mode))
- return true;
-
- break;
- }
- }
- }
-
- return false;
+ return true;
}
@@ -148,297 +117,13 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
walk(userData, ob, &pimd->ob, IDWALK_NOP);
}
-static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
-{
- ParticleData *pa;
-
- if (pimd->flag & eParticleInstanceFlag_Parents) {
- if (p >= psys->totpart) {
- if (psys->part->childtype == PART_CHILD_PARTICLES) {
- pa = psys->particles + (psys->child + p - psys->totpart)->parent;
- }
- else {
- pa = NULL;
- }
- }
- else {
- pa = psys->particles + p;
- }
- }
- else {
- if (psys->part->childtype == PART_CHILD_PARTICLES) {
- pa = psys->particles + (psys->child + p)->parent;
- }
- else {
- pa = NULL;
- }
- }
-
- if (pa) {
- if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1;
- if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1;
- if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1;
- }
-
- return 0;
-}
-
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
- DerivedMesh *dm = derivedData, *result;
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
- ParticleSimulationData sim;
- ParticleSystem *psys = NULL;
- ParticleData *pa = NULL;
- MPoly *mpoly, *orig_mpoly;
- MLoop *mloop, *orig_mloop;
- MVert *mvert, *orig_mvert;
- int totvert, totpoly, totloop /* , totedge */;
- int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
- int k, p, p_skip;
- short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
- float max_co = 0.0, min_co = 0.0, temp_co[3];
- float *size = NULL;
-
- trackneg = ((ob->trackflag > 2) ? 1 : 0);
-
- if (pimd->ob == ob) {
- pimd->ob = NULL;
- return derivedData;
- }
-
- if (pimd->ob) {
- psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
- if (psys == NULL || psys->totpart == 0)
- return derivedData;
- }
- else {
- return derivedData;
- }
-
- if (pimd->flag & eParticleInstanceFlag_Parents)
- totpart += psys->totpart;
- if (pimd->flag & eParticleInstanceFlag_Children) {
- if (totpart == 0)
- first_particle = psys->totpart;
- totpart += psys->totchild;
- }
-
- if (totpart == 0)
- return derivedData;
-
- sim.scene = md->scene;
- sim.ob = pimd->ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(pimd->ob, psys);
-
- if (pimd->flag & eParticleInstanceFlag_UseSize) {
- float *si;
- si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
-
- if (pimd->flag & eParticleInstanceFlag_Parents) {
- for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
- *si = pa->size;
- }
-
- if (pimd->flag & eParticleInstanceFlag_Children) {
- ChildParticle *cpa = psys->child;
-
- for (p = 0; p < psys->totchild; p++, cpa++, si++) {
- *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
- }
- }
- }
-
- totvert = dm->getNumVerts(dm);
- totpoly = dm->getNumPolys(dm);
- totloop = dm->getNumLoops(dm);
- /* totedge = dm->getNumEdges(dm); */ /* UNUSED */
-
- /* count particles */
- maxvert = 0;
- maxpoly = 0;
- maxloop = 0;
-
- for (p = 0; p < totpart; p++) {
- if (particle_skip(pimd, psys, p))
- continue;
-
- maxvert += totvert;
- maxpoly += totpoly;
- maxloop += totloop;
- }
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
- float min[3], max[3];
- INIT_MINMAX(min, max);
- dm->getMinMax(dm, min, max);
- min_co = min[track];
- max_co = max[track];
- }
-
- result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);
-
- mvert = result->getVertArray(result);
- orig_mvert = dm->getVertArray(dm);
-
- mpoly = result->getPolyArray(result);
- orig_mpoly = dm->getPolyArray(dm);
- mloop = result->getLoopArray(result);
- orig_mloop = dm->getLoopArray(dm);
-
- for (p = 0, p_skip = 0; p < totpart; p++) {
- float prev_dir[3];
- float frame[4]; /* frame orientation quaternion */
-
- /* skip particle? */
- if (particle_skip(pimd, psys, p))
- continue;
-
- /* set vertices coordinates */
- for (k = 0; k < totvert; k++) {
- ParticleKey state;
- MVert *inMV;
- MVert *mv = mvert + p_skip * totvert + k;
-
- inMV = orig_mvert + k;
- DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
- *mv = *inMV;
-
- /*change orientation based on object trackflag*/
- copy_v3_v3(temp_co, mv->co);
- mv->co[axis] = temp_co[track];
- mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
- mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
-
- /* get particle state */
- if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
- (pimd->flag & eParticleInstanceFlag_Path))
- {
- float ran = 0.0f;
- if (pimd->random_position != 0.0f) {
- ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
- }
-
- if (pimd->flag & eParticleInstanceFlag_KeepShape) {
- state.time = pimd->position * (1.0f - ran);
- }
- else {
- state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
-
- if (trackneg)
- state.time = 1.0f - state.time;
-
- mv->co[axis] = 0.0;
- }
-
- psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
-
- normalize_v3(state.vel);
-
- /* Incrementally Rotating Frame (Bishop Frame) */
- if (k == 0) {
- float hairmat[4][4];
- float mat[3][3];
-
- if (first_particle + p < psys->totpart)
- pa = psys->particles + first_particle + p;
- else {
- ChildParticle *cpa = psys->child + (p - psys->totpart);
- pa = psys->particles + cpa->parent;
- }
- psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat);
- copy_m3_m4(mat, hairmat);
- /* to quaternion */
- mat3_to_quat(frame, mat);
-
- /* note: direction is same as normal vector currently,
- * but best to keep this separate so the frame can be
- * rotated later if necessary
- */
- copy_v3_v3(prev_dir, state.vel);
- }
- else {
- float rot[4];
-
- /* incrementally rotate along bend direction */
- rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
- mul_qt_qtqt(frame, rot, frame);
-
- copy_v3_v3(prev_dir, state.vel);
- }
-
- copy_qt_qt(state.rot, frame);
-#if 0
- /* Absolute Frame (Frenet Frame) */
- if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
- unit_qt(state.rot);
- }
- else {
- float cross[3];
- float temp[3] = {0.0f, 0.0f, 0.0f};
- temp[axis] = 1.0f;
-
- cross_v3_v3v3(cross, temp, state.vel);
-
- /* state.vel[axis] is the only component surviving from a dot product with the axis */
- axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
- }
-#endif
- }
- else {
- state.time = -1.0;
- psys_get_particle_state(&sim, first_particle + p, &state, 1);
- }
-
- mul_qt_v3(state.rot, mv->co);
- if (pimd->flag & eParticleInstanceFlag_UseSize)
- mul_v3_fl(mv->co, size[p]);
- add_v3_v3(mv->co, state.co);
- }
-
- /* create polys and loops */
- for (k = 0; k < totpoly; k++) {
- MPoly *inMP = orig_mpoly + k;
- MPoly *mp = mpoly + p_skip * totpoly + k;
-
- DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
- *mp = *inMP;
- mp->loopstart += p_skip * totloop;
-
- {
- MLoop *inML = orig_mloop + inMP->loopstart;
- MLoop *ml = mloop + mp->loopstart;
- int j = mp->totloop;
-
- DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
- for (; j; j--, ml++, inML++) {
- ml->v = inML->v + (p_skip * totvert);
- }
- }
- }
-
- p_skip++;
- }
-
- CDDM_calc_edges(result);
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (size)
- MEM_freeN(size);
-
- result->dirty |= DM_DIRTY_NORMALS;
-
- return result;
+ return derivedData;
}
+
ModifierTypeInfo modifierType_ParticleInstance = {
/* name */ "ParticleInstance",
/* structName */ "ParticleInstanceModifierData",
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 4791e41d433..b61eea6d238 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -37,13 +37,13 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "MOD_util.h"
@@ -70,11 +70,6 @@ static void freeData(ModifierData *md)
psmd->dm_deformed = NULL;
}
}
-
- /* ED_object_modifier_remove may have freed this first before calling
- * modifier_free (which calls this function) */
- if (psmd->psys)
- psmd->psys->flag |= PSYS_DELETE;
}
static void copyData(ModifierData *md, ModifierData *target)
{
@@ -90,105 +85,20 @@ static void copyData(ModifierData *md, ModifierData *target)
tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
}
-static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
{
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- return psys_emitter_customdata_mask(psmd->psys);
+ return 0;
}
/* saves the current emitter state for a particle system and calculates particles */
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *UNUSED(md), Object *UNUSED(ob),
+ DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3],
int UNUSED(numVerts),
ModifierApplyFlag UNUSED(flag))
{
- DerivedMesh *dm = derivedData;
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- ParticleSystem *psys = NULL;
- bool needsFree = false;
- /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */
-
- if (ob->particlesystem.first)
- psys = psmd->psys;
- else
- return;
-
- if (!psys_check_enabled(ob, psys))
- return;
-
- if (dm == NULL) {
- dm = get_dm(ob, NULL, NULL, vertexCos, false, true);
-
- if (!dm)
- return;
-
- needsFree = true;
- }
-
- /* clear old dm */
- if (psmd->dm_final) {
- psmd->dm_final->needsFree = true;
- psmd->dm_final->release(psmd->dm_final);
- if (psmd->dm_deformed) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
- }
- else if (psmd->flag & eParticleSystemFlag_file_loaded) {
- /* in file read dm just wasn't saved in file so no need to reset everything */
- psmd->flag &= ~eParticleSystemFlag_file_loaded;
- }
- else {
- /* no dm before, so recalc particles fully */
- psys->recalc |= PSYS_RECALC_RESET;
- }
-
- /* make new dm */
- psmd->dm_final = CDDM_copy(dm);
- CDDM_apply_vert_coords(psmd->dm_final, vertexCos);
- CDDM_calc_normals(psmd->dm_final);
-
- if (needsFree) {
- dm->needsFree = true;
- dm->release(dm);
- }
-
- /* protect dm */
- psmd->dm_final->needsFree = false;
-
- DM_ensure_tessface(psmd->dm_final);
-
- if (!psmd->dm_final->deformedOnly) {
- /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set.
- * This is awfully weak though. :| */
- if (ob->derivedDeform) {
- psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
- }
- else { /* Can happen in some cases, e.g. when rendering from Edit mode... */
- psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
- }
- DM_ensure_tessface(psmd->dm_deformed);
- }
-
- /* report change in mesh structure */
- if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
- psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
- psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
- {
- psys->recalc |= PSYS_RECALC_RESET;
-
- psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
- psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
- psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
- }
-
- if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(md->scene, ob, psys);
- psmd->flag |= eParticleSystemFlag_psys_updated;
- }
+ UNUSED_VARS(vertexCos);
+ return;
}
/* disabled particles in editmode for now, until support for proper derivedmesh
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index a543aac74b9..a4d46527cd2 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -35,12 +35,12 @@
#include "BLI_math.h"
#include "DNA_key_types.h"
+#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_key.h"
-#include "BKE_particle.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index d45c8528510..66c9f613447 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -34,6 +34,7 @@
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -41,7 +42,6 @@
#include "MEM_guardedalloc.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index d958badc33c..fa458cd20dc 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -34,12 +34,12 @@
#include <stdio.h>
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 527576843e3..f70c29e793f 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -32,6 +32,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -42,7 +43,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
-#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index ccf54cb6bcd..f4a379d49d5 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -79,7 +79,6 @@
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "PIL_time.h"
@@ -744,1148 +743,6 @@ static Material *give_render_material(Render *re, Object *ob, short nr)
}
/* ------------------------------------------------------------------------- */
-/* Particles */
-/* ------------------------------------------------------------------------- */
-typedef struct ParticleStrandData {
- struct MCol *mcol;
- float *orco, *uvco, *surfnor;
- float time, adapt_angle, adapt_pix, size;
- int totuv, totcol;
- int first, line, adapt, override_uv;
-}
-ParticleStrandData;
-/* future thread problem... */
-static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, ParticleStrandData *sd, const float vec[3], const float vec1[3])
-{
- static VertRen *v1= NULL, *v2= NULL;
- VlakRen *vlr= NULL;
- float nor[3], cross[3], crosslen, w, dx, dy, width;
- static float anor[3], avec[3];
- int flag, i;
- static int second=0;
-
- sub_v3_v3v3(nor, vec, vec1);
- normalize_v3(nor); /* nor needed as tangent */
- cross_v3_v3v3(cross, vec, nor);
-
- /* turn cross in pixelsize */
- w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
- dx= re->winx*cross[0]*re->winmat[0][0];
- dy= re->winy*cross[1]*re->winmat[1][1];
- w = sqrtf(dx * dx + dy * dy) / w;
-
- if (w!=0.0f) {
- float fac;
- if (ma->strand_ease!=0.0f) {
- if (ma->strand_ease<0.0f)
- fac= pow(sd->time, 1.0f+ma->strand_ease);
- else
- fac= pow(sd->time, 1.0f/(1.0f-ma->strand_ease));
- }
- else fac= sd->time;
-
- width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end);
-
- /* use actual Blender units for strand width and fall back to minimum width */
- if (ma->mode & MA_STR_B_UNITS) {
- crosslen= len_v3(cross);
- w= 2.0f*crosslen*ma->strand_min/w;
-
- if (width < w)
- width= w;
-
- /*cross is the radius of the strand so we want it to be half of full width */
- mul_v3_fl(cross, 0.5f/crosslen);
- }
- else
- width/=w;
-
- mul_v3_fl(cross, width);
- }
-
- if (ma->mode & MA_TANGENT_STR)
- flag= R_SMOOTH|R_TANGENT;
- else
- flag= R_SMOOTH;
-
- /* only 1 pixel wide strands filled in as quads now, otherwise zbuf errors */
- if (ma->strand_sta==1.0f)
- flag |= R_STRAND;
-
- /* single face line */
- if (sd->line) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->flag= flag;
- vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- copy_v3_v3(vlr->v1->co, vec);
- add_v3_v3(vlr->v1->co, cross);
- copy_v3_v3(vlr->v1->n, nor);
- vlr->v1->orco= sd->orco;
- vlr->v1->accum = -1.0f; /* accum abuse for strand texco */
-
- copy_v3_v3(vlr->v2->co, vec);
- sub_v3_v3v3(vlr->v2->co, vlr->v2->co, cross);
- copy_v3_v3(vlr->v2->n, nor);
- vlr->v2->orco= sd->orco;
- vlr->v2->accum= vlr->v1->accum;
-
- copy_v3_v3(vlr->v4->co, vec1);
- add_v3_v3(vlr->v4->co, cross);
- copy_v3_v3(vlr->v4->n, nor);
- vlr->v4->orco= sd->orco;
- vlr->v4->accum = 1.0f; /* accum abuse for strand texco */
-
- copy_v3_v3(vlr->v3->co, vec1);
- sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross);
- copy_v3_v3(vlr->v3->n, nor);
- vlr->v3->orco= sd->orco;
- vlr->v3->accum= vlr->v4->accum;
-
- normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
-
- vlr->mat= ma;
- vlr->ec= ME_V2V3;
-
- if (sd->surfnor) {
- float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
- copy_v3_v3(snor, sd->surfnor);
- }
-
- if (sd->uvco) {
- for (i=0; i<sd->totuv; i++) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1);
- mtf->uv[0][0]=mtf->uv[1][0]=
- mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
- mtf->uv[0][1]=mtf->uv[1][1]=
- mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
- }
- if (sd->override_uv>=0) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0);
-
- mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
- mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
-
- mtf->uv[0][1]=mtf->uv[1][1]=0.0f;
- mtf->uv[2][1]=mtf->uv[3][1]=1.0f;
- }
- }
- if (sd->mcol) {
- for (i=0; i<sd->totcol; i++) {
- MCol *mc;
- mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1);
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- }
- }
- }
- /* first two vertices of a strand */
- else if (sd->first) {
- if (sd->adapt) {
- copy_v3_v3(anor, nor);
- copy_v3_v3(avec, vec);
- second=1;
- }
-
- v1= RE_findOrAddVert(obr, obr->totvert++);
- v2= RE_findOrAddVert(obr, obr->totvert++);
-
- copy_v3_v3(v1->co, vec);
- add_v3_v3(v1->co, cross);
- copy_v3_v3(v1->n, nor);
- v1->orco= sd->orco;
- v1->accum = -1.0f; /* accum abuse for strand texco */
-
- copy_v3_v3(v2->co, vec);
- sub_v3_v3v3(v2->co, v2->co, cross);
- copy_v3_v3(v2->n, nor);
- v2->orco= sd->orco;
- v2->accum= v1->accum;
- }
- /* more vertices & faces to strand */
- else {
- if (sd->adapt==0 || second) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->flag= flag;
- vlr->v1= v1;
- vlr->v2= v2;
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- v1= vlr->v4; /* cycle */
- v2= vlr->v3; /* cycle */
-
-
- if (sd->adapt) {
- second=0;
- copy_v3_v3(anor, nor);
- copy_v3_v3(avec, vec);
- }
-
- }
- else if (sd->adapt) {
- float dvec[3], pvec[3];
- sub_v3_v3v3(dvec, avec, vec);
- project_v3_v3v3(pvec, dvec, vec);
- sub_v3_v3v3(dvec, dvec, pvec);
-
- w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
- dx= re->winx*dvec[0]*re->winmat[0][0]/w;
- dy= re->winy*dvec[1]*re->winmat[1][1]/w;
- w = sqrtf(dx * dx + dy * dy);
- if (dot_v3v3(anor, nor)<sd->adapt_angle && w>sd->adapt_pix) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->flag= flag;
- vlr->v1= v1;
- vlr->v2= v2;
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- v1= vlr->v4; /* cycle */
- v2= vlr->v3; /* cycle */
-
- copy_v3_v3(anor, nor);
- copy_v3_v3(avec, vec);
- }
- else {
- vlr= RE_findOrAddVlak(obr, obr->totvlak-1);
- }
- }
-
- copy_v3_v3(vlr->v4->co, vec);
- add_v3_v3(vlr->v4->co, cross);
- copy_v3_v3(vlr->v4->n, nor);
- vlr->v4->orco= sd->orco;
- vlr->v4->accum= -1.0f + 2.0f * sd->time; /* accum abuse for strand texco */
-
- copy_v3_v3(vlr->v3->co, vec);
- sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross);
- copy_v3_v3(vlr->v3->n, nor);
- vlr->v3->orco= sd->orco;
- vlr->v3->accum= vlr->v4->accum;
-
- normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
-
- vlr->mat= ma;
- vlr->ec= ME_V2V3;
-
- if (sd->surfnor) {
- float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
- copy_v3_v3(snor, sd->surfnor);
- }
-
- if (sd->uvco) {
- for (i=0; i<sd->totuv; i++) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1);
- mtf->uv[0][0]=mtf->uv[1][0]=
- mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
- mtf->uv[0][1]=mtf->uv[1][1]=
- mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
- }
- if (sd->override_uv>=0) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0);
-
- mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
- mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
-
- mtf->uv[0][1]=mtf->uv[1][1]=(vlr->v1->accum+1.0f)/2.0f;
- mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f;
- }
- }
- if (sd->mcol) {
- for (i=0; i<sd->totcol; i++) {
- MCol *mc;
- mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1);
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- }
- }
- }
-}
-
-static void static_particle_wire(ObjectRen *obr, Material *ma, const float vec[3], const float vec1[3], int first, int line)
-{
- VlakRen *vlr;
- static VertRen *v1;
-
- if (line) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= vlr->v2;
- vlr->v4= NULL;
-
- copy_v3_v3(vlr->v1->co, vec);
- copy_v3_v3(vlr->v2->co, vec1);
-
- sub_v3_v3v3(vlr->n, vec, vec1);
- normalize_v3(vlr->n);
- copy_v3_v3(vlr->v1->n, vlr->n);
- copy_v3_v3(vlr->v2->n, vlr->n);
-
- vlr->mat= ma;
- vlr->ec= ME_V1V2;
-
- }
- else if (first) {
- v1= RE_findOrAddVert(obr, obr->totvert++);
- copy_v3_v3(v1->co, vec);
- }
- else {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->v1= v1;
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= vlr->v2;
- vlr->v4= NULL;
-
- v1= vlr->v2; /* cycle */
- copy_v3_v3(v1->co, vec);
-
- sub_v3_v3v3(vlr->n, vec, vec1);
- normalize_v3(vlr->n);
- copy_v3_v3(v1->n, vlr->n);
-
- vlr->mat= ma;
- vlr->ec= ME_V1V2;
- }
-
-}
-
-static void particle_curve(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd,
- const float loc[3], const float loc1[3], int seed, float *pa_co)
-{
- HaloRen *har = NULL;
-
- if (ma->material_type == MA_TYPE_WIRE)
- static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line);
- else if (ma->material_type == MA_TYPE_HALO) {
- har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed, pa_co);
- if (har) har->lay= obr->ob->lay;
- }
- else
- static_particle_strand(re, obr, ma, sd, loc, loc1);
-}
-static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb)
-{
- VlakRen *vlr;
- MTFace *mtf;
- float xvec[3], yvec[3], zvec[3], bb_center[3];
- /* Number of tiles */
- int totsplit = bb->uv_split * bb->uv_split;
- int tile, x, y;
- /* Tile offsets */
- float uvx = 0.0f, uvy = 0.0f, uvdx = 1.0f, uvdy = 1.0f, time = 0.0f;
-
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
-
- add_v3_v3v3(vlr->v1->co, bb_center, xvec);
- add_v3_v3(vlr->v1->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v1->co);
-
- sub_v3_v3v3(vlr->v2->co, bb_center, xvec);
- add_v3_v3(vlr->v2->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v2->co);
-
- sub_v3_v3v3(vlr->v3->co, bb_center, xvec);
- sub_v3_v3v3(vlr->v3->co, vlr->v3->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v3->co);
-
- add_v3_v3v3(vlr->v4->co, bb_center, xvec);
- sub_v3_v3(vlr->v4->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v4->co);
-
- normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
- copy_v3_v3(vlr->v1->n, vlr->n);
- copy_v3_v3(vlr->v2->n, vlr->n);
- copy_v3_v3(vlr->v3->n, vlr->n);
- copy_v3_v3(vlr->v4->n, vlr->n);
-
- vlr->mat= ma;
- vlr->ec= ME_V2V3;
-
- if (bb->uv_split > 1) {
- uvdx = uvdy = 1.0f / (float)bb->uv_split;
-
- if (ELEM(bb->anim, PART_BB_ANIM_AGE, PART_BB_ANIM_FRAME)) {
- if (bb->anim == PART_BB_ANIM_FRAME)
- time = ((int)(bb->time * bb->lifetime) % totsplit)/(float)totsplit;
- else
- time = bb->time;
- }
- else if (bb->anim == PART_BB_ANIM_ANGLE) {
- if (bb->align == PART_BB_VIEW) {
- time = (float)fmod((bb->tilt + 1.0f) / 2.0f, 1.0);
- }
- else {
- float axis1[3] = {0.0f, 0.0f, 0.0f};
- float axis2[3] = {0.0f, 0.0f, 0.0f};
-
- axis1[(bb->align + 1) % 3] = 1.0f;
- axis2[(bb->align + 2) % 3] = 1.0f;
-
- if (bb->lock == 0) {
- zvec[bb->align] = 0.0f;
- normalize_v3(zvec);
- }
-
- time = saacos(dot_v3v3(zvec, axis1)) / (float)M_PI;
-
- if (dot_v3v3(zvec, axis2) < 0.0f)
- time = 1.0f - time / 2.0f;
- else
- time /= 2.0f;
- }
- }
-
- if (bb->split_offset == PART_BB_OFF_LINEAR)
- time = (float)fmod(time + (float)bb->num / (float)totsplit, 1.0f);
- else if (bb->split_offset==PART_BB_OFF_RANDOM)
- time = (float)fmod(time + bb->random, 1.0f);
-
- /* Find the coordinates in tile space (integer), then convert to UV
- * space (float). Note that Y is flipped. */
- tile = (int)((time + FLT_EPSILON10) * totsplit);
- x = tile % bb->uv_split;
- y = tile / bb->uv_split;
- y = (bb->uv_split - 1) - y;
- uvx = uvdx * x;
- uvy = uvdy * y;
- }
-
- /* normal UVs */
- if (bb->uv[0] >= 0) {
- mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[0], NULL, 1);
- mtf->uv[0][0] = 1.0f;
- mtf->uv[0][1] = 1.0f;
- mtf->uv[1][0] = 0.0f;
- mtf->uv[1][1] = 1.0f;
- mtf->uv[2][0] = 0.0f;
- mtf->uv[2][1] = 0.0f;
- mtf->uv[3][0] = 1.0f;
- mtf->uv[3][1] = 0.0f;
- }
-
- /* time-index UVs */
- if (bb->uv[1] >= 0) {
- mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[1], NULL, 1);
- mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = bb->time;
- mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = (float)bb->num/(float)bb->totnum;
- }
-
- /* split UVs */
- if (bb->uv_split > 1 && bb->uv[2] >= 0) {
- mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[2], NULL, 1);
- mtf->uv[0][0] = uvx + uvdx;
- mtf->uv[0][1] = uvy + uvdy;
- mtf->uv[1][0] = uvx;
- mtf->uv[1][1] = uvy + uvdy;
- mtf->uv[2][0] = uvx;
- mtf->uv[2][1] = uvy;
- mtf->uv[3][0] = uvx + uvdx;
- mtf->uv[3][1] = uvy;
- }
-}
-static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, ParticleBillboardData *bb, ParticleKey *state, int seed, float hasize, float *pa_co)
-{
- float loc[3], loc0[3], loc1[3], vel[3];
-
- copy_v3_v3(loc, state->co);
-
- if (ren_as != PART_DRAW_BB)
- mul_m4_v3(re->viewmat, loc);
-
- switch (ren_as) {
- case PART_DRAW_LINE:
- sd->line = 1;
- sd->time = 0.0f;
- sd->size = hasize;
-
- mul_v3_mat3_m4v3(vel, re->viewmat, state->vel);
- normalize_v3(vel);
-
- if (part->draw & PART_DRAW_VEL_LENGTH)
- mul_v3_fl(vel, len_v3(state->vel));
-
- madd_v3_v3v3fl(loc0, loc, vel, -part->draw_line[0]);
- madd_v3_v3v3fl(loc1, loc, vel, part->draw_line[1]);
-
- particle_curve(re, obr, dm, ma, sd, loc0, loc1, seed, pa_co);
-
- break;
-
- case PART_DRAW_BB:
-
- copy_v3_v3(bb->vec, loc);
- copy_v3_v3(bb->vel, state->vel);
-
- particle_billboard(re, obr, ma, bb);
-
- break;
-
- default:
- {
- HaloRen *har = NULL;
-
- har = RE_inithalo_particle(re, obr, dm, ma, loc, NULL, sd->orco, sd->uvco, hasize, 0.0, seed, pa_co);
-
- if (har) har->lay= obr->ob->lay;
-
- break;
- }
- }
-}
-static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd)
-{
- int i;
-
- /* get uvco */
- if (sd->uvco && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- for (i=0; i<sd->totuv; i++) {
- if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
- MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
- MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
- mtface += num;
-
- psys_interpolate_uvs(mtface, mface->v4, fuv, sd->uvco + 2 * i);
- }
- else {
- sd->uvco[2*i] = 0.0f;
- sd->uvco[2*i + 1] = 0.0f;
- }
- }
- }
-
- /* get mcol */
- if (sd->mcol && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- for (i=0; i<sd->totcol; i++) {
- if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
- MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
- MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
- mc += num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, fuv, sd->mcol + i);
- }
- else
- memset(&sd->mcol[i], 0, sizeof(MCol));
- }
- }
-}
-static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset)
-{
- Object *ob= obr->ob;
-// Object *tob=0;
- Material *ma = NULL;
- ParticleSystemModifierData *psmd;
- ParticleSystem *tpsys = NULL;
- ParticleSettings *part, *tpart = NULL;
- ParticleData *pars, *pa = NULL, *tpa = NULL;
- ParticleKey *states = NULL;
- ParticleKey state;
- ParticleCacheKey *cache = NULL;
- ParticleBillboardData bb;
- ParticleSimulationData sim = {NULL};
- ParticleStrandData sd;
- StrandBuffer *strandbuf = NULL;
- StrandVert *svert = NULL;
- StrandBound *sbound = NULL;
- StrandRen *strand = NULL;
- RNG *rng = NULL;
- float loc[3], loc1[3], loc0[3], mat[4][4], nmat[3][3], co[3], nor[3], duplimat[4][4];
- float strandlen=0.0f, curlen=0.0f;
- float hasize, pa_size, r_tilt, r_length;
- float pa_time, pa_birthtime, pa_dietime;
- float random, simplify[2], pa_co[3];
- const float cfra= BKE_scene_frame_get(re->scene);
- int i, a, k, max_k=0, totpart;
- bool do_simplify = false, do_surfacecache = false, use_duplimat = false;
- int totchild=0, step_nbr;
- int seed, path_nbr=0, orco1=0, num;
- int totface;
-
- const int *index_mf_to_mpoly = NULL;
- const int *index_mp_to_orig = NULL;
-
-/* 1. check that everything is ok & updated */
- if (psys==NULL)
- return 0;
-
- part=psys->part;
- pars=psys->particles;
-
- if (part==NULL || pars==NULL || !psys_check_enabled(ob, psys))
- return 0;
-
- if (part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT)
- return 1;
-
- if ((re->r.scemode & R_VIEWPORT_PREVIEW) && (ob->mode & OB_MODE_PARTICLE_EDIT))
- return 0;
-
- if (part->ren_as == PART_DRAW_BB && part->bb_ob == NULL && RE_GetCamera(re) == NULL)
- return 0;
-
-/* 2. start initializing things */
-
- /* last possibility to bail out! */
- psmd = psys_get_modifier(ob, psys);
- if (!(psmd->modifier.mode & eModifierMode_Render))
- return 0;
-
- sim.scene= re->scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psmd;
-
- if (part->phystype==PART_PHYS_KEYED)
- psys_count_keyed_targets(&sim);
-
- totchild=psys->totchild;
-
- /* can happen for disconnected/global hair */
- if (part->type==PART_HAIR && !psys->childcache)
- totchild= 0;
-
- if (re->r.scemode & R_VIEWPORT_PREVIEW) { /* preview render */
- totchild = (int)((float)totchild * (float)part->disp / 100.0f);
- step_nbr = 1 << part->draw_step;
- }
- else {
- step_nbr = 1 << part->ren_step;
- }
- if (ELEM(part->kink, PART_KINK_SPIRAL))
- step_nbr += part->kink_extra_steps;
-
- psys->flag |= PSYS_DRAWING;
-
- rng= BLI_rng_new(psys->seed);
-
- totpart=psys->totpart;
-
- memset(&sd, 0, sizeof(ParticleStrandData));
- sd.override_uv = -1;
-
-/* 2.1 setup material stff */
- ma= give_render_material(re, ob, part->omat);
-
-#if 0 /* XXX old animation system */
- if (ma->ipo) {
- calc_ipo(ma->ipo, cfra);
- execute_ipo((ID *)ma, ma->ipo);
- }
-#endif /* XXX old animation system */
-
- hasize = ma->hasize;
- seed = ma->seed1;
-
- re->flag |= R_HALO;
-
- RE_set_customdata_names(obr, &psmd->dm_final->faceData);
- sd.totuv = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MTFACE);
- sd.totcol = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MCOL);
-
- if (ma->texco & TEXCO_UV && sd.totuv) {
- sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
-
- if (ma->strand_uvname[0]) {
- sd.override_uv = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, ma->strand_uvname);
- sd.override_uv -= CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
- }
- }
- else
- sd.uvco = NULL;
-
- if (sd.totcol)
- sd.mcol = MEM_callocN(sd.totcol * sizeof(MCol), "particle_mcols");
-
-/* 2.2 setup billboards */
- if (part->ren_as == PART_DRAW_BB) {
- int first_uv = CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
-
- bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[0]);
- if (bb.uv[0] < 0)
- bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
-
- bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[1]);
-
- bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[2]);
-
- if (first_uv >= 0) {
- bb.uv[0] -= first_uv;
- bb.uv[1] -= first_uv;
- bb.uv[2] -= first_uv;
- }
-
- bb.align = part->bb_align;
- bb.anim = part->bb_anim;
- bb.lock = part->draw & PART_DRAW_BB_LOCK;
- bb.ob = (part->bb_ob ? part->bb_ob : RE_GetCamera(re));
- bb.split_offset = part->bb_split_offset;
- bb.totnum = totpart+totchild;
- bb.uv_split = part->bb_uv_split;
- }
-
-/* 2.5 setup matrices */
- mul_m4_m4m4(mat, re->viewmat, ob->obmat);
- invert_m4_m4(ob->imat, mat); /* need to be that way, for imat texture */
- transpose_m3_m4(nmat, ob->imat);
-
- if (psys->flag & PSYS_USE_IMAT) {
- /* psys->imat is the original emitter's inverse matrix, ob->obmat is the duplicated object's matrix */
- mul_m4_m4m4(duplimat, ob->obmat, psys->imat);
- use_duplimat = true;
- }
-
-/* 2.6 setup strand rendering */
- if (part->ren_as == PART_DRAW_PATH && psys->pathcache) {
- path_nbr = step_nbr;
-
- if (path_nbr) {
- if (!ELEM(ma->material_type, MA_TYPE_HALO, MA_TYPE_WIRE)) {
- sd.orco = get_object_orco(re, psys);
- if (!sd.orco) {
- sd.orco = MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
- set_object_orco(re, psys, sd.orco);
- }
- }
- }
-
- if (part->draw & PART_DRAW_REN_ADAPT) {
- sd.adapt = 1;
- sd.adapt_pix = (float)part->adapt_pix;
- sd.adapt_angle = cosf(DEG2RADF((float)part->adapt_angle));
- }
-
- if (part->draw & PART_DRAW_REN_STRAND) {
- strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
- strandbuf->ma= ma;
- strandbuf->lay= ob->lay;
- copy_m4_m4(strandbuf->winmat, re->winmat);
- strandbuf->winx= re->winx;
- strandbuf->winy= re->winy;
- strandbuf->maxdepth= 2;
- strandbuf->adaptcos= cosf(DEG2RADF((float)part->adapt_angle));
- strandbuf->overrideuv= sd.override_uv;
- strandbuf->minwidth= ma->strand_min;
-
- if (ma->strand_widthfade == 0.0f)
- strandbuf->widthfade= -1.0f;
- else if (ma->strand_widthfade >= 1.0f)
- strandbuf->widthfade= 2.0f - ma->strand_widthfade;
- else
- strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f);
-
- if (part->flag & PART_HAIR_BSPLINE)
- strandbuf->flag |= R_STRAND_BSPLINE;
- if (ma->mode & MA_STR_B_UNITS)
- strandbuf->flag |= R_STRAND_B_UNITS;
-
- svert= strandbuf->vert;
-
- if (re->r.mode & R_SPEED)
- do_surfacecache = true;
- else if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
- if (ma->amb != 0.0f)
- do_surfacecache = true;
-
- totface= psmd->dm_final->getNumTessFaces(psmd->dm_final);
- index_mf_to_mpoly = psmd->dm_final->getTessFaceDataArray(psmd->dm_final, CD_ORIGINDEX);
- index_mp_to_orig = psmd->dm_final->getPolyDataArray(psmd->dm_final, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
- for (a=0; a<totface; a++)
- strandbuf->totbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a);
-
- strandbuf->totbound++;
- strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound");
- sbound= strandbuf->bound;
- sbound->start= sbound->end= 0;
- }
- }
-
- if (sd.orco == NULL) {
- sd.orco = MEM_mallocN(3 * sizeof(float), "particle orco");
- orco1 = 1;
- }
-
- if (path_nbr == 0)
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
-/* 3. start creating renderable things */
- for (a=0, pa=pars; a<totpart+totchild; a++, pa++, seed++) {
- random = BLI_rng_get_float(rng);
- /* setup per particle individual stuff */
- if (a<totpart) {
- if (pa->flag & PARS_UNEXIST) continue;
-
- pa_time=(cfra-pa->time)/pa->lifetime;
- pa_birthtime = pa->time;
- pa_dietime = pa->dietime;
-
- hasize = ma->hasize;
-
- /* XXX 'tpsys' is alwyas NULL, this code won't run! */
- /* get orco */
- if (tpsys && part->phystype == PART_PHYS_NO) {
- tpa = tpsys->particles + pa->num;
- psys_particle_on_emitter(
- psmd,
- tpart->from, tpa->num, pa->num_dmcache, tpa->fuv,
- tpa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
- else {
- psys_particle_on_emitter(
- psmd,
- part->from, pa->num, pa->num_dmcache,
- pa->fuv, pa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
-
- /* get uvco & mcol */
- num= pa->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- if (pa->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
- num= pa->num;
-
- get_particle_uvco_mcol(part->from, psmd->dm_final, pa->fuv, num, &sd);
-
- pa_size = pa->size;
-
- r_tilt = 2.0f*(psys_frand(psys, a) - 0.5f);
- r_length = psys_frand(psys, a+1);
-
- if (path_nbr) {
- cache = psys->pathcache[a];
- max_k = (int)cache->segments;
- }
-
- if (totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
- }
- else {
- ChildParticle *cpa= psys->child+a-totpart;
-
- if (path_nbr) {
- cache = psys->childcache[a-totpart];
-
- if (cache->segments < 0)
- continue;
-
- max_k = (int)cache->segments;
- }
-
- pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
- pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time);
-
- r_tilt = 2.0f*(psys_frand(psys, a + 21) - 0.5f);
- r_length = psys_frand(psys, a + 22);
-
- num = cpa->num;
-
- /* get orco */
- if (part->childtype == PART_CHILD_FACES) {
- psys_particle_on_emitter(
- psmd,
- PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD,
- cpa->fuv, cpa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
- else {
- ParticleData *par = psys->particles + cpa->parent;
- psys_particle_on_emitter(
- psmd,
- part->from, par->num, DMCACHE_ISCHILD, par->fuv,
- par->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
-
- /* get uvco & mcol */
- if (part->childtype==PART_CHILD_FACES) {
- get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm_final, cpa->fuv, cpa->num, &sd);
- }
- else {
- ParticleData *parent = psys->particles + cpa->parent;
- num = parent->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- if (parent->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
- num = parent->num;
-
- get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd);
- }
-
- do_simplify = psys_render_simplify_params(psys, cpa, simplify);
-
- if (strandbuf) {
- int orignum = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, cpa->num) : cpa->num;
-
- if ((orignum > sbound - strandbuf->bound) &&
- (orignum < strandbuf->totbound))
- {
- sbound = &strandbuf->bound[orignum];
- sbound->start = sbound->end = obr->totstrand;
- }
- }
- }
-
- /* TEXCO_PARTICLE */
- pa_co[0] = pa_time;
- pa_co[1] = 0.f;
- pa_co[2] = 0.f;
-
- /* surface normal shading setup */
- if (ma->mode_l & MA_STR_SURFDIFF) {
- mul_m3_v3(nmat, nor);
- sd.surfnor= nor;
- }
- else
- sd.surfnor= NULL;
-
- /* strand render setup */
- if (strandbuf) {
- strand= RE_findOrAddStrand(obr, obr->totstrand++);
- strand->buffer= strandbuf;
- strand->vert= svert;
- copy_v3_v3(strand->orco, sd.orco);
-
- if (do_simplify) {
- float *ssimplify= RE_strandren_get_simplify(obr, strand, 1);
- ssimplify[0]= simplify[0];
- ssimplify[1]= simplify[1];
- }
-
- if (sd.surfnor) {
- float *snor= RE_strandren_get_surfnor(obr, strand, 1);
- copy_v3_v3(snor, sd.surfnor);
- }
-
- if (do_surfacecache && num >= 0) {
- int *facenum= RE_strandren_get_face(obr, strand, 1);
- *facenum= num;
- }
-
- if (sd.uvco) {
- for (i=0; i<sd.totuv; i++) {
- if (i != sd.override_uv) {
- float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1);
-
- uv[0]= sd.uvco[2*i];
- uv[1]= sd.uvco[2*i+1];
- }
- }
- }
- if (sd.mcol) {
- for (i=0; i<sd.totcol; i++) {
- MCol *mc= RE_strandren_get_mcol(obr, strand, i, NULL, 1);
- *mc = sd.mcol[i];
- }
- }
-
- sbound->end++;
- }
-
- /* strandco computation setup */
- if (path_nbr) {
- strandlen= 0.0f;
- curlen= 0.0f;
- for (k=1; k<=path_nbr; k++)
- if (k<=max_k)
- strandlen += len_v3v3((cache+k-1)->co, (cache+k)->co);
- }
-
- if (path_nbr) {
- /* render strands */
- for (k=0; k<=path_nbr; k++) {
- float time;
-
- if (k<=max_k) {
- copy_v3_v3(state.co, (cache+k)->co);
- copy_v3_v3(state.vel, (cache+k)->vel);
- }
- else
- continue;
-
- if (k > 0)
- curlen += len_v3v3((cache+k-1)->co, (cache+k)->co);
- time= curlen/strandlen;
-
- copy_v3_v3(loc, state.co);
- mul_m4_v3(re->viewmat, loc);
-
- if (strandbuf) {
- copy_v3_v3(svert->co, loc);
- svert->strandco= -1.0f + 2.0f*time;
- svert++;
- strand->totvert++;
- }
- else {
- sd.size = hasize;
-
- if (k==1) {
- sd.first = 1;
- sd.time = 0.0f;
- sub_v3_v3v3(loc0, loc1, loc);
- add_v3_v3v3(loc0, loc1, loc0);
-
- particle_curve(re, obr, psmd->dm_final, ma, &sd, loc1, loc0, seed, pa_co);
- }
-
- sd.first = 0;
- sd.time = time;
-
- if (k)
- particle_curve(re, obr, psmd->dm_final, ma, &sd, loc, loc1, seed, pa_co);
-
- copy_v3_v3(loc1, loc);
- }
- }
-
- }
- else {
- /* render normal particles */
- if (part->trail_count > 1) {
- float length = part->path_end * (1.0f - part->randlength * r_length);
- int trail_count = part->trail_count * (1.0f - part->randlength * r_length);
- float ct = (part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time;
- float dt = length / (trail_count ? (float)trail_count : 1.0f);
-
- /* make sure we have pointcache in memory before getting particle on path */
- psys_make_temp_pointcache(ob, psys);
-
- for (i=0; i < trail_count; i++, ct -= dt) {
- if (part->draw & PART_ABS_PATH_TIME) {
- if (ct < pa_birthtime || ct > pa_dietime)
- continue;
- }
- else if (ct < 0.0f || ct > 1.0f)
- continue;
-
- state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct;
- psys_get_particle_on_path(&sim, a, &state, 1);
-
- if (psys->parent)
- mul_m4_v3(psys->parent->obmat, state.co);
-
- if (use_duplimat)
- mul_m4_v4(duplimat, state.co);
-
- if (part->ren_as == PART_DRAW_BB) {
- bb.random = random;
- bb.offset[0] = part->bb_offset[0];
- bb.offset[1] = part->bb_offset[1];
- bb.size[0] = part->bb_size[0] * pa_size;
- if (part->bb_align==PART_BB_VEL) {
- float pa_vel = len_v3(state.vel);
- float head = part->bb_vel_head*pa_vel;
- float tail = part->bb_vel_tail*pa_vel;
- bb.size[1] = part->bb_size[1]*pa_size + head + tail;
- /* use offset to adjust the particle center. this is relative to size, so need to divide! */
- if (bb.size[1] > 0.0f)
- bb.offset[1] += (head-tail) / bb.size[1];
- }
- else
- bb.size[1] = part->bb_size[1] * pa_size;
- bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
- bb.time = ct;
- bb.num = a;
- }
-
- pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct;
- pa_co[1] = (float)i/(float)(trail_count-1);
-
- particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
- }
- }
- else {
- state.time=cfra;
- if (psys_get_particle_state(&sim, a, &state, 0)==0)
- continue;
-
- if (psys->parent)
- mul_m4_v3(psys->parent->obmat, state.co);
-
- if (use_duplimat)
- mul_m4_v3(duplimat, state.co);
-
- if (part->ren_as == PART_DRAW_BB) {
- bb.random = random;
- bb.offset[0] = part->bb_offset[0];
- bb.offset[1] = part->bb_offset[1];
- bb.size[0] = part->bb_size[0] * pa_size;
- if (part->bb_align==PART_BB_VEL) {
- float pa_vel = len_v3(state.vel);
- float head = part->bb_vel_head*pa_vel;
- float tail = part->bb_vel_tail*pa_vel;
- bb.size[1] = part->bb_size[1]*pa_size + head + tail;
- /* use offset to adjust the particle center. this is relative to size, so need to divide! */
- if (bb.size[1] > 0.0f)
- bb.offset[1] += (head-tail) / bb.size[1];
- }
- else
- bb.size[1] = part->bb_size[1] * pa_size;
- bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
- bb.time = pa_time;
- bb.num = a;
- bb.lifetime = pa_dietime-pa_birthtime;
- }
-
- particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
- }
- }
-
- if (orco1==0)
- sd.orco+=3;
-
- if (re->test_break(re->tbh))
- break;
- }
-
- if (do_surfacecache)
- strandbuf->surface= cache_strand_surface(re, obr, psmd->dm_final, mat, timeoffset);
-
-/* 4. clean up */
-#if 0 /* XXX old animation system */
- if (ma) do_mat_ipo(re->scene, ma);
-#endif /* XXX old animation system */
-
- if (orco1)
- MEM_freeN(sd.orco);
-
- if (sd.uvco)
- MEM_freeN(sd.uvco);
-
- if (sd.mcol)
- MEM_freeN(sd.mcol);
-
- if (states)
- MEM_freeN(states);
-
- BLI_rng_free(rng);
-
- psys->flag &= ~PSYS_DRAWING;
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (path_nbr && (ma->mode_l & MA_TANGENT_STR)==0)
- calc_vertexnormals(re, obr, 1, 0, 0);
-
- return 1;
-}
-
-/* ------------------------------------------------------------------------- */
/* Halo's */
/* ------------------------------------------------------------------------- */
@@ -4590,38 +3447,15 @@ static void set_dupli_tex_mat(Render *re, ObjectInstanceRen *obi, DupliObject *d
static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
- ParticleSystem *psys;
- int i;
-
- if (obr->psysindex) {
- if ((!obr->prev || obr->prev->ob != ob || (obr->prev->flag & R_INSTANCEABLE)==0) && ob->type==OB_MESH) {
- /* the emitter mesh wasn't rendered so the modifier stack wasn't
- * evaluated with render settings */
- DerivedMesh *dm;
- const CustomDataMask mask = CD_MASK_RENDER_INTERNAL;
- if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm = mesh_create_derived_view(re->scene, ob, mask);
- else
- dm = mesh_create_derived_render(re->scene, ob, mask);
- dm->release(dm);
- }
-
- for (psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++)
- psys= psys->next;
-
- render_new_particle_system(re, obr, psys, timeoffset);
- }
- else {
- if (ELEM(ob->type, OB_FONT, OB_CURVE))
- init_render_curve(re, obr, timeoffset);
- else if (ob->type==OB_SURF)
- init_render_surf(re, obr, timeoffset);
- else if (ob->type==OB_MESH)
- init_render_mesh(re, obr, timeoffset);
- else if (ob->type==OB_MBALL)
- init_render_mball(re, obr);
- }
+ if (ELEM(ob->type, OB_FONT, OB_CURVE))
+ init_render_curve(re, obr, timeoffset);
+ else if (ob->type==OB_SURF)
+ init_render_surf(re, obr, timeoffset);
+ else if (ob->type==OB_MESH)
+ init_render_mesh(re, obr, timeoffset);
+ else if (ob->type==OB_MBALL)
+ init_render_mball(re, obr);
finalize_render_object(re, obr, timeoffset);
@@ -4635,26 +3469,10 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
{
ObjectRen *obr;
ObjectInstanceRen *obi;
- ParticleSystem *psys;
- int show_emitter, allow_render= 1, index, psysindex, i;
+ int allow_render= 1, index, i;
index= (dob)? dob->persistent_id[0]: 0;
- /* the emitter has to be processed first (render levels of modifiers) */
- /* so here we only check if the emitter should be rendered */
- if (ob->particlesystem.first) {
- show_emitter= 0;
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- show_emitter += psys->part->draw & PART_DRAW_EMITTER;
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
- }
-
- /* if no psys has "show emitter" selected don't render emitter */
- if (show_emitter == 0)
- allow_render= 0;
- }
-
/* one render object for the data itself */
if (allow_render) {
obr= RE_addRenderObject(re, ob, par, index, 0, ob->lay);
@@ -4678,35 +3496,6 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
add_volume(re, obr, ma);
}
}
-
- /* and one render object per particle system */
- if (ob->particlesystem.first) {
- psysindex= 1;
- for (psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) {
- if (!psys_check_enabled(ob, psys))
- continue;
-
- obr= RE_addRenderObject(re, ob, par, index, psysindex, ob->lay);
- if ((dob && !dob->animated) || (ob->transflag & OB_RENDER_DUPLI)) {
- obr->flag |= R_INSTANCEABLE;
- copy_m4_m4(obr->obmat, ob->obmat);
- }
- if (dob)
- psys->flag |= PSYS_USE_IMAT;
- init_render_object_data(re, obr, timeoffset);
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
- psys_render_restore(ob, psys);
- psys->flag &= ~PSYS_USE_IMAT;
-
- /* only add instance for objects that have not been used for dupli */
- if (!(ob->transflag & OB_RENDER_DUPLI)) {
- obi = RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay, dob);
- if (dob) set_dupli_tex_mat(re, obi, dob, omat);
- }
- else
- find_dupli_instances(re, obr, dob);
- }
- }
}
/* par = pointer to duplicator parent, needed for object lookup table */
@@ -4880,36 +3669,12 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
* settings before calling object_duplilist, to get render level duplis */
Group *group;
GroupObject *go;
- ParticleSystem *psys;
- DerivedMesh *dm;
if (re->r.scemode & R_VIEWPORT_PREVIEW)
return;
if (level >= MAX_DUPLI_RECUR)
return;
-
- if (ob->transflag & OB_DUPLIPARTS) {
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- if (ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- if (enable)
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
- else
- psys_render_restore(ob, psys);
- }
- }
-
- if (enable) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_RENDER_INTERNAL);
- dm->release(dm);
-
- for (psys=ob->particlesystem.first; psys; psys=psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
if (ob->dup_group==NULL) return;
group= ob->dup_group;
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index 59aaad661c9..8a25552bd2b 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -53,7 +53,6 @@
#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"
@@ -167,149 +166,6 @@ 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)) {
- 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)
{
@@ -468,9 +324,6 @@ 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) {
@@ -482,28 +335,7 @@ static void cache_pointdensity_ex(Scene *scene,
pd->point_tree = NULL;
}
- 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) {
+ 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);
@@ -512,11 +344,7 @@ static void cache_pointdensity_ex(Scene *scene,
void cache_pointdensity(Render *re, PointDensity *pd)
{
- cache_pointdensity_ex(re->scene,
- pd,
- re->viewmat, re->winmat,
- re->winx, re->winy,
- true);
+ cache_pointdensity_ex(re->scene, pd, true);
}
void free_pointdensity(PointDensity *pd)
@@ -867,83 +695,20 @@ 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, mat, mat, 1, 1, use_render_params);
+ cache_pointdensity_ex(scene, pd, use_render_params);
BLI_mutex_unlock(&sample_mutex);
}
void RE_point_density_minmax(
- struct Scene *scene,
+ struct Scene *UNUSED(scene),
struct PointDensity *pd,
- const bool use_render_params,
+ const bool UNUSED(use_render_params),
float r_min[3], float r_max[3])
{
Object *object = pd->object;
@@ -952,27 +717,7 @@ void RE_point_density_minmax(
zero_v3(r_max);
return;
}
- 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 {
+ if (pd->source == TEX_PD_OBJECT) {
float radius[3] = {pd->radius, pd->radius, pd->radius};
float *loc, *size;
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 1010c9f06c8..98e3a5c881c 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -65,7 +65,6 @@
#include "BKE_node.h"
#include "BKE_sound.h"
#include "BKE_image.h"
-#include "BKE_particle.h"
#include "IMB_imbuf.h" /* for IMB_init */
@@ -360,7 +359,6 @@ int main(
RE_engines_init();
init_nodesystem();
- psys_init_rng();
/* end second init */