コード例 #1
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag flag)
{
	SubsurfModifierData *smd = (SubsurfModifierData *) md;
	SubsurfFlags subsurf_flags = 0;
	DerivedMesh *result;
	const int useRenderParams = flag & MOD_APPLY_RENDER;
	const int isFinalCalc = flag & MOD_APPLY_USECACHE;

	if (useRenderParams)
		subsurf_flags |= SUBSURF_USE_RENDER_PARAMS;
	if (isFinalCalc)
		subsurf_flags |= SUBSURF_IS_FINAL_CALC;
	if (ob->flag & OB_MODE_EDIT)
		subsurf_flags |= SUBSURF_IN_EDIT_MODE;
	
	result = subsurf_make_derived_from_derived(derivedData, smd, NULL, subsurf_flags);
	
	if (useRenderParams || !isFinalCalc) {
		DerivedMesh *cddm = CDDM_copy(result);
		result->release(result);
		result = cddm;
	}

	return result;
}
コード例 #2
0
ファイル: MOD_multires.c プロジェクト: OldBrunet/BGERTPS
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
						   int useRenderParams, int isFinalCalc)
{
	SculptSession *ss= ob->sculpt;
	int sculpting= (ob->mode & OB_MODE_SCULPT) && ss;
	MultiresModifierData *mmd = (MultiresModifierData*)md;
	DerivedMesh *result;
	Mesh *me= (Mesh*)ob->data;

	if(mmd->totlvl) {
		if(!CustomData_get_layer(&me->fdata, CD_MDISPS)) {
			/* multires always needs a displacement layer */
			CustomData_add_layer(&me->fdata, CD_MDISPS, CD_CALLOC, NULL, me->totface);
		}
	}

	result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc);

	if(result == dm)
		return dm;

	if(useRenderParams || !isFinalCalc) {
		DerivedMesh *cddm= CDDM_copy(result);
		result->release(result);
		result= cddm;
	}
	else if(sculpting) {
		/* would be created on the fly too, just nicer this
		   way on first stroke after e.g. switching levels */
		ss->pbvh= result->getPBVH(ob, result);
	}

	return result;
}
コード例 #3
0
ファイル: MOD_cloth.c プロジェクト: vanangamudi/blender-main
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3],
                        int UNUSED(numVerts), ModifierApplyFlag UNUSED(flag))
{
	DerivedMesh *dm;
	ClothModifierData *clmd = (ClothModifierData *) md;
	DerivedMesh *result = NULL;
	
	/* check for alloc failing */
	if (!clmd->sim_parms || !clmd->coll_parms) {
		initData(md);

		if (!clmd->sim_parms || !clmd->coll_parms)
			return;
	}

	dm = get_dm(ob, NULL, derivedData, NULL, 0);
	if (dm == derivedData)
		dm = CDDM_copy(dm);

	CDDM_apply_vert_coords(dm, vertexCos);

	DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */

	clothModifier_do(clmd, md->scene, ob, dm, vertexCos);

	if (result) {
		result->getVertCos(result, vertexCos);
		result->release(result);
	}

	dm->release(dm);
}
コード例 #4
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag flag)
{
	SubsurfModifierData *smd = (SubsurfModifierData *) md;
	SubsurfFlags subsurf_flags = 0;
	DerivedMesh *result;
	const bool useRenderParams = (flag & MOD_APPLY_RENDER) != 0;
	const bool isFinalCalc = (flag & MOD_APPLY_USECACHE) != 0;

#ifdef WITH_OPENSUBDIV
	const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0;
	const bool do_cddm_convert = useRenderParams || (!isFinalCalc && !smd->use_opensubdiv);
#else
	const bool do_cddm_convert = useRenderParams || !isFinalCalc;
#endif

	if (useRenderParams)
		subsurf_flags |= SUBSURF_USE_RENDER_PARAMS;
	if (isFinalCalc)
		subsurf_flags |= SUBSURF_IS_FINAL_CALC;
	if (ob->mode & OB_MODE_EDIT)
		subsurf_flags |= SUBSURF_IN_EDIT_MODE;

#ifdef WITH_OPENSUBDIV
	/* TODO(sergey): Not entirely correct, modifiers on top of subsurf
	 * could be disabled.
	 */
	if (md->next == NULL &&
	    allow_gpu &&
	    do_cddm_convert == false &&
	    smd->use_opensubdiv)
	{
		if (U.opensubdiv_compute_type == USER_OPENSUBDIV_COMPUTE_NONE) {
			modifier_setError(md, "OpenSubdiv is disabled in User Preferences");
		}
		else if ((DAG_get_eval_flags_for_object(md->scene, ob) & DAG_EVAL_NEED_CPU) == 0) {
			subsurf_flags |= SUBSURF_USE_GPU_BACKEND;
		}
		else {
			modifier_setError(md, "OpenSubdiv is disabled due to dependencies");
		}
	}
#endif

	result = subsurf_make_derived_from_derived(derivedData, smd, NULL, subsurf_flags);
	result->cd_flag = derivedData->cd_flag;

	if (do_cddm_convert) {
		DerivedMesh *cddm = CDDM_copy(result);
		result->release(result);
		result = cddm;
	}

	return result;
}
コード例 #5
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
                                  ModifierApplyFlag flag)
{
	MultiresModifierData *mmd = (MultiresModifierData *)md;
	DerivedMesh *result;
	Mesh *me = (Mesh *)ob->data;
	const int useRenderParams = flag & MOD_APPLY_RENDER;

	if (mmd->totlvl) {
		if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) {
			/* multires always needs a displacement layer */
			CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop);
		}
	}

	result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams);

	if (result == dm)
		return dm;

	if(useRenderParams || !(flag & MOD_APPLY_USECACHE)) {
		DerivedMesh *cddm;
		
		cddm = CDDM_copy(result);

		/* copy hidden flag to vertices */
		if (!useRenderParams) {
			struct MDisps *mdisps;
			mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
			if (mdisps) {
				subsurf_copy_grid_hidden(result, me->mpoly,
				                         cddm->getVertArray(cddm),
				                         mdisps);

				BKE_mesh_flush_hidden_from_verts(cddm->getVertArray(cddm),
				                                 cddm->getLoopArray(cddm),
				                                 cddm->getEdgeArray(cddm),
				                                 cddm->getNumEdges(cddm),
				                                 cddm->getPolyArray(cddm),
				                                 cddm->getNumPolys(cddm));
			}
		}

		result->release(result);
		result = cddm;
	}

	return result;
}
コード例 #6
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
	DerivedMesh *dm = derivedData;
	ReportList reports;

	/* Only used to check wehther we are operating on org data or not... */
	Mesh *me = ob->data;
	MVert *mvert;

	const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;

	const float max_dist = (dtmd->flags & MOD_DATATRANSFER_MAP_MAXDIST) ? dtmd->map_max_distance : FLT_MAX;

	SpaceTransform space_transform_data;
	SpaceTransform *space_transform = (dtmd->flags & MOD_DATATRANSFER_OBSRC_TRANSFORM) ? &space_transform_data : NULL;

	if (space_transform) {
		BLI_SPACE_TRANSFORM_SETUP(space_transform, ob, dtmd->ob_source);
	}

	mvert = dm->getVertArray(dm);
	if ((me->mvert == mvert) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) {
		/* We need to duplicate data here, otherwise setting custom normals, edges' shaprness, etc., could
		 * modify org mesh, see T43671. */
		dm = CDDM_copy(dm);
	}

	BKE_reports_init(&reports, RPT_STORE);

	/* Note: no islands precision for now here. */
	BKE_object_data_transfer_dm(md->scene, dtmd->ob_source, ob, dm, dtmd->data_types, false,
	                     dtmd->vmap_mode, dtmd->emap_mode, dtmd->lmap_mode, dtmd->pmap_mode,
	                     space_transform, max_dist, dtmd->map_ray_radius, 0.0f,
	                     dtmd->layers_select_src, dtmd->layers_select_dst,
	                     dtmd->mix_mode, dtmd->mix_factor, dtmd->defgrp_name, invert_vgroup, &reports);

	if (BKE_reports_contain(&reports, RPT_ERROR)) {
		modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR));
	}
	else if (dm->getNumVerts(dm) > HIGH_POLY_WARNING || ((Mesh *)(dtmd->ob_source->data))->totvert > HIGH_POLY_WARNING) {
		modifier_setError(md, "You are using a rather high poly as source or destination, computation might be slow");
	}

	return dm;
}
コード例 #7
0
ファイル: MOD_cloth.c プロジェクト: mcgrathd/blender
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3],
                        int numVerts, ModifierApplyFlag UNUSED(flag))
{
	DerivedMesh *dm;
	ClothModifierData *clmd = (ClothModifierData *) md;
	
	/* check for alloc failing */
	if (!clmd->sim_parms || !clmd->coll_parms) {
		initData(md);

		if (!clmd->sim_parms || !clmd->coll_parms)
			return;
	}

	dm = get_dm(ob, NULL, derivedData, NULL, false, false);
	if (dm == derivedData)
		dm = CDDM_copy(dm);

	/* TODO(sergey): For now it actually duplicates logic from DerivedMesh.c
	 * and needs some more generic solution. But starting experimenting with
	 * this so close to the release is not that nice..
	 *
	 * Also hopefully new cloth system will arrive soon..
	 */
	if (derivedData == NULL && clmd->sim_parms->shapekey_rest) {
		KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob),
		                                     clmd->sim_parms->shapekey_rest);
		if (kb && kb->data != NULL) {
			float (*layerorco)[3];
			if (!(layerorco = DM_get_vert_data_layer(dm, CD_CLOTH_ORCO))) {
				DM_add_vert_layer(dm, CD_CLOTH_ORCO, CD_CALLOC, NULL);
				layerorco = DM_get_vert_data_layer(dm, CD_CLOTH_ORCO);
			}

			memcpy(layerorco, kb->data, sizeof(float) * 3 * numVerts);
		}
	}

	CDDM_apply_vert_coords(dm, vertexCos);

	DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */

	clothModifier_do(clmd, md->scene, ob, dm, vertexCos);

	dm->release(dm);
}
コード例 #8
0
/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */
DerivedMesh *get_cddm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], bool use_normals)
{
	if (dm) {
		if (dm->type != DM_TYPE_CDDM) {
			dm = CDDM_copy(dm);
			CDDM_apply_vert_coords(dm, vertexCos);
		}

		if (use_normals) {
			DM_ensure_normals(dm);
		}
	}
	else {
		dm = get_dm(ob, em, dm, vertexCos, use_normals, false);
	}

	return dm;
}
コード例 #9
0
/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */
DerivedMesh *get_cddm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3])
{
	if (dm && dm->type == DM_TYPE_CDDM)
		return dm;

	if (!dm) {
		dm = get_dm(ob, em, dm, vertexCos, 0);
	}
	else {
		dm = CDDM_copy(dm);
		CDDM_apply_vert_coords(dm, vertexCos);
	}

	if (dm)
		CDDM_calc_normals(dm);
	
	return dm;
}
コード例 #10
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
						DerivedMesh *derivedData,
						int useRenderParams,
						int isFinalCalc)
{
	SubsurfModifierData *smd = (SubsurfModifierData*) md;
	DerivedMesh *result;

	result = subsurf_make_derived_from_derived(derivedData, smd,
			useRenderParams, NULL, isFinalCalc, 0, (ob->flag & OB_MODE_EDIT));
	
	if(useRenderParams || !isFinalCalc) {
		DerivedMesh *cddm= CDDM_copy(result);
		result->release(result);
		result= cddm;
	}

	return result;
}
コード例 #11
0
ファイル: MOD_boolean.c プロジェクト: greg100795/blender-git
static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh *dm, int operation)
{
	DerivedMesh *result = NULL;

	if (derivedData->getNumPolys(derivedData) == 0 || dm->getNumPolys(dm) == 0) {
		switch (operation) {
			case eBooleanModifierOp_Intersect:
				result = CDDM_new(0, 0, 0, 0, 0);
				break;

			case eBooleanModifierOp_Union:
				if (derivedData->getNumPolys(derivedData)) result = derivedData;
				else result = CDDM_copy(dm);

				break;

			case eBooleanModifierOp_Difference:
				result = derivedData;
				break;
		}
	}

	return result;
}
コード例 #12
0
static void deformVerts(ModifierData *md, Object *ob,
                        DerivedMesh *derivedData,
                        float (*vertexCos)[3],
                        int UNUSED(numVerts),
                        ModifierApplyFlag UNUSED(flag))
{
	CollisionModifierData *collmd = (CollisionModifierData *) md;
	DerivedMesh *dm = NULL;
	MVert *tempVert = NULL;
	
	/* if possible use/create DerivedMesh */
	if (derivedData) dm = CDDM_copy(derivedData);
	else if (ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
	
	if (!ob->pd) {
		printf("CollisionModifier deformVerts: Should not happen!\n");
		return;
	}
	
	if (dm) {
		float current_time = 0;
		unsigned int numverts = 0;

		CDDM_apply_vert_coords(dm, vertexCos);
		CDDM_calc_normals(dm);
		
		current_time = BKE_scene_frame_get(md->scene);
		
		if (G.debug_value > 0)
			printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
		
		numverts = dm->getNumVerts(dm);
		
		if (current_time > collmd->time_xnew) {
			unsigned int i;

			/* check if mesh has changed */
			if (collmd->x && (numverts != collmd->numverts))
				freeData((ModifierData *)collmd);

			if (collmd->time_xnew == -1000) { /* first time */
				collmd->x = dm->dupVertArray(dm); /* frame start position */

				for (i = 0; i < numverts; i++) {
					/* we save global positions */
					mul_m4_v3(ob->obmat, collmd->x[i].co);
				}
				
				collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
				collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
				collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
				collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame

				collmd->numverts = numverts;
				
				DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */

				collmd->mfaces = dm->dupTessFaceArray(dm);
				collmd->numfaces = dm->getNumTessFaces(dm);
				
				/* create bounding box hierarchy */
				collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);

				collmd->time_x = collmd->time_xnew = current_time;
			}
			else if (numverts == collmd->numverts) {
				/* put positions to old positions */
				tempVert = collmd->x;
				collmd->x = collmd->xnew;
				collmd->xnew = tempVert;
				collmd->time_x = collmd->time_xnew;

				memcpy(collmd->xnew, dm->getVertArray(dm), numverts * sizeof(MVert));

				for (i = 0; i < numverts; i++) {
					/* we save global positions */
					mul_m4_v3(ob->obmat, collmd->xnew[i].co);
				}
				
				memcpy(collmd->current_xnew, collmd->x, numverts * sizeof(MVert));
				memcpy(collmd->current_x, collmd->x, numverts * sizeof(MVert));
				
				/* check if GUI setting has changed for bvh */
				if (collmd->bvhtree) {
					if (ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree)) {
						BLI_bvhtree_free(collmd->bvhtree);
						collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
					}
			
				}
				
				/* happens on file load (ONLY when i decomment changes in readfile.c) */
				if (!collmd->bvhtree) {
					collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
				}
				else {
					/* recalc static bounding boxes */
					bvhtree_update_from_mvert(collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1);
				}
				
				collmd->time_xnew = current_time;
			}
			else if (numverts != collmd->numverts) {
				freeData((ModifierData *)collmd);
			}
			
		}
		else if (current_time < collmd->time_xnew) {
			freeData((ModifierData *)collmd);
		}
		else {
			if (numverts != collmd->numverts) {
				freeData((ModifierData *)collmd);
			}
		}
	}
	
	if (dm)
		dm->release(dm);
}
コード例 #13
0
ファイル: particle_object.c プロジェクト: 244xiao/blender
static int connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
{
	ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
	ParticleData *pa;
	PTCacheEdit *edit;
	PTCacheEditPoint *point;
	PTCacheEditKey *ekey = NULL;
	HairKey *key;
	BVHTreeFromMesh bvhtree= {NULL};
	BVHTreeNearest nearest;
	MFace *mface, *mf;
	MVert *mvert;
	DerivedMesh *dm = NULL;
	int numverts;
	int i, k;
	float hairmat[4][4], imat[4][4];
	float v[4][3], vec[3];

	if (!psys || !psys->part || psys->part->type != PART_HAIR || !psmd->dm)
		return FALSE;
	
	edit= psys->edit;
	point=  edit ? edit->points : NULL;
	
	if (psmd->dm->deformedOnly) {
		/* we don't want to mess up psmd->dm when converting to global coordinates below */
		dm = psmd->dm;
	}
	else {
		dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
	}
	/* don't modify the original vertices */
	dm = CDDM_copy(dm);

	/* BMESH_ONLY, deform dm may not have tessface */
	DM_ensure_tessface(dm);

	numverts = dm->getNumVerts(dm);

	mvert = dm->getVertArray(dm);
	mface = dm->getTessFaceArray(dm);

	/* convert to global coordinates */
	for (i=0; i<numverts; i++)
		mul_m4_v3(ob->obmat, mvert[i].co);

	bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6);

	for (i=0, pa= psys->particles; i<psys->totpart; i++, pa++) {
		key = pa->hair;

		nearest.index = -1;
		nearest.dist = FLT_MAX;

		BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree);

		if (nearest.index == -1) {
			if (G.debug & G_DEBUG)
				printf("No nearest point found for hair root!");
			continue;
		}

		mf = &mface[nearest.index];

		copy_v3_v3(v[0], mvert[mf->v1].co);
		copy_v3_v3(v[1], mvert[mf->v2].co);
		copy_v3_v3(v[2], mvert[mf->v3].co);
		if (mf->v4) {
			copy_v3_v3(v[3], mvert[mf->v4].co);
			interp_weights_poly_v3(pa->fuv, v, 4, nearest.co);
		}
		else
			interp_weights_poly_v3(pa->fuv, v, 3, nearest.co);

		pa->num = nearest.index;
		pa->num_dmcache = psys_particle_dm_face_lookup(ob, psmd->dm, pa->num, pa->fuv, NULL);
		
		psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
		invert_m4_m4(imat, hairmat);

		sub_v3_v3v3(vec, nearest.co, key->co);

		if (point) {
			ekey = point->keys;
			point++;
		}

		for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
			add_v3_v3(key->co, vec);
			mul_m4_v3(imat, key->co);

			if (ekey) {
				ekey->flag |= PEK_USE_WCO;
				ekey++;
			}
		}
	}

	free_bvhtree_from_mesh(&bvhtree);
	dm->release(dm);

	psys_free_path_cache(psys, psys->edit);

	psys->flag &= ~PSYS_GLOBAL_HAIR;

	PE_update_object(scene, ob, 0);

	return TRUE;
}
コード例 #14
0
ファイル: MOD_particlesystem.c プロジェクト: LucaRood/Blender
/* saves the current emitter state for a particle system and calculates particles */
static void deformVerts(ModifierData *md, Object *ob,
                        DerivedMesh *derivedData,
                        float (*vertexCos)[3],
                        int UNUSED(numVerts),
                        ModifierApplyFlag flag)
{
	DerivedMesh *dm = derivedData;
	ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
	ParticleSystem *psys = NULL;
	bool needsFree = false;
	/* float cfra = BKE_scene_frame_get(md->scene); */  /* UNUSED */

	if (ob->particlesystem.first)
		psys = psmd->psys;
	else
		return;
	
	if (!psys_check_enabled(ob, psys, (flag & MOD_APPLY_RENDER) != 0))
		return;

	if (dm == NULL) {
		dm = get_dm(ob, NULL, NULL, vertexCos, false, true);

		if (!dm)
			return;

		needsFree = true;
	}

	/* clear old dm */
	if (psmd->dm_final) {
		psmd->dm_final->needsFree = true;
		psmd->dm_final->release(psmd->dm_final);
		if (psmd->dm_deformed) {
			psmd->dm_deformed->needsFree = 1;
			psmd->dm_deformed->release(psmd->dm_deformed);
			psmd->dm_deformed = NULL;
		}
	}
	else if (psmd->flag & eParticleSystemFlag_file_loaded) {
		/* in file read dm just wasn't saved in file so no need to reset everything */
		psmd->flag &= ~eParticleSystemFlag_file_loaded;
	}
	else {
		/* no dm before, so recalc particles fully */
		psys->recalc |= PSYS_RECALC_RESET;
	}

	/* make new dm */
	psmd->dm_final = CDDM_copy(dm);
	CDDM_apply_vert_coords(psmd->dm_final, vertexCos);
	CDDM_calc_normals(psmd->dm_final);

	if (needsFree) {
		dm->needsFree = true;
		dm->release(dm);
	}

	/* protect dm */
	psmd->dm_final->needsFree = false;

	DM_ensure_tessface(psmd->dm_final);

	if (!psmd->dm_final->deformedOnly) {
		/* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set.
		 *     This is awfully weak though. :| */
		if (ob->derivedDeform) {
			psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
		}
		else {  /* Can happen in some cases, e.g. when rendering from Edit mode... */
			psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
		}
		DM_ensure_tessface(psmd->dm_deformed);
	}

	/* report change in mesh structure */
	if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
	    psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
	    psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
	{
		psys->recalc |= PSYS_RECALC_RESET;

		psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
		psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
		psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
	}

	if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
		psmd->flag &= ~eParticleSystemFlag_psys_updated;
		particle_system_update(md->scene, ob, psys, (flag & MOD_APPLY_RENDER) != 0);
		psmd->flag |= eParticleSystemFlag_psys_updated;
	}
}
コード例 #15
0
ファイル: MOD_normal_edit.c プロジェクト: mgschwan/blensor
static DerivedMesh *normalEditModifier_do(NormalEditModifierData *enmd, Object *ob, DerivedMesh *dm)
{
	Mesh *me = ob->data;

	const int num_verts = dm->getNumVerts(dm);
	const int num_edges = dm->getNumEdges(dm);
	const int num_loops = dm->getNumLoops(dm);
	const int num_polys = dm->getNumPolys(dm);
	MVert *mvert;
	MEdge *medge;
	MLoop *mloop;
	MPoly *mpoly;

	const bool use_invert_vgroup = ((enmd->flag & MOD_NORMALEDIT_INVERT_VGROUP) != 0);
	const bool use_current_clnors = !((enmd->mix_mode == MOD_NORMALEDIT_MIX_COPY) &&
	                                  (enmd->mix_factor == 1.0f) &&
	                                  (enmd->defgrp_name[0] == '\0') &&
	                                  (enmd->mix_limit == (float)M_PI));

	int defgrp_index;
	MDeformVert *dvert;

	float (*loopnors)[3] = NULL;
	short (*clnors)[2];

	float (*polynors)[3];
	bool free_polynors = false;

	/* Do not run that modifier at all if autosmooth is disabled! */
	if (!is_valid_target(enmd) || !num_loops) {
		return dm;
	}

	if (!(me->flag & ME_AUTOSMOOTH)) {
		modifier_setError((ModifierData *)enmd, "Enable 'Auto Smooth' option in mesh settings");
		return dm;
	}

	medge = dm->getEdgeArray(dm);
	if (me->medge == medge) {
		/* We need to duplicate data here, otherwise setting custom normals (which may also affect sharp edges) could
		 * modify org mesh, see T43671. */
		dm = CDDM_copy(dm);
		medge = dm->getEdgeArray(dm);
	}
	mvert = dm->getVertArray(dm);
	mloop = dm->getLoopArray(dm);
	mpoly = dm->getPolyArray(dm);

	if (use_current_clnors) {
		dm->calcLoopNormals(dm, true, me->smoothresh);
		loopnors = dm->getLoopDataArray(dm, CD_NORMAL);
	}

	clnors = CustomData_duplicate_referenced_layer(&dm->loopData, CD_CUSTOMLOOPNORMAL, num_loops);
	if (!clnors) {
		DM_add_loop_layer(dm, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL);
		clnors = dm->getLoopDataArray(dm, CD_CUSTOMLOOPNORMAL);
	}

	polynors = dm->getPolyDataArray(dm, CD_NORMAL);
	if (!polynors) {
		polynors = MEM_malloc_arrayN((size_t)num_polys, sizeof(*polynors), __func__);
		BKE_mesh_calc_normals_poly(mvert, NULL, num_verts, mloop, mpoly, num_loops, num_polys, polynors, false);
		free_polynors = true;
	}

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

	if (enmd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
		normalEditModifier_do_radial(
		            enmd, ob, dm, clnors, loopnors, polynors,
		            enmd->mix_mode, enmd->mix_factor, enmd->mix_limit, dvert, defgrp_index, use_invert_vgroup,
		            mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
	}
	else if (enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) {
		normalEditModifier_do_directional(
		            enmd, ob, dm, clnors, loopnors, polynors,
		            enmd->mix_mode, enmd->mix_factor, enmd->mix_limit, dvert, defgrp_index, use_invert_vgroup,
		            mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
	}

	if (free_polynors) {
		MEM_freeN(polynors);
	}

	return dm;
}
コード例 #16
0
ファイル: displist.c プロジェクト: mgschwan/blensor
static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
                                      ListBase *dispbase, DerivedMesh **r_dm_final,
                                      const bool for_render, const bool use_render_resolution)
{
	VirtualModifierData virtualModifierData;
	ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
	ModifierData *pretessellatePoint;
	Curve *cu = ob->data;
	int required_mode = 0, totvert = 0;
	const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
	DerivedMesh *dm = NULL, *ndm;
	float (*vertCos)[3] = NULL;
	int useCache = !for_render;
	ModifierApplyFlag app_flag = 0;

	if (use_render_resolution) {
		app_flag |= MOD_APPLY_RENDER;
		required_mode = eModifierMode_Render;
	}
	else
		required_mode = eModifierMode_Realtime;

	pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode);

	if (editmode)
		required_mode |= eModifierMode_Editmode;

	if (pretessellatePoint) {
		md = pretessellatePoint->next;
	}

	if (r_dm_final && *r_dm_final) {
		(*r_dm_final)->release(*r_dm_final);
	}

	for (; md; md = md->next) {
		const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
		ModifierApplyFlag appf = app_flag;

		md->scene = scene;

		if (!modifier_isEnabled(scene, md, required_mode))
			continue;

		if (mti->type == eModifierTypeType_OnlyDeform ||
		    (mti->type == eModifierTypeType_DeformOrConstruct && !dm))
		{
			if (editmode)
				appf |= MOD_APPLY_USECACHE;
			if (dm) {
				if (!vertCos) {
					totvert = dm->getNumVerts(dm);
					vertCos = MEM_mallocN(sizeof(*vertCos) * totvert, "dfmv");
					dm->getVertCos(dm, vertCos);
				}

				mti->deformVerts(md, ob, dm, vertCos, totvert, appf);
			}
			else {
				if (!vertCos) {
					vertCos = displist_get_allverts(dispbase, &totvert);
				}

				mti->deformVerts(md, ob, NULL, vertCos, totvert, appf);
			}
		}
		else {
			if (!r_dm_final) {
				/* makeDisplistCurveTypes could be used for beveling, where derived mesh
				 * is totally unnecessary, so we could stop modifiers applying
				 * when we found constructive modifier but derived mesh is unwanted result
				 */
				break;
			}

			if (dm) {
				if (vertCos) {
					DerivedMesh *tdm = CDDM_copy(dm);
					dm->release(dm);
					dm = tdm;

					CDDM_apply_vert_coords(dm, vertCos);
				}
			}
			else {
				if (vertCos) {
					displist_apply_allverts(dispbase, vertCos);
				}

				if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
					curve_to_filledpoly(cu, nurb, dispbase);
				}

				dm = CDDM_from_curve_displist(ob, dispbase);
			}

			if (vertCos) {
				/* Vertex coordinates were applied to necessary data, could free it */
				MEM_freeN(vertCos);
				vertCos = NULL;
			}

			if (useCache)
				appf |= MOD_APPLY_USECACHE;

			ndm = modwrap_applyModifier(md, ob, dm, appf);

			if (ndm) {
				/* Modifier returned a new derived mesh */

				if (dm && dm != ndm) /* Modifier  */
					dm->release(dm);
				dm = ndm;
			}
		}
	}

	if (vertCos) {
		if (dm) {
			DerivedMesh *tdm = CDDM_copy(dm);
			dm->release(dm);
			dm = tdm;

			CDDM_apply_vert_coords(dm, vertCos);
			CDDM_calc_normals_mapping(dm);
			MEM_freeN(vertCos);
		}
		else {
			displist_apply_allverts(dispbase, vertCos);
			MEM_freeN(vertCos);
			vertCos = NULL;
		}
	}

	if (r_dm_final) {
		if (dm) {
			/* see: mesh_calc_modifiers */
			if (dm->getNumTessFaces(dm) == 0) {
				dm->recalcTessellation(dm);
			}
			/* Even if tessellation is not needed, some modifiers might have modified CD layers
			 * (like mloopcol or mloopuv), hence we have to update those. */
			else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) {
				DM_update_tessface_data(dm);
			}

			if (dm->type == DM_TYPE_CDDM) {
				CDDM_calc_normals_mapping_ex(dm, (dm->dirty & DM_DIRTY_NORMALS) ? false : true);
			}
		}
		(*r_dm_final) = dm;
	}
}
コード例 #17
0
ファイル: cloth.c プロジェクト: jinjoh/NOOR
/************************************************
 * clothModifier_do - main simulation function
************************************************/
DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
{
	DerivedMesh *result;
	PointCache *cache;
	PTCacheID pid;
	float timescale;
	int framedelta, framenr, startframe, endframe;
	int cache_result;

	clmd->scene= scene;	/* nice to pass on later :) */
	framenr= (int)scene->r.cfra;
	cache= clmd->point_cache;
	result = CDDM_copy(dm);

	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
	BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
	clmd->sim_parms->timescale= timescale;

	if(!result) {
		cache->flag &= ~PTCACHE_SIMULATION_VALID;
		cache->simframe= 0;
		cache->last_exact= 0;
		return dm;
	}
	
	/* verify we still have the same number of vertices, if not do nothing.
	 * note that this should only happen if the number of vertices changes
	 * during an animation due to a preceding modifier, this should not
	 * happen because of object changes! */
	if(clmd->clothObject) {
		if(result->getNumVerts(result) != clmd->clothObject->numverts) {
			cache->flag &= ~PTCACHE_SIMULATION_VALID;
			cache->simframe= 0;
			cache->last_exact= 0;
			return result;
		}
	}
	
	// unused in the moment, calculated seperately in implicit.c
	clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;

	/* handle continuous simulation with the play button */
	if(BKE_ptcache_get_continue_physics()) {
		cache->flag &= ~PTCACHE_SIMULATION_VALID;
		cache->simframe= 0;
		cache->last_exact= 0;

		/* do simulation */
		if(!do_init_cloth(ob, clmd, result, framenr))
			return result;

		do_step_cloth(ob, clmd, result, framenr);
		cloth_to_object(ob, clmd, result);

		return result;
	}

	/* simulation is only active during a specific period */
	if(framenr < startframe) {
		cache->flag &= ~PTCACHE_SIMULATION_VALID;
		cache->simframe= 0;
		cache->last_exact= 0;
		return result;
	}
	else if(framenr > endframe) {
		framenr= endframe;
	}

	if(cache->flag & PTCACHE_SIMULATION_VALID)
		framedelta= framenr - cache->simframe;
	else
		framedelta= -1;

	/* initialize simulation data if it didn't exist already */
	if(!do_init_cloth(ob, clmd, result, framenr))
		return result;

	if(framenr == startframe) {
		BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
		do_init_cloth(ob, clmd, result, framenr);
		cache->simframe= framenr;
		cache->flag |= PTCACHE_SIMULATION_VALID;
		cache->flag &= ~PTCACHE_REDO_NEEDED;
		return result;
	}

	/* try to read from cache */
	cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec);

	if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
		implicit_set_positions(clmd);
		cloth_to_object (ob, clmd, result);

		cache->simframe= framenr;
		cache->flag |= PTCACHE_SIMULATION_VALID;

		if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
			BKE_ptcache_write_cache(&pid, framenr);

		return result;
	}
	else if(cache_result==PTCACHE_READ_OLD) {
		implicit_set_positions(clmd);
		cache->flag |= PTCACHE_SIMULATION_VALID;
	}
	else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
		/* if baked and nothing in cache, do nothing */
		cache->flag &= ~PTCACHE_SIMULATION_VALID;
		cache->simframe= 0;
		cache->last_exact= 0;
		return result;
	}

	/* if on second frame, write cache for first frame */
	if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
		BKE_ptcache_write_cache(&pid, startframe);

	clmd->sim_parms->timescale *= framenr - cache->simframe;

	/* do simulation */
	cache->flag |= PTCACHE_SIMULATION_VALID;
	cache->simframe= framenr;

	if(!do_step_cloth(ob, clmd, result, framenr)) {
		cache->flag &= ~PTCACHE_SIMULATION_VALID;
		cache->simframe= 0;
		cache->last_exact= 0;
	}
	else
		BKE_ptcache_write_cache(&pid, framenr);

	cloth_to_object (ob, clmd, result);

	return result;
}
コード例 #18
0
/* single_psys_from is optional, if NULL all psys of ob_from are copied */
static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, ParticleSystem *single_psys_from, Object *ob_to, int space)
{
	ModifierData *md;
	ParticleSystem *psys_start = NULL, *psys, *psys_from;
	ParticleSystem **tmp_psys;
	DerivedMesh *final_dm;
	CustomDataMask cdmask;
	int i, totpsys;
	
	if (ob_to->type != OB_MESH)
		return false;
	if (!ob_to->data || ((ID *)ob_to->data)->lib)
		return false;
	
	/* For remapping we need a valid DM.
	 * Because the modifiers are appended at the end it's safe to use
	 * the final DM of the object without particles.
	 * However, when evaluating the DM all the particle modifiers must be valid,
	 * i.e. have the psys assigned already.
	 * To break this hen/egg problem we create all psys separately first (to collect required customdata masks),
	 * then create the DM, then add them to the object and make the psys modifiers ...
	 */
	#define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first)
	#define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next)
	totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem);
	
	tmp_psys = MEM_mallocN(sizeof(ParticleSystem*) * totpsys, "temporary particle system array");
	
	cdmask = 0;
	for (psys_from = PSYS_FROM_FIRST, i = 0;
	     psys_from;
	     psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
		
		psys = BKE_object_copy_particlesystem(psys_from);
		tmp_psys[i] = psys;
		
		if (psys_start == NULL)
			psys_start = psys;
		
		cdmask |= psys_emitter_customdata_mask(psys);
	}
	/* to iterate source and target psys in sync,
	 * we need to know where the newly added psys start
	 */
	psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
	
	/* get the DM (psys and their modifiers have not been appended yet) */
	final_dm = mesh_get_derived_final(scene, ob_to, cdmask);
	
	/* now append psys to the object and make modifiers */
	for (i = 0, psys_from = PSYS_FROM_FIRST;
	     i < totpsys;
	     ++i, psys_from = PSYS_FROM_NEXT(psys_from)) {
		
		ParticleSystemModifierData *psmd;
		
		psys = tmp_psys[i];
		
		/* append to the object */
		BLI_addtail(&ob_to->particlesystem, psys);
		
		/* add a particle system modifier for each system */
		md = modifier_new(eModifierType_ParticleSystem);
		psmd = (ParticleSystemModifierData *)md;
		/* push on top of the stack, no use trying to reproduce old stack order */
		BLI_addtail(&ob_to->modifiers, md);
		
		BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i);
		modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
		
		psmd->psys = psys;
		psmd->dm = CDDM_copy(final_dm);
		CDDM_calc_normals(psmd->dm);
		DM_ensure_tessface(psmd->dm);
		
		if (psys_from->edit)
			copy_particle_edit(scene, ob_to, psys, psys_from);
	}
	MEM_freeN(tmp_psys);
	
	/* note: do this after creating DM copies for all the particle system modifiers,
	 * the remapping otherwise makes final_dm invalid!
	 */
	for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0;
	     psys;
	     psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
		
		float (*from_mat)[4], (*to_mat)[4];
		
		switch (space) {
			case PAR_COPY_SPACE_OBJECT:
				from_mat = I;
				to_mat = I;
				break;
			case PAR_COPY_SPACE_WORLD:
				from_mat = ob_from->obmat;
				to_mat = ob_to->obmat;
				break;
			default:
				/* should not happen */
				from_mat = to_mat = NULL;
				BLI_assert(false);
				break;
		}
		
		remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
		
		/* tag for recalc */
//		psys->recalc |= PSYS_RECALC_RESET;
	}
	
	#undef PSYS_FROM_FIRST
	#undef PSYS_FROM_NEXT
	
	DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA);
	WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
	return true;
}
コード例 #19
0
/* saves the current emitter state for a particle system and calculates particles */
static void deformVerts(ModifierData *md, Object *ob,
                        DerivedMesh *derivedData,
                        float (*vertexCos)[3],
                        int UNUSED(numVerts),
                        ModifierApplyFlag UNUSED(flag))
{
	DerivedMesh *dm = derivedData;
	ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
	ParticleSystem *psys = NULL;
	int needsFree = 0;
	/* float cfra = BKE_scene_frame_get(md->scene); */  /* UNUSED */

	if (ob->particlesystem.first)
		psys = psmd->psys;
	else
		return;
	
	if (!psys_check_enabled(ob, psys))
		return;

	if (dm == NULL) {
		dm = get_dm(ob, NULL, NULL, vertexCos, false, true);

		if (!dm)
			return;

		needsFree = 1;
	}

	/* clear old dm */
	if (psmd->dm) {
		psmd->dm->needsFree = 1;
		psmd->dm->release(psmd->dm);
	}
	else if (psmd->flag & eParticleSystemFlag_file_loaded) {
		/* in file read dm just wasn't saved in file so no need to reset everything */
		psmd->flag &= ~eParticleSystemFlag_file_loaded;
	}
	else {
		/* no dm before, so recalc particles fully */
		psys->recalc |= PSYS_RECALC_RESET;
	}

	/* make new dm */
	psmd->dm = CDDM_copy(dm);
	CDDM_apply_vert_coords(psmd->dm, vertexCos);
	CDDM_calc_normals(psmd->dm);

	if (needsFree) {
		dm->needsFree = 1;
		dm->release(dm);
	}

	/* protect dm */
	psmd->dm->needsFree = 0;

	/* report change in mesh structure */
	DM_ensure_tessface(psmd->dm);
	if (psmd->dm->getNumVerts(psmd->dm) != psmd->totdmvert ||
	    psmd->dm->getNumEdges(psmd->dm) != psmd->totdmedge ||
	    psmd->dm->getNumTessFaces(psmd->dm) != psmd->totdmface)
	{
		psys->recalc |= PSYS_RECALC_RESET;

		psmd->totdmvert = psmd->dm->getNumVerts(psmd->dm);
		psmd->totdmedge = psmd->dm->getNumEdges(psmd->dm);
		psmd->totdmface = psmd->dm->getNumTessFaces(psmd->dm);
	}

	if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
		psmd->flag &= ~eParticleSystemFlag_psys_updated;
		particle_system_update(md->scene, ob, psys);
		psmd->flag |= eParticleSystemFlag_psys_updated;
	}
}
コード例 #20
0
bool BKE_object_data_transfer_dm(
        Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, const int data_types, bool use_create,
        const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
        SpaceTransform *space_transform, const bool auto_transform,
        const float max_distance, const float ray_radius, const float islands_handling_precision,
        const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
        const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
        ReportList *reports)
{
#define VDATA 0
#define EDATA 1
#define LDATA 2
#define PDATA 3
#define DATAMAX 4

	SpaceTransform auto_space_transform;

	DerivedMesh *dm_src;
	Mesh *me_dst, *me_src;
	bool dirty_nors_dst = true;  /* Assumed always true if not using a dm as destination. */
	int i;

	MDeformVert *mdef = NULL;
	int vg_idx = -1;
	float *weights[DATAMAX] = {NULL};

	MeshPairRemap geom_map[DATAMAX] = {{0}};
	bool geom_map_init[DATAMAX] = {0};
	ListBase lay_map = {NULL};
	bool changed = false;

	const bool use_delete = false;  /* We never delete data layers from destination here. */

	CustomDataMask dm_src_mask = CD_MASK_BAREMESH;

	BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));

	me_dst = ob_dst->data;
	me_src = ob_src->data;
	if (dm_dst) {
		dirty_nors_dst = (dm_dst->dirty & DM_DIRTY_NORMALS) != 0;
		use_create = false;  /* Never create needed custom layers on DM (modifier case). */
	}

	if (vgroup_name) {
		if (dm_dst) {
			mdef = dm_dst->getVertDataArray(dm_dst, CD_MDEFORMVERT);
		}
		else {
			mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT);
		}
		if (mdef) {
			vg_idx = defgroup_name_index(ob_dst, vgroup_name);
		}
	}

	/* Get source DM.*/
	dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
	/* XXX Hack! In case this is being evaluated from dm stack, we cannot compute final dm,
	 *     can lead to infinite recursion in case of dependency cycles of DataTransfer modifiers...
	 *     Issue is, this means we cannot be sure to have requested cd layers in source.
	 *
	 *     Also, we need to make a local copy of dm_src, otherwise we may end with concurrent creation
	 *     of data in it (multi-threaded evaluation of the modifier stack, see T46672).
	 */
	dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask);
	if (!dm_src) {
		return changed;
	}
	dm_src = CDDM_copy(dm_src);

	if (auto_transform) {
		MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
		const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;

		if (space_transform == NULL) {
			space_transform = &auto_space_transform;
		}

		BKE_mesh_remap_find_best_match_from_dm(verts_dst, num_verts_dst, dm_src, space_transform);
	}

	/* Check all possible data types.
	 * Note item mappings and dest mix weights are cached. */
	for (i = 0; i < DT_TYPE_MAX; i++) {
		const int dtdata_type = 1 << i;
		int cddata_type;
		int fromlayers, tolayers, fromto_idx;

		if (!(data_types & dtdata_type)) {
			continue;
		}

		data_transfer_dtdata_type_preprocess(ob_src, ob_dst, dm_src, dm_dst, me_dst,
		                                     dtdata_type, dirty_nors_dst,
		                                     (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh);

		cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);

		fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);
		if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
			fromlayers = fromlayers_select[fromto_idx];
			tolayers = tolayers_select[fromto_idx];
		}
		else {
			fromlayers = tolayers = 0;
		}

		if (DT_DATATYPE_IS_VERT(dtdata_type)) {
			MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;

			if (!geom_map_init[VDATA]) {
				const int num_verts_src = dm_src->getNumVerts(dm_src);

				if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != num_verts_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source and destination meshes do not have the same amount of vertices, "
					           "'Topology' mapping cannot be used in this case");
					continue;
				}
				if (ELEM(0, num_verts_dst, num_verts_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source or destination meshes do not have any vertices, cannot transfer vertex data");
					continue;
				}

				BKE_mesh_remap_calc_verts_from_dm(
				        map_vert_mode, space_transform, max_distance, ray_radius,
				        verts_dst, num_verts_dst, dirty_nors_dst, dm_src, &geom_map[VDATA]);
				geom_map_init[VDATA] = true;
			}

			if (mdef && vg_idx != -1 && !weights[VDATA]) {
				weights[VDATA] = MEM_mallocN(sizeof(*(weights[VDATA])) * (size_t)num_verts_dst, __func__);
				BKE_defvert_extract_vgroup_to_vertweights(mdef, vg_idx, num_verts_dst, weights[VDATA], invert_vgroup);
			}

			if (data_transfer_layersmapping_generate(
			        &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_VERT,
			        cddata_type, mix_mode, mix_factor, weights[VDATA],
			        num_verts_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
			{
				CustomDataTransferLayerMap *lay_mapit;

				changed = (lay_map.first != NULL);

				for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
					CustomData_data_transfer(&geom_map[VDATA], lay_mapit);
				}

				BLI_freelistN(&lay_map);
			}
		}
		if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
			MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
			MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
			const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;

			if (!geom_map_init[EDATA]) {
				const int num_edges_src = dm_src->getNumEdges(dm_src);

				if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (num_edges_dst != num_edges_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source and destination meshes do not have the same amount of edges, "
					           "'Topology' mapping cannot be used in this case");
					continue;
				}
				if (ELEM(0, num_edges_dst, num_edges_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source or destination meshes do not have any edges, cannot transfer edge data");
					continue;
				}

				BKE_mesh_remap_calc_edges_from_dm(
				        map_edge_mode, space_transform, max_distance, ray_radius,
				        verts_dst, num_verts_dst, edges_dst, num_edges_dst, dirty_nors_dst,
				        dm_src, &geom_map[EDATA]);
				geom_map_init[EDATA] = true;
			}

			if (mdef && vg_idx != -1 && !weights[EDATA]) {
				weights[EDATA] = MEM_mallocN(sizeof(*weights[EDATA]) * (size_t)num_edges_dst, __func__);
				BKE_defvert_extract_vgroup_to_edgeweights(
				        mdef, vg_idx, num_verts_dst, edges_dst, num_edges_dst,
				        weights[EDATA], invert_vgroup);
			}

			if (data_transfer_layersmapping_generate(
			        &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_EDGE,
			        cddata_type, mix_mode, mix_factor, weights[EDATA],
			        num_edges_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
			{
				CustomDataTransferLayerMap *lay_mapit;

				changed = (lay_map.first != NULL);

				for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
					CustomData_data_transfer(&geom_map[EDATA], lay_mapit);
				}

				BLI_freelistN(&lay_map);
			}
		}
		if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
			MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
			MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
			const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
			MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
			const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
			MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
			const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
			CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
			CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;

			MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type);

			if (!geom_map_init[LDATA]) {
				const int num_loops_src = dm_src->getNumLoops(dm_src);

				if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (num_loops_dst != num_loops_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source and destination meshes do not have the same amount of face corners, "
					           "'Topology' mapping cannot be used in this case");
					continue;
				}
				if (ELEM(0, num_loops_dst, num_loops_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source or destination meshes do not have any polygons, cannot transfer loop data");
					continue;
				}

				BKE_mesh_remap_calc_loops_from_dm(
				        map_loop_mode, space_transform, max_distance, ray_radius,
				        verts_dst, num_verts_dst, edges_dst, num_edges_dst,
				        loops_dst, num_loops_dst, polys_dst, num_polys_dst,
				        ldata_dst, pdata_dst,
				        (me_dst->flag & ME_AUTOSMOOTH) != 0, me_dst->smoothresh, dirty_nors_dst,
				        dm_src, (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh,
				        island_callback, islands_handling_precision, &geom_map[LDATA]);
				geom_map_init[LDATA] = true;
			}

			if (mdef && vg_idx != -1 && !weights[LDATA]) {
				weights[LDATA] = MEM_mallocN(sizeof(*weights[LDATA]) * (size_t)num_loops_dst, __func__);
				BKE_defvert_extract_vgroup_to_loopweights(
				        mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst,
				        weights[LDATA], invert_vgroup);
			}

			if (data_transfer_layersmapping_generate(
			        &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_LOOP,
			        cddata_type, mix_mode, mix_factor, weights[LDATA],
			        num_loops_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
			{
				CustomDataTransferLayerMap *lay_mapit;

				changed = (lay_map.first != NULL);

				for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
					CustomData_data_transfer(&geom_map[LDATA], lay_mapit);
				}

				BLI_freelistN(&lay_map);
			}
		}
		if (DT_DATATYPE_IS_POLY(dtdata_type)) {
			MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
			const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
			MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
			const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
			MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
			const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
			CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;

			if (!geom_map_init[PDATA]) {
				const int num_polys_src = dm_src->getNumPolys(dm_src);

				if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (num_polys_dst != num_polys_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source and destination meshes do not have the same amount of faces, "
					           "'Topology' mapping cannot be used in this case");
					continue;
				}
				if (ELEM(0, num_polys_dst, num_polys_src)) {
					BKE_report(reports, RPT_ERROR,
					           "Source or destination meshes do not have any polygons, cannot transfer poly data");
					continue;
				}

				BKE_mesh_remap_calc_polys_from_dm(
				        map_poly_mode, space_transform, max_distance, ray_radius,
				        verts_dst, num_verts_dst, loops_dst, num_loops_dst,
				        polys_dst, num_polys_dst, pdata_dst, dirty_nors_dst,
				        dm_src, &geom_map[PDATA]);
				geom_map_init[PDATA] = true;
			}

			if (mdef && vg_idx != -1 && !weights[PDATA]) {
				weights[PDATA] = MEM_mallocN(sizeof(*weights[PDATA]) * (size_t)num_polys_dst, __func__);
				BKE_defvert_extract_vgroup_to_polyweights(
				        mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst,
				        polys_dst, num_polys_dst, weights[PDATA], invert_vgroup);
			}

			if (data_transfer_layersmapping_generate(
			        &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_POLY,
			        cddata_type, mix_mode, mix_factor, weights[PDATA],
			        num_polys_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
			{
				CustomDataTransferLayerMap *lay_mapit;

				changed = (lay_map.first != NULL);

				for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
					CustomData_data_transfer(&geom_map[PDATA], lay_mapit);
				}

				BLI_freelistN(&lay_map);
			}
		}

		data_transfer_dtdata_type_postprocess(ob_src, ob_dst, dm_src, dm_dst, me_dst, dtdata_type, changed);
	}

	for (i = 0; i < DATAMAX; i++) {
		BKE_mesh_remap_free(&geom_map[i]);
		MEM_SAFE_FREE(weights[i]);
	}
	dm_src->release(dm_src);

	return changed;

#undef VDATA
#undef EDATA
#undef LDATA
#undef PDATA
#undef DATAMAX
}
コード例 #21
0
ファイル: smoke.c プロジェクト: jinjoh/NOOR
void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
{	
	if((smd->type & MOD_SMOKE_TYPE_FLOW))
	{
		if(scene->r.cfra >= smd->time)
			smokeModifier_init(smd, ob, scene, dm);

		if(scene->r.cfra > smd->time)
		{
			// XXX TODO
			smd->time = scene->r.cfra;

			// rigid movement support
			/*
			Mat4CpyMat4(smd->flow->mat_old, smd->flow->mat);
			Mat4CpyMat4(smd->flow->mat, ob->obmat);
			*/
		}
		else if(scene->r.cfra < smd->time)
		{
			smd->time = scene->r.cfra;
			smokeModifier_reset(smd);
		}
	}
	else if(smd->type & MOD_SMOKE_TYPE_COLL)
	{
		if(scene->r.cfra >= smd->time)
			smokeModifier_init(smd, ob, scene, dm);

		if(scene->r.cfra > smd->time)
		{
			// XXX TODO
			smd->time = scene->r.cfra;
			
			if(smd->coll->dm)
				smd->coll->dm->release(smd->coll->dm);

			smd->coll->dm = CDDM_copy(dm);

			// rigid movement support
			Mat4CpyMat4(smd->coll->mat_old, smd->coll->mat);
			Mat4CpyMat4(smd->coll->mat, ob->obmat);
		}
		else if(scene->r.cfra < smd->time)
		{
			smd->time = scene->r.cfra;
			smokeModifier_reset(smd);
		}
	}
	else if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
	{
		SmokeDomainSettings *sds = smd->domain;
		float light[3];	
		PointCache *cache = NULL;
		PTCacheID pid;
		PointCache *cache_wt = NULL;
		PTCacheID pid_wt;
		int startframe, endframe, framenr;
		float timescale;
		int cache_result = 0, cache_result_wt = 0;

		framenr = scene->r.cfra;

		// printf("time: %d\n", scene->r.cfra);

		if(framenr == smd->time)
			return;

		cache = sds->point_cache[0];
		BKE_ptcache_id_from_smoke(&pid, ob, smd);
		BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);

		cache_wt = sds->point_cache[1];
		BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd);

		if(!smd->domain->fluid)
		{
			BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
			BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED);
		}

		if(framenr < startframe)
			return;

		if(framenr > endframe)
			return;

		if(!smd->domain->fluid && (framenr != startframe))
			return;

		// printf("startframe: %d, framenr: %d\n", startframe, framenr);

		if(!smokeModifier_init(smd, ob, scene, dm))
		{
			printf("bad smokeModifier_init\n");
			return;
		}

		/* try to read from cache */
		cache_result =  BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec);
		// printf("cache_result: %d\n", cache_result);

		if(cache_result == PTCACHE_READ_EXACT) 
		{
			cache->flag |= PTCACHE_SIMULATION_VALID;
			cache->simframe= framenr;

			if(sds->wt)
			{
				cache_result_wt = BKE_ptcache_read_cache(&pid_wt, (float)framenr, scene->r.frs_sec);
				
				if(cache_result_wt == PTCACHE_READ_EXACT) 
				{
					cache_wt->flag |= PTCACHE_SIMULATION_VALID;
					cache_wt->simframe= framenr;
				}
			}
			return;
		}

		tstart();

		smoke_calc_domain(scene, ob, smd);
		
		// set new time
		smd->time = scene->r.cfra;

		/* do simulation */

		// low res
		cache->flag |= PTCACHE_SIMULATION_VALID;
		cache->simframe= framenr;

		// simulate the actual smoke (c++ code in intern/smoke)
		// DG: interesting commenting this line + deactivating loading of noise files
		if(framenr!=startframe)
		{
			if(sds->flags & MOD_SMOKE_DISSOLVE)
				smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
			smoke_step(sds->fluid, smd->time);
		}

		// create shadows before writing cache so we get nice shadows for sstartframe, too
		if(get_lamp(scene, light))
			smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx);
	
		BKE_ptcache_write_cache(&pid, framenr);

		if(sds->wt)
		{
			if(framenr!=startframe)
			{
				if(sds->flags & MOD_SMOKE_DISSOLVE)
					smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
				smoke_turbulence_step(sds->wt, sds->fluid);
			}

			cache_wt->flag |= PTCACHE_SIMULATION_VALID;
			cache_wt->simframe= framenr;
			BKE_ptcache_write_cache(&pid_wt, framenr);
		}

		tend();
		printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() );
	}
}
コード例 #22
0
ファイル: MOD_surface.c プロジェクト: BHCLL/blendocv
static void deformVerts(ModifierData *md, Object *ob,
						DerivedMesh *derivedData,
						float (*vertexCos)[3],
						int UNUSED(numVerts),
						int UNUSED(useRenderParams),
						int UNUSED(isFinalCalc))
{
	SurfaceModifierData *surmd = (SurfaceModifierData*) md;
	
	if(surmd->dm)
		surmd->dm->release(surmd->dm);

	/* if possible use/create DerivedMesh */
	if(derivedData) surmd->dm = CDDM_copy(derivedData);
	else surmd->dm = get_dm(ob, NULL, NULL, NULL, 0);
	
	if(!ob->pd)
	{
		printf("SurfaceModifier deformVerts: Should not happen!\n");
		return;
	}
	
	if(surmd->dm)
	{
		unsigned int numverts = 0, i = 0;
		int init = 0;
		float *vec;
		MVert *x, *v;

		CDDM_apply_vert_coords(surmd->dm, vertexCos);
		CDDM_calc_normals(surmd->dm);
		
		numverts = surmd->dm->getNumVerts ( surmd->dm );

		if(numverts != surmd->numverts || surmd->x == NULL || surmd->v == NULL || md->scene->r.cfra != surmd->cfra+1) {
			if(surmd->x) {
				MEM_freeN(surmd->x);
				surmd->x = NULL;
			}
			if(surmd->v) {
				MEM_freeN(surmd->v);
				surmd->v = NULL;
			}

			surmd->x = MEM_callocN(numverts * sizeof(MVert), "MVert");
			surmd->v = MEM_callocN(numverts * sizeof(MVert), "MVert");

			surmd->numverts = numverts;

			init = 1;
		}

		/* convert to global coordinates and calculate velocity */
		for(i = 0, x = surmd->x, v = surmd->v; i<numverts; i++, x++, v++) {
			vec = CDDM_get_vert(surmd->dm, i)->co;
			mul_m4_v3(ob->obmat, vec);

			if(init)
				v->co[0] = v->co[1] = v->co[2] = 0.0f;
			else
				sub_v3_v3v3(v->co, vec, x->co);
			
			copy_v3_v3(x->co, vec);
		}

		surmd->cfra = md->scene->r.cfra;

		if(surmd->bvhtree)
			free_bvhtree_from_mesh(surmd->bvhtree);
		else
			surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");

		if(surmd->dm->getNumFaces(surmd->dm))
			bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
		else
			bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
	}
}
コード例 #23
0
ファイル: cloth.c プロジェクト: OldBrunet/BGERTPS
/************************************************
 * clothModifier_do - main simulation function
************************************************/
DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm)
{
	DerivedMesh *result;
	PointCache *cache;
	PTCacheID pid;
	float timescale;
	int framenr, startframe, endframe;
	int cache_result;

	clmd->scene= scene;	/* nice to pass on later :) */
	framenr= (int)scene->r.cfra;
	cache= clmd->point_cache;
	result = CDDM_copy(dm);

	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
	BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
	clmd->sim_parms->timescale= timescale;

	if(!result) {
		BKE_ptcache_invalidate(cache);
		return dm;
	}

	if(clmd->sim_parms->reset
		|| (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0)
		|| (clmd->clothObject && result->getNumVerts(result) != clmd->clothObject->numverts))
	{
		clmd->sim_parms->reset = 0;
		cache->flag |= PTCACHE_OUTDATED;
		BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
		BKE_ptcache_validate(cache, 0);
		cache->last_exact= 0;
		cache->flag &= ~PTCACHE_REDO_NEEDED;
		return result;
	}
	
	// unused in the moment, calculated separately in implicit.c
	clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;

	/* handle continuous simulation with the play button */
	if(BKE_ptcache_get_continue_physics() || ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe))) {
		BKE_ptcache_invalidate(cache);

		/* do simulation */
		if(!do_init_cloth(ob, clmd, dm, framenr))
			return result;

		do_step_cloth(ob, clmd, dm, framenr);
		cloth_to_object(ob, clmd, result);

		return result;
	}

	/* simulation is only active during a specific period */
	if(framenr < startframe) {
		BKE_ptcache_invalidate(cache);
		return result;
	}
	else if(framenr > endframe) {
		framenr= endframe;
	}

	/* initialize simulation data if it didn't exist already */
	if(!do_init_cloth(ob, clmd, dm, framenr))
		return result;

	if((framenr == startframe) && (clmd->sim_parms->preroll == 0)) {
		BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
		do_init_cloth(ob, clmd, dm, framenr);
		BKE_ptcache_validate(cache, framenr);
		cache->flag &= ~PTCACHE_REDO_NEEDED;
		return result;
	}

	/* try to read from cache */
	cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe);

	if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
		implicit_set_positions(clmd);
		cloth_to_object (ob, clmd, result);

		BKE_ptcache_validate(cache, framenr);

		if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
			BKE_ptcache_write(&pid, framenr);

		return result;
	}
	else if(cache_result==PTCACHE_READ_OLD) {
		implicit_set_positions(clmd);
	}
	else if( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */
		/* if baked and nothing in cache, do nothing */
		BKE_ptcache_invalidate(cache);
		return result;
	}

	/* if on second frame, write cache for first frame */
	if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
		BKE_ptcache_write(&pid, startframe);

	clmd->sim_parms->timescale *= framenr - cache->simframe;

	/* do simulation */
	BKE_ptcache_validate(cache, framenr);

	if(!do_step_cloth(ob, clmd, dm, framenr)) {
		BKE_ptcache_invalidate(cache);
	}
	else
		BKE_ptcache_write(&pid, framenr);

	cloth_to_object (ob, clmd, result);

	return result;
}
コード例 #24
0
ファイル: MOD_multires.c プロジェクト: greg100795/blender-git
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
                                  ModifierApplyFlag flag)
{
	MultiresModifierData *mmd = (MultiresModifierData *)md;
	DerivedMesh *result;
	Mesh *me = (Mesh *)ob->data;
	const bool useRenderParams = (flag & MOD_APPLY_RENDER) != 0;
	const bool ignore_simplify = (flag & MOD_APPLY_IGNORE_SIMPLIFY) != 0;
	MultiresFlags flags = 0;
	const bool has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK);

	if (mmd->totlvl) {
		if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) {
			/* multires always needs a displacement layer */
			CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop);
		}
	}

	if (has_mask)
		flags |= MULTIRES_ALLOC_PAINT_MASK;

	if (useRenderParams)
		flags |= MULTIRES_USE_RENDER_PARAMS;

	if (ignore_simplify)
		flags |= MULTIRES_IGNORE_SIMPLIFY;

	result = multires_make_derived_from_derived(dm, mmd, ob, flags);

	if (result == dm)
		return dm;

	if (useRenderParams || !(flag & MOD_APPLY_USECACHE)) {
		DerivedMesh *cddm;
		
		cddm = CDDM_copy(result);

		/* copy hidden/masks to vertices */
		if (!useRenderParams) {
			struct MDisps *mdisps;
			struct GridPaintMask *grid_paint_mask;
			
			mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
			grid_paint_mask = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
			
			if (mdisps) {
				subsurf_copy_grid_hidden(result, me->mpoly,
				                         cddm->getVertArray(cddm),
				                         mdisps);

				BKE_mesh_flush_hidden_from_verts_ex(cddm->getVertArray(cddm),
				                                    cddm->getLoopArray(cddm),
				                                    cddm->getEdgeArray(cddm),
				                                    cddm->getNumEdges(cddm),
				                                    cddm->getPolyArray(cddm),
				                                    cddm->getNumPolys(cddm));
			}
			if (grid_paint_mask) {
				float *paint_mask = CustomData_add_layer(&cddm->vertData,
				                                         CD_PAINT_MASK,
				                                         CD_CALLOC, NULL,
				                                         cddm->getNumVerts(cddm));

				subsurf_copy_grid_paint_mask(result, me->mpoly,
				                             paint_mask, grid_paint_mask);
			}
		}

		result->release(result);
		result = cddm;
	}

	return result;
}
コード例 #25
0
ファイル: displist.c プロジェクト: OldBrunet/BGERTPS
static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase,
	DerivedMesh **derivedFinal, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3])
{
	ModifierData *md = modifiers_getVirtualModifierList(ob);
	ModifierData *preTesselatePoint;
	Curve *cu= ob->data;
	ListBase *nurb= BKE_curve_nurbs(cu);
	int required_mode = 0, totvert = 0;
	int editmode = (!forRender && cu->editnurb);
	DerivedMesh *dm= NULL, *ndm;
	float (*vertCos)[3] = NULL;

	if(forRender) required_mode = eModifierMode_Render;
	else required_mode = eModifierMode_Realtime;

	preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode);
	
	if(editmode) required_mode |= eModifierMode_Editmode;

	if (preTesselatePoint) {
		md = preTesselatePoint->next;
	}

	if (derivedFinal && *derivedFinal) {
		(*derivedFinal)->release (*derivedFinal);
	}

	for (; md; md=md->next) {
		ModifierTypeInfo *mti = modifierType_getInfo(md->type);

		md->scene= scene;

		if ((md->mode & required_mode) != required_mode) continue;
		if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;

		if (mti->type == eModifierTypeType_OnlyDeform ||
				(mti->type == eModifierTypeType_DeformOrConstruct && !dm)) {
			if (dm) {
				if (!vertCos) {
					totvert = dm->getNumVerts(dm);
					vertCos = MEM_mallocN(sizeof(*vertCos) * totvert, "dfmv");
					dm->getVertCos(dm, vertCos);
				}

				mti->deformVerts(md, ob, dm, vertCos, totvert, forRender, editmode);
			} else {
				if (!vertCos) {
					vertCos= displist_get_allverts(dispbase, &totvert);
				}

				mti->deformVerts(md, ob, NULL, vertCos, totvert, forRender, editmode);
			}
		} else {
			if (!derivedFinal) {
				/* makeDisplistCurveTypes could be used for beveling, where derived mesh */
				/* is totally unnecessary, so we could stop modifiers applying */
				/* when we found constructive modifier but derived mesh is unwanted result */
				break;
			}

			if (dm) {
				if (vertCos) {
					DerivedMesh *tdm = CDDM_copy(dm);
					dm->release(dm);
					dm = tdm;

					CDDM_apply_vert_coords(dm, vertCos);
					CDDM_calc_normals(dm);
				}
			} else {
				if (vertCos) {
					displist_apply_allverts(dispbase, vertCos);
				}

				if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
					curve_to_filledpoly(cu, nurb, dispbase);
				}

				dm= CDDM_from_curve_customDB(ob, dispbase);

				CDDM_calc_normals(dm);
			}

			if (vertCos) {
				/* Vertex coordinates were applied to necessary data, could free it */
				MEM_freeN(vertCos);
				vertCos= NULL;
			}

			ndm = mti->applyModifier(md, ob, dm, forRender, editmode);

			if (ndm) {
				/* Modifier returned a new derived mesh */

				if (dm && dm != ndm) /* Modifier  */
					dm->release (dm);
				dm = ndm;
			}
		}
	}

	if (vertCos) {
		if (dm) {
			DerivedMesh *tdm = CDDM_copy(dm);
			dm->release(dm);
			dm = tdm;

			CDDM_apply_vert_coords(dm, vertCos);
			CDDM_calc_normals(dm);
			MEM_freeN(vertCos);
		} else {
			displist_apply_allverts(dispbase, vertCos);
			MEM_freeN(vertCos);
			vertCos= NULL;
		}
	}

	if (derivedFinal) {
		(*derivedFinal) = dm;
	}

	if (deformedVerts) {
		curve_applyVertexCos(ob->data, nurb, originalVerts);
		MEM_freeN(originalVerts);
		MEM_freeN(deformedVerts);
	}
}
コード例 #26
0
/* from/to_world_space : whether from/to particles are in world or hair space
 * from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
 */
static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
                               Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
                               float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
{
	ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys);
	ParticleData *pa, *tpa;
	PTCacheEditPoint *edit_point;
	PTCacheEditKey *ekey;
	BVHTreeFromMesh bvhtree= {NULL};
	MFace *mface = NULL, *mf;
	MEdge *medge = NULL, *me;
	MVert *mvert;
	DerivedMesh *dm, *target_dm;
	int numverts;
	int i, k;
	float from_ob_imat[4][4], to_ob_imat[4][4];
	float from_imat[4][4], to_imat[4][4];

	if (!target_psmd->dm)
		return false;
	if (!psys->part || psys->part->type != PART_HAIR)
		return false;
	if (!target_psys->part || target_psys->part->type != PART_HAIR)
		return false;
	
	edit_point = target_edit ? target_edit->points : NULL;
	
	invert_m4_m4(from_ob_imat, ob->obmat);
	invert_m4_m4(to_ob_imat, target_ob->obmat);
	invert_m4_m4(from_imat, from_mat);
	invert_m4_m4(to_imat, to_mat);
	
	if (target_psmd->dm->deformedOnly) {
		/* we don't want to mess up target_psmd->dm when converting to global coordinates below */
		dm = target_psmd->dm;
	}
	else {
		/* warning: this rebuilds target_psmd->dm! */
		dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH | CD_MASK_MFACE);
	}
	target_dm = target_psmd->dm;
	/* don't modify the original vertices */
	dm = CDDM_copy(dm);

	/* BMESH_ONLY, deform dm may not have tessface */
	DM_ensure_tessface(dm);

	numverts = dm->getNumVerts(dm);
	mvert = dm->getVertArray(dm);

	/* convert to global coordinates */
	for (i=0; i<numverts; i++)
		mul_m4_v3(to_mat, mvert[i].co);

	if (dm->getNumTessFaces(dm) != 0) {
		mface = dm->getTessFaceArray(dm);
		bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6);
	}
	else if (dm->getNumEdges(dm) != 0) {
		medge = dm->getEdgeArray(dm);
		bvhtree_from_mesh_edges(&bvhtree, dm, 0.0, 2, 6);
	}
	else {
		dm->release(dm);
		return false;
	}

	for (i = 0, tpa = target_psys->particles, pa = psys->particles;
	     i < target_psys->totpart;
	     i++, tpa++, pa++) {

		float from_co[3];
		BVHTreeNearest nearest;

		if (from_global)
			mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co);
		else
			mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co);
		mul_m4_v3(from_mat, from_co);

		nearest.index = -1;
		nearest.dist_sq = FLT_MAX;

		BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);

		if (nearest.index == -1) {
			if (G.debug & G_DEBUG)
				printf("No nearest point found for hair root!");
			continue;
		}

		if (mface) {
			float v[4][3];
			
			mf = &mface[nearest.index];

			copy_v3_v3(v[0], mvert[mf->v1].co);
			copy_v3_v3(v[1], mvert[mf->v2].co);
			copy_v3_v3(v[2], mvert[mf->v3].co);
			if (mf->v4) {
				copy_v3_v3(v[3], mvert[mf->v4].co);
				interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
			}
			else
				interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
			tpa->foffset = 0.0f;

			tpa->num = nearest.index;
			tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL);
		}
		else {
			me = &medge[nearest.index];

			tpa->fuv[1] = line_point_factor_v3(nearest.co,
			                                   mvert[me->v1].co,
			                                   mvert[me->v2].co);
			tpa->fuv[0] = 1.0f - tpa->fuv[1];
			tpa->fuv[2] = tpa->fuv[3] = 0.0f;
			tpa->foffset = 0.0f;

			tpa->num = nearest.index;
			tpa->num_dmcache = -1;
		}

		/* translate hair keys */
		{
			HairKey *key, *tkey;
			float hairmat[4][4], imat[4][4];
			float offset[3];
			
			if (to_global)
				copy_m4_m4(imat, target_ob->obmat);
			else {
				/* note: using target_dm here, which is in target_ob object space and has full modifiers */
				psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat);
				invert_m4_m4(imat, hairmat);
			}
			mul_m4_m4m4(imat, imat, to_imat);
			
			/* offset in world space */
			sub_v3_v3v3(offset, nearest.co, from_co);
			
			if (edit_point) {
				for (k=0, key=pa->hair, tkey=tpa->hair, ekey = edit_point->keys; k<tpa->totkey; k++, key++, tkey++, ekey++) {
					float co_orig[3];
					
					if (from_global)
						mul_v3_m4v3(co_orig, from_ob_imat, key->co);
					else
						mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
					mul_m4_v3(from_mat, co_orig);
					
					add_v3_v3v3(tkey->co, co_orig, offset);
					
					mul_m4_v3(imat, tkey->co);
					
					ekey->flag |= PEK_USE_WCO;
				}
				
				edit_point++;
			}
			else {
				for (k=0, key=pa->hair, tkey=tpa->hair; k<tpa->totkey; k++, key++, tkey++) {
					float co_orig[3];
					
					if (from_global)
						mul_v3_m4v3(co_orig, from_ob_imat, key->co);
					else
						mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
					mul_m4_v3(from_mat, co_orig);
					
					add_v3_v3v3(tkey->co, co_orig, offset);
					
					mul_m4_v3(imat, tkey->co);
				}
			}
		}
	}

	free_bvhtree_from_mesh(&bvhtree);
	dm->release(dm);

	psys_free_path_cache(target_psys, target_edit);

	PE_update_object(scene, target_ob, 0);

	return true;
}
コード例 #27
0
static DerivedMesh *doOcean(ModifierData *md, Object *ob,
                            DerivedMesh *derivedData,
                            int UNUSED(useRenderParams))
{
	OceanModifierData *omd = (OceanModifierData *) md;

	DerivedMesh *dm = NULL;
	OceanResult ocr;

	MVert *mverts, *mv;
	MLoop *mloops;

	int i, j;

	int num_verts;
	int num_faces;

	int cfra;

	/* use cached & inverted value for speed
	 * expanded this would read...
	 *
	 * (axis / (omd->size * omd->spatial_size)) + 0.5f) */
#define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f)

	const float size_co_inv = 1.0f / (omd->size * omd->spatial_size);

	/* can happen in when size is small, avoid bad array lookups later and quit now */
	if (!finite(size_co_inv)) {
		return derivedData;
	}

	/* update modifier */
	if (omd->refresh & MOD_OCEAN_REFRESH_ADD)
		omd->ocean = BKE_ocean_add();
	if (omd->refresh & MOD_OCEAN_REFRESH_RESET)
		init_ocean_modifier(omd);
	if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE)
		clear_cache_data(omd);

	omd->refresh = 0;

	/* do ocean simulation */
	if (omd->cached == true) {
		if (!omd->oceancache) init_cache_data(ob, omd);
		BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra);
	}
	else {
		simulate_ocean_modifier(omd);
	}

	if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
		dm = generate_ocean_geometry(omd);
		DM_ensure_normals(dm);
	}
	else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
		dm = CDDM_copy(derivedData);
	}

	cfra = md->scene->r.cfra;
	CLAMP(cfra, omd->bakestart, omd->bakeend);
	cfra -= omd->bakestart; /* shift to 0 based */

	num_verts = dm->getNumVerts(dm);
	num_faces = dm->getNumPolys(dm);

	mverts = dm->getVertArray(dm);
	mloops = dm->getLoopArray(dm);

	/* add vcols before displacement - allows lookup based on position */

	if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
		int cdlayer = CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL);

		if (cdlayer < MAX_MCOL) {
			MLoopCol *mloopcols = CustomData_add_layer_named(&dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL,
			                                                 num_faces * 4, omd->foamlayername);

			if (mloopcols) { /* unlikely to fail */
				MLoopCol *mlcol;
				MPoly *mpolys = dm->getPolyArray(dm);
				MPoly *mp;

				float foam;

				for (i = 0, mp = mpolys; i < num_faces; i++, mp++) {
					j = mp->totloop - 1;

					/* highly unlikely */
					if (j <= 0) continue;

					do {
						const float *co = mverts[mloops[mp->loopstart + j].v].co;
						const float u = OCEAN_CO(size_co_inv, co[0]);
						const float v = OCEAN_CO(size_co_inv, co[1]);

						if (omd->oceancache && omd->cached == true) {
							BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
							foam = ocr.foam;
							CLAMP(foam, 0.0f, 1.0f);
						}
						else {
							BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
							foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
						}

						mlcol = &mloopcols[mp->loopstart + j];
						mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
						/* This needs to be set (render engine uses) */
						mlcol->a = 255;
					} while (j--);
				}
			}
		}
	}


	/* displace the geometry */

	/* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */
	for (i = 0, mv = mverts; i < num_verts; i++, mv++) {
		const float u = OCEAN_CO(size_co_inv, mv->co[0]);
		const float v = OCEAN_CO(size_co_inv, mv->co[1]);

		if (omd->oceancache && omd->cached == true)
			BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
		else
			BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);

		mv->co[2] += ocr.disp[1];

		if (omd->chop_amount > 0.0f) {
			mv->co[0] += ocr.disp[0];
			mv->co[1] += ocr.disp[2];
		}
	}

#undef OCEAN_CO

	return dm;
}
コード例 #28
0
ファイル: fluidsim.c プロジェクト: jinjoh/NOOR
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
{
#ifndef DISABLE_ELBEEM
	DerivedMesh *result = NULL;
	int framenr;
	FluidsimSettings *fss = NULL;

	framenr= (int)scene->r.cfra;
	
	// only handle fluidsim domains
	if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
		return dm;
	
	// sanity check
	if(!fluidmd || (fluidmd && !fluidmd->fss))
		return dm;
	
	fss = fluidmd->fss;
	
	// timescale not supported yet
	// clmd->sim_parms->timescale= timescale;
	
	// support reversing of baked fluid frames here
	if((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0))
	{
		framenr = fss->lastgoodframe - framenr + 1;
		CLAMP(framenr, 1, fss->lastgoodframe);
	}
	
	/* try to read from cache */
	if(((fss->lastgoodframe >= framenr) || (fss->lastgoodframe < 0)) && (result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams)))
	{
		// fss->lastgoodframe = framenr; // set also in src/fluidsim.c
		return result;
	}
	else
	{	
		// display last known good frame
		if(fss->lastgoodframe >= 0)
		{
			if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams))) 
			{
				return result;
			}
			
			// it was supposed to be a valid frame but it isn't!
			fss->lastgoodframe = framenr - 1;
			
			
			// this could be likely the case when you load an old fluidsim
			if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams))) 
			{
				return result;
			}
		}
		
		result = CDDM_copy(dm);

		if(result) 
		{
			return result;
		}
	}
	
	return dm;
#else
	return NULL;
#endif
}