bool BL_ModifierDeformer::Update(void) { bool bShapeUpdate = BL_ShapeDeformer::Update(); if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) { // static derived mesh are not updated if (m_dm == NULL || m_bDynamic) { /* execute the modifiers */ Object* blendobj = m_gameobj->GetBlendObject(); /* hack: the modifiers require that the mesh is attached to the object * It may not be the case here because of replace mesh actuator */ Mesh *oldmesh = (Mesh*)blendobj->data; blendobj->data = m_bmesh; /* execute the modifiers */ DerivedMesh *dm = mesh_create_derived_no_virtual(m_scene, blendobj, m_transverts, CD_MASK_MESH); /* restore object data */ blendobj->data = oldmesh; /* free the current derived mesh and replace, (dm should never be NULL) */ if (m_dm != NULL) { // HACK! use deformedOnly as a user counter if (--m_dm->deformedOnly == 0) { m_dm->needsFree = 1; m_dm->release(m_dm); } } m_dm = dm; // get rid of temporary data m_dm->needsFree = 0; m_dm->release(m_dm); // HACK! use deformedOnly as a user counter m_dm->deformedOnly = 1; DM_update_materials(m_dm, blendobj); /* update the graphic controller */ PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController(); if (ctrl) { float min[3], max[3]; INIT_MINMAX(min, max); m_dm->getMinMax(m_dm, min, max); ctrl->SetLocalAabb(min, max); } } m_lastModifierUpdate=m_gameobj->GetLastFrame(); bShapeUpdate = true; int nmat = m_pMeshObject->NumMaterials(); for (int imat=0; imat<nmat; imat++) { RAS_MeshMaterial *mmat = m_pMeshObject->GetMeshMaterial(imat); RAS_MeshSlot **slot = mmat->m_slots[(void*)m_gameobj]; if (!slot || !*slot) continue; (*slot)->m_pDerivedMesh = m_dm; } } return bShapeUpdate; }
bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, unsigned short* &polys, int& npolys, unsigned short *&dmeshes, float *&dvertices, int &ndvertsuniq, unsigned short *&dtris, int& ndtris, int &vertsPerPoly) { DerivedMesh* dm = mesh_create_derived_no_virtual(GetScene()->GetBlenderScene(), GetBlenderObject(), NULL, CD_MASK_MESH); CustomData *pdata = dm->getPolyDataLayout(dm); int* recastData = (int*) CustomData_get_layer(pdata, CD_RECAST); if (recastData) { int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL; int nAllVerts = 0; float *allVerts = NULL; buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nAllVerts, &allVerts, &ndtris, &dtris, &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap, &trisToFacesMap); MEM_SAFE_FREE(dtrisToPolysMap); MEM_SAFE_FREE(dtrisToTrisMap); MEM_SAFE_FREE(trisToFacesMap); unsigned short *verticesMap = (unsigned short *)MEM_mallocN(sizeof(*verticesMap) * nAllVerts, __func__); memset(verticesMap, 0xff, sizeof(*verticesMap) * nAllVerts); int curIdx = 0; //vertices - mesh verts //iterate over all polys and create map for their vertices first... for (int polyidx=0; polyidx<npolys; polyidx++) { unsigned short* poly = &polys[polyidx*vertsPerPoly*2]; for (int i=0; i<vertsPerPoly; i++) { unsigned short idx = poly[i]; if (idx==0xffff) break; if (verticesMap[idx]==0xffff) { verticesMap[idx] = curIdx++; } poly[i] = verticesMap[idx]; } } nverts = curIdx; //...then iterate over detailed meshes //transform indices to local ones (for each navigation polygon) for (int polyidx=0; polyidx<npolys; polyidx++) { unsigned short *poly = &polys[polyidx*vertsPerPoly*2]; int nv = polyNumVerts(poly, vertsPerPoly); unsigned short *dmesh = &dmeshes[4*polyidx]; unsigned short tribase = dmesh[2]; unsigned short trinum = dmesh[3]; unsigned short vbase = curIdx; for (int j=0; j<trinum; j++) { unsigned short* dtri = &dtris[(tribase+j)*3*2]; for (int k=0; k<3; k++) { int newVertexIdx = verticesMap[dtri[k]]; if (newVertexIdx==0xffff) { newVertexIdx = curIdx++; verticesMap[dtri[k]] = newVertexIdx; } if (newVertexIdx<nverts) { //it's polygon vertex ("shared") int idxInPoly = polyFindVertex(poly, vertsPerPoly, newVertexIdx); if (idxInPoly==-1) { printf("Building NavMeshObject: Error! Can't find vertex in polygon\n"); return false; } dtri[k] = idxInPoly; } else { dtri[k] = newVertexIdx - vbase + nv; } } } dmesh[0] = vbase-nverts; //verts base dmesh[1] = curIdx-vbase; //verts num } vertices = new float[nverts*3]; ndvertsuniq = curIdx - nverts; if (ndvertsuniq>0) { dvertices = new float[ndvertsuniq*3]; } for (int vi=0; vi<nAllVerts; vi++) { int newIdx = verticesMap[vi]; if (newIdx!=0xffff) { if (newIdx<nverts) { //navigation mesh vertex memcpy(vertices+3*newIdx, allVerts+3*vi, 3*sizeof(float)); } else { //detailed mesh vertex memcpy(dvertices+3*(newIdx-nverts), allVerts+3*vi, 3*sizeof(float)); } } } MEM_SAFE_FREE(allVerts); MEM_freeN(verticesMap); } else { //create from RAS_MeshObject (detailed mesh is fake) RAS_MeshObject* meshobj = GetMesh(0); vertsPerPoly = 3; nverts = meshobj->m_sharedvertex_map.size(); if (nverts >= 0xffff) return false; //calculate count of tris int nmeshpolys = meshobj->NumPolygons(); npolys = nmeshpolys; for (int p=0; p<nmeshpolys; p++) { int vertcount = meshobj->GetPolygon(p)->VertexCount(); npolys+=vertcount-3; } //create verts vertices = new float[nverts*3]; float* vert = vertices; for (int vi=0; vi<nverts; vi++) { const float* pos = !meshobj->m_sharedvertex_map[vi].empty() ? meshobj->GetVertexLocation(vi) : NULL; if (pos) copy_v3_v3(vert, pos); else { memset(vert, 0, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates } vert+=3; } //create tris polys = (unsigned short *)MEM_callocN(sizeof(unsigned short)*3*2*npolys, "BuildVertIndArrays polys"); memset(polys, 0xff, sizeof(unsigned short)*3*2*npolys); unsigned short *poly = polys; RAS_Polygon* raspoly; for (int p=0; p<nmeshpolys; p++) { raspoly = meshobj->GetPolygon(p); for (int v=0; v<raspoly->VertexCount()-2; v++) { poly[0] = raspoly->GetVertex(0)->getOrigIndex(); for (size_t i=1; i<3; i++) { poly[i] = raspoly->GetVertex(v+i)->getOrigIndex(); } poly += 6; } } dmeshes = NULL; dvertices = NULL; ndvertsuniq = 0; dtris = NULL; ndtris = npolys; } dm->release(dm); return true; }
static void createVertsTrisData(bContext *C, LinkNode* obs, int *nverts_r, float **verts_r, int *ntris_r, int **tris_r) { MVert *mvert; int nfaces= 0, *tri, i, curnverts, basenverts, curnfaces; MFace *mface; float co[3], wco[3]; Object *ob; LinkNode *oblink, *dmlink; DerivedMesh *dm; Scene* scene= CTX_data_scene(C); LinkNode* dms= NULL; int nverts, ntris, *tris; float *verts; nverts= 0; ntris= 0; /* calculate number of verts and tris */ for(oblink= obs; oblink; oblink= oblink->next) { ob= (Object*) oblink->link; dm= mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); BLI_linklist_append(&dms, (void*)dm); nverts+= dm->getNumVerts(dm); nfaces= dm->getNumFaces(dm); ntris+= nfaces; /* resolve quad faces */ mface= dm->getFaceArray(dm); for(i= 0; i<nfaces; i++) { MFace* mf= &mface[i]; if(mf->v4) ntris+=1; } } /* create data */ verts= MEM_mallocN(sizeof(float)*3*nverts, "createVertsTrisData verts"); tris= MEM_mallocN(sizeof(int)*3*ntris, "createVertsTrisData faces"); basenverts= 0; tri= tris; for(oblink= obs, dmlink= dms; oblink && dmlink; oblink= oblink->next, dmlink= dmlink->next) { ob= (Object*) oblink->link; dm= (DerivedMesh*) dmlink->link; curnverts= dm->getNumVerts(dm); mvert= dm->getVertArray(dm); /* copy verts */ for(i= 0; i<curnverts; i++) { MVert *v= &mvert[i]; copy_v3_v3(co, v->co); mul_v3_m4v3(wco, ob->obmat, co); verts[3*(basenverts+i)+0]= wco[0]; verts[3*(basenverts+i)+1]= wco[2]; verts[3*(basenverts+i)+2]= wco[1]; } /* create tris */ curnfaces= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); for(i= 0; i<curnfaces; i++) { MFace* mf= &mface[i]; tri[0]= basenverts + mf->v1; tri[1]= basenverts + mf->v3; tri[2]= basenverts + mf->v2; tri += 3; if(mf->v4) { tri[0]= basenverts + mf->v1; tri[1]= basenverts + mf->v4; tri[2]= basenverts + mf->v3; tri += 3; } } basenverts+= curnverts; } /* release derived mesh */ for(dmlink= dms; dmlink; dmlink= dmlink->next) { dm= (DerivedMesh*) dmlink->link; dm->release(dm); } BLI_linklist_free(dms, NULL); *nverts_r= nverts; *verts_r= verts; *ntris_r= ntris; *tris_r= tris; }