/* compute uv coordinates of mouse in face */ void imapaint_pick_uv(Scene *scene, Object *ob, Mesh *mesh, unsigned int faceindex, int *xy, float *uv) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf; int numfaces = dm->getNumFaces(dm), a; float p[2], w[3], absw, minabsw; MFace mf; MVert mv[4]; minabsw = 1e10; uv[0] = uv[1] = 0.0; /* test all faces in the derivedmesh with the original index of the picked face */ for(a = 0; a < numfaces; a++) { if(index[a] == faceindex) { dm->getFace(dm, a, &mf); dm->getVert(dm, mf.v1, &mv[0]); dm->getVert(dm, mf.v2, &mv[1]); dm->getVert(dm, mf.v3, &mv[2]); if(mf.v4) dm->getVert(dm, mf.v4, &mv[3]); tf= &tface[a]; p[0]= xy[0]; p[1]= xy[1]; if(mf.v4) { /* the triangle with the largest absolute values is the one with the most negative weights */ imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[3].co, p, w); absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]); if(absw < minabsw) { uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[3][0]*w[2]; uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[3][1]*w[2]; minabsw = absw; } imapaint_tri_weights(ob, mv[1].co, mv[2].co, mv[3].co, p, w); absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]); if(absw < minabsw) { uv[0]= tf->uv[1][0]*w[0] + tf->uv[2][0]*w[1] + tf->uv[3][0]*w[2]; uv[1]= tf->uv[1][1]*w[0] + tf->uv[2][1]*w[1] + tf->uv[3][1]*w[2]; minabsw = absw; } } else { imapaint_tri_weights(ob, mv[0].co, mv[1].co, mv[2].co, p, w); absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]); if(absw < minabsw) { uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2]; uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2]; minabsw = absw; } } } } dm->release(dm); }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, int useRenderParams, int UNUSED(isFinalCalc)) { DerivedMesh *dm= derivedData; DerivedMesh *result; ScrewModifierData *ltmd= (ScrewModifierData*) md; int *origindex; int mface_index=0; int step; int i, j; int i1,i2; int step_tot= useRenderParams ? ltmd->render_steps : ltmd->steps; const int do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0; int maxVerts=0, maxEdges=0, maxFaces=0; int totvert= dm->getNumVerts(dm); int totedge= dm->getNumEdges(dm); char axis_char= 'X', close; float angle= ltmd->angle; float screw_ofs= ltmd->screw_ofs; float axis_vec[3]= {0.0f, 0.0f, 0.0f}; float tmp_vec1[3], tmp_vec2[3]; float mat3[3][3]; float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */ float mtx_tx_inv[4][4]; /* inverted */ float mtx_tmp_a[4][4]; int vc_tot_linked= 0; short other_axis_1, other_axis_2; float *tmpf1, *tmpf2; MFace *mface_new, *mf_new; MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new; MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base; ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL; /* dont do anything? */ if (!totvert) return CDDM_from_template(dm, 0, 0, 0); switch(ltmd->axis) { case 0: other_axis_1=1; other_axis_2=2; break; case 1: other_axis_1=0; other_axis_2=2; break; default: /* 2, use default to quiet warnings */ other_axis_1=0; other_axis_2=1; break; } axis_vec[ltmd->axis]= 1.0f; if (ltmd->ob_axis) { /* calc the matrix relative to the axis object */ invert_m4_m4(mtx_tmp_a, ob->obmat); copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat); mul_m4_m4m4(mtx_tx, mtx_tx_inv, mtx_tmp_a); /* calc the axis vec */ mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */ normalize_v3(axis_vec); /* screw */ if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) { /* find the offset along this axis relative to this objects matrix */ float totlen = len_v3(mtx_tx[3]); if(totlen != 0.0f) { float zero[3]= {0.0f, 0.0f, 0.0f}; float cp[3]; screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec); } else { screw_ofs= 0.0f; } } /* angle */ #if 0 // cant incluide this, not predictable enough, though quite fun,. if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) { float mtx3_tx[3][3]; copy_m3_m4(mtx3_tx, mtx_tx); float vec[3] = {0,1,0}; float cross1[3]; float cross2[3]; cross_v3_v3v3(cross1, vec, axis_vec); mul_v3_m3v3(cross2, mtx3_tx, cross1); { float c1[3]; float c2[3]; float axis_tmp[3]; cross_v3_v3v3(c1, cross2, axis_vec); cross_v3_v3v3(c2, axis_vec, c1); angle= angle_v3v3(cross1, c2); cross_v3_v3v3(axis_tmp, cross1, c2); normalize_v3(axis_tmp); if(len_v3v3(axis_tmp, axis_vec) > 1.0f) angle= -angle; } } #endif } else { /* exis char is used by i_rotate*/ axis_char += ltmd->axis; /* 'X' + axis */ /* useful to be able to use the axis vec in some cases still */ zero_v3(axis_vec); axis_vec[ltmd->axis]= 1.0f; } /* apply the multiplier */ angle *= ltmd->iter; screw_ofs *= ltmd->iter; /* multiplying the steps is a bit tricky, this works best */ step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1); /* will the screw be closed? * Note! smaller then FLT_EPSILON*100 gives problems with float precision so its never closed. */ if (fabsf(screw_ofs) <= (FLT_EPSILON*100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON*100.0f)) { close= 1; step_tot--; if(step_tot < 3) step_tot= 3; maxVerts = totvert * step_tot; /* -1 because we're joining back up */ maxEdges = (totvert * step_tot) + /* these are the edges between new verts */ (totedge * step_tot); /* -1 because vert edges join */ maxFaces = totedge * step_tot; screw_ofs= 0.0f; } else { close= 0; if(step_tot < 3) step_tot= 3; maxVerts = totvert * step_tot; /* -1 because we're joining back up */ maxEdges = (totvert * (step_tot-1)) + /* these are the edges between new verts */ (totedge * step_tot); /* -1 because vert edges join */ maxFaces = totedge * (step_tot-1); } result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces); /* copy verts from mesh */ mvert_orig = dm->getVertArray(dm); medge_orig = dm->getEdgeArray(dm); mvert_new = result->getVertArray(result); mface_new = result->getFaceArray(result); medge_new = result->getEdgeArray(result); origindex= result->getFaceDataArray(result, CD_ORIGINDEX); DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */ /* Set the locations of the first set of verts */ mv_new= mvert_new; mv_orig= mvert_orig; /* Copy the first set of edges */ med_orig= medge_orig; med_new= medge_new; for (i=0; i < totedge; i++, med_orig++, med_new++) { med_new->v1= med_orig->v1; med_new->v2= med_orig->v2; med_new->crease= med_orig->crease; med_new->flag= med_orig->flag & ~ME_LOOSEEDGE; } if(ltmd->flag & MOD_SCREW_NORMAL_CALC) { /* * Normal Calculation (for face flipping) * Sort edge verts for correct face flipping * NOT REALLY NEEDED but face flipping is nice. * * */ /* Notice! * * Since we are only ordering the edges here it can avoid mallocing the * extra space by abusing the vert array berfore its filled with new verts. * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3 * so its safe to use the second 2 thrids of MVert the array for vert_connect, * just make sure ScrewVertConnect struct is no more then twice as big as MVert, * at the moment there is no chance of that being a problem, * unless MVert becomes half its current size. * * once the edges are ordered, vert_connect is not needed and it can be used for verts * * This makes the modifier faster with one less alloc. */ vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect"); //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */ vc= vert_connect; /* Copy Vert Locations */ /* - We can do this in a later loop - only do here if no normal calc */ if (!totedge) { for (i=0; i < totvert; i++, mv_orig++, mv_new++) { copy_v3_v3(mv_new->co, mv_orig->co); normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is really a dummy normal */ } } else { /*printf("\n\n\n\n\nStarting Modifier\n");*/ /* set edge users */ med_new= medge_new; mv_new= mvert_new; if (ltmd->ob_axis) { /*mtx_tx is initialized early on */ for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { vc->co[0]= mv_new->co[0]= mv_orig->co[0]; vc->co[1]= mv_new->co[1]= mv_orig->co[1]; vc->co[2]= mv_new->co[2]= mv_orig->co[2]; vc->flag= 0; vc->e[0]= vc->e[1]= NULL; vc->v[0]= vc->v[1]= -1; mul_m4_v3(mtx_tx, vc->co); /* length in 2d, dont sqrt because this is only for comparison */ vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + vc->co[other_axis_2]*vc->co[other_axis_2]; /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ } } else { for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { vc->co[0]= mv_new->co[0]= mv_orig->co[0]; vc->co[1]= mv_new->co[1]= mv_orig->co[1]; vc->co[2]= mv_new->co[2]= mv_orig->co[2]; vc->flag= 0; vc->e[0]= vc->e[1]= NULL; vc->v[0]= vc->v[1]= -1; /* length in 2d, dont sqrt because this is only for comparison */ vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + vc->co[other_axis_2]*vc->co[other_axis_2]; /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ } } /* this loop builds connectivity info for verts */ for (i=0; i<totedge; i++, med_new++) { vc= &vert_connect[med_new->v1]; if (vc->v[0] == -1) { /* unused */ vc->v[0]= med_new->v2; vc->e[0]= med_new; } else if (vc->v[1] == -1) { vc->v[1]= med_new->v2; vc->e[1]= med_new; } else { vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */ } vc= &vert_connect[med_new->v2]; /* same as above but swap v1/2 */ if (vc->v[0] == -1) { /* unused */ vc->v[0]= med_new->v1; vc->e[0]= med_new; } else if (vc->v[1] == -1) { vc->v[1]= med_new->v1; vc->e[1]= med_new; } else { vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */ } } /* find the first vert */ vc= vert_connect; for (i=0; i < totvert; i++, vc++) { /* Now do search for connected verts, order all edges and flip them * so resulting faces are flipped the right way */ vc_tot_linked= 0; /* count the number of linked verts for this loop */ if (vc->flag == 0) { int v_best=-1, ed_loop_closed=0; /* vert and vert new */ ScrewVertIter lt_iter; int ed_loop_flip= 0; /* compiler complains if not initialized, but it should be initialized below */ float fl= -1.0f; /*printf("Loop on connected vert: %i\n", i);*/ for(j=0; j<2; j++) { /*printf("\tSide: %i\n", j);*/ screwvert_iter_init(<_iter, vert_connect, i, j); if (j == 1) { screwvert_iter_step(<_iter); } while (lt_iter.v_poin) { /*printf("\t\tVERT: %i\n", lt_iter.v);*/ if (lt_iter.v_poin->flag) { /*printf("\t\t\tBreaking Found end\n");*/ //endpoints[0]= endpoints[1]= -1; ed_loop_closed= 1; /* circle */ break; } lt_iter.v_poin->flag= 1; vc_tot_linked++; /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/ if (fl <= lt_iter.v_poin->dist) { fl= lt_iter.v_poin->dist; v_best= lt_iter.v; /*printf("\t\t\tVERT BEST: %i\n", v_best);*/ } screwvert_iter_step(<_iter); if (!lt_iter.v_poin) { /*printf("\t\t\tFound End Also Num %i\n", j);*/ /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */ break; } } } /* now we have a collection of used edges. flip their edges the right way*/ /*if (v_best != -1) - */ /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/ if (vc_tot_linked>1) { float vf_1, vf_2, vf_best; vc_tmp= &vert_connect[v_best]; tmpf1= vert_connect[vc_tmp->v[0]].co; tmpf2= vert_connect[vc_tmp->v[1]].co; /* edge connects on each side! */ if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) { /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ /* find out which is higher */ vf_1= tmpf1[ltmd->axis]; vf_2= tmpf2[ltmd->axis]; vf_best= vc_tmp->co[ltmd->axis]; if (vf_1 < vf_best && vf_best < vf_2) { ed_loop_flip= 0; } else if (vf_1 > vf_best && vf_best > vf_2) { ed_loop_flip= 1; } else { /* not so simple to work out which edge is higher */ sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co); sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co); normalize_v3(tmp_vec1); normalize_v3(tmp_vec2); if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) { ed_loop_flip= 1; } else { ed_loop_flip= 0; } } } else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */ /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */ ed_loop_flip= 1; } else { /* best is below or even... in even case we cant know whet to do. */ ed_loop_flip= 0; } }/* else { printf("No Connected ___\n"); }*/ /*printf("flip direction %i\n", ed_loop_flip);*/ /* switch the flip option if set * note: flip is now done at face level so copying vgroup slizes is easier */ /* if (do_flip) ed_loop_flip= !ed_loop_flip; */ if (angle < 0.0f) ed_loop_flip= !ed_loop_flip; /* if its closed, we only need 1 loop */ for(j=ed_loop_closed; j<2; j++) { /*printf("Ordering Side J %i\n", j);*/ screwvert_iter_init(<_iter, vert_connect, v_best, j); /*printf("\n\nStarting - Loop\n");*/ lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */ /* If this is the vert off the best vert and * the best vert has 2 edges connected too it * then swap the flip direction */ if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) ed_loop_flip= !ed_loop_flip; while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) { /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/ lt_iter.v_poin->flag= 2; if (lt_iter.e) { if (lt_iter.v == lt_iter.e->v1) { if (ed_loop_flip == 0) { /*printf("\t\t\tFlipping 0\n");*/ SWAP(int, lt_iter.e->v1, lt_iter.e->v2); }/* else { printf("\t\t\tFlipping Not 0\n"); }*/ } else if (lt_iter.v == lt_iter.e->v2) { if (ed_loop_flip == 1) { /*printf("\t\t\tFlipping 1\n");*/ SWAP(int, lt_iter.e->v1, lt_iter.e->v2); }/* else { printf("\t\t\tFlipping Not 1\n"); }*/ }/* else { printf("\t\tIncorrect edge topology"); }*/ }/* else { printf("\t\tNo Edge at this point\n"); }*/ screwvert_iter_step(<_iter); } }
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(KX_GetActiveScene()->GetBlenderScene(), GetBlenderObject(), NULL, CD_MASK_MESH); int* recastData = (int*) dm->getFaceDataArray(dm, 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_freeN(dtrisToPolysMap); MEM_freeN(dtrisToTrisMap); MEM_freeN(trisToFacesMap); unsigned short *verticesMap = new unsigned short[nAllVerts]; memset(verticesMap, 0xffff, sizeof(unsigned short)*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_freeN(allVerts); } 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 = new unsigned short[npolys*3*2]; 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; }
DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) { MFace *mface, *mf; MEdge *medge, *me; MVert *mvert, *mv; int *origindex; int totface,totedge,totvert,i,bmeshok,len, numTex, numCol; BME_Vert *v1=NULL; BME_Edge *e=NULL, *oe=NULL; BME_Poly *f=NULL; DerivedMesh *result; EdgeHash *edge_hash = BLI_edgehash_new(); totvert = BLI_countlist(&(bm->verts)); totedge = 0; /*we cannot have double edges in a derived mesh!*/ for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i; for(e=bm->edges.first; e; e=e->next){ oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1); if(!oe){ totedge++; BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e); e->tflag2 = 1; } else{ e->tflag2 = 0; } } /*count quads and tris*/ totface = 0; bmeshok = 1; for(f=bm->polys.first;f;f=f->next){ len = BME_cycle_length(f->loopbase); if(len == 3 || len == 4) totface++; } /*convert back to mesh*/ result = CDDM_from_template(dm,totvert,totedge,totface); CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert); CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge); CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface); CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface); numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); /*Make Verts*/ mvert = CDDM_get_verts(result); origindex = result->getVertDataArray(result, CD_ORIGINDEX); for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){ VECCOPY(mv->co,v1->co); mv->flag = (unsigned char)v1->flag; mv->bweight = (char)(255.0*v1->bweight); CustomData_from_bmesh_block(&bm->vdata, &result->vertData, &v1->data, i); origindex[i] = ORIGINDEX_NONE; } medge = CDDM_get_edges(result); origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); i=0; for(e=bm->edges.first,me=medge;e;e=e->next){ if(e->tflag2){ if(e->v1->tflag1 < e->v2->tflag1){ me->v1 = e->v1->tflag1; me->v2 = e->v2->tflag1; } else{ me->v1 = e->v2->tflag1; me->v2 = e->v1->tflag1; } me->crease = (char)(255.0*e->crease); me->bweight = (char)(255.0*e->bweight); me->flag = e->flag; CustomData_from_bmesh_block(&bm->edata, &result->edgeData, &e->data, i); origindex[i] = ORIGINDEX_NONE; me++; i++; } } if(totface){ mface = CDDM_get_faces(result); origindex = result->getFaceDataArray(result, CD_ORIGINDEX); /*make faces*/ for(i=0,f=bm->polys.first;f;f=f->next){ mf = &mface[i]; len = BME_cycle_length(f->loopbase); if(len==3 || len==4){ mf->v1 = f->loopbase->v->tflag1; mf->v2 = f->loopbase->next->v->tflag1; mf->v3 = f->loopbase->next->next->v->tflag1; if(len == 4){ mf->v4 = f->loopbase->prev->v->tflag1; } /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */ if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){ test_index_face(mf, NULL, i, len); } mf->mat_nr = (unsigned char)f->mat_nr; mf->flag = (unsigned char)f->flag; CustomData_from_bmesh_block(&bm->pdata, &result->faceData, &f->data, i); BME_DMloops_to_corners(bm, &result->faceData, i, f,numCol,numTex); origindex[i] = ORIGINDEX_NONE; i++; } } } BLI_edgehash_free(edge_hash, NULL); return result; }