예제 #1
0
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);
}
예제 #2
0
static DerivedMesh *applyModifier(ModifierData *md,
                                  Object *UNUSED(ob),
                                  DerivedMesh *dm,
                                  ModifierApplyFlag UNUSED(flag))
{
	RemeshModifierData *rmd;
	DualConOutput *output;
	DualConInput input;
	DerivedMesh *result;
	DualConFlags flags = 0;
	DualConMode mode = 0;

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

	rmd = (RemeshModifierData *)md;

	init_dualcon_mesh(&input, dm);

	if (rmd->flag & MOD_REMESH_FLOOD_FILL)
		flags |= DUALCON_FLOOD_FILL;

	switch (rmd->mode) {
		case MOD_REMESH_CENTROID:
			mode = DUALCON_CENTROID;
			break;
		case MOD_REMESH_MASS_POINT:
			mode = DUALCON_MASS_POINT;
			break;
		case MOD_REMESH_SHARP_FEATURES:
			mode = DUALCON_SHARP_FEATURES;
			break;
	}
	
	output = dualcon(&input,
	                 dualcon_alloc_output,
	                 dualcon_add_vert,
	                 dualcon_add_quad,
	                 flags,
	                 mode,
	                 rmd->threshold,
	                 rmd->hermite_num,
	                 rmd->scale,
	                 rmd->depth);
	result = output->dm;
	MEM_freeN(output);

	if (rmd->flag & MOD_REMESH_SMOOTH_SHADING) {
		MPoly *mpoly = CDDM_get_polys(result);
		int i, totpoly = result->getNumPolys(result);
		
		/* Apply smooth shading to output faces */
		for (i = 0; i < totpoly; i++) {
			mpoly[i].flag |= ME_SMOOTH;
		}
	}

	CDDM_calc_edges(result);
	result->dirty |= DM_DIRTY_NORMALS;
	return result;
}
예제 #3
0
void initElbeemMesh(struct Scene *scene, struct Object *ob,
                    int *numVertices, float **vertices,
                    int *numTriangles, int **triangles,
                    int useGlobalCoords, int modifierIndex)
{
	DerivedMesh *dm = NULL;
	MVert *mvert;
	MFace *mface;
	int countTris = 0, i, totvert, totface;
	float *verts;
	int *tris;

	dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex);

	DM_ensure_tessface(dm);

	mvert = dm->getVertArray(dm);
	mface = dm->getTessFaceArray(dm);
	totvert = dm->getNumVerts(dm);
	totface = dm->getNumTessFaces(dm);

	*numVertices = totvert;
	verts = MEM_callocN(totvert * 3 * sizeof(float), "elbeemmesh_vertices");
	for (i = 0; i < totvert; i++) {
		copy_v3_v3(&verts[i * 3], mvert[i].co);
		if (useGlobalCoords) { mul_m4_v3(ob->obmat, &verts[i * 3]); }
	}
	*vertices = verts;

	for (i = 0; i < totface; i++) {
		countTris++;
		if (mface[i].v4) { countTris++; }
	}
	*numTriangles = countTris;
	tris = MEM_callocN(countTris * 3 * sizeof(int), "elbeemmesh_triangles");
	countTris = 0;
	for (i = 0; i < totface; i++) {
		int face[4];
		face[0] = mface[i].v1;
		face[1] = mface[i].v2;
		face[2] = mface[i].v3;
		face[3] = mface[i].v4;

		tris[countTris * 3 + 0] = face[0];
		tris[countTris * 3 + 1] = face[1];
		tris[countTris * 3 + 2] = face[2];
		countTris++;
		if (face[3]) {
			tris[countTris * 3 + 0] = face[0];
			tris[countTris * 3 + 1] = face[2];
			tris[countTris * 3 + 2] = face[3];
			countTris++;
		}
	}
	*triangles = tris;

	dm->release(dm);
}
static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm,
                       float (*vertexCos)[3], int numVerts)
{
	int i;
	int defgrp_index;
	int total_anchors;
	float wpaint;
	MDeformVert *dvert = NULL;
	MDeformVert *dv = NULL;
	LaplacianSystem *sys;
	if (isValidVertexGroup(lmd, ob, dm)) {
		int *index_anchors = MEM_mallocN(sizeof(int) * numVerts, __func__);  /* over-alloc */
		MFace *tessface;
		STACK_DECLARE(index_anchors);
		STACK_INIT(index_anchors);

		modifier_get_vgroup(ob, dm, lmd->anchor_grp_name, &dvert, &defgrp_index);
		BLI_assert(dvert != NULL);
		dv = dvert;
		for (i = 0; i < numVerts; i++) {
			wpaint = defvert_find_weight(dv, defgrp_index);
			dv++;
			if (wpaint > 0.0f) {
				STACK_PUSH(index_anchors, i);
			}
		}
		DM_ensure_tessface(dm);
		total_anchors = STACK_SIZE(index_anchors);
		lmd->cache_system = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumTessFaces(dm),
		                                       total_anchors, lmd->anchor_grp_name, lmd->repeat);
		sys = (LaplacianSystem *)lmd->cache_system;
		memcpy(sys->index_anchors, index_anchors, sizeof(int) * total_anchors);
		memcpy(sys->co, vertexCos, sizeof(float[3]) * numVerts);
		MEM_freeN(index_anchors);
		STACK_FREE(index_anchors);
		lmd->vertexco = MEM_mallocN(sizeof(float[3]) * numVerts, "ModDeformCoordinates");
		memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * numVerts);
		lmd->total_verts = numVerts;

		createFaceRingMap(
		            dm->getNumVerts(dm), dm->getTessFaceArray(dm), dm->getNumTessFaces(dm),
		            &sys->ringf_map, &sys->ringf_indices);
		createVertRingMap(
		            dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm),
		            &sys->ringv_map, &sys->ringv_indices);


		tessface = dm->getTessFaceArray(dm);

		for (i = 0; i < sys->total_faces; i++) {
			memcpy(&sys->faces[i], &tessface[i].v1, sizeof(*sys->faces));
		}
	}
}
예제 #5
0
static DerivedMesh *applyModifier(ModifierData *md,
                                  Object *UNUSED(ob),
                                  DerivedMesh *dm,
                                  ModifierApplyFlag UNUSED(flag))
{
	RemeshModifierData *rmd;
	DualConOutput *output;
	DualConInput input;
	DerivedMesh *result;
	DualConFlags flags = 0;
	DualConMode mode = 0;

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

	rmd = (RemeshModifierData *)md;

	init_dualcon_mesh(&input, dm);

	if (rmd->flag & MOD_REMESH_FLOOD_FILL)
		flags |= DUALCON_FLOOD_FILL;

	switch (rmd->mode) {
		case MOD_REMESH_CENTROID:
			mode = DUALCON_CENTROID;
			break;
		case MOD_REMESH_MASS_POINT:
			mode = DUALCON_MASS_POINT;
			break;
		case MOD_REMESH_SHARP_FEATURES:
			mode = DUALCON_SHARP_FEATURES;
			break;
	}
	
	output = dualcon(&input,
	                 dualcon_alloc_output,
	                 dualcon_add_vert,
	                 dualcon_add_quad,
	                 flags,
	                 mode,
	                 rmd->threshold,
	                 rmd->hermite_num,
	                 rmd->scale,
	                 rmd->depth);
	result = output->dm;
	MEM_freeN(output);

	CDDM_calc_edges(result);
	CDDM_calc_normals(result);
	return result;
}
예제 #6
0
static DerivedMesh *cloth_to_triangles(DerivedMesh *dm)
{
	DerivedMesh *result = NULL;
	unsigned int i = 0, j = 0;
	unsigned int quads = 0, numfaces = dm->getNumTessFaces(dm);
	MFace *mface = dm->getTessFaceArray(dm);
	MFace *mface2 = NULL;

	/* calc faces */
	for (i = 0; i < numfaces; i++) {
		if (mface[i].v4) {
			quads++;
		}
	}
		
	result = CDDM_from_template(dm, dm->getNumVerts(dm), 0, numfaces + quads, 0, 0);

	DM_copy_vert_data(dm, result, 0, 0, dm->getNumVerts(dm));
	DM_copy_tessface_data(dm, result, 0, 0, numfaces);

	DM_ensure_tessface(result);
	mface2 = result->getTessFaceArray(result);

	for (i = 0, j = numfaces; i < numfaces; i++) {
		// DG TODO: is this necessary?
		mface2[i].v1 = mface[i].v1;
		mface2[i].v2 = mface[i].v2;
		mface2[i].v3 = mface[i].v3;

		mface2[i].v4 = 0;
		//test_index_face(&mface2[i], &result->faceData, i, 3);

		if (mface[i].v4) {
			DM_copy_tessface_data(dm, result, i, j, 1);

			mface2[j].v1 = mface[i].v1;
			mface2[j].v2 = mface[i].v3;
			mface2[j].v3 = mface[i].v4;
			mface2[j].v4 = 0;
			//test_index_face(&mface2[j], &result->faceData, j, 3);

			j++;
		}
	}

	CDDM_calc_edges_tessface(result);
	CDDM_tessfaces_to_faces(result); /* builds ngon faces from tess (mface) faces */

	return result;
}
예제 #7
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	DerivedMesh *dm = derivedData;
	ExplodeModifierData *emd = (ExplodeModifierData *) md;
	ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ob, md);

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

	if (psmd) {
		ParticleSystem *psys = psmd->psys;

		if (psys == NULL || psys->totpart == 0) return derivedData;
		if (psys->part == NULL || psys->particles == NULL) return derivedData;
		if (psmd->dm == NULL) return derivedData;

		/* 1. find faces to be exploded if needed */
		if (emd->facepa == NULL ||
		    psmd->flag & eParticleSystemFlag_Pars ||
		    emd->flag & eExplodeFlag_CalcFaces ||
		    MEM_allocN_len(emd->facepa) / sizeof(int) != dm->getNumTessFaces(dm))
		{
			if (psmd->flag & eParticleSystemFlag_Pars)
				psmd->flag &= ~eParticleSystemFlag_Pars;
			
			if (emd->flag & eExplodeFlag_CalcFaces)
				emd->flag &= ~eExplodeFlag_CalcFaces;

			createFacepa(emd, psmd, derivedData);
		}
		/* 2. create new mesh */
		if (emd->flag & eExplodeFlag_EdgeCut) {
			int *facepa = emd->facepa;
			DerivedMesh *splitdm = cutEdges(emd, dm);
			DerivedMesh *explode = explodeMesh(emd, psmd, md->scene, ob, splitdm);

			MEM_freeN(emd->facepa);
			emd->facepa = facepa;
			splitdm->release(splitdm);
			return explode;
		}
		else
			return explodeMesh(emd, psmd, md->scene, ob, derivedData);
	}
	return derivedData;
}
예제 #8
0
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);
}
예제 #9
0
static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
						DerivedMesh *derivedData,
						int UNUSED(useRenderParams),
						int UNUSED(isFinalCalc))
{
	DerivedMesh *dm = derivedData, *result;
	ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
	ParticleSimulationData sim;
	ParticleSystem *psys= NULL;
	ParticleData *pa= NULL, *pars= NULL;
	MFace *mface, *orig_mface;
	MVert *mvert, *orig_mvert;
	int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
	short track=ob->trackflag%3, trackneg, axis = pimd->axis;
	float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
	float *size=NULL;

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

	trackneg=((ob->trackflag>2)?1:0);

	if (pimd->ob==ob) {
		pimd->ob= NULL;
		return derivedData;
	}

	if (pimd->ob) {
		psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
		if (psys==NULL || psys->totpart==0)
			return derivedData;
	}
	else return derivedData;

	if (pimd->flag & eParticleInstanceFlag_Parents)
		totpart+=psys->totpart;
	if (pimd->flag & eParticleInstanceFlag_Children) {
		if (totpart==0)
			first_particle=psys->totpart;
		totpart+=psys->totchild;
	}

	if (totpart==0)
		return derivedData;

	sim.scene = md->scene;
	sim.ob = pimd->ob;
	sim.psys = psys;
	sim.psmd = psys_get_modifier(pimd->ob, psys);

	if (pimd->flag & eParticleInstanceFlag_UseSize) {
		int p;
		float *si;
		si = size = MEM_callocN(totpart * sizeof(float), "particle size array");

		if (pimd->flag & eParticleInstanceFlag_Parents) {
			for (p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
				*si = pa->size;
		}

		if (pimd->flag & eParticleInstanceFlag_Children) {
			ChildParticle *cpa = psys->child;

			for (p=0; p<psys->totchild; p++, cpa++, si++) {
				*si = psys_get_child_size(psys, cpa, 0.0f, NULL);
			}
		}
	}

	pars=psys->particles;

	totvert=dm->getNumVerts(dm);
	totface=dm->getNumTessFaces(dm);

	maxvert=totvert*totpart;
	maxface=totface*totpart;

	psys->lattice=psys_get_lattice(&sim);

	if (psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {

		float min_r[3], max_r[3];
		INIT_MINMAX(min_r, max_r);
		dm->getMinMax(dm, min_r, max_r);
		min_co=min_r[track];
		max_co=max_r[track];
	}

	result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface, 0, 0);

	mvert=result->getVertArray(result);
	orig_mvert=dm->getVertArray(dm);

	for (i=0; i<maxvert; i++) {
		MVert *inMV;
		MVert *mv = mvert + i;
		ParticleKey state;

		inMV = orig_mvert + i%totvert;
		DM_copy_vert_data(dm, result, i%totvert, i, 1);
		*mv = *inMV;

		/*change orientation based on object trackflag*/
		copy_v3_v3(temp_co, mv->co);
		mv->co[axis]=temp_co[track];
		mv->co[(axis+1)%3]=temp_co[(track+1)%3];
		mv->co[(axis+2)%3]=temp_co[(track+2)%3];

		if ((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path) {
			float ran = 0.0f;
			if (pimd->random_position != 0.0f) {
				BLI_srandom(psys->seed + (i/totvert)%totpart);
				ran = pimd->random_position * BLI_frand();
			}

			if (pimd->flag & eParticleInstanceFlag_KeepShape) {
				state.time = pimd->position * (1.0f - ran);
			}
			else {
				state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);

				if (trackneg)
					state.time=1.0f-state.time;

				mv->co[axis] = 0.0;
			}

			psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);

			normalize_v3(state.vel);

			/* TODO: incremental rotations somehow */
			if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
				state.rot[0] = 1;
				state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
			}
			else {
				float temp[3] = {0.0f,0.0f,0.0f};
				temp[axis] = 1.0f;

				cross_v3_v3v3(cross, temp, state.vel);

				/* state.vel[axis] is the only component surviving from a dot product with the axis */
				axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
			}

		}
		else {
			state.time=-1.0;
			psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
		}

		mul_qt_v3(state.rot,mv->co);
		if (pimd->flag & eParticleInstanceFlag_UseSize)
			mul_v3_fl(mv->co, size[i/totvert]);
		add_v3_v3(mv->co, state.co);
	}

	mface=result->getTessFaceArray(result);
	orig_mface=dm->getTessFaceArray(dm);

	for (i=0; i<maxface; i++) {
		MFace *inMF;
		MFace *mf = mface + i;

		if (pimd->flag & eParticleInstanceFlag_Parents) {
			if (i/totface>=psys->totpart) {
				if (psys->part->childtype==PART_CHILD_PARTICLES) {
					pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
				}
				else {
					pa= NULL;
				}
			}
			else {
				pa=pars+i/totface;
			}
		}
		else {
			if (psys->part->childtype==PART_CHILD_PARTICLES) {
				pa=psys->particles+(psys->child+i/totface)->parent;
			}
			else {
				pa= NULL;
			}
		}

		if (pa) {
			if (pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
			if (pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
			if (pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
		}

		inMF = orig_mface + i%totface;
		DM_copy_poly_data(dm, result, i%totface, i, 1);
		*mf = *inMF;

		mf->v1+=(i/totface)*totvert;
		mf->v2+=(i/totface)*totvert;
		mf->v3+=(i/totface)*totvert;
		if (mf->v4) {
			mf->v4+=(i/totface)*totvert;
		}
	}

	CDDM_calc_edges_tessface(result);

	if (psys->lattice) {
		end_latt_deform(psys->lattice);
		psys->lattice= NULL;
	}

	if (size)
		MEM_freeN(size);

	CDDM_tessfaces_to_faces(result); /*builds ngon faces from tess (mface) faces*/
	CDDM_calc_normals(result);

	return result;
}
예제 #10
0
/* create collision shape of mesh - triangulated mesh
 * returns NULL if creation fails.
 */
static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
{
	rbCollisionShape *shape = NULL;

	if (ob->type == OB_MESH) {
		DerivedMesh *dm = NULL;
		MVert *mvert;
		MFace *mface;
		int totvert;
		int totface;
		int tottris = 0;
		int triangle_index = 0;

		dm = rigidbody_get_mesh(ob);

		/* ensure mesh validity, then grab data */
		if (dm == NULL)
			return NULL;

		DM_ensure_tessface(dm);

		mvert   = (dm) ? dm->getVertArray(dm) : NULL;
		totvert = (dm) ? dm->getNumVerts(dm) : 0;
		mface   = (dm) ? dm->getTessFaceArray(dm) : NULL;
		totface = (dm) ? dm->getNumTessFaces(dm) : 0;

		/* sanity checking - potential case when no data will be present */
		if ((totvert == 0) || (totface == 0)) {
			printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2);
		}
		else {
			rbMeshData *mdata;
			int i;
			
			/* count triangles */
			for (i = 0; i < totface; i++) {
				(mface[i].v4) ? (tottris += 2) : (tottris += 1);
			}

			/* init mesh data for collision shape */
			mdata = RB_trimesh_data_new(tottris, totvert);
			
			RB_trimesh_add_vertices(mdata, (float *)mvert, totvert, sizeof(MVert));

			/* loop over all faces, adding them as triangles to the collision shape
			 * (so for some faces, more than triangle will get added)
			 */
			for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
				/* add first triangle - verts 1,2,3 */
				RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v2, mface->v3);
				triangle_index++;

				/* add second triangle if needed - verts 1,3,4 */
				if (mface->v4) {
					RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v3, mface->v4);
					triangle_index++;
				}
			}
			RB_trimesh_finish(mdata);

			/* construct collision shape
			 *
			 * These have been chosen to get better speed/accuracy tradeoffs with regards
			 * to limitations of each:
			 *    - BVH-Triangle Mesh: for passive objects only. Despite having greater
			 *                         speed/accuracy, they cannot be used for moving objects.
			 *    - GImpact Mesh:      for active objects. These are slower and less stable,
			 *                         but are more flexible for general usage.
			 */
			if (ob->rigidbody_object->type == RBO_TYPE_PASSIVE) {
				shape = RB_shape_new_trimesh(mdata);
			}
			else {
				shape = RB_shape_new_gimpact_mesh(mdata);
			}
		}

		/* cleanup temp data */
		if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
			dm->release(dm);
		}
	}
	else {
		printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n");
	}

	return shape;
}
예제 #11
0
static void laplaciansmoothModifier_do(
        LaplacianSmoothModifierData *smd, Object *ob, DerivedMesh *dm,
        float (*vertexCos)[3], int numVerts)
{
	LaplacianSystem *sys;
	MDeformVert *dvert = NULL;
	MDeformVert *dv = NULL;
	float w, wpaint;
	int i, iter;
	int defgrp_index;

	DM_ensure_tessface(dm);

	sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumTessFaces(dm), numVerts);
	if (!sys) {
		return;
	}

	sys->mfaces = dm->getTessFaceArray(dm);
	sys->medges = dm->getEdgeArray(dm);
	sys->vertexCos = vertexCos;
	sys->min_area = 0.00001f;
	modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index);

	sys->vert_centroid[0] = 0.0f;
	sys->vert_centroid[1] = 0.0f;
	sys->vert_centroid[2] = 0.0f;
	memset_laplacian_system(sys, 0);

#ifdef OPENNL_THREADING_HACK
	modifier_opennl_lock();
#endif

	nlNewContext();
	sys->context = nlGetCurrent();
	nlSolverParameteri(NL_NB_VARIABLES, numVerts);
	nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
	nlSolverParameteri(NL_NB_ROWS, numVerts);
	nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3);

	init_laplacian_matrix(sys);

	for (iter = 0; iter < smd->repeat; iter++) {
		nlBegin(NL_SYSTEM);
		for (i = 0; i < numVerts; i++) {
			nlSetVariable(0, i, vertexCos[i][0]);
			nlSetVariable(1, i, vertexCos[i][1]);
			nlSetVariable(2, i, vertexCos[i][2]);
			if (iter == 0) {
				add_v3_v3(sys->vert_centroid, vertexCos[i]);
			}
		}
		if (iter == 0 && numVerts > 0) {
			mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts);
		}

		nlBegin(NL_MATRIX);
		dv = dvert;
		for (i = 0; i < numVerts; i++) {
			nlRightHandSideSet(0, i, vertexCos[i][0]);
			nlRightHandSideSet(1, i, vertexCos[i][1]);
			nlRightHandSideSet(2, i, vertexCos[i][2]);
			if (iter == 0) {
				if (dv) {
					wpaint = defvert_find_weight(dv, defgrp_index);
					dv++;
				}
				else {
					wpaint = 1.0f;
				}

				if (sys->zerola[i] == 0) {
					if (smd->flag & MOD_LAPLACIANSMOOTH_NORMALIZED) {
						w = sys->vweights[i];
						sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w;
						w = sys->vlengths[i];
						sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
						if (sys->numNeEd[i] == sys->numNeFa[i]) {
							nlMatrixAdd(i, i,  1.0f + fabsf(smd->lambda) * wpaint);
						}
						else {
							nlMatrixAdd(i, i,  1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
						}
					}
					else {
						w = sys->vweights[i] * sys->ring_areas[i];
						sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / (4.0f * w);
						w = sys->vlengths[i];
						sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;

						if (sys->numNeEd[i] == sys->numNeFa[i]) {
							nlMatrixAdd(i, i,  1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i]));
						}
						else {
							nlMatrixAdd(i, i,  1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
						}
					}
				}
				else {
					nlMatrixAdd(i, i, 1.0f);
				}
			}
		}

		if (iter == 0) {
			fill_laplacian_matrix(sys);
		}

		nlEnd(NL_MATRIX);
		nlEnd(NL_SYSTEM);

		if (nlSolveAdvanced(NULL, NL_TRUE)) {
			validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border);
		}
	}
	nlDeleteContext(sys->context);
	sys->context = NULL;

#ifdef OPENNL_THREADING_HACK
	modifier_opennl_unlock();
#endif

	delete_laplacian_system(sys);
}
예제 #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
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
/* 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;
}
예제 #15
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;
}
예제 #16
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;
	}
}
예제 #17
0
bool RE_bake_pixels_populate_from_objects(
        struct Mesh *me_low, BakePixel pixel_array_from[],  BakePixel pixel_array_to[],
        BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
        const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage)
{
	size_t i;
	int primitive_id;
	float u, v;
	float imat_low[4][4];
	bool is_cage = me_cage != NULL;
	bool result = true;

	DerivedMesh *dm_low = NULL;
	DerivedMesh **dm_highpoly;
	BVHTreeFromMesh *treeData;

	/* Note: all coordinates are in local space */
	TriTessFace *tris_low = NULL;
	TriTessFace *tris_cage = NULL;
	TriTessFace **tris_high;

	/* assume all lowpoly tessfaces can be quads */
	tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array");

	/* assume all highpoly tessfaces are triangles */
	dm_highpoly = MEM_mallocN(sizeof(DerivedMesh *) * tot_highpoly, "Highpoly Derived Meshes");
	treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees");

	if (!is_cage) {
		dm_low = CDDM_from_mesh(me_low);
		tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh");
		mesh_calc_tri_tessface(tris_low, me_low, true, dm_low);
	}
	else if (is_custom_cage) {
		tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh");
		mesh_calc_tri_tessface(tris_low, me_low, false, NULL);

		tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh");
		mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
	}
	else {
		tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh");
		mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
	}

	invert_m4_m4(imat_low, mat_low);

	for (i = 0; i < tot_highpoly; i++) {
		tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly[i].me->totface, "MVerts Highpoly Mesh");
		mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL);

		dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me);
		DM_ensure_tessface(dm_highpoly[i]);

		if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) {
			/* Create a bvh-tree for each highpoly object */
			bvhtree_from_mesh_faces(&treeData[i], dm_highpoly[i], 0.0, 2, 6);

			if (treeData[i].tree == NULL) {
				printf("Baking: out of memory while creating BHVTree for object \"%s\"\n", highpoly[i].ob->id.name + 2);
				result = false;
				goto cleanup;
			}
		}
	}

	for (i = 0; i < num_pixels; i++) {
		float co[3];
		float dir[3];

		primitive_id = pixel_array_from[i].primitive_id;

		if (primitive_id == -1) {
			pixel_array_to[i].primitive_id = -1;
			continue;
		}

		u = pixel_array_from[i].uv[0];
		v = pixel_array_from[i].uv[1];

		/* calculate from low poly mesh cage */
		if (is_custom_cage) {
			calc_point_from_barycentric_cage(tris_low, tris_cage, mat_low, mat_cage, primitive_id, u, v, co, dir);
		}
		else if (is_cage) {
			calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true);
		}
		else {
			calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false);
		}

		/* cast ray */
		if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly,
		                       pixel_array_from[i].du_dx, pixel_array_from[i].du_dy,
		                       pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) {
			/* if it fails mask out the original pixel array */
			pixel_array_from[i].primitive_id = -1;
		}
	}


	/* garbage collection */
cleanup:
	for (i = 0; i < tot_highpoly; i++) {
		free_bvhtree_from_mesh(&treeData[i]);

		if (dm_highpoly[i]) {
			dm_highpoly[i]->release(dm_highpoly[i]);
		}

		if (tris_high[i]) {
			MEM_freeN(tris_high[i]);
		}
	}

	MEM_freeN(tris_high);
	MEM_freeN(treeData);
	MEM_freeN(dm_highpoly);

	if (dm_low) {
		dm_low->release(dm_low);
	}
	if (tris_low) {
		MEM_freeN(tris_low);
	}
	if (tris_cage) {
		MEM_freeN(tris_cage);
	}

	return result;
}
예제 #18
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 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;
	}
}