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); }
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; }
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)); } } }
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; }
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; }
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; }
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); }
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; }
/* 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; }
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); }
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); }
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; }
/* 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; }
/* 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; }
/* 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; } }
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; }
/* 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; } }