Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/particle_system.c')
-rw-r--r--source/blender/blenkernel/intern/particle_system.c108
1 files changed, 95 insertions, 13 deletions
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 9840852ad7e..16ea71204cc 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -1660,17 +1660,22 @@ void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, P
{
Object *ob = sim->ob;
ParticleSystem *psys = sim->psys;
- ParticleSettings *part;
+ 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;
- part=psys->part;
/* get birth location from object */
- if (part->tanfac != 0.f)
+ 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);
@@ -1688,7 +1693,7 @@ void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, P
normalize_v3(nor);
/* -tangent */
- if (part->tanfac!=0.0f) {
+ 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)));
@@ -1737,7 +1742,7 @@ void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, P
mul_qt_qtqt(r_rot,r_rot,rot);
}
- if (part->phystype==PART_PHYS_BOIDS && pa->boid) {
+ if (use_boids) {
float dvec[3], q[4], mat[3][3];
copy_v3_v3(state->co,loc);
@@ -1823,35 +1828,112 @@ void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, P
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 */
- 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);
+
+ 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(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;
@@ -4313,7 +4395,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
/* SPH_SOLVER_CLASSICAL */
/* Apply SPH forces using classical algorithm (due to Gingold
* and Monaghan). Note that, unlike double-density relaxation,
- * this algorthim is separated into distinct loops. */
+ * this algorithm is separated into distinct loops. */
#pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
LOOP_DYNAMIC_PARTICLES {