This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/modifiers/intern/MOD_particleinstance.c

365 lines
10 KiB
C
Raw Normal View History

/*
* ***** 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) 2005 by the Blender Foundation.
* All rights reserved.
*
* Contributor(s): Daniel Dunbar
* Ton Roosendaal,
* Ben Batt,
* Brecht Van Lommel,
* Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/modifiers/intern/MOD_particleinstance.c
* \ingroup modifiers
*/
#include "DNA_meshdata_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "MOD_util.h"
#include "depsgraph_private.h"
static void initData(ModifierData *md)
{
2012-05-06 13:38:33 +00:00
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
2012-05-06 13:38:33 +00:00
pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn |
eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead;
pimd->psys = 1;
pimd->position = 1.0f;
pimd->axis = 2;
}
static void copyData(ModifierData *md, ModifierData *target)
{
2012-05-06 13:38:33 +00:00
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
ParticleInstanceModifierData *tpimd = (ParticleInstanceModifierData *) target;
tpimd->ob = pimd->ob;
tpimd->psys = pimd->psys;
tpimd->flag = pimd->flag;
tpimd->axis = pimd->axis;
tpimd->position = pimd->position;
tpimd->random_position = pimd->random_position;
}
static int dependsOnTime(ModifierData *UNUSED(md))
{
return 0;
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
2012-05-06 13:38:33 +00:00
struct Scene *UNUSED(scene),
Object *UNUSED(ob),
DagNode *obNode)
{
2012-05-06 13:38:33 +00:00
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
if (pimd->ob) {
DagNode *curNode = dag_get_node(forest, pimd->ob);
dag_add_relation(forest, curNode, obNode,
2012-05-06 13:38:33 +00:00
DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
"Particle Instance Modifier");
}
}
static void foreachObjectLink(ModifierData *md, Object *ob,
2012-05-06 13:38:33 +00:00
ObjectWalkFunc walk, void *userData)
{
2012-05-06 13:38:33 +00:00
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
walk(userData, ob, &pimd->ob);
}
2012-05-06 13:38:33 +00:00
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
int UNUSED(useRenderParams),
int UNUSED(isFinalCalc))
{
DerivedMesh *dm = derivedData, *result;
2012-05-06 13:38:33 +00:00
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
ParticleSimulationData sim;
2012-05-06 13:38:33 +00:00
ParticleSystem *psys = NULL;
ParticleData *pa = NULL, *pars = NULL;
MFace *mface, *orig_mface;
MVert *mvert, *orig_mvert;
2012-05-06 13:38:33 +00:00
int i, totvert, totpart = 0, totface, maxvert, maxface, first_particle = 0;
short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
float max_co = 0.0, min_co = 0.0, temp_co[3], cross[3];
float *size = NULL;
DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
2012-05-06 13:38:33 +00:00
trackneg = ((ob->trackflag > 2) ? 1 : 0);
2012-05-06 13:38:33 +00:00
if (pimd->ob == ob) {
pimd->ob = NULL;
return derivedData;
}
if (pimd->ob) {
2012-05-06 13:38:33 +00:00
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)
2012-05-06 13:38:33 +00:00
totpart += psys->totpart;
if (pimd->flag & eParticleInstanceFlag_Children) {
2012-05-06 13:38:33 +00:00
if (totpart == 0)
first_particle = psys->totpart;
totpart += psys->totchild;
}
2012-05-06 13:38:33 +00:00
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) {
int p;
float *si;
si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
if (pimd->flag & eParticleInstanceFlag_Parents) {
2012-05-06 13:38:33 +00:00
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
*si = pa->size;
}
if (pimd->flag & eParticleInstanceFlag_Children) {
ChildParticle *cpa = psys->child;
2012-05-06 13:38:33 +00:00
for (p = 0; p < psys->totchild; p++, cpa++, si++) {
*si = psys_get_child_size(psys, cpa, 0.0f, NULL);
}
}
}
2012-05-06 13:38:33 +00:00
pars = psys->particles;
2012-05-06 13:38:33 +00:00
totvert = dm->getNumVerts(dm);
totface = dm->getNumTessFaces(dm);
2012-05-06 13:38:33 +00:00
maxvert = totvert * totpart;
maxface = totface * totpart;
2012-05-06 13:38:33 +00:00
psys->lattice = psys_get_lattice(&sim);
2012-05-06 13:38:33 +00:00
if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
float min_r[3], max_r[3];
INIT_MINMAX(min_r, max_r);
dm->getMinMax(dm, min_r, max_r);
2012-05-06 13:38:33 +00:00
min_co = min_r[track];
max_co = max_r[track];
}
2012-05-06 13:38:33 +00:00
result = CDDM_from_template(dm, maxvert, dm->getNumEdges(dm) * totpart, maxface, 0, 0);
2012-05-06 13:38:33 +00:00
mvert = result->getVertArray(result);
orig_mvert = dm->getVertArray(dm);
2012-05-06 13:38:33 +00:00
for (i = 0; i < maxvert; i++) {
MVert *inMV;
MVert *mv = mvert + i;
ParticleKey state;
2012-05-06 13:38:33 +00:00
inMV = orig_mvert + i % totvert;
DM_copy_vert_data(dm, result, i % totvert, i, 1);
*mv = *inMV;
/*change orientation based on object trackflag*/
copy_v3_v3(temp_co, mv->co);
2012-05-06 13:38:33 +00:00
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];
2012-05-06 13:38:33 +00:00
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) {
2012-05-06 13:38:33 +00:00
BLI_srandom(psys->seed + (i / totvert) % totpart);
ran = pimd->random_position * BLI_frand();
}
if (pimd->flag & eParticleInstanceFlag_KeepShape) {
state.time = pimd->position * (1.0f - ran);
}
else {
2012-05-06 13:38:33 +00:00
state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
if (trackneg)
2012-05-06 13:38:33 +00:00
state.time = 1.0f - state.time;
mv->co[axis] = 0.0;
}
2012-05-06 13:38:33 +00:00
psys_get_particle_on_path(&sim, first_particle + i / totvert, &state, 1);
normalize_v3(state.vel);
/* TODO: incremental rotations somehow */
if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
state.rot[0] = 1;
state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
}
else {
2012-04-29 15:47:02 +00:00
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 */
2012-04-29 15:47:02 +00:00
axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
}
}
else {
2012-05-06 13:38:33 +00:00
state.time = -1.0;
psys_get_particle_state(&sim, first_particle + i / totvert, &state, 1);
}
2012-04-29 15:47:02 +00:00
mul_qt_v3(state.rot, mv->co);
if (pimd->flag & eParticleInstanceFlag_UseSize)
2012-05-06 13:38:33 +00:00
mul_v3_fl(mv->co, size[i / totvert]);
add_v3_v3(mv->co, state.co);
}
2012-05-06 13:38:33 +00:00
mface = result->getTessFaceArray(result);
orig_mface = dm->getTessFaceArray(dm);
2012-05-06 13:38:33 +00:00
for (i = 0; i < maxface; i++) {
MFace *inMF;
MFace *mf = mface + i;
if (pimd->flag & eParticleInstanceFlag_Parents) {
2012-05-06 13:38:33 +00:00
if (i / totface >= psys->totpart) {
if (psys->part->childtype == PART_CHILD_PARTICLES) {
pa = psys->particles + (psys->child + i / totface - psys->totpart)->parent;
}
else {
2012-05-06 13:38:33 +00:00
pa = NULL;
}
}
else {
2012-05-06 13:38:33 +00:00
pa = pars + i / totface;
}
}
else {
2012-05-06 13:38:33 +00:00
if (psys->part->childtype == PART_CHILD_PARTICLES) {
pa = psys->particles + (psys->child + i / totface)->parent;
}
else {
2012-05-06 13:38:33 +00:00
pa = NULL;
}
}
if (pa) {
2012-05-06 13:38:33 +00:00
if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) continue;
if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) continue;
if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) continue;
}
2012-05-06 13:38:33 +00:00
inMF = orig_mface + i % totface;
DM_copy_poly_data(dm, result, i % totface, i, 1);
*mf = *inMF;
2012-05-06 13:38:33 +00:00
mf->v1 += (i / totface) * totvert;
mf->v2 += (i / totface) * totvert;
mf->v3 += (i / totface) * totvert;
if (mf->v4) {
2012-05-06 13:38:33 +00:00
mf->v4 += (i / totface) * totvert;
}
}
CDDM_calc_edges_tessface(result);
if (psys->lattice) {
end_latt_deform(psys->lattice);
2012-05-06 13:38:33 +00:00
psys->lattice = NULL;
}
if (size)
MEM_freeN(size);
CDDM_tessfaces_to_faces(result); /*builds ngon faces from tess (mface) faces*/
CDDM_calc_normals(result);
return result;
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
2012-05-06 13:38:33 +00:00
struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
}
ModifierTypeInfo modifierType_ParticleInstance = {
2012-05-06 13:38:33 +00:00
/* name */ "ParticleInstance",
/* structName */ "ParticleInstanceModifierData",
/* structSize */ sizeof(ParticleInstanceModifierData),
/* type */ eModifierTypeType_Constructive,
/* flags */ eModifierTypeFlag_AcceptsMesh |
eModifierTypeFlag_SupportsMapping |
eModifierTypeFlag_SupportsEditmode |
eModifierTypeFlag_EnableInEditmode,
/* copyData */ copyData,
/* deformVerts */ NULL,
/* deformMatrices */ NULL,
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* applyModifier */ applyModifier,
/* applyModifierEM */ applyModifierEM,
/* initData */ initData,
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ updateDepgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ foreachObjectLink,
2012-05-06 13:38:33 +00:00
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
};