Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c
- This file was moved from source/blender/modifiers/intern/MOD_gpencilinstance.c.
| Show All 29 Lines | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_gpencil_types.h" | #include "DNA_gpencil_types.h" | ||||
| #include "DNA_gpencil_modifier_types.h" | |||||
| #include "BLI_blenlib.h" | #include "BLI_blenlib.h" | ||||
| #include "BLI_rand.h" | #include "BLI_rand.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BKE_gpencil.h" | #include "BKE_gpencil.h" | ||||
| #include "BKE_gpencil_modifier.h" | |||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_object.h" | #include "BKE_object.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "BKE_layer.h" | #include "BKE_layer.h" | ||||
| #include "BKE_collection.h" | #include "BKE_collection.h" | ||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_build.h" | #include "DEG_depsgraph_build.h" | ||||
| #include "MOD_modifiertypes.h" | |||||
| #include "MOD_gpencil_util.h" | #include "MOD_gpencil_util.h" | ||||
| #include "MOD_gpencil_modifiertypes.h" | |||||
| static void initData(ModifierData *md) | static void initData(GpencilModifierData *md) | ||||
| { | { | ||||
| InstanceGpencilModifierData *gpmd = (InstanceGpencilModifierData *)md; | InstanceGpencilModifierData *gpmd = (InstanceGpencilModifierData *)md; | ||||
| gpmd->count[0] = 1; | gpmd->count[0] = 1; | ||||
| gpmd->count[1] = 1; | gpmd->count[1] = 1; | ||||
| gpmd->count[2] = 1; | gpmd->count[2] = 1; | ||||
| gpmd->offset[0] = 1.0f; | gpmd->offset[0] = 1.0f; | ||||
| gpmd->offset[1] = 1.0f; | gpmd->offset[1] = 1.0f; | ||||
| gpmd->offset[2] = 1.0f; | gpmd->offset[2] = 1.0f; | ||||
| gpmd->shift[0] = 0.0f; | gpmd->shift[0] = 0.0f; | ||||
| gpmd->shift[1] = 0.0f; | gpmd->shift[1] = 0.0f; | ||||
| gpmd->shift[2] = 0.0f; | gpmd->shift[2] = 0.0f; | ||||
| gpmd->scale[0] = 1.0f; | gpmd->scale[0] = 1.0f; | ||||
| gpmd->scale[1] = 1.0f; | gpmd->scale[1] = 1.0f; | ||||
| gpmd->scale[2] = 1.0f; | gpmd->scale[2] = 1.0f; | ||||
| gpmd->rnd_rot = 0.5f; | gpmd->rnd_rot = 0.5f; | ||||
| gpmd->rnd_size = 0.5f; | gpmd->rnd_size = 0.5f; | ||||
| gpmd->lock_axis |= GP_LOCKAXIS_X; | gpmd->lock_axis |= GP_LOCKAXIS_X; | ||||
| gpmd->flag |= GP_INSTANCE_MAKE_OBJECTS; | gpmd->flag |= GP_INSTANCE_MAKE_OBJECTS; | ||||
| /* fill random values */ | /* fill random values */ | ||||
| BLI_array_frand(gpmd->rnd, 20, 1); | BLI_array_frand(gpmd->rnd, 20, 1); | ||||
| gpmd->rnd[0] = 1; | gpmd->rnd[0] = 1; | ||||
| } | } | ||||
| static void copyData(const ModifierData *md, ModifierData *target) | static void copyData(const GpencilModifierData *md, GpencilModifierData *target) | ||||
| { | { | ||||
| modifier_copyData_generic(md, target); | BKE_gpencil_modifier_copyData_generic(md, target); | ||||
| } | |||||
| /* -------------------------------- */ | |||||
| /* helper function for per-instance positioning */ | |||||
| void BKE_gpencil_instance_modifier_instance_tfm(InstanceGpencilModifierData *mmd, const int elem_idx[3], float r_mat[4][4]) | |||||
| { | |||||
| float offset[3], rot[3], scale[3]; | |||||
| int ri = mmd->rnd[0]; | |||||
| float factor; | |||||
| offset[0] = mmd->offset[0] * elem_idx[0]; | |||||
| offset[1] = mmd->offset[1] * elem_idx[1]; | |||||
| offset[2] = mmd->offset[2] * elem_idx[2]; | |||||
| /* rotation */ | |||||
| if (mmd->flag & GP_INSTANCE_RANDOM_ROT) { | |||||
| factor = mmd->rnd_rot * mmd->rnd[ri]; | |||||
| mul_v3_v3fl(rot, mmd->rot, factor); | |||||
| add_v3_v3(rot, mmd->rot); | |||||
| } | |||||
| else { | |||||
| copy_v3_v3(rot, mmd->rot); | |||||
| } | |||||
| /* scale */ | |||||
| if (mmd->flag & GP_INSTANCE_RANDOM_SIZE) { | |||||
| factor = mmd->rnd_size * mmd->rnd[ri]; | |||||
| mul_v3_v3fl(scale, mmd->scale, factor); | |||||
| add_v3_v3(scale, mmd->scale); | |||||
| } | |||||
| else { | |||||
| copy_v3_v3(scale, mmd->scale); | |||||
| } | |||||
| /* advance random index */ | |||||
| mmd->rnd[0]++; | |||||
| if (mmd->rnd[0] > 19) { | |||||
| mmd->rnd[0] = 1; | |||||
| } | |||||
| /* calculate matrix */ | |||||
| loc_eul_size_to_mat4(r_mat, offset, rot, scale); | |||||
| } | } | ||||
| /* -------------------------------- */ | /* -------------------------------- */ | ||||
| /* array modifier - generate geometry callback (for viewport/rendering) */ | /* array modifier - generate geometry callback (for viewport/rendering) */ | ||||
| /* TODO: How to skip this for the simplify options? --> !GP_SIMPLIFY_MODIF(ts, playing) */ | /* TODO: How to skip this for the simplify options? --> !GP_SIMPLIFY_MODIF(ts, playing) */ | ||||
| static void generate_geometry( | static void generate_geometry( | ||||
| ModifierData *md, Depsgraph *UNUSED(depsgraph), | GpencilModifierData *md, Depsgraph *UNUSED(depsgraph), | ||||
| Object *ob, bGPDlayer *gpl, bGPDframe *gpf) | Object *ob, bGPDlayer *gpl, bGPDframe *gpf) | ||||
| { | { | ||||
| InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | ||||
| ListBase stroke_cache = {NULL, NULL}; | ListBase stroke_cache = {NULL, NULL}; | ||||
| bGPDstroke *gps; | bGPDstroke *gps; | ||||
| int idx; | int idx; | ||||
| /* Check which strokes we can use once, and store those results in an array | /* Check which strokes we can use once, and store those results in an array | ||||
| ▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | static void generate_geometry( | ||||
| /* free temp data */ | /* free temp data */ | ||||
| MEM_SAFE_FREE(valid_strokes); | MEM_SAFE_FREE(valid_strokes); | ||||
| } | } | ||||
| /* gp_bakeModifier - "Bake to Data" Mode */ | /* gp_bakeModifier - "Bake to Data" Mode */ | ||||
| static void bakeModifierGP_strokes( | static void bakeModifierGP_strokes( | ||||
| Depsgraph *depsgraph, | Depsgraph *depsgraph, | ||||
| ModifierData *md, Object *ob) | GpencilModifierData *md, Object *ob) | ||||
| { | { | ||||
| bGPdata *gpd = ob->data; | bGPdata *gpd = ob->data; | ||||
| for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { | for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { | ||||
| for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { | for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { | ||||
| generate_geometry(md, depsgraph, ob, gpl, gpf); | generate_geometry(md, depsgraph, ob, gpl, gpf); | ||||
| } | } | ||||
| } | } | ||||
| Show All 15 Lines | static Object *array_instance_add_ob_copy(Main *bmain, Scene *scene, Object *from_ob) | ||||
| DEG_id_type_tag(bmain, ID_OB); | DEG_id_type_tag(bmain, ID_OB); | ||||
| DEG_relations_tag_update(bmain); | DEG_relations_tag_update(bmain); | ||||
| DEG_id_tag_update(&scene->id, 0); | DEG_id_tag_update(&scene->id, 0); | ||||
| return ob; | return ob; | ||||
| } | } | ||||
| /* gp_bakeModifier - "Make Objects" Mode */ | /* gp_bakeModifier - "Make Objects" Mode */ | ||||
| static void bakeModifierGP_objects(Main *bmain, ModifierData *md, Object *ob) | static void bakeModifierGP_objects(Main *bmain, GpencilModifierData *md, Object *ob) | ||||
| { | { | ||||
| InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | ||||
| Scene *scene = md->scene; | Scene *scene = md->scene; | ||||
| /* reset random */ | /* reset random */ | ||||
| mmd->rnd[0] = 1; | mmd->rnd[0] = 1; | ||||
| /* generate instances as objects */ | /* generate instances as objects */ | ||||
| for (int x = 0; x < mmd->count[0]; x++) { | for (int x = 0; x < mmd->count[0]; x++) { | ||||
| for (int y = 0; y < mmd->count[1]; y++) { | for (int y = 0; y < mmd->count[1]; y++) { | ||||
| for (int z = 0; z < mmd->count[2]; z++) { | for (int z = 0; z < mmd->count[2]; z++) { | ||||
| Object *newob; | Object *newob; | ||||
| ModifierData *fmd; | GpencilModifierData *fmd; | ||||
| const int elem_idx[3] = {x, y, z}; | const int elem_idx[3] = {x, y, z}; | ||||
| float mat[4][4], finalmat[4][4]; | float mat[4][4], finalmat[4][4]; | ||||
| int sh; | int sh; | ||||
| /* original strokes are at index = 0,0,0 */ | /* original strokes are at index = 0,0,0 */ | ||||
| if ((x == 0) && (y == 0) && (z == 0)) { | if ((x == 0) && (y == 0) && (z == 0)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| Show All 17 Lines | for (int y = 0; y < mmd->count[1]; y++) { | ||||
| * NOTE: Copies share the same original GP datablock | * NOTE: Copies share the same original GP datablock | ||||
| * Artists can later user make_single_user on these | * Artists can later user make_single_user on these | ||||
| * to make them unique (if necessary), without too | * to make them unique (if necessary), without too | ||||
| * much extra memory usage. | * much extra memory usage. | ||||
| */ | */ | ||||
| newob = array_instance_add_ob_copy(bmain, scene, ob); | newob = array_instance_add_ob_copy(bmain, scene, ob); | ||||
| /* remove array on destination object */ | /* remove array on destination object */ | ||||
| fmd = (ModifierData *)BLI_findstring(&newob->modifiers, md->name, offsetof(ModifierData, name)); | fmd = (GpencilModifierData *)BLI_findstring(&newob->modifiers, md->name, offsetof(GpencilModifierData, name)); | ||||
| if (fmd) { | if (fmd) { | ||||
| BLI_remlink(&newob->modifiers, fmd); | BLI_remlink(&newob->modifiers, fmd); | ||||
| modifier_free(fmd); | BKE_gpencil_modifier_free(fmd); | ||||
| } | } | ||||
| /* copy transforms to destination object */ | /* copy transforms to destination object */ | ||||
| copy_m4_m4(newob->obmat, finalmat); | copy_m4_m4(newob->obmat, finalmat); | ||||
| copy_v3_v3(newob->loc, finalmat[3]); | copy_v3_v3(newob->loc, finalmat[3]); | ||||
| mat4_to_eul(newob->rot, finalmat); | mat4_to_eul(newob->rot, finalmat); | ||||
| mat4_to_size(newob->size, finalmat); | mat4_to_size(newob->size, finalmat); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* -------------------------------- */ | /* -------------------------------- */ | ||||
| /* Generic "gp_generateStrokes" callback */ | /* Generic "gp_generateStrokes" callback */ | ||||
| static void gp_generateStrokes( | static void gp_generateStrokes( | ||||
| ModifierData *md, Depsgraph *depsgraph, | GpencilModifierData *md, Depsgraph *depsgraph, | ||||
| Object *ob, bGPDlayer *gpl, bGPDframe *gpf) | Object *ob, bGPDlayer *gpl, bGPDframe *gpf) | ||||
| { | { | ||||
| InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | ||||
| /* When the "make_objects" flag is set, this modifier is handled as part of the | /* When the "make_objects" flag is set, this modifier is handled as part of the | ||||
| * draw engine instead. The main benefit is that the instances won't suffer from | * draw engine instead. The main benefit is that the instances won't suffer from | ||||
| * z-ordering problems. | * z-ordering problems. | ||||
| * | * | ||||
| * FIXME: Ultimately, the draw-engine hack here shouldn't be necessary, but until | * FIXME: Ultimately, the draw-engine hack here shouldn't be necessary, but until | ||||
| * we find a better fix to the z-ordering problems, it's better to have | * we find a better fix to the z-ordering problems, it's better to have | ||||
| * working functionality | * working functionality | ||||
| */ | */ | ||||
| if ((mmd->flag & GP_INSTANCE_MAKE_OBJECTS) == 0) { | if ((mmd->flag & GP_INSTANCE_MAKE_OBJECTS) == 0) { | ||||
| generate_geometry(md, depsgraph, ob, gpl, gpf); | generate_geometry(md, depsgraph, ob, gpl, gpf); | ||||
| } | } | ||||
| } | } | ||||
| /* Generic "gp_bakeModifier" callback */ | /* Generic "gp_bakeModifier" callback */ | ||||
| static void gp_bakeModifier( | static void gp_bakeModifier( | ||||
| Main *bmain, Depsgraph *depsgraph, | Main *bmain, Depsgraph *depsgraph, | ||||
| ModifierData *md, Object *ob) | GpencilModifierData *md, Object *ob) | ||||
| { | { | ||||
| InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; | ||||
| /* Create new objects or add all to current datablock. | /* Create new objects or add all to current datablock. | ||||
| * Sometimes it's useful to have the option to do either of these... | * Sometimes it's useful to have the option to do either of these... | ||||
| */ | */ | ||||
| if (mmd->flag & GP_INSTANCE_MAKE_OBJECTS) { | if (mmd->flag & GP_INSTANCE_MAKE_OBJECTS) { | ||||
| bakeModifierGP_objects(bmain, md, ob); | bakeModifierGP_objects(bmain, md, ob); | ||||
| } | } | ||||
| else { | else { | ||||
| bakeModifierGP_strokes(depsgraph, md, ob); | bakeModifierGP_strokes(depsgraph, md, ob); | ||||
| } | } | ||||
| } | } | ||||
| ModifierTypeInfo modifierType_Gpencil_Instance = { | GpencilModifierTypeInfo modifierType_Gpencil_Instance = { | ||||
| /* name */ "Instance", | /* name */ "Instance", | ||||
| /* structName */ "InstanceGpencilModifierData", | /* structName */ "InstanceGpencilModifierData", | ||||
| /* structSize */ sizeof(InstanceGpencilModifierData), | /* structSize */ sizeof(InstanceGpencilModifierData), | ||||
| /* type */ eModifierTypeType_Gpencil, | /* type */ eGpencilModifierTypeType_Gpencil, | ||||
| /* flags */ eModifierTypeFlag_GpencilMod | eModifierTypeFlag_SupportsEditmode, | /* flags */ 0, | ||||
| /* copyData */ copyData, | /* copyData */ copyData, | ||||
| /* deformVerts_DM */ NULL, | |||||
| /* deformMatrices_DM */ NULL, | |||||
| /* deformVertsEM_DM */ NULL, | |||||
| /* deformMatricesEM_DM*/NULL, | |||||
| /* applyModifier_DM */ NULL, | |||||
| /* applyModifierEM_DM */NULL, | |||||
| /* deformVerts */ NULL, | |||||
| /* deformMatrices */ NULL, | |||||
| /* deformVertsEM */ NULL, | |||||
| /* deformMatricesEM */ NULL, | |||||
| /* applyModifier */ NULL, | |||||
| /* applyModifierEM */ NULL, | |||||
| /* gp_deformStroke */ NULL, | /* gp_deformStroke */ NULL, | ||||
| /* gp_generateStrokes */ gp_generateStrokes, | /* gp_generateStrokes */ gp_generateStrokes, | ||||
| /* gp_bakeModifier */ gp_bakeModifier, | /* gp_bakeModifier */ gp_bakeModifier, | ||||
| /* initData */ initData, | /* initData */ initData, | ||||
| /* requiredDataMask */ NULL, | |||||
| /* freeData */ NULL, | /* freeData */ NULL, | ||||
| /* isDisabled */ NULL, | /* isDisabled */ NULL, | ||||
| /* updateDepsgraph */ NULL, | /* updateDepsgraph */ NULL, | ||||
| /* dependsOnTime */ NULL, | /* dependsOnTime */ NULL, | ||||
| /* dependsOnNormals */ NULL, | |||||
| /* foreachObjectLink */ NULL, | /* foreachObjectLink */ NULL, | ||||
| /* foreachIDLink */ NULL, | /* foreachIDLink */ NULL, | ||||
| /* foreachTexLink */ NULL, | /* foreachTexLink */ NULL, | ||||
| }; | }; | ||||