Exemple #1
1
/* turns Mesh into editmesh */
void make_editMesh(Scene *scene, Object *ob)
{
	Mesh *me= ob->data;
	MFace *mface;
	MVert *mvert;
	MSelect *mselect;
	KeyBlock *actkey;
	EditMesh *em;
	EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
	EditFace *efa, *efa_last_sel= NULL;
	EditEdge *eed;
	EditSelection *ese;
	float *co, (*keyco)[3]= NULL;
	int tot, a, eekadoodle= 0;
	const short is_paint_face_sel=                             paint_facesel_test(ob);
	const short is_paint_vert_sel= is_paint_face_sel ? FALSE : paint_vertsel_test(ob);

	if(me->edit_mesh==NULL)
		me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
	else 
		/* because of reload */
		free_editMesh(me->edit_mesh);
	
	em= me->edit_mesh;
	
	em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
	em->act_face = NULL;
	em->totvert= tot= me->totvert;
	em->totedge= me->totedge;
	em->totface= me->totface;
	
	if(tot==0) {
		return;
	}
	
	if(ob->actcol > 0)
		em->mat_nr= ob->actcol-1;

	/* initialize fastmalloc for editmesh */
	init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);

	actkey = ob_get_keyblock(ob);
	if(actkey) {
		/* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */
		undo_editmode_clear();
		keyco= actkey->data;
		em->shapenr= ob->shapenr;
	}

	/* make editverts */
	CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
	mvert= me->mvert;

	evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
	for(a=0; a<tot; a++, mvert++) {
		
		co= mvert->co;

		/* edit the shape key coordinate if available */
		if(keyco && a < actkey->totelem)
			co= keyco[a];

		eve= addvertlist(em, co, NULL);
		evlist[a]= eve;
		
		/* face select sets selection in next loop */
		if(!is_paint_face_sel)
			eve->f |= (mvert->flag & SELECT);
		
		if (mvert->flag & ME_HIDE) eve->h= 1;
		normal_short_to_float_v3(eve->no, mvert->no);

		eve->bweight= ((float)mvert->bweight)/255.0f;

		/* lets overwrite the keyindex of the editvert
		 * with the order it used to be in before
		 * editmode
		 */
		eve->keyindex = a;

		CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data);
	}

	if(actkey && actkey->totelem!=me->totvert);
	else {
		MEdge *medge= me->medge;
		
		CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
		/* make edges */
		for(a=0; a<me->totedge; a++, medge++) {
			eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL);
			/* eed can be zero when v1 and v2 are identical, dxf import does this... */
			if(eed) {
				int is_sel;
				if (is_paint_vert_sel) {
					/* when from vertex select, flush flags to edges,
					 * allow selection, code below handles editmode selection conversion */
					is_sel= (eed->v1->f & SELECT) && (eed->v2->f & SELECT);
				}
				else {
					is_sel= (medge->flag & SELECT);
				}

				eed->crease= ((float)medge->crease)/255.0f;
				eed->bweight= ((float)medge->bweight)/255.0f;
				
				if(medge->flag & ME_SEAM) eed->seam= 1;
				if(medge->flag & ME_SHARP) eed->sharp = 1;
				if(medge->flag & ME_FGON) eed->h= EM_FGON;	// 2 different defines!
				if(medge->flag & ME_HIDE) eed->h |= 1;
				if(is_sel) eed->f |= SELECT;
				if(em->selectmode==SCE_SELECT_EDGE)
					EM_select_edge(eed, eed->f & SELECT);		// force edge selection to vertices, seems to be needed ...
				CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data);
			}
		}
		
		CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);

		/* make faces */
		mface= me->mface;

		for(a=0; a<me->totface; a++, mface++) {
			eve1= evlist[mface->v1];
			eve2= evlist[mface->v2];
			if(!mface->v3) eekadoodle= 1;
			eve3= evlist[mface->v3];
			if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL;
			
			efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);

			if(efa) {
				CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data);

				efa->mat_nr= mface->mat_nr;
				efa->flag= mface->flag & ~ME_HIDE;
				
				/* select and hide face flag */
				if(mface->flag & ME_HIDE) {
					efa->h= 1;
				} else {
					int is_sel;

					if (!is_paint_vert_sel) {
						is_sel= (mface->flag & ME_FACE_SEL);
					}
					else {
						/* when from vertex select, flush flags to edges,
						 * allow selection, code below handles editmode selection conversion */
						is_sel= ( (efa->v1->f & SELECT) &&
						          (efa->v2->f & SELECT) &&
						          (efa->v3->f & SELECT) &&
						          (efa->v4 == NULL || efa->v4->f & SELECT)
						          );
					}

					if (a==me->act_face) {
						EM_set_actFace(em, efa);
					}
					
					/* dont allow hidden and selected */
					if(is_sel) {
						efa->f |= SELECT;
						
						if(is_paint_face_sel) {
							EM_select_face(efa, 1); /* flush down */
						}

						efa_last_sel= efa;
					}
				}
			}
		}
	}
	
	if(EM_get_actFace(em, 0)==NULL && efa_last_sel) {
		EM_set_actFace(em, efa_last_sel);
	}

	if(eekadoodle)
		error("This Mesh has old style edgecodes, please put it in the bugtracker!");
	
	MEM_freeN(evlist);

	end_editmesh_fastmalloc();	// resets global function pointers
	
	if(me->mselect){
		//restore editselections
		EM_init_index_arrays(em, 1,1,1);
		mselect = me->mselect;
		
		for(a=0; a<me->totselect; a++, mselect++){
			/*check if recorded selection is still valid, if so copy into editmesh*/
			if ( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) ||
			     (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) ||
			     (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) )
			{
				ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
				ese->type = mselect->type;	
				if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else
				if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else
				if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index);
				BLI_addtail(&(em->selected),ese);
			}
		}
		EM_free_index_arrays();
	}
	/* this creates coherent selections. also needed for older files */
	EM_selectmode_set(em);
	/* paranoia check to enforce hide rules */
	EM_hide_reset(em);
	/* sets helper flags which arent saved */
	EM_fgon_flags(em);
	
	if (EM_get_actFace(em, 0)==NULL) {
		EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */
	}
}
Exemple #2
1
static void undoMesh_to_editMesh(void *umv, void *emv)
{
	EditMesh *em= (EditMesh *)emv;
	UndoMesh *um= (UndoMesh *)umv;
	EditVert *eve, **evar=NULL;
	EditEdge *eed;
	EditFace *efa;
	EditSelection *ese;
	EditVertC *evec;
	EditEdgeC *eedc;
	EditFaceC *efac;
	EditSelectionC *esec;
	int a=0;

	free_editMesh(em);
	
	/* malloc blocks */
	memset(em, 0, sizeof(EditMesh));
		
	em->selectmode = um->selectmode;
	em->shapenr = um->shapenr;
	
	init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);

	CustomData_free(&em->vdata, 0);
	CustomData_free(&em->edata, 0);
	CustomData_free(&em->fdata, 0);

	CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
	CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
	CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);

	/* now copy vertices */

	if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
	for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
		eve= addvertlist(em, evec->co, NULL);
		evar[a]= eve;

		copy_v3_v3(eve->no, evec->no);
		eve->f= evec->f;
		eve->h= evec->h;
		eve->keyindex= evec->keyindex;
		eve->bweight= ((float)evec->bweight)/255.0f;

		CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data);
	}

	/* copy edges */
	for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) {
		eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL);

		eed->f= eedc->f;
		eed->h= eedc->h;
		eed->seam= eedc->seam;
		eed->sharp= eedc->sharp;
		eed->fgoni= eedc->fgoni;
		eed->crease= ((float)eedc->crease)/255.0f;
		eed->bweight= ((float)eedc->bweight)/255.0f;
		CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data);
	}
	
	/* copy faces */
	for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
		if(efac->v4 != -1)
			efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
		else 
			efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL);

		efa->mat_nr= efac->mat_nr;
		efa->flag= efac->flag;
		efa->f= efac->f;
		efa->h= efac->h;
		efa->fgonf= efac->fgonf;
		
		CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
	}
	
	end_editmesh_fastmalloc();
	if(evar) MEM_freeN(evar);
	
	em->totvert = um->totvert;
	em->totedge = um->totedge;
	em->totface = um->totface;
	/*restore stored editselections*/
	if(um->totsel){
		EM_init_index_arrays(em, 1,1,1);
		for(a=0, esec= um->selected; a<um->totsel; a++, esec++){
			ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
			ese->type = esec->type;
			if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else
			if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else
			if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index);
			BLI_addtail(&(em->selected),ese);
		}
		EM_free_index_arrays();
	}

	/* restore total selections */
	EM_nvertices_selected(em);
	EM_nedges_selected(em);
	EM_nfaces_selected(em);
}
Exemple #3
0
Mesh *BKE_mesh_copy_ex(Main *bmain, Mesh *me)
{
	Mesh *men;
	MTFace *tface;
	MTexPoly *txface;
	int a, i;
	const int do_tessface = ((me->totface != 0) && (me->totpoly == 0)); /* only do tessface if we have no polys */
	
	men = BKE_libblock_copy_ex(bmain, &me->id);
	
	men->mat = MEM_dupallocN(me->mat);
	for (a = 0; a < men->totcol; a++) {
		id_us_plus((ID *)men->mat[a]);
	}
	id_us_plus((ID *)men->texcomesh);

	CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert);
	CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge);
	CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop);
	CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly);
	if (do_tessface) {
		CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface);
	}
	else {
		mesh_tessface_clear_intern(men, FALSE);
	}

	BKE_mesh_update_customdata_pointers(men, do_tessface);

	/* ensure indirect linked data becomes lib-extern */
	for (i = 0; i < me->fdata.totlayer; i++) {
		if (me->fdata.layers[i].type == CD_MTFACE) {
			tface = (MTFace *)me->fdata.layers[i].data;

			for (a = 0; a < me->totface; a++, tface++)
				if (tface->tpage)
					id_lib_extern((ID *)tface->tpage);
		}
	}
	
	for (i = 0; i < me->pdata.totlayer; i++) {
		if (me->pdata.layers[i].type == CD_MTEXPOLY) {
			txface = (MTexPoly *)me->pdata.layers[i].data;

			for (a = 0; a < me->totpoly; a++, txface++)
				if (txface->tpage)
					id_lib_extern((ID *)txface->tpage);
		}
	}

	men->edit_btmesh = NULL;

	men->mselect = MEM_dupallocN(men->mselect);
	men->bb = MEM_dupallocN(men->bb);
	
	men->key = BKE_key_copy(me->key);
	if (men->key) men->key->from = (ID *)men;

	return men;
}
// =================================================================
// This functin is copied from source/blender/editors/mesh/mesh_data.c
//
// TODO: (As discussed with sergey-) :
// Maybe move this function to blenderkernel/intern/mesh.c 
// and add definition to BKE_mesh.c
// =================================================================
void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
{
	CustomData edata;
	MEdge *medge;
	int i, totedge;

	if (len == 0)
		return;

	totedge = mesh->totedge + len;

	/* update customdata  */
	CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
	CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);

	if (!CustomData_has_layer(&edata, CD_MEDGE))
		CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);

	CustomData_free(&mesh->edata, mesh->totedge);
	mesh->edata = edata;
	BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */

	/* set default flags */
	medge = &mesh->medge[mesh->totedge];
	for (i = 0; i < len; i++, medge++)
		medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;

	mesh->totedge = totedge;
}
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
{
	if (allocsize == NULL) {
		allocsize = &bm_mesh_allocsize_default;
	}

	CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH, CD_CALLOC, 0);

	CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
	CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
	CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
	CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
}
Exemple #6
0
static void mesh_add_faces(Mesh *mesh, int len)
{
	CustomData fdata;
	MFace *mface;
	int i, totface;

	if(len == 0)
		return;

	totface= mesh->totface + len;	/* new face count */

	/* update customdata */
	CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
	CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);

	if(!CustomData_has_layer(&fdata, CD_MFACE))
		CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);

	CustomData_free(&mesh->fdata, mesh->totface);
	mesh->fdata= fdata;
	mesh_update_customdata_pointers(mesh);

	/* set default flags */
	mface= &mesh->mface[mesh->totface];
	for(i=0; i<len; i++, mface++)
		mface->flag= ME_FACE_SEL;

	mesh->totface= totface;
}
Exemple #7
0
static void mesh_add_verts(Mesh *mesh, int len)
{
	CustomData vdata;
	MVert *mvert;
	int i, totvert;

	if(len == 0)
		return;

	totvert= mesh->totvert + len;
	CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
	CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);

	if(!CustomData_has_layer(&vdata, CD_MVERT))
		CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);

	CustomData_free(&mesh->vdata, mesh->totvert);
	mesh->vdata= vdata;
	mesh_update_customdata_pointers(mesh);

	/* scan the input list and insert the new vertices */

	mvert= &mesh->mvert[mesh->totvert];
	for(i=0; i<len; i++, mvert++)
		mvert->flag |= SELECT;

	/* set final vertex list size */
	mesh->totvert= totvert;
}
Exemple #8
0
Mesh *copy_mesh(Mesh *me)
{
	Mesh *men;
	MTFace *tface;
	int a, i;
	
	men= copy_libblock(me);
	
	men->mat= MEM_dupallocN(me->mat);
	for(a=0; a<men->totcol; a++) {
		id_us_plus((ID *)men->mat[a]);
	}
	id_us_plus((ID *)men->texcomesh);

	CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert);
	CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge);
	CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface);
	mesh_update_customdata_pointers(men);

	/* ensure indirect linked data becomes lib-extern */
	for(i=0; i<me->fdata.totlayer; i++) {
		if(me->fdata.layers[i].type == CD_MTFACE) {
			tface= (MTFace*)me->fdata.layers[i].data;

			for(a=0; a<me->totface; a++, tface++)
				if(tface->tpage)
					id_lib_extern((ID*)tface->tpage);
		}
	}
	
	men->mselect= NULL;
	men->edit_mesh= NULL;
	men->pv= NULL; /* looks like this is no-longer supported but NULL just incase */

	men->bb= MEM_dupallocN(men->bb);
	
	men->key= copy_key(me->key);
	if(men->key) men->key->from= (ID *)men;

	return men;
}
Exemple #9
0
/**
 * \brief Mesh -> BMesh
 *
 * \warning This function doesn't calculate face normals.
 */
void BM_mesh_bm_from_me(BMesh *bm, Mesh *me,
                        const bool calc_face_normal, const bool set_key, int act_key_nr)
{
	MVert *mvert;
	MEdge *medge;
	MLoop *mloop;
	MPoly *mp;
	KeyBlock *actkey, *block;
	BMVert *v, **vtable = NULL;
	BMEdge *e, **etable = NULL;
	BMFace *f;
	float (*keyco)[3] = NULL;
	int *keyi;
	int totuv, i, j;

	int cd_vert_bweight_offset;
	int cd_edge_bweight_offset;
	int cd_edge_crease_offset;

	/* free custom data */
	/* this isnt needed in most cases but do just incase */
	CustomData_free(&bm->vdata, bm->totvert);
	CustomData_free(&bm->edata, bm->totedge);
	CustomData_free(&bm->ldata, bm->totloop);
	CustomData_free(&bm->pdata, bm->totface);

	if (!me || !me->totvert) {
		if (me) { /*no verts? still copy customdata layout*/
			CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_ASSIGN, 0);

			CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
			CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
			CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
			CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
		}
		return; /* sanity check */
	}

	vtable = MEM_mallocN(sizeof(void **) * me->totvert, "mesh to bmesh vtable");

	CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);

	/* make sure uv layer names are consisten */
	totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	for (i = 0; i < totuv; i++) {
		int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
		CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
	}

	if ((act_key_nr != 0) && (me->key != NULL)) {
		actkey = BLI_findlink(&me->key->block, act_key_nr - 1);
	}
	else {
		actkey = NULL;
	}

	if (me->key) {
		CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);

		/* check if we need to generate unique ids for the shapekeys.
		 * this also exists in the file reading code, but is here for
		 * a sanity check */
		if (!me->key->uidgen) {
			fprintf(stderr,
			        "%s had to generate shape key uid's in a situation we shouldn't need to! "
			        "(bmesh internal error)\n",
			        __func__);

			me->key->uidgen = 1;
			for (block = me->key->block.first; block; block = block->next) {
				block->uid = me->key->uidgen++;
			}
		}

		if (actkey && actkey->totelem == me->totvert) {
			keyco = actkey->data;
			bm->shapenr = act_key_nr;
		}

		for (i = 0, block = me->key->block.first; block; block = block->next, i++) {
			CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
			                           CD_ASSIGN, NULL, 0, block->name);

			j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
			bm->vdata.layers[j].uid = block->uid;
		}
	}

	CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
	CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
	CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
	CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);

	BM_mesh_cd_flag_apply(bm, me->cd_flag);

	cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
	cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
	cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);

	for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
		v = vtable[i] = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD);
		BM_elem_index_set(v, i); /* set_ok */

		/* transfer flag */
		v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT);

		/* this is necessary for selection counts to work properly */
		if (mvert->flag & SELECT) {
			BM_vert_select_set(bm, v, true);
		}

		normal_short_to_float_v3(v->no, mvert->no);

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);

		if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f);

		/* set shapekey data */
		if (me->key) {
			/* set shape key original index */
			keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
			if (keyi) {
				*keyi = i;
			}

			for (block = me->key->block.first, j = 0; block; block = block->next, j++) {
				float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, j);

				if (co) {
					copy_v3_v3(co, ((float *)block->data) + 3 * i);
				}
			}
		}
	}

	bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */

	if (!me->totedge) {
		MEM_freeN(vtable);
		return;
	}

	etable = MEM_mallocN(sizeof(void **) * me->totedge, "mesh to bmesh etable");

	medge = me->medge;
	for (i = 0; i < me->totedge; i++, medge++) {
		e = etable[i] = BM_edge_create(bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD);
		BM_elem_index_set(e, i); /* set_ok */

		/* transfer flags */
		e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT);

		/* this is necessary for selection counts to work properly */
		if (medge->flag & SELECT) {
			BM_edge_select_set(bm, e, true);
		}

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);

		if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f);
		if (cd_edge_crease_offset  != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset,  (float)medge->crease  / 255.0f);

	}

	bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */

	mloop = me->mloop;
	mp = me->mpoly;
	for (i = 0; i < me->totpoly; i++, mp++) {
		BMLoop *l_iter;
		BMLoop *l_first;

		f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart,
		                              bm, vtable, etable);

		if (UNLIKELY(f == NULL)) {
			printf("%s: Warning! Bad face in mesh"
			       " \"%s\" at index %d!, skipping\n",
			       __func__, me->id.name + 2, i);
			continue;
		}

		/* don't use 'i' since we may have skipped the face */
		BM_elem_index_set(f, bm->totface - 1); /* set_ok */

		/* transfer flag */
		f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL);

		/* this is necessary for selection counts to work properly */
		if (mp->flag & ME_FACE_SEL) {
			BM_face_select_set(bm, f, true);
		}

		f->mat_nr = mp->mat_nr;
		if (i == me->act_face) bm->act_face = f;

		j = mp->loopstart;
		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
		do {
			/* Save index of correspsonding MLoop */
			CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
		} while ((l_iter = l_iter->next) != l_first);

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);

		if (calc_face_normal) {
			BM_face_normal_update(f);
		}
	}

	bm->elem_index_dirty &= ~BM_FACE; /* added in order, clear dirty flag */

	if (me->mselect && me->totselect != 0) {

		BMVert **vert_array = MEM_mallocN(sizeof(BMVert *) * bm->totvert, "VSelConv");
		BMEdge **edge_array = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, "ESelConv");
		BMFace **face_array = MEM_mallocN(sizeof(BMFace *) * bm->totface, "FSelConv");
		MSelect *msel;

#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
		{
#pragma omp section
			{ BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)vert_array, bm->totvert); }
#pragma omp section
			{ BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edge_array, bm->totedge); }
#pragma omp section
			{ BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)face_array, bm->totface); }
		}

		for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) {
			switch (msel->type) {
				case ME_VSEL:
					BM_select_history_store(bm, (BMElem *)vert_array[msel->index]);
					break;
				case ME_ESEL:
					BM_select_history_store(bm, (BMElem *)edge_array[msel->index]);
					break;
				case ME_FSEL:
					BM_select_history_store(bm, (BMElem *)face_array[msel->index]);
					break;
			}
		}

		MEM_freeN(vert_array);
		MEM_freeN(edge_array);
		MEM_freeN(face_array);
	}
	else {
		me->totselect = 0;
		if (me->mselect) {
			MEM_freeN(me->mselect);
			me->mselect = NULL;
		}
	}

	MEM_freeN(vtable);
	MEM_freeN(etable);
}
Exemple #10
0
/* Adds the geometry found in dm to bm
  */
BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
{
	
	BME_Mesh *bm;
	int allocsize[4] = {512,512,2048,512};
	MVert *mvert, *mv;
	MEdge *medge, *me;
	MFace *mface, *mf;
	int totface,totedge,totvert,i,len, numTex, numCol;
	BME_Vert *v1=NULL,*v2=NULL, **vert_array;
	BME_Edge *e=NULL;
	BME_Poly *f=NULL;
	
	EdgeHash *edge_hash = BLI_edgehash_new();

	bm = BME_make_mesh(allocsize);
	/*copy custom data layout*/
	CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);

	/*copy face corner data*/
	CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
	/*initialize memory pools*/
	CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
	CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
	CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
	CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
	/*needed later*/
	numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);

	totvert = dm->getNumVerts(dm);
	totedge = dm->getNumEdges(dm);
	totface = dm->getNumFaces(dm);
	mvert = dm->getVertArray(dm);
	medge = dm->getEdgeArray(dm);
	mface = dm->getFaceArray(dm);

	vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");

	BME_model_begin(bm);
	/*add verts*/
	for(i=0,mv = mvert; i < totvert;i++,mv++){
		v1 = BME_MV(bm,mv->co);
		vert_array[i] = v1;
		v1->flag = mv->flag;
		v1->bweight = mv->bweight/255.0f;
		CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v1->data);
	}
	/*add edges*/
	for(i=0,me = medge; i < totedge;i++,me++){
		v1 = vert_array[me->v1];
		v2 = vert_array[me->v2];
		e = BME_ME(bm, v1, v2);
		e->crease = me->crease/255.0f;
		e->bweight = me->bweight/255.0f;
		e->flag = (unsigned char)me->flag;
		BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
		CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->data);
	}
	/*add faces.*/
	for(i=0,mf = mface; i < totface;i++,mf++){
		BME_Edge *edar[4];
		if(mf->v4) len = 4;
		else len = 3;
		
		edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
		edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
		if(len == 4){
			edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
			edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
		}
		else
			edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
		
		/*find v1 and v2*/
		v1 = vert_array[mf->v1];
		v2 = vert_array[mf->v2];
		
		f = BME_MF(bm,v1,v2,edar,len);
		f->mat_nr = mf->mat_nr;
		f->flag = mf->flag;
		CustomData_to_bmesh_block(&dm->faceData,&bm->pdata,i,&f->data);
		BME_DMcorners_to_loops(bm, &dm->faceData,i,f, numCol,numTex);
	}
	
	BME_model_end(bm);
	BLI_edgehash_free(edge_hash, NULL);
	MEM_freeN(vert_array);
	return bm;
}
Exemple #11
0
/* adds the geometry in the bmesh to editMesh (does not free editMesh)
 * if td != NULL, the transdata will be mapped to the EditVert's co */
void BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td, EditMesh *em) {
	BME_Vert *v1;
	BME_Edge *e;
	BME_Poly *f;
	
	BME_TransData *vtd;

	EditVert *eve1, *eve2, *eve3, *eve4, **evlist;
	EditEdge *eed;
	EditFace *efa;

	int totvert, len, i, numTex, numCol;

	if (em == NULL) return;

	CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0);
	numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);


	/* convert to EditMesh */
	/* make editverts */
	totvert = BLI_countlist(&(bm->verts));
	evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist");
	for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) {
		v1->tflag1 = i;
		eve1 = NULL; //XXX addvertlist(v1->co,NULL);
		if (td && (vtd = BME_get_transdata(td,v1))) {
			vtd->loc = eve1->co;
		}
		eve1->keyindex = i;
		evlist[i]= eve1;
		eve1->f = (unsigned char)v1->flag;
		eve1->h = (unsigned char)v1->h;
		eve1->bweight = v1->bweight;
		CustomData_em_copy_data(&bm->vdata, &em->vdata, v1->data, &eve1->data);
	}
	
	/* make edges */
	for (e=bm->edges.first;e;e=e->next) {
		if(0) { //XXX if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
			eed= NULL; //XXX addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
			eed->crease = e->crease;
			eed->bweight = e->bweight;
			if(e->flag & ME_SEAM) eed->seam = 1;
			if(e->flag & ME_SHARP) eed->sharp = 1;
			if(e->flag & SELECT) eed->f |= SELECT;
			//XXX if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
			if(e->flag & ME_HIDE) eed->h |= 1;
			if(em->selectmode==SCE_SELECT_EDGE) { 
				; //XXX EM_select_edge(eed, eed->f & SELECT);
			}
			CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data);
		}
	}

	/* make faces */
	for (f=bm->polys.first;f;f=f->next) {
		len = BME_cycle_length(f->loopbase);
		if (len==3 || len==4) {
			eve1= evlist[f->loopbase->v->tflag1];
			eve2= evlist[f->loopbase->next->v->tflag1];
			eve3= evlist[f->loopbase->next->next->v->tflag1];
			if (len == 4) {
				eve4= evlist[f->loopbase->prev->v->tflag1];
			}
			else {
				eve4= NULL;
			}

			efa = NULL; //XXX addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
			efa->mat_nr = (unsigned char)f->mat_nr;
			efa->flag= f->flag & ~ME_HIDE;
			if(f->flag & ME_FACE_SEL) {
				efa->f |= SELECT;
			}
			if(f->flag & ME_HIDE) efa->h= 1;
			// XXX flag depricated
			// if((G.f & G_FACESELECT) && (efa->f & SELECT))
				//XXX EM_select_face(efa, 1); /* flush down */
			CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data);
			BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex);
		}
	}

	MEM_freeN(evlist);

}
Exemple #12
0
/* return 1: success */
static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
{
	EditMesh *em, *emnew;
	EditVert *eve, *v1;
	EditEdge *eed, *e1;
	EditFace *efa, *f1;
	Object *obedit;
	Mesh *me, *menew;
	Base *basenew;
	
	if(editbase==NULL) return 0;
	
	obedit= editbase->object;
	me= obedit->data;
	em= BKE_mesh_get_editmesh(me);
	if(me->key) {
		BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys");
		BKE_mesh_end_editmesh(me, em);
		return 0;
	}
	
	if(em->selected.first) 
		BLI_freelistN(&(em->selected)); /* clear the selection order */
		
	EM_selectmode_set(em);	// enforce full consistent selection flags 
	
	EM_stats_update(em);
	
	if(em->totvertsel==0) {
		BKE_mesh_end_editmesh(me, em);
		return 0;
	}
	
	/* we are going to work as follows:
	 * 1. add a linked duplicate object: this will be the new one, we remember old pointer
	 * 2. give new object empty mesh and put in editmode
	 * 3: do a split if needed on current editmesh.
	 * 4. copy over: all NOT selected verts, edges, faces
	 * 5. call load_editMesh() on the new object
	 */
	
	/* 1 */
	basenew= ED_object_add_duplicate(bmain, scene, editbase, 0);	/* 0 = fully linked */
	ED_base_object_select(basenew, BA_DESELECT);
	
	/* 2 */
	basenew->object->data= menew= add_mesh(me->id.name+2);	/* empty */
	assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
	me->id.us--;
	make_editMesh(scene, basenew->object);
	emnew= menew->edit_mesh;
	CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
	CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
	CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
	
	/* 3 */
	/* SPLIT: first make duplicate */
	adduplicateflag(em, SELECT);
	/* SPLIT: old faces have 3x flag 128 set, delete these ones */
	delfaceflag(em, 128);
	/* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */
	EM_selectmode_set(em);
	
	/* 4 */
	/* move over: everything that is selected */
	for(eve= em->verts.first; eve; eve= v1) {
		v1= eve->next;
		if(eve->f & SELECT) {
			BLI_remlink(&em->verts, eve);
			BLI_addtail(&emnew->verts, eve);
		}
	}
	
	for(eed= em->edges.first; eed; eed= e1) {
		e1= eed->next;
		if(eed->f & SELECT) {
			BLI_remlink(&em->edges, eed);
			BLI_addtail(&emnew->edges, eed);
		}
	}
	
	for(efa= em->faces.first; efa; efa= f1) {
		f1= efa->next;
		if (efa == em->act_face && (efa->f & SELECT)) {
			EM_set_actFace(em, NULL);
		}

		if(efa->f & SELECT) {
			BLI_remlink(&em->faces, efa);
			BLI_addtail(&emnew->faces, efa);
		}
	}

	/* 5 */
	load_editMesh(scene, basenew->object);
	free_editMesh(emnew);
	MEM_freeN(menew->edit_mesh);
	menew->edit_mesh= NULL;

	/* copy settings */
	menew->texflag= me->texflag;
	menew->drawflag= me->drawflag;
	menew->flag= me->flag;
	menew->editflag= me->editflag;
	menew->smoothresh= me->smoothresh;

	/* hashedges are invalid now, make new! */
	editMesh_set_hash(em);

	DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);	
	DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA);	

	BKE_mesh_end_editmesh(me, em);

	return 1;
}
Exemple #13
0
/* makes Mesh out of editmesh */
void load_editMesh(Scene *scene, Object *obedit)
{
	Mesh *me= obedit->data;
	MVert *mvert, *oldverts;
	MEdge *medge;
	MFace *mface;
	MSelect *mselect;
	EditMesh *em= me->edit_mesh;
	EditVert *eve;
	EditFace *efa, *efa_act;
	EditEdge *eed;
	EditSelection *ese;
	float *fp, *newkey, *oldkey;
	int i, a, ototvert;
	
	/* this one also tests of edges are not in faces: */
	/* eed->f2==0: not in face, f2==1: draw it */
	/* eed->f1 : flag for dynaface (cylindertest, old engine) */
	/* eve->f1 : flag for dynaface (sphere test, old engine) */
	/* eve->f2 : being used in vertexnormals */
	edge_drawflags(me, em);
	
	EM_stats_update(em);
	
	/* new Vertex block */
	if(em->totvert==0) mvert= NULL;
	else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert");

	/* new Edge block */
	if(em->totedge==0) medge= NULL;
	else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge");
	
	/* new Face block */
	if(em->totface==0) mface= NULL;
	else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face");

	/* lets save the old verts just in case we are actually working on
	 * a key ... we now do processing of the keys at the end */
	oldverts= me->mvert;
	ototvert= me->totvert;

	/* don't free this yet */
	CustomData_set_layer(&me->vdata, CD_MVERT, NULL);

	/* free custom data */
	CustomData_free(&me->vdata, me->totvert);
	CustomData_free(&me->edata, me->totedge);
	CustomData_free(&me->fdata, me->totface);

	/* add new custom data */
	me->totvert= em->totvert;
	me->totedge= em->totedge;
	me->totface= em->totface;

	CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
	CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
	CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface);

	CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
	CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
	CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
	mesh_update_customdata_pointers(me);

	/* the vertices, use ->tmp.l as counter */
	eve= em->verts.first;
	a= 0;

	while(eve) {
		VECCOPY(mvert->co, eve->co);

		/* vertex normal */
		normal_float_to_short_v3(mvert->no, eve->no);

		/* note: it used to remove me->dvert when it was not in use, cancelled
		   that... annoying when you have a fresh vgroup */
		CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a);

		eve->tmp.l = a++;  /* counter */
			
		mvert->flag= 0;
		mvert->flag |= (eve->f & SELECT);
		if (eve->h) mvert->flag |= ME_HIDE;
		
		mvert->bweight= (char)(255.0f*eve->bweight);

		eve= eve->next;
		mvert++;
	}

	/* the edges */
	a= 0;
	eed= em->edges.first;
	while(eed) {
		medge->v1= (unsigned int) eed->v1->tmp.l;
		medge->v2= (unsigned int) eed->v2->tmp.l;
		
		medge->flag= (eed->f & SELECT) | ME_EDGERENDER;
		if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
		if(eed->f2==0) medge->flag |= ME_LOOSEEDGE;
		if(eed->sharp) medge->flag |= ME_SHARP;
		if(eed->seam) medge->flag |= ME_SEAM;
		if(eed->h & EM_FGON) medge->flag |= ME_FGON;	// different defines yes
		if(eed->h & 1) medge->flag |= ME_HIDE;
		
		medge->crease= (char)(255.0f*eed->crease);
		medge->bweight= (char)(255.0f*eed->bweight);
		CustomData_from_em_block(&em->edata, &me->edata, eed->data, a);		

		eed->tmp.l = a++;
		
		medge++;
		eed= eed->next;
	}

	/* the faces */
	a = 0;
	efa= em->faces.first;
	efa_act= EM_get_actFace(em, 0);
	i = 0;
	me->act_face = -1;
	while(efa) {
		mface= &((MFace *) me->mface)[i];
		
		mface->v1= (unsigned int) efa->v1->tmp.l;
		mface->v2= (unsigned int) efa->v2->tmp.l;
		mface->v3= (unsigned int) efa->v3->tmp.l;
		if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l;

		mface->mat_nr= efa->mat_nr;
		
		mface->flag= efa->flag;
		/* bit 0 of flag is already taken for smooth... */
		
		if(efa->h) {
			mface->flag |= ME_HIDE;
			mface->flag &= ~ME_FACE_SEL;
		} else {
			if(efa->f & 1) mface->flag |= ME_FACE_SEL;
			else mface->flag &= ~ME_FACE_SEL;
		}
			
		/* watch: efa->e1->f2==0 means loose edge */ 
			
		if(efa->e1->f2==1) {
			efa->e1->f2= 2;
		}			
		if(efa->e2->f2==1) {
			efa->e2->f2= 2;
		}
		if(efa->e3->f2==1) {
			efa->e3->f2= 2;
		}
		if(efa->e4 && efa->e4->f2==1) {
			efa->e4->f2= 2;
		}

		CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i);

		/* no index '0' at location 3 or 4 */
		test_index_face(mface, &me->fdata, i, efa->v4?4:3);
		
		if (efa_act == efa)
			me->act_face = a;

		efa->tmp.l = a++;
		i++;
		efa= efa->next;
	}

	/* patch hook indices and vertex parents */
	{
		Object *ob;
		ModifierData *md;
		EditVert **vertMap = NULL;
		int j;

		for (ob=G.main->object.first; ob; ob=ob->id.next) {
			if (ob->parent==obedit && ELEM(ob->partype, PARVERT1,PARVERT3)) {
				
				/* duplicate code from below, make it function later...? */
				if (!vertMap) {
					vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
					
					for (eve=em->verts.first; eve; eve=eve->next) {
						if (eve->keyindex!=-1)
							vertMap[eve->keyindex] = eve;
					}
				}
				if(ob->par1 < ototvert) {
					eve = vertMap[ob->par1];
					if(eve) ob->par1= eve->tmp.l;
				}
				if(ob->par2 < ototvert) {
					eve = vertMap[ob->par2];
					if(eve) ob->par2= eve->tmp.l;
				}
				if(ob->par3 < ototvert) {
					eve = vertMap[ob->par3];
					if(eve) ob->par3= eve->tmp.l;
				}
				
			}
			if (ob->data==me) {
				for (md=ob->modifiers.first; md; md=md->next) {
					if (md->type==eModifierType_Hook) {
						HookModifierData *hmd = (HookModifierData*) md;

						if (!vertMap) {
							vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");

							for (eve=em->verts.first; eve; eve=eve->next) {
								if (eve->keyindex!=-1)
									vertMap[eve->keyindex] = eve;
							}
						}
						
						for (i=j=0; i<hmd->totindex; i++) {
							if(hmd->indexar[i] < ototvert) {
								eve = vertMap[hmd->indexar[i]];
								
								if (eve) {
									hmd->indexar[j++] = eve->tmp.l;
								}
							}
							else j++;
						}

						hmd->totindex = j;
					}
				}
			}
		}

		if (vertMap) MEM_freeN(vertMap);
	}

	/* are there keys? */
	if(me->key) {
		KeyBlock *currkey;
		KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1);

		float (*ofs)[3] = NULL;

		/* editing the base key should update others */
		if(me->key->type==KEY_RELATIVE && oldverts) {
			int act_is_basis = 0;
			/* find if this key is a basis for any others */
			for(currkey = me->key->block.first; currkey; currkey= currkey->next) {
				if(em->shapenr-1 == currkey->relative) {
					act_is_basis = 1;
					break;
				}
			}

			if(act_is_basis) { /* active key is a base */
				float (*fp)[3]= actkey->data;
				i=0;
				ofs= MEM_callocN(sizeof(float) * 3 * em->totvert,  "currkey->data");
				eve= em->verts.first;
				mvert = me->mvert;
				while(eve) {
					if(eve->keyindex>=0) {
						sub_v3_v3v3(ofs[i], mvert->co, fp[eve->keyindex]);
					}

					eve= eve->next;
					i++;
					mvert++;
				}
			}
		}


		/* Lets reorder the key data so that things line up roughly
		 * with the way things were before editmode */
		currkey = me->key->block.first;
		while(currkey) {
			int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative));

			fp= newkey= MEM_callocN(me->key->elemsize*em->totvert,  "currkey->data");
			oldkey = currkey->data;

			eve= em->verts.first;

			i = 0;
			mvert = me->mvert;
			while(eve) {
				if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex
					if(currkey == actkey) {
						if(actkey == me->key->refkey) {
							VECCOPY(fp, mvert->co);
						}
						else {
							VECCOPY(fp, mvert->co);
							if(oldverts) {
								VECCOPY(mvert->co, oldverts[eve->keyindex].co);
							}
						}
					}
					else {
						if(oldkey) {
							VECCOPY(fp, oldkey + 3 * eve->keyindex);
						}
					}
				}
				else {
					VECCOPY(fp, mvert->co);
				}

				/* propagate edited basis offsets to other shapes */
				if(apply_offset) {
					VECADD(fp, fp, ofs[i]);
				}

				fp+= 3;
				++i;
				++mvert;
				eve= eve->next;
			}
			currkey->totelem= em->totvert;
			if(currkey->data) MEM_freeN(currkey->data);
			currkey->data = newkey;
			
			currkey= currkey->next;
		}

		if(ofs) MEM_freeN(ofs);
	}

	if(oldverts) MEM_freeN(oldverts);
	
	i = 0;
	for(ese=em->selected.first; ese; ese=ese->next) i++;
	me->totselect = i;
	if(i==0) mselect= NULL;
	else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections");
	
	if(me->mselect) MEM_freeN(me->mselect);
	me->mselect= mselect;
	
	for(ese=em->selected.first; ese; ese=ese->next){
		mselect->type = ese->type;
		if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l;
		else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l;
		else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l;
		mselect++;
	}
	
	/* to be sure: clear ->tmp.l pointers */
	eve= em->verts.first;
	while(eve) {
		eve->tmp.l = 0;
		eve= eve->next;
	}
	
	eed= em->edges.first;
	while(eed) { 
		eed->tmp.l = 0;
		eed= eed->next;
	}
	
	efa= em->faces.first;
	while(efa) {
		efa->tmp.l = 0;
		efa= efa->next;
	}
	
	/* remake softbody of all users */
	if(me->id.us>1) {
		Base *base;
		for(base= scene->base.first; base; base= base->next)
			if(base->object->data==me)
				base->object->recalc |= OB_RECALC_DATA;
	}

	mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);

	/* topology could be changed, ensure mdisps are ok */
	multires_topology_changed(scene, obedit);
}
Exemple #14
0
static void *editMesh_to_undoMesh(void *emv)
{
	EditMesh *em= (EditMesh *)emv;
	UndoMesh *um;
	EditVert *eve;
	EditEdge *eed;
	EditFace *efa;
	EditSelection *ese;
	EditVertC *evec=NULL;
	EditEdgeC *eedc=NULL;
	EditFaceC *efac=NULL;
	EditSelectionC *esec=NULL;
	int a;

	um= MEM_callocN(sizeof(UndoMesh), "undomesh");
	
	um->selectmode = em->selectmode;
	um->shapenr = em->shapenr;
	
	for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
	for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
	for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
	for(ese=em->selected.first; ese; ese=ese->next) um->totsel++; 
	/* malloc blocks */
	
	if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
	if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
	if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
	if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");

	if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert);
	if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge);
	if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface);
	
	/* now copy vertices */
	a = 0;
	for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
		copy_v3_v3(evec->co, eve->co);
		copy_v3_v3(evec->no, eve->no);

		evec->f= eve->f;
		evec->h= eve->h;
		evec->keyindex= eve->keyindex;
		eve->tmp.l = a; /*store index*/
		evec->bweight= (short)(eve->bweight*255.0f);

		CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a);
	}
	
	/* copy edges */
	a = 0;
	for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++)  {
		eedc->v1= (int)eed->v1->tmp.l;
		eedc->v2= (int)eed->v2->tmp.l;
		eedc->f= eed->f;
		eedc->h= eed->h;
		eedc->seam= eed->seam;
		eedc->sharp= eed->sharp;
		eedc->crease= (short)(eed->crease*255.0f);
		eedc->bweight= (short)(eed->bweight*255.0f);
		eedc->fgoni= eed->fgoni;
		eed->tmp.l = a; /*store index*/
		CustomData_from_em_block(&em->edata, &um->edata, eed->data, a);
	
	}
	
	/* copy faces */
	a = 0;
	for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) {
		efac->v1= (int)efa->v1->tmp.l;
		efac->v2= (int)efa->v2->tmp.l;
		efac->v3= (int)efa->v3->tmp.l;
		if(efa->v4) efac->v4= (int)efa->v4->tmp.l;
		else efac->v4= -1;
		
		efac->mat_nr= efa->mat_nr;
		efac->flag= efa->flag;
		efac->f= efa->f;
		efac->h= efa->h;
		efac->fgonf= efa->fgonf;

		efa->tmp.l = a; /*store index*/

		CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
	}
	
	a = 0;
	for(ese=em->selected.first; ese; ese=ese->next, esec++){
		esec->type = ese->type;
		if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l; 
		else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l; 
		else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l;
	}

	return um;
}
/**
 * \brief Mesh -> BMesh
 * \param bm: The mesh to write into, while this is typically a newly created BMesh,
 * merging into existing data is supported.
 * Note the custom-data layout isn't used.
 * If more comprehensive merging is needed we should move this into a separate function
 * since this should be kept fast for edit-mode switching and storing undo steps.
 *
 * \warning This function doesn't calculate face normals.
 */
void BM_mesh_bm_from_me(
        BMesh *bm, Mesh *me,
        const struct BMeshFromMeshParams *params)
{
	const bool is_new =
	        !(bm->totvert ||
	          (bm->vdata.totlayer || bm->edata.totlayer || bm->pdata.totlayer || bm->ldata.totlayer));
	MVert *mvert;
	MEdge *medge;
	MLoop *mloop;
	MPoly *mp;
	KeyBlock *actkey, *block;
	BMVert *v, **vtable = NULL;
	BMEdge *e, **etable = NULL;
	BMFace *f, **ftable = NULL;
	float (*keyco)[3] = NULL;
	int totuv, totloops, i;

	if (!me || !me->totvert) {
		if (me && is_new) { /*no verts? still copy customdata layout*/
			CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_ASSIGN, 0);

			CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
			CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
			CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
			CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
		}
		return; /* sanity check */
	}

	if (is_new) {
		CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
		CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
		CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
		CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);

		/* make sure uv layer names are consisten */
		totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
		for (i = 0; i < totuv; i++) {
			int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
			CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
		}
	}

	/* -------------------------------------------------------------------- */
	/* Shape Key */
	int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0;
	if (is_new == false) {
		tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY));
	}
	const float (**shape_key_table)[3] = tot_shape_keys ? BLI_array_alloca(shape_key_table, tot_shape_keys) : NULL;

	if ((params->active_shapekey != 0) && (me->key != NULL)) {
		actkey = BLI_findlink(&me->key->block, params->active_shapekey - 1);
	}
	else {
		actkey = NULL;
	}

	if (is_new) {
		if (tot_shape_keys || params->add_key_index) {
			CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
		}
	}

	if (tot_shape_keys) {
		if (is_new) {
			/* check if we need to generate unique ids for the shapekeys.
			 * this also exists in the file reading code, but is here for
			 * a sanity check */
			if (!me->key->uidgen) {
				fprintf(stderr,
				        "%s had to generate shape key uid's in a situation we shouldn't need to! "
				        "(bmesh internal error)\n",
				        __func__);

				me->key->uidgen = 1;
				for (block = me->key->block.first; block; block = block->next) {
					block->uid = me->key->uidgen++;
				}
			}
		}

		if (actkey && actkey->totelem == me->totvert) {
			keyco = params->use_shapekey ? actkey->data : NULL;
			if (is_new) {
				bm->shapenr = params->active_shapekey;
			}
		}

		for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) {
			if (is_new) {
				CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
				                           CD_ASSIGN, NULL, 0, block->name);
				int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
				bm->vdata.layers[j].uid = block->uid;
			}
			shape_key_table[i] = (const float (*)[3])block->data;
		}
	}

	if (is_new) {
		CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
		CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
		CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
		CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);

		BM_mesh_cd_flag_apply(bm, me->cd_flag);
	}

	const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
	const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
	const int cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
	const int cd_shape_key_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) : -1;
	const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ?
	          CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1;

	vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__);

	for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
		v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD);
		BM_elem_index_set(v, i); /* set_ok */

		/* transfer flag */
		v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT);

		/* this is necessary for selection counts to work properly */
		if (mvert->flag & SELECT) {
			BM_vert_select_set(bm, v, true);
		}

		normal_short_to_float_v3(v->no, mvert->no);

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);

		if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f);

		/* set shape key original index */
		if (cd_shape_keyindex_offset != -1) BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i);

		/* set shapekey data */
		if (tot_shape_keys) {
			float (*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset);
			for (int j = 0; j < tot_shape_keys; j++, co_dst++) {
				copy_v3_v3(*co_dst, shape_key_table[j][i]);
			}
		}
	}
	if (is_new) {
		bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */
	}

	etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__);

	medge = me->medge;
	for (i = 0; i < me->totedge; i++, medge++) {
		e = etable[i] = BM_edge_create(bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD);
		BM_elem_index_set(e, i); /* set_ok */

		/* transfer flags */
		e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT);

		/* this is necessary for selection counts to work properly */
		if (medge->flag & SELECT) {
			BM_edge_select_set(bm, e, true);
		}

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);

		if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f);
		if (cd_edge_crease_offset  != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset,  (float)medge->crease  / 255.0f);

	}
	if (is_new) {
		bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */
	}

	/* only needed for selection. */
	if (me->mselect && me->totselect != 0) {
		ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__);
	}

	mloop = me->mloop;
	mp = me->mpoly;
	for (i = 0, totloops = 0; i < me->totpoly; i++, mp++) {
		BMLoop *l_iter;
		BMLoop *l_first;

		f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart,
		                              bm, vtable, etable);
		if (ftable != NULL) {
			ftable[i] = f;
		}

		if (UNLIKELY(f == NULL)) {
			printf("%s: Warning! Bad face in mesh"
			       " \"%s\" at index %d!, skipping\n",
			       __func__, me->id.name + 2, i);
			continue;
		}

		/* don't use 'i' since we may have skipped the face */
		BM_elem_index_set(f, bm->totface - 1); /* set_ok */

		/* transfer flag */
		f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL);

		/* this is necessary for selection counts to work properly */
		if (mp->flag & ME_FACE_SEL) {
			BM_face_select_set(bm, f, true);
		}

		f->mat_nr = mp->mat_nr;
		if (i == me->act_face) bm->act_face = f;

		int j = mp->loopstart;
		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
		do {
			/* don't use 'j' since we may have skipped some faces, hence some loops. */
			BM_elem_index_set(l_iter, totloops++); /* set_ok */

			/* Save index of correspsonding MLoop */
			CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
		} while ((l_iter = l_iter->next) != l_first);

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);

		if (params->calc_face_normal) {
			BM_face_normal_update(f);
		}
	}
	if (is_new) {
		bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */
	}

	/* -------------------------------------------------------------------- */
	/* MSelect clears the array elements (avoid adding multiple times).
	 *
	 * Take care to keep this last and not use (v/e/ftable) after this.
	 */

	if (me->mselect && me->totselect != 0) {
		MSelect *msel;
		for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) {
			BMElem **ele_p;
			switch (msel->type) {
				case ME_VSEL:
					ele_p = (BMElem **)&vtable[msel->index];
					break;
				case ME_ESEL:
					ele_p = (BMElem **)&etable[msel->index];
					break;
				case ME_FSEL:
					ele_p = (BMElem **)&ftable[msel->index];
					break;
				default:
					continue;
			}

			if (*ele_p != NULL) {
				BM_select_history_store_notest(bm, *ele_p);
				*ele_p = NULL;
			}
		}
	}
	else {
		BM_select_history_clear(bm);
	}

	MEM_freeN(vtable);
	MEM_freeN(etable);
	if (ftable) {
		MEM_freeN(ftable);
	}
}
Exemple #16
0
/*move the EditMesh conversion functions to editmesh_tools.c*/
BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
	BME_Mesh *bm;
	int allocsize[4] = {512,512,2048,512}, numTex, numCol;
	BME_Vert *v1, *v2;
	BME_Edge *e, *edar[4];
	BME_Poly *f;

	EditVert *eve;
	EditEdge *eed;
	EditFace *efa;

	int len;
	bm = BME_make_mesh(allocsize);

	/*copy custom data layout*/
	CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);

	/*copy face corner data*/
	CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
	/*initialize memory pools*/
	CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
	CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
	CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
	CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
	/*needed later*/
	numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);

	BME_model_begin(bm);
	/*add verts*/
	eve= em->verts.first;
	while(eve) {
		v1 = BME_MV(bm,eve->co);
		VECCOPY(v1->no,eve->no);
		v1->flag = eve->f;
		v1->h = eve->h;
		v1->bweight = eve->bweight;
		/*Copy Custom Data*/
		CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v1->data);
		eve->tmp.v = (EditVert*)v1;
		eve = eve->next;
	}
	
	/*add edges*/
	eed= em->edges.first;
	while(eed) {
		v1 = (BME_Vert*)eed->v1->tmp.v;
		v2 = (BME_Vert*)eed->v2->tmp.v;
		e = BME_ME(bm, v1, v2);
		e->crease = eed->crease;
		e->bweight = eed->bweight;
		e->flag = eed->f & SELECT;
		if(eed->sharp) e->flag |= ME_SHARP;
		if(eed->seam) e->flag |= ME_SEAM;
		//XXX if(eed->h & EM_FGON) e->flag |= ME_FGON;
		if(eed->h & 1) e->flag |= ME_HIDE;
		eed->tmp.e = (EditEdge*)e;
		CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data);
		eed = eed->next;
	}
	/*add faces.*/
	efa= em->faces.first;
	while(efa) {
		if(efa->v4) len = 4;
		else len = 3;
		
		edar[0] = (BME_Edge*)efa->e1->tmp.e;
		edar[1] = (BME_Edge*)efa->e2->tmp.e;
		edar[2] = (BME_Edge*)efa->e3->tmp.e;
		if(len == 4){
			edar[3] = (BME_Edge*)efa->e4->tmp.e;
		}
		
		/*find v1 and v2*/
		v1 = (BME_Vert*)efa->v1->tmp.v;
		v2 = (BME_Vert*)efa->v2->tmp.v;
		
		f = BME_MF(bm,v1,v2,edar,len);
		f->mat_nr = efa->mat_nr;
		f->flag = efa->flag;
		if(efa->h) {
			f->flag |= ME_HIDE;
			f->flag &= ~ME_FACE_SEL;
		}
		else {
			if(efa->f & 1) f->flag |= ME_FACE_SEL;
			else f->flag &= ~ME_FACE_SEL;
		}
		CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data);
		BME_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
		efa = efa->next;
	}
	BME_model_end(bm);
	return bm;
}
Exemple #17
0
/* This is a Mesh-based copy of DM_to_mesh() */
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
                             Mesh *mesh_dst,
                             Object *ob,
                             const CustomData_MeshMasks *mask,
                             bool take_ownership)
{
  /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */
  /* TODO(Sybren): the above claim came from DM_to_mesh();
   * check whether it is still true with Mesh */
  Mesh tmp = *mesh_dst;
  int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
  int did_shapekeys = 0;
  eCDAllocType alloctype = CD_DUPLICATE;

  if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) {
    bool has_any_referenced_layers = CustomData_has_referenced(&mesh_src->vdata) ||
                                     CustomData_has_referenced(&mesh_src->edata) ||
                                     CustomData_has_referenced(&mesh_src->ldata) ||
                                     CustomData_has_referenced(&mesh_src->fdata) ||
                                     CustomData_has_referenced(&mesh_src->pdata);
    if (!has_any_referenced_layers) {
      alloctype = CD_ASSIGN;
    }
  }
  CustomData_reset(&tmp.vdata);
  CustomData_reset(&tmp.edata);
  CustomData_reset(&tmp.fdata);
  CustomData_reset(&tmp.ldata);
  CustomData_reset(&tmp.pdata);

  BKE_mesh_ensure_normals(mesh_src);

  totvert = tmp.totvert = mesh_src->totvert;
  totedge = tmp.totedge = mesh_src->totedge;
  totloop = tmp.totloop = mesh_src->totloop;
  totpoly = tmp.totpoly = mesh_src->totpoly;
  tmp.totface = 0;

  CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask->vmask, alloctype, totvert);
  CustomData_copy(&mesh_src->edata, &tmp.edata, mask->emask, alloctype, totedge);
  CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask->lmask, alloctype, totloop);
  CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask->pmask, alloctype, totpoly);
  tmp.cd_flag = mesh_src->cd_flag;
  tmp.runtime.deformed_only = mesh_src->runtime.deformed_only;

  if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) {
    KeyBlock *kb;
    int uid;

    if (ob) {
      kb = BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1);
      if (kb) {
        uid = kb->uid;
      }
      else {
        CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1);

        uid = INT_MAX;
      }
    }
    else {
      /* if no object, set to INT_MAX so we don't mess up any shapekey layers */
      uid = INT_MAX;
    }

    shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid);
    did_shapekeys = 1;
  }

  /* copy texture space */
  if (ob) {
    BKE_mesh_texspace_copy_from_object(&tmp, ob);
  }

  /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
   * we set them here in case they are missing */
  /* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and
   * always directly pass mesh_src->mxxx, instead of using a ternary operator. */
  if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
    CustomData_add_layer(&tmp.vdata,
                         CD_MVERT,
                         CD_ASSIGN,
                         (alloctype == CD_ASSIGN) ? mesh_src->mvert :
                                                    MEM_dupallocN(mesh_src->mvert),
                         totvert);
  }
  if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
    CustomData_add_layer(&tmp.edata,
                         CD_MEDGE,
                         CD_ASSIGN,
                         (alloctype == CD_ASSIGN) ? mesh_src->medge :
                                                    MEM_dupallocN(mesh_src->medge),
                         totedge);
  }
  if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
    /* TODO(Sybren): assignment to tmp.mxxx is probably not necessary due to the
     * BKE_mesh_update_customdata_pointers() call below. */
    tmp.mloop = (alloctype == CD_ASSIGN) ? mesh_src->mloop : MEM_dupallocN(mesh_src->mloop);
    tmp.mpoly = (alloctype == CD_ASSIGN) ? mesh_src->mpoly : MEM_dupallocN(mesh_src->mpoly);

    CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop);
    CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly);
  }

  /* object had got displacement layer, should copy this layer to save sculpted data */
  /* NOTE: maybe some other layers should be copied? nazgul */
  if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) {
    if (totloop == mesh_dst->totloop) {
      MDisps *mdisps = CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS);
      CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
    }
  }

  /* yes, must be before _and_ after tessellate */
  BKE_mesh_update_customdata_pointers(&tmp, false);

  /* since 2.65 caller must do! */
  // BKE_mesh_tessface_calc(&tmp);

  CustomData_free(&mesh_dst->vdata, mesh_dst->totvert);
  CustomData_free(&mesh_dst->edata, mesh_dst->totedge);
  CustomData_free(&mesh_dst->fdata, mesh_dst->totface);
  CustomData_free(&mesh_dst->ldata, mesh_dst->totloop);
  CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly);

  /* ok, this should now use new CD shapekey data,
   * which should be fed through the modifier
   * stack */
  if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) {
    CLOG_ERROR(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name);
    if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) {
      id_us_min(&tmp.key->id);
    }
    tmp.key = NULL;
  }

  /* Clear selection history */
  MEM_SAFE_FREE(tmp.mselect);
  tmp.totselect = 0;
  BLI_assert(ELEM(tmp.bb, NULL, mesh_dst->bb));
  if (mesh_dst->bb) {
    MEM_freeN(mesh_dst->bb);
    tmp.bb = NULL;
  }

  /* skip the listbase */
  MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev);

  if (take_ownership) {
    if (alloctype == CD_ASSIGN) {
      CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask);
      CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask->emask);
      CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask->lmask);
      CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask->pmask);
    }
    BKE_id_free(NULL, mesh_src);
  }
}