2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2005 Blender Foundation. All rights reserved. */
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup modifiers
|
2016-12-28 17:30:58 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2019-02-25 11:39:14 +01:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "BLI_listbase.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_math.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "BLI_rand.h"
|
2018-04-18 12:14:28 +02:00
|
|
|
#include "BLI_string.h"
|
2019-02-25 11:39:14 +01:00
|
|
|
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "BLT_translation.h"
|
|
|
|
|
|
2020-10-01 09:38:00 -05:00
|
|
|
#include "DNA_defaults.h"
|
2019-02-25 11:39:14 +01:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
|
#include "DNA_meshdata_types.h"
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "DNA_screen_types.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "BKE_context.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "BKE_effect.h"
|
|
|
|
|
#include "BKE_lattice.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_query.h"
|
2018-05-17 13:45:47 +02:00
|
|
|
#include "BKE_mesh.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "BKE_modifier.h"
|
|
|
|
|
#include "BKE_particle.h"
|
|
|
|
|
#include "BKE_pointcache.h"
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "BKE_screen.h"
|
|
|
|
|
|
|
|
|
|
#include "UI_interface.h"
|
|
|
|
|
#include "UI_resources.h"
|
|
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
2022-03-14 16:54:46 +01:00
|
|
|
#include "RNA_prototypes.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
|
|
|
|
|
#include "DEG_depsgraph_build.h"
|
2018-06-22 15:03:42 +02:00
|
|
|
#include "DEG_depsgraph_query.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2018-12-30 15:14:00 +11:00
|
|
|
#include "MOD_modifiertypes.h"
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "MOD_ui_common.h"
|
2018-12-30 15:14:00 +11:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
static void initData(ModifierData *md)
|
|
|
|
|
{
|
|
|
|
|
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-01 09:38:00 -05:00
|
|
|
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(pimd, modifier));
|
|
|
|
|
|
|
|
|
|
MEMCPY_STRUCT_AFTER(pimd, DNA_struct_default_get(ParticleInstanceModifierData), modifier);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
|
2022-09-14 14:49:40 -05:00
|
|
|
static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
|
2018-04-18 12:14:28 +02:00
|
|
|
{
|
|
|
|
|
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
|
|
|
|
|
|
|
|
|
if (pimd->index_layer_name[0] != '\0' || pimd->value_layer_name[0] != '\0') {
|
2022-04-20 09:10:10 -05:00
|
|
|
r_cddata_masks->lmask |= CD_MASK_PROP_BYTE_COLOR;
|
2018-04-18 12:14:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-10 12:14:08 +02:00
|
|
|
static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRenderParams)
|
2016-12-28 17:30:58 +01:00
|
|
|
{
|
|
|
|
|
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
|
|
|
|
ParticleSystem *psys;
|
|
|
|
|
ModifierData *ob_md;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-23 15:50:53 +02:00
|
|
|
/* The object type check is only needed here in case we have a placeholder
|
|
|
|
|
* object assigned (because the library containing the mesh is missing).
|
|
|
|
|
*
|
2019-08-31 01:19:22 +10:00
|
|
|
* In other cases it should be impossible to have a type mismatch.
|
2019-08-23 15:50:53 +02:00
|
|
|
*/
|
|
|
|
|
if (!pimd->ob || pimd->ob->type != OB_MESH) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return true;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
|
2019-04-22 09:15:10 +10:00
|
|
|
if (psys == NULL) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return true;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* 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;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:15:10 +10:00
|
|
|
if (useRenderParams) {
|
2016-12-28 17:30:58 +01:00
|
|
|
required_mode = eModifierMode_Render;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2016-12-28 17:30:58 +01:00
|
|
|
required_mode = eModifierMode_Realtime;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-05-08 10:14:02 +02:00
|
|
|
if (!BKE_modifier_is_enabled(scene, ob_md, required_mode)) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return true;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-22 12:54:06 +01:00
|
|
|
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
|
2016-12-28 17:30:58 +01:00
|
|
|
{
|
|
|
|
|
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
|
|
|
|
if (pimd->ob != NULL) {
|
2018-02-22 12:54:06 +01:00
|
|
|
DEG_add_object_relation(
|
|
|
|
|
ctx->node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
|
2018-04-18 13:54:02 +02:00
|
|
|
DEG_add_object_relation(
|
|
|
|
|
ctx->node, pimd->ob, DEG_OB_COMP_GEOMETRY, "Particle Instance Modifier");
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-01 18:05:23 +02:00
|
|
|
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
|
2016-12-28 17:30:58 +01:00
|
|
|
{
|
|
|
|
|
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
|
|
|
|
|
2020-10-01 18:05:23 +02:00
|
|
|
walk(userData, ob, (ID **)&pimd->ob, IDWALK_CB_NOP);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
|
2016-12-28 17:30:58 +01:00
|
|
|
{
|
2018-04-18 12:14:28 +02:00
|
|
|
const bool between = (psys->part->childtype == PART_CHILD_FACES);
|
2016-12-28 17:30:58 +01:00
|
|
|
ParticleData *pa;
|
2018-04-18 12:14:28 +02:00
|
|
|
int totpart, randp, minp, maxp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
if (p >= psys->totpart) {
|
|
|
|
|
ChildParticle *cpa = psys->child + (p - psys->totpart);
|
2018-06-06 22:17:06 +02:00
|
|
|
pa = psys->particles + (between ? cpa->pa[0] : cpa->parent);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2018-04-18 12:14:28 +02:00
|
|
|
pa = psys->particles + p;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (pa) {
|
2019-04-22 09:15:10 +10:00
|
|
|
if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) {
|
2018-04-18 12:14:28 +02:00
|
|
|
return true;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
|
|
|
|
if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) {
|
2018-04-18 12:14:28 +02:00
|
|
|
return true;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
|
|
|
|
if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) {
|
2018-04-18 12:14:28 +02:00
|
|
|
return true;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2020-01-27 17:36:50 +01:00
|
|
|
if (pa->flag & (PARS_UNEXIST | PARS_NO_DISP)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
if (pimd->particle_amount == 1.0f) {
|
|
|
|
|
/* Early output, all particles are to be instanced. */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
/* Randomly skip particles based on desired amount of visible particles. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
totpart = psys->totpart + psys->totchild;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* TODO: make randomization optional? */
|
2018-04-18 12:14:28 +02:00
|
|
|
randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-06 22:17:06 +02:00
|
|
|
minp = (int)(totpart * pimd->particle_offset) % (totpart + 1);
|
|
|
|
|
maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart + 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
if (maxp > minp) {
|
|
|
|
|
return randp < minp || randp >= maxp;
|
|
|
|
|
}
|
2020-08-07 12:40:29 +02:00
|
|
|
if (maxp < minp) {
|
2018-04-18 12:14:28 +02:00
|
|
|
return randp < minp && randp >= maxp;
|
|
|
|
|
}
|
2020-08-07 12:40:29 +02:00
|
|
|
|
|
|
|
|
return true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void store_float_in_vcol(MLoopCol *vcol, float float_value)
|
|
|
|
|
{
|
2018-05-07 17:31:28 +02:00
|
|
|
const uchar value = unit_float_to_uchar_clamp(float_value);
|
2018-04-18 12:14:28 +02:00
|
|
|
vcol->r = vcol->g = vcol->b = value;
|
|
|
|
|
vcol->a = 1.0f;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-21 13:09:41 +02:00
|
|
|
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
|
2016-12-28 17:30:58 +01:00
|
|
|
{
|
2018-05-17 13:45:47 +02:00
|
|
|
Mesh *result;
|
2016-12-28 17:30:58 +01:00
|
|
|
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
|
2018-06-22 15:03:42 +02:00
|
|
|
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
|
2016-12-28 17:30:58 +01:00
|
|
|
ParticleSimulationData sim;
|
|
|
|
|
ParticleSystem *psys = NULL;
|
|
|
|
|
ParticleData *pa = NULL;
|
2018-05-08 16:57:07 +02:00
|
|
|
int totvert, totpoly, totloop, totedge;
|
2018-05-04 09:20:57 +02:00
|
|
|
int maxvert, maxpoly, maxloop, maxedge, part_end = 0, part_start;
|
2016-12-28 17:30:58 +01:00
|
|
|
int k, p, p_skip;
|
2018-05-01 17:33:04 +02:00
|
|
|
short track = ctx->object->trackflag % 3, trackneg, axis = pimd->axis;
|
2016-12-28 17:30:58 +01:00
|
|
|
float max_co = 0.0, min_co = 0.0, temp_co[3];
|
|
|
|
|
float *size = NULL;
|
2018-04-18 12:14:28 +02:00
|
|
|
float spacemat[4][4];
|
|
|
|
|
const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents;
|
|
|
|
|
const bool use_children = pimd->flag & eParticleInstanceFlag_Children;
|
|
|
|
|
bool between;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-01 17:33:04 +02:00
|
|
|
trackneg = ((ctx->object->trackflag > 2) ? 1 : 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-01 17:33:04 +02:00
|
|
|
if (pimd->ob == ctx->object) {
|
2016-12-28 17:30:58 +01:00
|
|
|
pimd->ob = NULL;
|
2018-05-17 13:45:47 +02:00
|
|
|
return mesh;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (pimd->ob) {
|
|
|
|
|
psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
|
2019-04-22 09:15:10 +10:00
|
|
|
if (psys == NULL || psys->totpart == 0) {
|
2018-05-17 13:45:47 +02:00
|
|
|
return mesh;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2018-05-17 13:45:47 +02:00
|
|
|
return mesh;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
part_start = use_parents ? 0 : psys->totpart;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
part_end = 0;
|
2019-04-22 09:15:10 +10:00
|
|
|
if (use_parents) {
|
2018-04-18 12:14:28 +02:00
|
|
|
part_end += psys->totpart;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
|
|
|
|
if (use_children) {
|
2018-04-18 12:14:28 +02:00
|
|
|
part_end += psys->totchild;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:15:10 +10:00
|
|
|
if (part_end == 0) {
|
2018-05-17 13:45:47 +02:00
|
|
|
return mesh;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-01 17:33:04 +02:00
|
|
|
sim.depsgraph = ctx->depsgraph;
|
2018-06-22 15:03:42 +02:00
|
|
|
sim.scene = scene;
|
2016-12-28 17:30:58 +01:00
|
|
|
sim.ob = pimd->ob;
|
|
|
|
|
sim.psys = psys;
|
|
|
|
|
sim.psmd = psys_get_modifier(pimd->ob, psys);
|
2018-04-18 12:14:28 +02:00
|
|
|
between = (psys->part->childtype == PART_CHILD_FACES);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (pimd->flag & eParticleInstanceFlag_UseSize) {
|
|
|
|
|
float *si;
|
2018-04-18 12:14:28 +02:00
|
|
|
si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (pimd->flag & eParticleInstanceFlag_Parents) {
|
2019-04-22 09:15:10 +10:00
|
|
|
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++) {
|
2016-12-28 17:30:58 +01:00
|
|
|
*si = pa->size;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (pimd->flag & eParticleInstanceFlag_Children) {
|
|
|
|
|
ChildParticle *cpa = psys->child;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
for (p = 0; p < psys->totchild; p++, cpa++, si++) {
|
|
|
|
|
*si = psys_get_child_size(psys, cpa, 0.0f, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-17 13:45:47 +02:00
|
|
|
totvert = mesh->totvert;
|
|
|
|
|
totpoly = mesh->totpoly;
|
|
|
|
|
totloop = mesh->totloop;
|
|
|
|
|
totedge = mesh->totedge;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* count particles */
|
|
|
|
|
maxvert = 0;
|
|
|
|
|
maxpoly = 0;
|
|
|
|
|
maxloop = 0;
|
2018-05-04 09:20:57 +02:00
|
|
|
maxedge = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
for (p = part_start; p < part_end; p++) {
|
2019-04-22 09:15:10 +10:00
|
|
|
if (particle_skip(pimd, psys, p)) {
|
2016-12-28 17:30:58 +01:00
|
|
|
continue;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
maxvert += totvert;
|
|
|
|
|
maxpoly += totpoly;
|
|
|
|
|
maxloop += totloop;
|
2018-05-04 09:20:57 +02:00
|
|
|
maxedge += totedge;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
|
|
|
|
|
float min[3], max[3];
|
|
|
|
|
INIT_MINMAX(min, max);
|
2018-05-17 13:45:47 +02:00
|
|
|
BKE_mesh_minmax(mesh, min, max);
|
2016-12-28 17:30:58 +01:00
|
|
|
min_co = min[track];
|
|
|
|
|
max_co = max[track];
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-17 13:45:47 +02:00
|
|
|
result = BKE_mesh_new_nomain_from_template(mesh, maxvert, maxedge, 0, maxloop, maxpoly);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-07 00:06:31 -05:00
|
|
|
const MVert *orig_mvert = BKE_mesh_verts(mesh);
|
|
|
|
|
const MPoly *orig_mpoly = BKE_mesh_polys(mesh);
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
const MLoop *orig_mloop = BKE_mesh_loops(mesh);
|
2022-09-07 00:06:31 -05:00
|
|
|
MVert *mvert = BKE_mesh_verts_for_write(result);
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
MEdge *edges = BKE_mesh_edges_for_write(result);
|
2022-09-07 00:06:31 -05:00
|
|
|
MPoly *mpoly = BKE_mesh_polys_for_write(result);
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
MLoop *mloop = BKE_mesh_loops_for_write(result);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-17 13:45:47 +02:00
|
|
|
MLoopCol *mloopcols_index = CustomData_get_layer_named(
|
2022-04-20 09:10:10 -05:00
|
|
|
&result->ldata, CD_PROP_BYTE_COLOR, pimd->index_layer_name);
|
2018-05-17 13:45:47 +02:00
|
|
|
MLoopCol *mloopcols_value = CustomData_get_layer_named(
|
2022-04-20 09:10:10 -05:00
|
|
|
&result->ldata, CD_PROP_BYTE_COLOR, pimd->value_layer_name);
|
2018-04-18 12:14:28 +02:00
|
|
|
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");
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
for (p = part_start, p_skip = 0; p < part_end; p++) {
|
2016-12-28 17:30:58 +01:00
|
|
|
float prev_dir[3];
|
|
|
|
|
float frame[4]; /* frame orientation quaternion */
|
2018-06-06 22:17:06 +02:00
|
|
|
float p_random = psys_frand(psys, 77091 + 283 * p);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* skip particle? */
|
2019-04-22 09:15:10 +10:00
|
|
|
if (particle_skip(pimd, psys, p)) {
|
2016-12-28 17:30:58 +01:00
|
|
|
continue;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* set vertices coordinates */
|
|
|
|
|
for (k = 0; k < totvert; k++) {
|
|
|
|
|
ParticleKey state;
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
const MVert *inMV;
|
2018-04-18 12:14:28 +02:00
|
|
|
int vindex = p_skip * totvert + k;
|
|
|
|
|
MVert *mv = mvert + vindex;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
inMV = orig_mvert + k;
|
2018-05-17 13:45:47 +02:00
|
|
|
CustomData_copy_data(&mesh->vdata, &result->vdata, k, p_skip * totvert + k, 1);
|
2016-12-28 17:30:58 +01:00
|
|
|
*mv = *inMV;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
if (vert_part_index != NULL) {
|
|
|
|
|
vert_part_index[vindex] = p;
|
|
|
|
|
}
|
|
|
|
|
if (vert_part_value != NULL) {
|
|
|
|
|
vert_part_value[vindex] = p_random;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-26 21:35:18 +10:00
|
|
|
/* Change orientation based on object trackflag. */
|
2016-12-28 17:30:58 +01:00
|
|
|
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];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* 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);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
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);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:15:10 +10:00
|
|
|
if (trackneg) {
|
2016-12-28 17:30:58 +01:00
|
|
|
state.time = 1.0f - state.time;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
mv->co[axis] = 0.0;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
psys_get_particle_on_path(&sim, p, &state, 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
normalize_v3(state.vel);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* Incrementally Rotating Frame (Bishop Frame) */
|
|
|
|
|
if (k == 0) {
|
|
|
|
|
float hairmat[4][4];
|
|
|
|
|
float mat[3][3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:15:10 +10:00
|
|
|
if (p < psys->totpart) {
|
2018-04-18 12:14:28 +02:00
|
|
|
pa = psys->particles + p;
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
else {
|
|
|
|
|
ChildParticle *cpa = psys->child + (p - psys->totpart);
|
2018-06-06 22:17:06 +02:00
|
|
|
pa = psys->particles + (between ? cpa->pa[0] : cpa->parent);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-06-21 11:49:43 +02:00
|
|
|
psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, sim.psys->part->from, pa, hairmat);
|
2016-12-28 17:30:58 +01:00
|
|
|
copy_m3_m4(mat, hairmat);
|
|
|
|
|
/* to quaternion */
|
|
|
|
|
mat3_to_quat(frame, mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) {
|
2018-06-06 22:17:06 +02:00
|
|
|
float angle = 2.0f * M_PI *
|
|
|
|
|
(pimd->rotation +
|
|
|
|
|
pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f));
|
2020-08-07 22:36:11 +10:00
|
|
|
const float eul[3] = {0.0f, 0.0f, angle};
|
2018-04-18 12:14:28 +02:00
|
|
|
float rot[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
eul_to_quat(rot, eul);
|
|
|
|
|
mul_qt_qtqt(frame, frame, rot);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: direction is same as normal vector currently,
|
2016-12-28 17:30:58 +01:00
|
|
|
* 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];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* incrementally rotate along bend direction */
|
|
|
|
|
rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
|
|
|
|
|
mul_qt_qtqt(frame, rot, frame);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
copy_v3_v3(prev_dir, state.vel);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
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;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
cross_v3_v3v3(cross, temp, state.vel);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* 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;
|
2018-04-18 12:14:28 +02:00
|
|
|
psys_get_particle_state(&sim, p, &state, 1);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
mul_qt_v3(state.rot, mv->co);
|
2019-04-22 09:15:10 +10:00
|
|
|
if (pimd->flag & eParticleInstanceFlag_UseSize) {
|
2016-12-28 17:30:58 +01:00
|
|
|
mul_v3_fl(mv->co, size[p]);
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
add_v3_v3(mv->co, state.co);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
mul_m4_v3(spacemat, mv->co);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-26 21:35:18 +10:00
|
|
|
/* Create edges and adjust edge vertex indices. */
|
2018-05-17 13:45:47 +02:00
|
|
|
CustomData_copy_data(&mesh->edata, &result->edata, 0, p_skip * totedge, totedge);
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
MEdge *me = &edges[p_skip * totedge];
|
2018-05-04 09:20:57 +02:00
|
|
|
for (k = 0; k < totedge; k++, me++) {
|
|
|
|
|
me->v1 += p_skip * totvert;
|
|
|
|
|
me->v2 += p_skip * totvert;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* create polys and loops */
|
|
|
|
|
for (k = 0; k < totpoly; k++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
const MPoly *inMP = orig_mpoly + k;
|
2016-12-28 17:30:58 +01:00
|
|
|
MPoly *mp = mpoly + p_skip * totpoly + k;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-17 13:45:47 +02:00
|
|
|
CustomData_copy_data(&mesh->pdata, &result->pdata, k, p_skip * totpoly + k, 1);
|
2016-12-28 17:30:58 +01:00
|
|
|
*mp = *inMP;
|
|
|
|
|
mp->loopstart += p_skip * totloop;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
{
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
const MLoop *inML = orig_mloop + inMP->loopstart;
|
2016-12-28 17:30:58 +01:00
|
|
|
MLoop *ml = mloop + mp->loopstart;
|
|
|
|
|
int j = mp->totloop;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-17 13:45:47 +02:00
|
|
|
CustomData_copy_data(&mesh->ldata, &result->ldata, inMP->loopstart, mp->loopstart, j);
|
2016-12-28 17:30:58 +01:00
|
|
|
for (; j; j--, ml++, inML++) {
|
|
|
|
|
ml->v = inML->v + (p_skip * totvert);
|
2018-05-04 09:20:57 +02:00
|
|
|
ml->e = inML->e + (p_skip * totedge);
|
2018-04-18 12:14:28 +02:00
|
|
|
const int ml_index = (ml - mloop);
|
|
|
|
|
if (mloopcols_index != NULL) {
|
|
|
|
|
const int part_index = vert_part_index[ml->v];
|
2018-12-08 15:01:47 +11:00
|
|
|
store_float_in_vcol(&mloopcols_index[ml_index],
|
|
|
|
|
(float)part_index / (float)(psys->totpart - 1));
|
2018-04-18 12:14:28 +02:00
|
|
|
}
|
|
|
|
|
if (mloopcols_value != NULL) {
|
|
|
|
|
const float part_value = vert_part_value[ml->v];
|
|
|
|
|
store_float_in_vcol(&mloopcols_value[ml_index], part_value);
|
|
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p_skip++;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (psys->lattice_deform_data) {
|
2020-06-13 15:41:34 +10:00
|
|
|
BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
|
2016-12-28 17:30:58 +01:00
|
|
|
psys->lattice_deform_data = NULL;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:15:10 +10:00
|
|
|
if (size) {
|
2016-12-28 17:30:58 +01:00
|
|
|
MEM_freeN(size);
|
2019-04-22 09:15:10 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-18 12:14:28 +02:00
|
|
|
MEM_SAFE_FREE(vert_part_index);
|
|
|
|
|
MEM_SAFE_FREE(vert_part_value);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
return result;
|
|
|
|
|
}
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
2020-06-05 10:41:03 -04:00
|
|
|
{
|
|
|
|
|
uiLayout *row;
|
|
|
|
|
uiLayout *layout = panel->layout;
|
|
|
|
|
int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
|
|
|
|
|
|
|
|
|
|
PointerRNA ob_ptr;
|
2020-09-02 14:13:26 -05:00
|
|
|
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
PointerRNA particle_obj_ptr = RNA_pointer_get(ptr, "object");
|
2020-06-05 10:41:03 -04:00
|
|
|
|
|
|
|
|
uiLayoutSetPropSep(layout, true);
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
if (!RNA_pointer_is_null(&particle_obj_ptr)) {
|
|
|
|
|
uiItemPointerR(layout,
|
2020-09-02 14:13:26 -05:00
|
|
|
ptr,
|
2020-06-05 10:41:03 -04:00
|
|
|
"particle_system",
|
|
|
|
|
&particle_obj_ptr,
|
|
|
|
|
"particle_systems",
|
2022-08-09 12:42:16 +02:00
|
|
|
IFACE_("Particle System"),
|
2020-06-05 10:41:03 -04:00
|
|
|
ICON_NONE);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(layout, ptr, "particle_system_index", 0, IFACE_("Particle System"), ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uiItemS(layout);
|
|
|
|
|
|
|
|
|
|
row = uiLayoutRowWithHeading(layout, true, IFACE_("Create Instances"));
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(row, ptr, "use_normal", toggles_flag, NULL, ICON_NONE);
|
|
|
|
|
uiItemR(row, ptr, "use_children", toggles_flag, NULL, ICON_NONE);
|
|
|
|
|
uiItemR(row, ptr, "use_size", toggles_flag, NULL, ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
|
|
|
|
row = uiLayoutRowWithHeading(layout, true, IFACE_("Show"));
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(row, ptr, "show_alive", toggles_flag, NULL, ICON_NONE);
|
|
|
|
|
uiItemR(row, ptr, "show_dead", toggles_flag, NULL, ICON_NONE);
|
|
|
|
|
uiItemR(row, ptr, "show_unborn", toggles_flag, NULL, ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(layout, ptr, "particle_amount", 0, IFACE_("Amount"), ICON_NONE);
|
|
|
|
|
uiItemR(layout, ptr, "particle_offset", 0, IFACE_("Offset"), ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
|
|
|
|
uiItemS(layout);
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(layout, ptr, "space", 0, IFACE_("Coordinate Space"), ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
row = uiLayoutRow(layout, true);
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
modifier_panel_end(layout, ptr);
|
2020-06-05 10:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
static void path_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
|
2020-06-05 10:41:03 -04:00
|
|
|
{
|
|
|
|
|
uiLayout *layout = panel->layout;
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(layout, ptr, "use_path", 0, IFACE_("Create Along Paths"), ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
static void path_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
2020-06-05 10:41:03 -04:00
|
|
|
{
|
|
|
|
|
uiLayout *col;
|
|
|
|
|
uiLayout *layout = panel->layout;
|
|
|
|
|
|
|
|
|
|
PointerRNA ob_ptr;
|
2020-09-02 14:13:26 -05:00
|
|
|
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
|
|
|
|
uiLayoutSetPropSep(layout, true);
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_path"));
|
2020-06-05 10:41:03 -04:00
|
|
|
|
|
|
|
|
col = uiLayoutColumn(layout, true);
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(col, ptr, "position", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
|
|
|
|
|
uiItemR(col, ptr, "random_position", UI_ITEM_R_SLIDER, IFACE_("Random"), ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
col = uiLayoutColumn(layout, true);
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(col, ptr, "rotation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
|
|
|
|
|
uiItemR(col, ptr, "random_rotation", UI_ITEM_R_SLIDER, IFACE_("Random"), ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(layout, ptr, "use_preserve_shape", 0, NULL, ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
static void layers_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
2020-06-05 10:41:03 -04:00
|
|
|
{
|
UI: Small Tweaks to Modifier Layouts for Consistency
These changes are smaller, made based on feedback and a pass on all
the layouts for clarity and consistency. The Multires modifier UI will
be addressed in a separate patch. Here is an overview of the changes:
Renaming Options:
- Build: "Start" -> "Start Frame"
- Curve: "From Radius" -> "Size from Radius"
- Screw: "Calc Order" -> "Calculate Order"
- Displace, Warp, Wave: "Texture Coordinates Object" -> "Object"
Move Mode Toggle to Top & Expand:
- Bevel, Boolean, Normal Edit, Subdivision
Use Columns for Tighter Spacing:
- Displace, Explode, Ocean, Particle Instance, Remesh, Shrinkwrap,
Solidify, Warp, Weighted Normal, Wave
Misc:
- Bevel: Set inactive properties for vertex bevel
- Mesh Sequence Cache: Remove box for cache file
- Skin: Don't align "Mark Loose" and "Clear Loose"
- Array: Expand relative offset subpanel by default
- Array: Move start cap, end cap to a new subpanel
- Bevel: Move width type above width
Differential Revision: https://developer.blender.org/D8115
2020-07-02 10:47:02 -04:00
|
|
|
uiLayout *col;
|
2020-06-05 10:41:03 -04:00
|
|
|
uiLayout *layout = panel->layout;
|
|
|
|
|
|
|
|
|
|
PointerRNA ob_ptr;
|
2020-09-02 14:13:26 -05:00
|
|
|
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
|
|
|
|
PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
|
|
|
|
|
|
|
|
|
|
uiLayoutSetPropSep(layout, true);
|
|
|
|
|
|
UI: Small Tweaks to Modifier Layouts for Consistency
These changes are smaller, made based on feedback and a pass on all
the layouts for clarity and consistency. The Multires modifier UI will
be addressed in a separate patch. Here is an overview of the changes:
Renaming Options:
- Build: "Start" -> "Start Frame"
- Curve: "From Radius" -> "Size from Radius"
- Screw: "Calc Order" -> "Calculate Order"
- Displace, Warp, Wave: "Texture Coordinates Object" -> "Object"
Move Mode Toggle to Top & Expand:
- Bevel, Boolean, Normal Edit, Subdivision
Use Columns for Tighter Spacing:
- Displace, Explode, Ocean, Particle Instance, Remesh, Shrinkwrap,
Solidify, Warp, Weighted Normal, Wave
Misc:
- Bevel: Set inactive properties for vertex bevel
- Mesh Sequence Cache: Remove box for cache file
- Skin: Don't align "Mark Loose" and "Clear Loose"
- Array: Expand relative offset subpanel by default
- Array: Move start cap, end cap to a new subpanel
- Bevel: Move width type above width
Differential Revision: https://developer.blender.org/D8115
2020-07-02 10:47:02 -04:00
|
|
|
col = uiLayoutColumn(layout, false);
|
|
|
|
|
uiItemPointerR(
|
2020-09-02 14:13:26 -05:00
|
|
|
col, ptr, "index_layer_name", &obj_data_ptr, "vertex_colors", IFACE_("Index"), ICON_NONE);
|
UI: Small Tweaks to Modifier Layouts for Consistency
These changes are smaller, made based on feedback and a pass on all
the layouts for clarity and consistency. The Multires modifier UI will
be addressed in a separate patch. Here is an overview of the changes:
Renaming Options:
- Build: "Start" -> "Start Frame"
- Curve: "From Radius" -> "Size from Radius"
- Screw: "Calc Order" -> "Calculate Order"
- Displace, Warp, Wave: "Texture Coordinates Object" -> "Object"
Move Mode Toggle to Top & Expand:
- Bevel, Boolean, Normal Edit, Subdivision
Use Columns for Tighter Spacing:
- Displace, Explode, Ocean, Particle Instance, Remesh, Shrinkwrap,
Solidify, Warp, Weighted Normal, Wave
Misc:
- Bevel: Set inactive properties for vertex bevel
- Mesh Sequence Cache: Remove box for cache file
- Skin: Don't align "Mark Loose" and "Clear Loose"
- Array: Expand relative offset subpanel by default
- Array: Move start cap, end cap to a new subpanel
- Bevel: Move width type above width
Differential Revision: https://developer.blender.org/D8115
2020-07-02 10:47:02 -04:00
|
|
|
uiItemPointerR(
|
2020-09-02 14:13:26 -05:00
|
|
|
col, ptr, "value_layer_name", &obj_data_ptr, "vertex_colors", IFACE_("Value"), ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void panelRegister(ARegionType *region_type)
|
|
|
|
|
{
|
|
|
|
|
PanelType *panel_type = modifier_panel_register(
|
|
|
|
|
region_type, eModifierType_ParticleInstance, panel_draw);
|
|
|
|
|
modifier_subpanel_register(
|
|
|
|
|
region_type, "paths", "", path_panel_draw_header, path_panel_draw, panel_type);
|
|
|
|
|
modifier_subpanel_register(region_type, "layers", "Layers", NULL, layers_panel_draw, panel_type);
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
ModifierTypeInfo modifierType_ParticleInstance = {
|
2022-07-15 14:12:34 +02:00
|
|
|
/* name */ N_("ParticleInstance"),
|
2016-12-28 17:30:58 +01:00
|
|
|
/* structName */ "ParticleInstanceModifierData",
|
|
|
|
|
/* structSize */ sizeof(ParticleInstanceModifierData),
|
2020-09-25 12:49:18 +02:00
|
|
|
/* srna */ &RNA_ParticleInstanceModifier,
|
2016-12-28 17:30:58 +01:00
|
|
|
/* type */ eModifierTypeType_Constructive,
|
|
|
|
|
/* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping |
|
|
|
|
|
eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode,
|
2020-09-25 12:45:30 +02:00
|
|
|
/* icon */ ICON_MOD_PARTICLE_INSTANCE,
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-05-08 10:14:02 +02:00
|
|
|
/* copyData */ BKE_modifier_copydata_generic,
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* deformVerts */ NULL,
|
|
|
|
|
/* deformMatrices */ NULL,
|
|
|
|
|
/* deformVertsEM */ NULL,
|
|
|
|
|
/* deformMatricesEM */ NULL,
|
2020-04-21 13:09:41 +02:00
|
|
|
/* modifyMesh */ modifyMesh,
|
2020-12-10 14:35:02 +01:00
|
|
|
/* modifyGeometrySet */ NULL,
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
/* initData */ initData,
|
2018-04-18 12:14:28 +02:00
|
|
|
/* requiredDataMask */ requiredDataMask,
|
2016-12-28 17:30:58 +01:00
|
|
|
/* freeData */ NULL,
|
|
|
|
|
/* isDisabled */ isDisabled,
|
|
|
|
|
/* updateDepsgraph */ updateDepsgraph,
|
|
|
|
|
/* dependsOnTime */ NULL,
|
|
|
|
|
/* dependsOnNormals */ NULL,
|
2020-10-01 18:05:23 +02:00
|
|
|
/* foreachIDLink */ foreachIDLink,
|
2016-12-28 17:30:58 +01:00
|
|
|
/* foreachTexLink */ NULL,
|
2019-03-18 15:56:16 +01:00
|
|
|
/* freeRuntimeData */ NULL,
|
2020-06-05 10:41:03 -04:00
|
|
|
/* panelRegister */ panelRegister,
|
2020-06-15 17:37:07 +02:00
|
|
|
/* blendWrite */ NULL,
|
|
|
|
|
/* blendRead */ NULL,
|
2016-12-28 17:30:58 +01:00
|
|
|
};
|