Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_convert.c
| Show First 20 Lines • Show All 831 Lines • ▼ Show 20 Lines | if (nurblist.first) { | ||||
| id_us_min(&((Mesh *)ob->data)->id); | id_us_min(&((Mesh *)ob->data)->id); | ||||
| ob->data = cu; | ob->data = cu; | ||||
| ob->type = OB_CURVE; | ob->type = OB_CURVE; | ||||
| BKE_object_free_derived_caches(ob); | BKE_object_free_derived_caches(ob); | ||||
| } | } | ||||
| } | } | ||||
| /* settings: 1 - preview, 2 - render */ | /* settings: 1 - preview, 2 - render | ||||
| * | |||||
| * The convention goes as following: | |||||
zeddb: Just a little grammar nitpick
`foes` -> `goes`
So:
`The convention goes as following:` | |||||
| * | |||||
| * - Passing original object with apply_modifiers=false will give a | |||||
| * non-modified non-deformed mesh. | |||||
| * The result mesh will point to datablocks from the original "domain". For | |||||
| * example, materials will be original. | |||||
| * | |||||
| * - Passing original object with apply_modifiers=true will give a mesh which | |||||
| * has all modifiers applied. | |||||
| * The result mesh will point to datablocks from the original "domain". For | |||||
| * example, materials will be original. | |||||
| * | |||||
| * - Passing evaluated object will ignore apply_modifiers argument, and the | |||||
| * result always contains all modifiers applied. | |||||
| * The result mesh will point to an evaluated datablocks. For example, | |||||
| * materials will be an evaluated IDs from the dependency graph. | |||||
| */ | |||||
| Mesh *BKE_mesh_new_from_object( | Mesh *BKE_mesh_new_from_object( | ||||
| Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob, | Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob, | ||||
| const bool apply_modifiers, const bool calc_undeformed) | const bool apply_modifiers, const bool calc_undeformed) | ||||
| { | { | ||||
| Mesh *tmpmesh; | Mesh *tmpmesh; | ||||
| Curve *tmpcu = NULL, *copycu; | Curve *tmpcu = NULL, *copycu; | ||||
| int i; | int i; | ||||
| const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); | const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); | ||||
| const bool cage = !apply_modifiers; | bool effective_apply_modifiers = apply_modifiers; | ||||
| bool do_mat_id_data_us = true; | bool do_mat_id_data_us = true; | ||||
| Object *object_input = ob; | |||||
| Object *object_eval = DEG_get_evaluated_object(depsgraph, object_input); | |||||
| Object object_for_eval = *object_eval; | |||||
| if (object_eval == object_input) { | |||||
| effective_apply_modifiers = false; | |||||
| } | |||||
| else { | |||||
| if (apply_modifiers) { | |||||
| if (object_for_eval.runtime.mesh_orig != NULL) { | |||||
| object_for_eval.data = object_for_eval.runtime.mesh_orig; | |||||
| } | |||||
| } | |||||
| } | |||||
| const bool cage = !effective_apply_modifiers; | |||||
| /* perform the mesh extraction based on type */ | /* perform the mesh extraction based on type */ | ||||
| switch (ob->type) { | switch (object_for_eval.type) { | ||||
| case OB_FONT: | case OB_FONT: | ||||
| case OB_CURVE: | case OB_CURVE: | ||||
| case OB_SURF: | case OB_SURF: | ||||
| { | { | ||||
| ListBase dispbase = {NULL, NULL}; | ListBase dispbase = {NULL, NULL}; | ||||
| Mesh *me_eval_final = NULL; | Mesh *me_eval_final = NULL; | ||||
| int uv_from_orco; | int uv_from_orco; | ||||
| /* copies object and modifiers (but not the data) */ | /* copies object and modifiers (but not the data) */ | ||||
| Object *tmpobj; | Object *tmpobj; | ||||
| BKE_id_copy_ex(NULL, &ob->id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE); | BKE_id_copy_ex(NULL, &object_for_eval.id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE); | ||||
| tmpcu = (Curve *)tmpobj->data; | tmpcu = (Curve *)tmpobj->data; | ||||
| /* Copy cached display list, it might be needed by the stack evaluation. | /* Copy cached display list, it might be needed by the stack evaluation. | ||||
| * Ideally stack should be able to use render-time display list, but doing | * Ideally stack should be able to use render-time display list, but doing | ||||
| * so is quite tricky and not safe so close to the release. | * so is quite tricky and not safe so close to the release. | ||||
| * | * | ||||
| * TODO(sergey): Look into more proper solution. | * TODO(sergey): Look into more proper solution. | ||||
| */ | */ | ||||
| if (ob->runtime.curve_cache != NULL) { | if (object_for_eval.runtime.curve_cache != NULL) { | ||||
| if (tmpobj->runtime.curve_cache == NULL) { | if (tmpobj->runtime.curve_cache == NULL) { | ||||
| tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types"); | tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types"); | ||||
| } | } | ||||
| BKE_displist_copy(&tmpobj->runtime.curve_cache->disp, &ob->runtime.curve_cache->disp); | BKE_displist_copy(&tmpobj->runtime.curve_cache->disp, &object_for_eval.runtime.curve_cache->disp); | ||||
| } | } | ||||
| /* if getting the original caged mesh, delete object modifiers */ | /* if getting the original caged mesh, delete object modifiers */ | ||||
| if (cage) | if (cage) | ||||
| BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT); | BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT); | ||||
| /* copies the data, but *not* the shapekeys. */ | /* copies the data, but *not* the shapekeys. */ | ||||
| BKE_id_copy_ex(NULL, ob->data, (ID **)©cu, LIB_ID_COPY_LOCALIZE); | BKE_id_copy_ex(NULL, object_for_eval.data, (ID **)©cu, LIB_ID_COPY_LOCALIZE); | ||||
| tmpobj->data = copycu; | tmpobj->data = copycu; | ||||
| /* make sure texture space is calculated for a copy of curve, | /* make sure texture space is calculated for a copy of curve, | ||||
| * it will be used for the final result. | * it will be used for the final result. | ||||
| */ | */ | ||||
| BKE_curve_texspace_calc(copycu); | BKE_curve_texspace_calc(copycu); | ||||
| /* temporarily set edit so we get updates from edit mode, but | /* temporarily set edit so we get updates from edit mode, but | ||||
| Show All 39 Lines | case OB_SURF: | ||||
| do_mat_id_data_us = false; | do_mat_id_data_us = false; | ||||
| break; | break; | ||||
| } | } | ||||
| case OB_MBALL: | case OB_MBALL: | ||||
| { | { | ||||
| /* metaballs don't have modifiers, so just convert to mesh */ | /* metaballs don't have modifiers, so just convert to mesh */ | ||||
| Object *basis_ob = BKE_mball_basis_find(sce, ob); | Object *basis_ob = BKE_mball_basis_find(sce, object_input); | ||||
| /* todo, re-generatre for render-res */ | /* todo, re-generatre for render-res */ | ||||
| /* metaball_polygonize(scene, ob) */ | /* metaball_polygonize(scene, ob) */ | ||||
| if (ob != basis_ob) | if (basis_ob != object_input) { | ||||
| return NULL; /* only do basis metaball */ | /* Only do basis metaball. */ | ||||
| return NULL; | |||||
| } | |||||
| tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2); | tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2); | ||||
| /* BKE_mesh_add gives us a user count we don't need */ | /* BKE_mesh_add gives us a user count we don't need */ | ||||
| id_us_min(&tmpmesh->id); | id_us_min(&tmpmesh->id); | ||||
| if (render) { | if (render) { | ||||
| ListBase disp = {NULL, NULL}; | ListBase disp = {NULL, NULL}; | ||||
| BKE_displist_make_mball_forRender(depsgraph, sce, ob, &disp); | BKE_displist_make_mball_forRender(depsgraph, sce, &object_for_eval, &disp); | ||||
| BKE_mesh_from_metaball(&disp, tmpmesh); | BKE_mesh_from_metaball(&disp, tmpmesh); | ||||
| BKE_displist_free(&disp); | BKE_displist_free(&disp); | ||||
| } | } | ||||
| else { | else { | ||||
| ListBase disp = {NULL, NULL}; | ListBase disp = {NULL, NULL}; | ||||
| if (ob->runtime.curve_cache) { | if (object_for_eval.runtime.curve_cache) { | ||||
| disp = ob->runtime.curve_cache->disp; | disp = object_for_eval.runtime.curve_cache->disp; | ||||
| } | } | ||||
| BKE_mesh_from_metaball(&disp, tmpmesh); | BKE_mesh_from_metaball(&disp, tmpmesh); | ||||
| } | } | ||||
| BKE_mesh_texspace_copy_from_object(tmpmesh, ob); | BKE_mesh_texspace_copy_from_object(tmpmesh, &object_for_eval); | ||||
| break; | break; | ||||
| } | } | ||||
| case OB_MESH: | case OB_MESH: | ||||
| /* copies object and modifiers (but not the data) */ | /* copies object and modifiers (but not the data) */ | ||||
| if (cage) { | if (cage) { | ||||
| /* copies the data (but *not* the shapekeys). */ | /* copies the data (but *not* the shapekeys). */ | ||||
| Mesh *mesh = ob->data; | Mesh *mesh = object_for_eval.data; | ||||
| BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0); | BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0); | ||||
| /* XXX BKE_mesh_copy() already handles materials usercount. */ | /* XXX BKE_mesh_copy() already handles materials usercount. */ | ||||
| do_mat_id_data_us = false; | do_mat_id_data_us = false; | ||||
| } | } | ||||
| /* if not getting the original caged mesh, get final derived mesh */ | /* if not getting the original caged mesh, get final derived mesh */ | ||||
| else { | else { | ||||
| /* Make a dummy mesh, saves copying */ | /* Make a dummy mesh, saves copying */ | ||||
| Mesh *me_eval; | Mesh *me_eval; | ||||
| CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter, | CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter, | ||||
| * for example, needs CD_MASK_MDEFORMVERT */ | * for example, needs CD_MASK_MDEFORMVERT */ | ||||
| if (calc_undeformed) { | if (calc_undeformed) { | ||||
| mask.vmask |= CD_MASK_ORCO; | mask.vmask |= CD_MASK_ORCO; | ||||
| } | } | ||||
| if (render) { | if (render) { | ||||
| me_eval = mesh_create_eval_final_render(depsgraph, sce, ob, &mask); | me_eval = mesh_create_eval_final_render(depsgraph, sce, &object_for_eval, &mask); | ||||
| } | } | ||||
| else { | else { | ||||
| me_eval = mesh_create_eval_final_view(depsgraph, sce, ob, &mask); | me_eval = mesh_create_eval_final_view(depsgraph, sce, &object_for_eval, &mask); | ||||
| } | } | ||||
| tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2); | tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2); | ||||
| BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, ob, &mask, true); | BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, &object_for_eval, &mask, true); | ||||
| /* Copy autosmooth settings from original mesh. */ | /* Copy autosmooth settings from original mesh. */ | ||||
| Mesh *me = (Mesh *)ob->data; | Mesh *me = (Mesh *)object_for_eval.data; | ||||
| tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH); | tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH); | ||||
| tmpmesh->smoothresh = me->smoothresh; | tmpmesh->smoothresh = me->smoothresh; | ||||
| } | } | ||||
| /* BKE_mesh_add/copy gives us a user count we don't need */ | /* BKE_mesh_add/copy gives us a user count we don't need */ | ||||
| id_us_min(&tmpmesh->id); | id_us_min(&tmpmesh->id); | ||||
| break; | break; | ||||
| default: | default: | ||||
| /* "Object does not have geometry data") */ | /* "Object does not have geometry data") */ | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* Copy materials to new mesh */ | /* Copy materials to new mesh */ | ||||
| switch (ob->type) { | switch (object_for_eval.type) { | ||||
| case OB_SURF: | case OB_SURF: | ||||
| case OB_FONT: | case OB_FONT: | ||||
| case OB_CURVE: | case OB_CURVE: | ||||
| tmpmesh->totcol = tmpcu->totcol; | tmpmesh->totcol = tmpcu->totcol; | ||||
| /* free old material list (if it exists) and adjust user counts */ | /* free old material list (if it exists) and adjust user counts */ | ||||
| if (tmpcu->mat) { | if (tmpcu->mat) { | ||||
| for (i = tmpcu->totcol; i-- > 0; ) { | for (i = tmpcu->totcol; i-- > 0; ) { | ||||
| /* are we an object material or data based? */ | /* are we an object material or data based? */ | ||||
| tmpmesh->mat[i] = give_current_material(ob, i + 1); | tmpmesh->mat[i] = give_current_material(object_input, i + 1); | ||||
| if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { | if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { | ||||
| id_us_plus(&tmpmesh->mat[i]->id); | id_us_plus(&tmpmesh->mat[i]->id); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| case OB_MBALL: | case OB_MBALL: | ||||
| { | { | ||||
| MetaBall *tmpmb = (MetaBall *)ob->data; | MetaBall *tmpmb = (MetaBall *)object_for_eval.data; | ||||
| tmpmesh->mat = MEM_dupallocN(tmpmb->mat); | tmpmesh->mat = MEM_dupallocN(tmpmb->mat); | ||||
| tmpmesh->totcol = tmpmb->totcol; | tmpmesh->totcol = tmpmb->totcol; | ||||
| /* free old material list (if it exists) and adjust user counts */ | /* free old material list (if it exists) and adjust user counts */ | ||||
| if (tmpmb->mat) { | if (tmpmb->mat) { | ||||
| for (i = tmpmb->totcol; i-- > 0; ) { | for (i = tmpmb->totcol; i-- > 0; ) { | ||||
| /* are we an object material or data based? */ | /* are we an object material or data based? */ | ||||
| tmpmesh->mat[i] = give_current_material(ob, i + 1); | tmpmesh->mat[i] = give_current_material(object_input, i + 1); | ||||
| if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { | if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { | ||||
| id_us_plus(&tmpmesh->mat[i]->id); | id_us_plus(&tmpmesh->mat[i]->id); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case OB_MESH: | case OB_MESH: | ||||
| if (!cage) { | if (!cage) { | ||||
| Mesh *origmesh = ob->data; | Mesh *origmesh = object_for_eval.data; | ||||
| tmpmesh->flag = origmesh->flag; | tmpmesh->flag = origmesh->flag; | ||||
| tmpmesh->mat = MEM_dupallocN(origmesh->mat); | tmpmesh->mat = MEM_dupallocN(origmesh->mat); | ||||
| tmpmesh->totcol = origmesh->totcol; | tmpmesh->totcol = origmesh->totcol; | ||||
| tmpmesh->smoothresh = origmesh->smoothresh; | tmpmesh->smoothresh = origmesh->smoothresh; | ||||
| if (origmesh->mat) { | if (origmesh->mat) { | ||||
| for (i = origmesh->totcol; i-- > 0; ) { | for (i = origmesh->totcol; i-- > 0; ) { | ||||
| /* are we an object material or data based? */ | /* are we an object material or data based? */ | ||||
| tmpmesh->mat[i] = give_current_material(ob, i + 1); | tmpmesh->mat[i] = give_current_material(object_input, i + 1); | ||||
| if (((ob->matbits && ob->matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { | if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { | ||||
| id_us_plus(&tmpmesh->mat[i]->id); | id_us_plus(&tmpmesh->mat[i]->id); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } /* end copy materials */ | } /* end copy materials */ | ||||
| Show All 38 Lines | static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src) | ||||
| } | } | ||||
| } | } | ||||
| Mesh *BKE_mesh_create_derived_for_modifier( | Mesh *BKE_mesh_create_derived_for_modifier( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, | struct Depsgraph *depsgraph, Scene *scene, Object *ob, | ||||
| ModifierData *md, int build_shapekey_layers) | ModifierData *md, int build_shapekey_layers) | ||||
| { | { | ||||
| Mesh *me = ob->data; | Mesh *me = ob->runtime.mesh_orig ? ob->runtime.mesh_orig : ob->data; | ||||
| const ModifierTypeInfo *mti = modifierType_getInfo(md->type); | const ModifierTypeInfo *mti = modifierType_getInfo(md->type); | ||||
| Mesh *result; | Mesh *result; | ||||
| KeyBlock *kb; | KeyBlock *kb; | ||||
| ModifierEvalContext mectx = {depsgraph, ob, 0}; | ModifierEvalContext mectx = {depsgraph, ob, 0}; | ||||
| if (!(md->mode & eModifierMode_Realtime)) { | if (!(md->mode & eModifierMode_Realtime)) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 273 Lines • Show Last 20 Lines | |||||
Just a little grammar nitpick
foes -> goes
So:
The convention goes as following: