Merge branch 'master' into blender2.8
This commit is contained in:
commit
9d6a175756
@ -711,11 +711,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
|
||||
def PARTICLE_INSTANCE(self, layout, ob, md):
|
||||
layout.prop(md, "object")
|
||||
layout.prop(md, "particle_system_index", text="Particle System")
|
||||
if md.object:
|
||||
layout.prop_search(md, "particle_system", md.object, "particle_systems", text="Particle System")
|
||||
else:
|
||||
layout.prop(md, "particle_system_index", text="Particle System")
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label(text="Create From:")
|
||||
layout.prop(md, "space", text="")
|
||||
col.prop(md, "use_normal")
|
||||
col.prop(md, "use_children")
|
||||
col.prop(md, "use_size")
|
||||
@ -726,6 +730,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
col.prop(md, "show_unborn")
|
||||
col.prop(md, "show_dead")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "particle_amount", text="Amount")
|
||||
row.prop(md, "particle_offset", text="Offset")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.prop(md, "use_path", text="Create Along Paths")
|
||||
@ -737,8 +745,16 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
col.prop(md, "use_preserve_shape")
|
||||
|
||||
col = split.column()
|
||||
col.prop(md, "position", slider=True)
|
||||
col.prop(md, "random_position", text="Random", slider=True)
|
||||
col2 = col.column(align=True)
|
||||
col2.prop(md, "position", slider=True)
|
||||
col2.prop(md, "random_position", text="Random", slider=True)
|
||||
col2 = col.column(align=True)
|
||||
col2.prop(md, "rotation", slider=True)
|
||||
col2.prop(md, "random_rotation", text="Random", slider=True)
|
||||
|
||||
col = layout.column()
|
||||
col.prop_search(md, "index_layer_name", ob.data, "vertex_colors", text="Index Layer")
|
||||
col.prop_search(md, "value_layer_name", ob.data, "vertex_colors", text="Value Layer")
|
||||
|
||||
def PARTICLE_SYSTEM(self, layout, ob, md):
|
||||
layout.label(text="Settings can be found inside the Particle context")
|
||||
|
@ -39,7 +39,8 @@ typedef void (*DrawInfoFreeFP)(void *drawinfo);
|
||||
struct Icon {
|
||||
void *drawinfo;
|
||||
void *obj;
|
||||
short type;
|
||||
/** #ID_Type or 0 when not used for ID preview. */
|
||||
short id_type;
|
||||
DrawInfoFreeFP drawinfo_free;
|
||||
};
|
||||
|
||||
|
@ -477,7 +477,7 @@ void BKE_icon_changed(const int icon_id)
|
||||
|
||||
if (icon) {
|
||||
/* We *only* expect ID-tied icons here, not non-ID icon/preview! */
|
||||
BLI_assert(icon->type != 0);
|
||||
BLI_assert(icon->id_type != 0);
|
||||
|
||||
/* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here ,
|
||||
* we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */
|
||||
@ -503,7 +503,7 @@ static int icon_id_ensure_create_icon(struct ID *id)
|
||||
new_icon = MEM_mallocN(sizeof(Icon), __func__);
|
||||
|
||||
new_icon->obj = id;
|
||||
new_icon->type = GS(id->name);
|
||||
new_icon->id_type = GS(id->name);
|
||||
|
||||
/* next two lines make sure image gets created */
|
||||
new_icon->drawinfo = NULL;
|
||||
@ -579,7 +579,7 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
|
||||
new_icon = MEM_mallocN(sizeof(Icon), __func__);
|
||||
|
||||
new_icon->obj = preview;
|
||||
new_icon->type = 0; /* Special, tags as non-ID icon/preview. */
|
||||
new_icon->id_type = 0; /* Special, tags as non-ID icon/preview. */
|
||||
|
||||
/* next two lines make sure image gets created */
|
||||
new_icon->drawinfo = NULL;
|
||||
@ -656,7 +656,7 @@ void BKE_icon_delete(const int icon_id)
|
||||
icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL);
|
||||
|
||||
if (icon) {
|
||||
if (icon->type) {
|
||||
if (icon->id_type != 0) {
|
||||
((ID *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
else {
|
||||
|
@ -1787,6 +1787,18 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
}
|
||||
scene->r.ffcodecdata.ffmpeg_preset = preset;
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "ParticleInstanceModifierData", "float", "particle_amount")) {
|
||||
for (Object *ob = main->object.first; ob; ob = ob->id.next) {
|
||||
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
|
||||
if (md->type == eModifierType_ParticleInstance) {
|
||||
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
||||
pimd->space = eParticleInstanceSpace_World;
|
||||
pimd->particle_amount = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs,
|
||||
new_icon = MEM_callocN(sizeof(Icon), "texicon");
|
||||
|
||||
new_icon->obj = NULL; /* icon is not for library object */
|
||||
new_icon->type = 0;
|
||||
new_icon->id_type = 0;
|
||||
|
||||
di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
|
||||
di->type = type;
|
||||
@ -195,7 +195,7 @@ static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc)
|
||||
new_icon = MEM_callocN(sizeof(Icon), "texicon");
|
||||
|
||||
new_icon->obj = NULL; /* icon is not for library object */
|
||||
new_icon->type = 0;
|
||||
new_icon->id_type = 0;
|
||||
|
||||
di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
|
||||
di->type = ICON_TYPE_VECTOR;
|
||||
@ -874,7 +874,7 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
|
||||
switch (di->type) {
|
||||
case ICON_TYPE_PREVIEW:
|
||||
{
|
||||
ID *id = (icon->type != 0) ? icon->obj : NULL;
|
||||
ID *id = (icon->id_type != 0) ? icon->obj : NULL;
|
||||
PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
|
||||
/* Using jobs for screen previews crashes due to offscreen rendering.
|
||||
* XXX would be nicer if PreviewImage could store if it supports jobs */
|
||||
@ -933,7 +933,7 @@ PreviewImage *UI_icon_to_preview(int icon_id)
|
||||
DrawInfo *di = (DrawInfo *)icon->drawinfo;
|
||||
if (di) {
|
||||
if (di->type == ICON_TYPE_PREVIEW) {
|
||||
PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
|
||||
PreviewImage *prv = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
|
||||
|
||||
if (prv) {
|
||||
return BKE_previewimg_copy(prv);
|
||||
@ -1237,7 +1237,7 @@ static void icon_draw_size(
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else if (di->type == ICON_TYPE_PREVIEW) {
|
||||
PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
|
||||
PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
|
||||
|
||||
if (pi) {
|
||||
/* no create icon on this level in code */
|
||||
|
@ -753,12 +753,21 @@ typedef enum {
|
||||
eParticleInstanceFlag_UseSize = (1 << 7),
|
||||
} ParticleInstanceModifierFlag;
|
||||
|
||||
typedef enum {
|
||||
eParticleInstanceSpace_World = 0,
|
||||
eParticleInstanceSpace_Local = 1,
|
||||
} ParticleInstanceModifierSpace;
|
||||
|
||||
typedef struct ParticleInstanceModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
struct Object *ob;
|
||||
short psys, flag, axis, pad;
|
||||
short psys, flag, axis, space;
|
||||
float position, random_position;
|
||||
float rotation, random_rotation;
|
||||
float particle_amount, particle_offset;
|
||||
char index_layer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
|
||||
char value_layer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
|
||||
} ParticleInstanceModifierData;
|
||||
|
||||
typedef enum {
|
||||
|
@ -1157,6 +1157,43 @@ static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene,
|
||||
rna_Modifier_update(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static int rna_ParticleInstanceModifier_particle_system_poll(PointerRNA *ptr, const PointerRNA value)
|
||||
{
|
||||
ParticleInstanceModifierData *psmd = ptr->data;
|
||||
ParticleSystem *psys = value.data;
|
||||
|
||||
if (!psmd->ob)
|
||||
return false;
|
||||
|
||||
/* make sure psys is in the object */
|
||||
return BLI_findindex(&psmd->ob->particlesystem, psys) >= 0;
|
||||
}
|
||||
|
||||
static PointerRNA rna_ParticleInstanceModifier_particle_system_get(PointerRNA *ptr)
|
||||
{
|
||||
ParticleInstanceModifierData *psmd = ptr->data;
|
||||
ParticleSystem *psys;
|
||||
PointerRNA rptr;
|
||||
|
||||
if (!psmd->ob)
|
||||
return PointerRNA_NULL;
|
||||
|
||||
psys = BLI_findlink(&psmd->ob->particlesystem, psmd->psys - 1);
|
||||
RNA_pointer_create((ID *)psmd->ob, &RNA_ParticleSystem, psys, &rptr);
|
||||
return rptr;
|
||||
}
|
||||
|
||||
static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr, const PointerRNA value)
|
||||
{
|
||||
ParticleInstanceModifierData *psmd = ptr->data;
|
||||
|
||||
if (!psmd->ob)
|
||||
return;
|
||||
|
||||
psmd->psys = BLI_findindex(&psmd->ob->particlesystem, value.data) + 1;
|
||||
CLAMP_MIN(psmd->psys, 1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
|
||||
@ -2652,6 +2689,12 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem particleinstance_space[] = {
|
||||
{eParticleInstanceSpace_Local, "LOCAL", 0, "Local", "Use offset from the particle object in the instance object"},
|
||||
{eParticleInstanceSpace_World, "WORLD", 0, "World", "Use world space offset in the instance object"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "ParticleInstanceModifier", "Modifier");
|
||||
RNA_def_struct_ui_text(srna, "ParticleInstance Modifier", "Particle system instancing modifier");
|
||||
RNA_def_struct_sdna(srna, "ParticleInstanceModifierData");
|
||||
@ -2666,16 +2709,30 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
|
||||
|
||||
prop = RNA_def_property(srna, "particle_system_index", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "psys");
|
||||
RNA_def_property_range(prop, 1, 10);
|
||||
RNA_def_property_range(prop, 1, SHRT_MAX);
|
||||
RNA_def_property_ui_text(prop, "Particle System Number", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ParticleSystem");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_ParticleInstanceModifier_particle_system_get", "rna_ParticleInstanceModifier_particle_system_set",
|
||||
NULL, "rna_ParticleInstanceModifier_particle_system_poll");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Particle System", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "axis");
|
||||
RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
|
||||
RNA_def_property_ui_text(prop, "Axis", "Pole axis for rotation");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
|
||||
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "space");
|
||||
RNA_def_property_enum_items(prop, particleinstance_space);
|
||||
RNA_def_property_ui_text(prop, "Space", "Space to use for copying mesh data");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_normal", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Parents);
|
||||
RNA_def_property_ui_text(prop, "Normal", "Create instances from normal particles");
|
||||
@ -2727,6 +2784,40 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_ui_text(prop, "Random Position", "Randomize position along path");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "rotation");
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_ui_text(prop, "Rotation", "Rotation around path");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "random_rotation", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "random_rotation");
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_ui_text(prop, "Random Rotation", "Randomize rotation around path");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "particle_amount", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_ui_text(prop, "Particle Amount", "Amount of particles to use for instancing");
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "particle_offset", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_ui_text(prop, "Particle Offset", "Relative offset of particles to use for instancing, to avoid overlap of multiple instances");
|
||||
RNA_def_property_float_default(prop, 0.0f);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "index_layer_name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "index_layer_name");
|
||||
RNA_def_property_ui_text(prop, "Index Layer Name", "Custom data layer name for the index");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "value_layer_name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "value_layer_name");
|
||||
RNA_def_property_ui_text(prop, "Value Layer Name", "Custom data layer name for the randomized value");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_explode(BlenderRNA *brna)
|
||||
|
@ -40,10 +40,12 @@
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_library_query.h"
|
||||
#include "BKE_modifier.h"
|
||||
@ -52,8 +54,6 @@
|
||||
|
||||
#include "DEG_depsgraph_build.h"
|
||||
|
||||
#include "MOD_modifiertypes.h"
|
||||
|
||||
static void initData(ModifierData *md)
|
||||
{
|
||||
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
|
||||
@ -63,7 +63,12 @@ static void initData(ModifierData *md)
|
||||
pimd->psys = 1;
|
||||
pimd->position = 1.0f;
|
||||
pimd->axis = 2;
|
||||
pimd->space = eParticleInstanceSpace_World;
|
||||
pimd->particle_amount = 1.0f;
|
||||
pimd->particle_offset = 0.0f;
|
||||
|
||||
STRNCPY(pimd->index_layer_name, "");
|
||||
STRNCPY(pimd->value_layer_name, "");
|
||||
}
|
||||
static void copyData(ModifierData *md, ModifierData *target)
|
||||
{
|
||||
@ -74,6 +79,21 @@ static void copyData(ModifierData *md, ModifierData *target)
|
||||
modifier_copyData_generic(md, target);
|
||||
}
|
||||
|
||||
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
|
||||
{
|
||||
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
||||
CustomDataMask dataMask = 0;
|
||||
|
||||
if (pimd->index_layer_name[0] != '\0' ||
|
||||
pimd->value_layer_name[0] != '\0')
|
||||
{
|
||||
dataMask |= CD_MASK_MLOOPCOL;
|
||||
}
|
||||
|
||||
return dataMask;
|
||||
|
||||
}
|
||||
|
||||
static bool isDisabled(ModifierData *md, int useRenderParams)
|
||||
{
|
||||
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
||||
@ -127,39 +147,59 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
|
||||
walk(userData, ob, &pimd->ob, IDWALK_CB_NOP);
|
||||
}
|
||||
|
||||
static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
|
||||
static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
|
||||
{
|
||||
const bool between = (psys->part->childtype == PART_CHILD_FACES);
|
||||
ParticleData *pa;
|
||||
int totpart, randp, minp, maxp;
|
||||
|
||||
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;
|
||||
}
|
||||
if (p >= psys->totpart) {
|
||||
ChildParticle *cpa = psys->child + (p - psys->totpart);
|
||||
pa = psys->particles + (between? cpa->pa[0]: cpa->parent);
|
||||
}
|
||||
else {
|
||||
if (psys->part->childtype == PART_CHILD_PARTICLES) {
|
||||
pa = psys->particles + (psys->child + p)->parent;
|
||||
}
|
||||
else {
|
||||
pa = NULL;
|
||||
}
|
||||
pa = psys->particles + p;
|
||||
}
|
||||
|
||||
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;
|
||||
if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return true;
|
||||
if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return true;
|
||||
if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (pimd->particle_amount == 1.0f) {
|
||||
/* Early output, all particles are to be instanced. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Randomly skip particles based on desired amount of visible particles. */
|
||||
|
||||
totpart = psys->totpart + psys->totchild;
|
||||
|
||||
/* TODO make randomization optional? */
|
||||
randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart;
|
||||
|
||||
minp = (int)(totpart * pimd->particle_offset) % (totpart+1);
|
||||
maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart+1);
|
||||
|
||||
if (maxp > minp) {
|
||||
return randp < minp || randp >= maxp;
|
||||
}
|
||||
else if (maxp < minp) {
|
||||
return randp < minp && randp >= maxp;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void store_float_in_vcol(MLoopCol *vcol, float float_value)
|
||||
{
|
||||
const uchar value = FTOCHAR(float_value);
|
||||
vcol->r = vcol->g = vcol->b = value;
|
||||
vcol->a = 1.0f;
|
||||
}
|
||||
|
||||
static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
@ -175,11 +215,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
MLoop *mloop, *orig_mloop;
|
||||
MVert *mvert, *orig_mvert;
|
||||
int totvert, totpoly, totloop /* , totedge */;
|
||||
int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
|
||||
int maxvert, maxpoly, maxloop, part_end = 0, part_start;
|
||||
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;
|
||||
float spacemat[4][4];
|
||||
const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents;
|
||||
const bool use_children = pimd->flag & eParticleInstanceFlag_Children;
|
||||
bool between;
|
||||
|
||||
trackneg = ((ob->trackflag > 2) ? 1 : 0);
|
||||
|
||||
@ -197,15 +241,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
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;
|
||||
}
|
||||
part_start = use_parents ? 0 : psys->totpart;
|
||||
|
||||
if (totpart == 0)
|
||||
part_end = 0;
|
||||
if (use_parents)
|
||||
part_end += psys->totpart;
|
||||
if (use_children)
|
||||
part_end += psys->totchild;
|
||||
|
||||
if (part_end == 0)
|
||||
return derivedData;
|
||||
|
||||
sim.depsgraph = depsgraph;
|
||||
@ -213,10 +257,11 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
sim.ob = pimd->ob;
|
||||
sim.psys = psys;
|
||||
sim.psmd = psys_get_modifier(pimd->ob, psys);
|
||||
between = (psys->part->childtype == PART_CHILD_FACES);
|
||||
|
||||
if (pimd->flag & eParticleInstanceFlag_UseSize) {
|
||||
float *si;
|
||||
si = size = MEM_calloc_arrayN(totpart, sizeof(float), "particle size array");
|
||||
si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array");
|
||||
|
||||
if (pimd->flag & eParticleInstanceFlag_Parents) {
|
||||
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
|
||||
@ -232,6 +277,21 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
}
|
||||
}
|
||||
|
||||
switch (pimd->space) {
|
||||
case eParticleInstanceSpace_World:
|
||||
/* particle states are in world space already */
|
||||
unit_m4(spacemat);
|
||||
break;
|
||||
case eParticleInstanceSpace_Local:
|
||||
/* get particle states in the particle object's local space */
|
||||
invert_m4_m4(spacemat, pimd->ob->obmat);
|
||||
break;
|
||||
default:
|
||||
/* should not happen */
|
||||
BLI_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
totvert = dm->getNumVerts(dm);
|
||||
totpoly = dm->getNumPolys(dm);
|
||||
totloop = dm->getNumLoops(dm);
|
||||
@ -242,7 +302,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
maxpoly = 0;
|
||||
maxloop = 0;
|
||||
|
||||
for (p = 0; p < totpart; p++) {
|
||||
for (p = part_start; p < part_end; p++) {
|
||||
if (particle_skip(pimd, psys, p))
|
||||
continue;
|
||||
|
||||
@ -271,9 +331,21 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
mloop = result->getLoopArray(result);
|
||||
orig_mloop = dm->getLoopArray(dm);
|
||||
|
||||
for (p = 0, p_skip = 0; p < totpart; p++) {
|
||||
MLoopCol *mloopcols_index = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->index_layer_name);
|
||||
MLoopCol *mloopcols_value = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->value_layer_name);
|
||||
int *vert_part_index = NULL;
|
||||
float *vert_part_value = NULL;
|
||||
if (mloopcols_index != NULL) {
|
||||
vert_part_index = MEM_calloc_arrayN(maxvert, sizeof(int), "vertex part index array");
|
||||
}
|
||||
if (mloopcols_value) {
|
||||
vert_part_value = MEM_calloc_arrayN(maxvert, sizeof(float), "vertex part value array");
|
||||
}
|
||||
|
||||
for (p = part_start, p_skip = 0; p < part_end; p++) {
|
||||
float prev_dir[3];
|
||||
float frame[4]; /* frame orientation quaternion */
|
||||
float p_random = psys_frand(psys, 77091 + 283*p);
|
||||
|
||||
/* skip particle? */
|
||||
if (particle_skip(pimd, psys, p))
|
||||
@ -283,12 +355,20 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
for (k = 0; k < totvert; k++) {
|
||||
ParticleKey state;
|
||||
MVert *inMV;
|
||||
MVert *mv = mvert + p_skip * totvert + k;
|
||||
int vindex = p_skip * totvert + k;
|
||||
MVert *mv = mvert + vindex;
|
||||
|
||||
inMV = orig_mvert + k;
|
||||
DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
|
||||
*mv = *inMV;
|
||||
|
||||
if (vert_part_index != NULL) {
|
||||
vert_part_index[vindex] = p;
|
||||
}
|
||||
if (vert_part_value != NULL) {
|
||||
vert_part_value[vindex] = p_random;
|
||||
}
|
||||
|
||||
/*change orientation based on object trackflag*/
|
||||
copy_v3_v3(temp_co, mv->co);
|
||||
mv->co[axis] = temp_co[track];
|
||||
@ -316,7 +396,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
mv->co[axis] = 0.0;
|
||||
}
|
||||
|
||||
psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
|
||||
psys_get_particle_on_path(&sim, p, &state, 1);
|
||||
|
||||
normalize_v3(state.vel);
|
||||
|
||||
@ -325,17 +405,26 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
float hairmat[4][4];
|
||||
float mat[3][3];
|
||||
|
||||
if (first_particle + p < psys->totpart)
|
||||
pa = psys->particles + first_particle + p;
|
||||
if (p < psys->totpart)
|
||||
pa = psys->particles + p;
|
||||
else {
|
||||
ChildParticle *cpa = psys->child + (p - psys->totpart);
|
||||
pa = psys->particles + cpa->parent;
|
||||
pa = psys->particles + (between? cpa->pa[0]: 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);
|
||||
|
||||
if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) {
|
||||
float angle = 2.0f*M_PI * (pimd->rotation + pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f));
|
||||
float eul[3] = { 0.0f, 0.0f, angle };
|
||||
float rot[4];
|
||||
|
||||
eul_to_quat(rot, eul);
|
||||
mul_qt_qtqt(frame, frame, rot);
|
||||
}
|
||||
|
||||
/* note: direction is same as normal vector currently,
|
||||
* but best to keep this separate so the frame can be
|
||||
* rotated later if necessary
|
||||
@ -372,13 +461,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
}
|
||||
else {
|
||||
state.time = -1.0;
|
||||
psys_get_particle_state(&sim, first_particle + p, &state, 1);
|
||||
psys_get_particle_state(&sim, 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);
|
||||
|
||||
mul_m4_v3(spacemat, mv->co);
|
||||
}
|
||||
|
||||
/* create polys and loops */
|
||||
@ -398,6 +489,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
|
||||
for (; j; j--, ml++, inML++) {
|
||||
ml->v = inML->v + (p_skip * totvert);
|
||||
const int ml_index = (ml - mloop);
|
||||
if (mloopcols_index != NULL) {
|
||||
const int part_index = vert_part_index[ml->v];
|
||||
store_float_in_vcol(&mloopcols_index[ml_index], (float)part_index / psys->totpart);
|
||||
}
|
||||
if (mloopcols_value != NULL) {
|
||||
const float part_value = vert_part_value[ml->v];
|
||||
store_float_in_vcol(&mloopcols_value[ml_index], part_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -415,6 +515,9 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
|
||||
if (size)
|
||||
MEM_freeN(size);
|
||||
|
||||
MEM_SAFE_FREE(vert_part_index);
|
||||
MEM_SAFE_FREE(vert_part_value);
|
||||
|
||||
result->dirty |= DM_DIRTY_NORMALS;
|
||||
|
||||
return result;
|
||||
@ -437,7 +540,7 @@ ModifierTypeInfo modifierType_ParticleInstance = {
|
||||
/* applyModifier */ applyModifier,
|
||||
/* applyModifierEM */ NULL,
|
||||
/* initData */ initData,
|
||||
/* requiredDataMask */ NULL,
|
||||
/* requiredDataMask */ requiredDataMask,
|
||||
/* freeData */ NULL,
|
||||
/* isDisabled */ isDisabled,
|
||||
/* updateDepsgraph */ updateDepsgraph,
|
||||
|
Loading…
Reference in New Issue
Block a user