Esempio n. 1
0
Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
                                           Scene *scene,
                                           Object *ob_eval,
                                           ModifierData *md_eval,
                                           int build_shapekey_layers)
{
  Mesh *me = ob_eval->runtime.mesh_orig ? ob_eval->runtime.mesh_orig : ob_eval->data;
  const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type);
  Mesh *result;
  KeyBlock *kb;
  ModifierEvalContext mectx = {depsgraph, ob_eval, 0};

  if (!(md_eval->mode & eModifierMode_Realtime)) {
    return NULL;
  }

  if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) {
    return NULL;
  }

  if (build_shapekey_layers && me->key &&
      (kb = BLI_findlink(&me->key->block, ob_eval->shapenr - 1))) {
    BKE_keyblock_convert_to_mesh(kb, me);
  }

  if (mti->type == eModifierTypeType_OnlyDeform) {
    int numVerts;
    float(*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts);

    BKE_id_copy_ex(NULL, &me->id, (ID **)&result, LIB_ID_COPY_LOCALIZE);
    mti->deformVerts(md_eval, &mectx, result, deformedVerts, numVerts);
    BKE_mesh_apply_vert_coords(result, deformedVerts);

    if (build_shapekey_layers) {
      add_shapekey_layers(result, me);
    }

    MEM_freeN(deformedVerts);
  }
  else {
    Mesh *mesh_temp;
    BKE_id_copy_ex(NULL, &me->id, (ID **)&mesh_temp, LIB_ID_COPY_LOCALIZE);

    if (build_shapekey_layers) {
      add_shapekey_layers(mesh_temp, me);
    }

    result = mti->applyModifier(md_eval, &mectx, mesh_temp);
    ASSERT_IS_VALID_MESH(result);

    if (mesh_temp != result) {
      BKE_id_free(NULL, mesh_temp);
    }
  }

  return result;
}
static void correctivesmooth_modifier_do(
        ModifierData *md, Object *ob, DerivedMesh *dm,
        float (*vertexCos)[3], unsigned int numVerts,
        struct BMEditMesh *em)
{
	CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;

	const bool force_delta_cache_update =
	        /* XXX, take care! if mesh data its self changes we need to forcefully recalculate deltas */
	        ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) &&
	         (((ID *)ob->data)->tag & LIB_TAG_ID_RECALC));

	bool use_only_smooth = (csmd->flag & MOD_CORRECTIVESMOOTH_ONLY_SMOOTH) != 0;
	MDeformVert *dvert = NULL;
	int defgrp_index;

	modifier_get_vgroup(ob, dm, csmd->defgrp_name, &dvert, &defgrp_index);

	/* if rest bind_coords not are defined, set them (only run during bind) */
	if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) &&
	    /* signal to recalculate, whoever sets MUST also free bind coords */
	    (csmd->bind_coords_num == (unsigned int)-1))
	{
		BLI_assert(csmd->bind_coords == NULL);
		csmd->bind_coords = MEM_dupallocN(vertexCos);
		csmd->bind_coords_num = numVerts;
		BLI_assert(csmd->bind_coords != NULL);
	}

	if (UNLIKELY(use_only_smooth)) {
		smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts);
		return;
	}

	if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) {
		modifier_setError(md, "Bind data required");
		goto error;
	}

	/* If the number of verts has changed, the bind is invalid, so we do nothing */
	if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
		if (csmd->bind_coords_num != numVerts) {
			modifier_setError(md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts);
			goto error;
		}
	}
	else {
		/* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */
		if (ob->type != OB_MESH) {
			modifier_setError(md, "Object is not a mesh");
			goto error;
		}
		else {
			unsigned int me_numVerts = (unsigned int)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert);

			if (me_numVerts != numVerts) {
				modifier_setError(md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts);
				goto error;
			}
		}
	}

	/* check to see if our deltas are still valid */
	if (!csmd->delta_cache || (csmd->delta_cache_num != numVerts) || force_delta_cache_update) {
		const float (*rest_coords)[3];
		bool is_rest_coords_alloc = false;

		if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
			/* caller needs to do sanity check here */
			csmd->bind_coords_num = numVerts;
			rest_coords = (const float (*)[3])csmd->bind_coords;
		}
		else {
			int me_numVerts;
			rest_coords = (const float (*)[3]) ((em) ?
			        BKE_editmesh_vertexCos_get_orco(em, &me_numVerts) :
			        BKE_mesh_vertexCos_get(ob->data, &me_numVerts));

			BLI_assert((unsigned int)me_numVerts == numVerts);
			is_rest_coords_alloc = true;
		}

#ifdef DEBUG_TIME
	TIMEIT_START(corrective_smooth_deltas);
#endif

		calc_deltas(csmd, dm, dvert, defgrp_index, rest_coords, numVerts);

#ifdef DEBUG_TIME
	TIMEIT_END(corrective_smooth_deltas);
#endif
		if (is_rest_coords_alloc) {
			MEM_freeN((void *)rest_coords);
		}
	}

	if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
		/* this could be a check, but at this point it _must_ be valid */
		BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache);
	}


#ifdef DEBUG_TIME
	TIMEIT_START(corrective_smooth);
#endif

	/* do the actual delta mush */
	smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts);

	{
		unsigned int i;

		float (*tangent_spaces)[3][3];

		/* calloc, since values are accumulated */
		tangent_spaces = MEM_callocN((size_t)numVerts * sizeof(float[3][3]), __func__);

		calc_tangent_spaces(dm, vertexCos, tangent_spaces);

		for (i = 0; i < numVerts; i++) {
			float delta[3];

#ifdef USE_TANGENT_CALC_INLINE
			calc_tangent_ortho(tangent_spaces[i]);
#endif

			mul_v3_m3v3(delta, tangent_spaces[i], csmd->delta_cache[i]);
			add_v3_v3(vertexCos[i], delta);
		}

		MEM_freeN(tangent_spaces);
	}

#ifdef DEBUG_TIME
	TIMEIT_END(corrective_smooth);
#endif

	return;

	/* when the modifier fails to execute */
error:
	MEM_SAFE_FREE(csmd->delta_cache);
	csmd->delta_cache_num = 0;

}