コード例 #1
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);
}
コード例 #2
0
/* do not free mesh itself */
void free_mesh(Mesh *me)
{
	unlink_mesh(me);

	if(me->pv) {
		if(me->pv->vert_map) MEM_freeN(me->pv->vert_map);
		if(me->pv->edge_map) MEM_freeN(me->pv->edge_map);
		if(me->pv->old_faces) MEM_freeN(me->pv->old_faces);
		if(me->pv->old_edges) MEM_freeN(me->pv->old_edges);
		me->totvert= me->pv->totvert;
		me->totedge= me->pv->totedge;
		me->totface= me->pv->totface;
		MEM_freeN(me->pv);
	}

	CustomData_free(&me->vdata, me->totvert);
	CustomData_free(&me->edata, me->totedge);
	CustomData_free(&me->fdata, me->totface);
	
	if(me->adt) {
		BKE_free_animdata(&me->id);
		me->adt= NULL;
	}
	
	if(me->mat) MEM_freeN(me->mat);
	
	if(me->bb) MEM_freeN(me->bb);
	if(me->mselect) MEM_freeN(me->mselect);
	if(me->edit_mesh) MEM_freeN(me->edit_mesh);
}
コード例 #3
0
static void free_undoMesh(void *umv)
{
	UndoMesh *um= umv;
	
	if(um->verts) MEM_freeN(um->verts);
	if(um->edges) MEM_freeN(um->edges);
	if(um->faces) MEM_freeN(um->faces);
	if(um->selected) MEM_freeN(um->selected);
	CustomData_free(&um->vdata, um->totvert);
	CustomData_free(&um->edata, um->totedge);
	CustomData_free(&um->fdata, um->totface);
	MEM_freeN(um);
}
コード例 #4
0
ファイル: mesh_data.c プロジェクト: rexbron/blender-ocio
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;
}
コード例 #5
0
ファイル: mesh_data.c プロジェクト: rexbron/blender-ocio
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;
}
コード例 #6
0
// =================================================================
// 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;
}
コード例 #7
0
ファイル: mesh.c プロジェクト: ideasman42/blender-wayland
/* do not free mesh itself */
void BKE_mesh_free(Mesh *me, int unlink)
{
	if (unlink)
		BKE_mesh_unlink(me);

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

	if (me->adt) {
		BKE_free_animdata(&me->id);
		me->adt = NULL;
	}
	
	if (me->mat) MEM_freeN(me->mat);
	
	if (me->bb) MEM_freeN(me->bb);
	if (me->mselect) MEM_freeN(me->mselect);
	if (me->edit_btmesh) MEM_freeN(me->edit_btmesh);
}
コード例 #8
0
ファイル: mesh_data.c プロジェクト: jinjoh/NOOR
static void mesh_calc_edges(Mesh *mesh)
{
	CustomData edata;
	EdgeHashIterator *ehi;
	MFace *mf = mesh->mface;
	MEdge *med;
	EdgeHash *eh = BLI_edgehash_new();
	int i, *index, totedge, totface = mesh->totface;

	for (i = 0; i < totface; i++, mf++) {
		if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
			BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
		if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
			BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
		
		if (mf->v4) {
			if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
				BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
			if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
				BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
		} else {
			if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
				BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
		}
	}

	totedge = BLI_edgehash_size(eh);

	/* write new edges into a temporary CustomData */
	memset(&edata, 0, sizeof(edata));
	CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);

	ehi = BLI_edgehashIterator_new(eh);
	med = CustomData_get_layer(&edata, CD_MEDGE);
	for(i = 0; !BLI_edgehashIterator_isDone(ehi);
	    BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
		BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);

		med->flag = ME_EDGEDRAW|ME_EDGERENDER;
	}
	BLI_edgehashIterator_free(ehi);

	/* free old CustomData and assign new one */
	CustomData_free(&mesh->edata, mesh->totedge);
	mesh->edata = edata;
	mesh->totedge = totedge;

	mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);

	BLI_edgehash_free(eh, NULL);
}
コード例 #9
0
void BME_free_mesh(BME_Mesh *bm)
{
	BME_Vert *v;
	BME_Edge *e;
	BME_Loop *l;
	BME_Poly *f;

	for(v=bm->verts.first; v; v=v->next) CustomData_bmesh_free_block(&bm->vdata, &v->data);
	for(e=bm->edges.first; e; e=e->next) CustomData_bmesh_free_block(&bm->edata, &e->data);
	for(f=bm->polys.first; f; f=f->next){
		CustomData_bmesh_free_block(&bm->pdata, &f->data);
		l = f->loopbase;
		do{
			CustomData_bmesh_free_block(&bm->ldata, &l->data);
			l = l->next;
		}while(l!=f->loopbase);
	}

	/*Free custom data pools, This should probably go in CustomData_free?*/
	if(bm->vdata.totlayer) BLI_mempool_destroy(bm->vdata.pool);
	if(bm->edata.totlayer) BLI_mempool_destroy(bm->edata.pool);
	if(bm->ldata.totlayer) BLI_mempool_destroy(bm->ldata.pool);
	if(bm->pdata.totlayer) BLI_mempool_destroy(bm->pdata.pool);

	 /*free custom data*/
	CustomData_free(&bm->vdata,0);
	CustomData_free(&bm->edata,0);
	CustomData_free(&bm->ldata,0);
	CustomData_free(&bm->pdata,0);

	/*destroy element pools*/
	BLI_mempool_destroy(bm->vpool);
	BLI_mempool_destroy(bm->epool);
	BLI_mempool_destroy(bm->ppool);
	BLI_mempool_destroy(bm->lpool);
	
	MEM_freeN(bm);	
}
コード例 #10
0
ファイル: mesh.c プロジェクト: ideasman42/blender-wayland
static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
{
	if (free_customdata) {
		CustomData_free(&mesh->fdata, mesh->totface);
	}
	else {
		CustomData_reset(&mesh->fdata);
	}

	mesh->mface = NULL;
	mesh->mtface = NULL;
	mesh->mcol = NULL;
	mesh->totface = 0;
}
コード例 #11
0
ファイル: mesh_validate.c プロジェクト: 244xiao/blender
/**
 * Calculate edges from polygons
 *
 * \param mesh  The mesh to add edges into
 * \param update  When true create new edges co-exist
 */
void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
{
	CustomData edata;
	EdgeHashIterator *ehi;
	MPoly *mp;
	MEdge *med, *med_orig;
	EdgeHash *eh = BLI_edgehash_new();
	int i, totedge, totpoly = mesh->totpoly;
	int med_index;
	/* select for newly created meshes which are selected [#25595] */
	const short ed_flag = (ME_EDGEDRAW | ME_EDGERENDER) | (select ? SELECT : 0);

	if (mesh->totedge == 0)
		update = false;

	if (update) {
		/* assume existing edges are valid
		 * useful when adding more faces and generating edges from them */
		med = mesh->medge;
		for (i = 0; i < mesh->totedge; i++, med++)
			BLI_edgehash_insert(eh, med->v1, med->v2, med);
	}

	/* mesh loops (bmesh only) */
	for (mp = mesh->mpoly, i = 0; i < totpoly; mp++, i++) {
		MLoop *l = &mesh->mloop[mp->loopstart];
		int j, l_prev = (l + (mp->totloop - 1))->v;
		for (j = 0; j < mp->totloop; j++, l++) {
			if (!BLI_edgehash_haskey(eh, l_prev, l->v)) {
				BLI_edgehash_insert(eh, l_prev, l->v, NULL);
			}
			l_prev = l->v;
		}
	}

	totedge = BLI_edgehash_size(eh);

	/* write new edges into a temporary CustomData */
	CustomData_reset(&edata);
	CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);

	med = CustomData_get_layer(&edata, CD_MEDGE);
	for (ehi = BLI_edgehashIterator_new(eh), i = 0;
	     BLI_edgehashIterator_isDone(ehi) == FALSE;
	     BLI_edgehashIterator_step(ehi), ++i, ++med)
	{
		if (update && (med_orig = BLI_edgehashIterator_getValue(ehi))) {
			*med = *med_orig; /* copy from the original */
		}
		else {
			BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
			med->flag = ed_flag;
		}

		/* store the new edge index in the hash value */
		BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
	}
	BLI_edgehashIterator_free(ehi);

	if (mesh->totpoly) {
		/* second pass, iterate through all loops again and assign
		 * the newly created edges to them. */
		for (mp = mesh->mpoly, i = 0; i < mesh->totpoly; mp++, i++) {
			MLoop *l = &mesh->mloop[mp->loopstart];
			MLoop *l_prev = (l + (mp->totloop - 1));
			int j;
			for (j = 0; j < mp->totloop; j++, l++) {
				/* lookup hashed edge index */
				med_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, l_prev->v, l->v));
				l_prev->e = med_index;
				l_prev = l;
			}
		}
	}

	/* free old CustomData and assign new one */
	CustomData_free(&mesh->edata, mesh->totedge);
	mesh->edata = edata;
	mesh->totedge = totedge;

	mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);

	BLI_edgehash_free(eh, NULL);
}
コード例 #12
0
ファイル: bmesh_mesh_conv.c プロジェクト: doug65536/blender
/**
 * \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);
}
コード例 #13
0
ファイル: meshtools.c プロジェクト: BHCLL/blendocv
int join_mesh_exec(bContext *C, wmOperator *op)
{
	Main *bmain= CTX_data_main(C);
	Scene *scene= CTX_data_scene(C);
	Object *ob= CTX_data_active_object(C);
	Material **matar, *ma;
	Mesh *me;
	MVert *mvert, *mv;
	MEdge *medge = NULL;
	MFace *mface = NULL;
	Key *key, *nkey=NULL;
	KeyBlock *kb, *okb, *kbn;
	float imat[4][4], cmat[4][4], *fp1, *fp2, curpos;
	int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0;
	int vertofs, *matmap=NULL;
	int	i, j, index, haskey=0, edgeofs, faceofs;
	bDeformGroup *dg, *odg;
	MDeformVert *dvert;
	CustomData vdata, edata, fdata;

	if(scene->obedit) {
		BKE_report(op->reports, RPT_WARNING, "Cant join while in editmode");
		return OPERATOR_CANCELLED;
	}
	
	/* ob is the object we are adding geometry to */
	if(!ob || ob->type!=OB_MESH) {
		BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh");
		return OPERATOR_CANCELLED;
	}
	
	/* count & check */
	CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
		if(base->object->type==OB_MESH) {
			me= base->object->data;
			
			totvert+= me->totvert;
			totedge+= me->totedge;
			totface+= me->totface;
			totmat+= base->object->totcol;
			
			if(base->object == ob)
				ok= 1;
			
			/* check for shapekeys */
			if(me->key)
				haskey++;
		}
	}
	CTX_DATA_END;
	
	/* that way the active object is always selected */ 
	if(ok==0) {
		BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh");
		return OPERATOR_CANCELLED;
	}
	
	/* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */
	me= (Mesh *)ob->data;
	key= me->key;

	if(totvert==0 || totvert==me->totvert) {
		BKE_report(op->reports, RPT_WARNING, "No mesh data to join");
		return OPERATOR_CANCELLED;
	}
	
	if(totvert > MESH_MAX_VERTS) {
		BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is " STRINGIFY(MESH_MAX_VERTS), totvert);
		return OPERATOR_CANCELLED;		
	}

	/* new material indices and material array */
	matar= MEM_callocN(sizeof(void*)*totmat, "join_mesh matar");
	if (totmat) matmap= MEM_callocN(sizeof(int)*totmat, "join_mesh matmap");
	totcol= ob->totcol;
	
	/* obact materials in new main array, is nicer start! */
	for(a=0; a<ob->totcol; a++) {
		matar[a]= give_current_material(ob, a+1);
		id_us_plus((ID *)matar[a]);
		/* increase id->us : will be lowered later */
	}
	
	/* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
	 * 	with arrays that are large enough to hold shapekey data for all meshes
	 * -	if destination mesh didn't have shapekeys, but we encountered some in the meshes we're 
	 *	joining, set up a new keyblock and assign to the mesh
	 */
	if(key) {
		/* make a duplicate copy that will only be used here... (must remember to free it!) */
		nkey= copy_key(key);
		
		/* for all keys in old block, clear data-arrays */
		for(kb= key->block.first; kb; kb= kb->next) {
			if(kb->data) MEM_freeN(kb->data);
			kb->data= MEM_callocN(sizeof(float)*3*totvert, "join_shapekey");
			kb->totelem= totvert;
			kb->weights= NULL;
		}
	}
	else if(haskey) {
		/* add a new key-block and add to the mesh */
		key= me->key= add_key((ID *)me);
		key->type = KEY_RELATIVE;
	}
	
	/* first pass over objects - copying materials and vertexgroups across */
	CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
		/* only act if a mesh, and not the one we're joining to */
		if((ob!=base->object) && (base->object->type==OB_MESH)) {
			me= base->object->data;
			
			/* Join this object's vertex groups to the base one's */
			for(dg=base->object->defbase.first; dg; dg=dg->next) {
				/* See if this group exists in the object (if it doesn't, add it to the end) */
				if(!defgroup_find_name(ob, dg->name)) {
					odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup");
					memcpy(odg, dg, sizeof(bDeformGroup));
					BLI_addtail(&ob->defbase, odg);
				}
			}
			if(ob->defbase.first && ob->actdef==0)
				ob->actdef=1;
			
			
			if(me->totvert) {
				/* Add this object's materials to the base one's if they don't exist already (but only if limits not exceeded yet) */
				if(totcol < MAXMAT) {
					for(a=1; a<=base->object->totcol; a++) {
						ma= give_current_material(base->object, a);

						for(b=0; b<totcol; b++) {
							if(ma == matar[b]) break;
						}
						if(b==totcol) {
							matar[b]= ma;
							if(ma) {
								id_us_plus(&ma->id);
							}
							totcol++;
						}
						if(totcol >= MAXMAT)
							break;
					}
				}
				
				/* if this mesh has shapekeys, check if destination mesh already has matching entries too */
				if(me->key && key) {
					for(kb= me->key->block.first; kb; kb= kb->next) {
						/* if key doesn't exist in destination mesh, add it */
						if(key_get_named_keyblock(key, kb->name) == NULL) {
							/* copy this existing one over to the new shapekey block */
							kbn= MEM_dupallocN(kb);
							kbn->prev= kbn->next= NULL;
							
							/* adjust adrcode and other settings to fit (allocate a new data-array) */
							kbn->data= MEM_callocN(sizeof(float)*3*totvert, "joined_shapekey");
							kbn->totelem= totvert;
							kbn->weights= NULL;
							
							okb= key->block.last;
							curpos= (okb) ? okb->pos : -0.1f;
							if(key->type == KEY_RELATIVE)
								kbn->pos= curpos + 0.1f;
							else
								kbn->pos= curpos;
							
							BLI_addtail(&key->block, kbn);
							kbn->adrcode= key->totkey;
							key->totkey++;
							if(key->totkey==1) key->refkey= kbn;
							
							// XXX 2.5 Animato
#if 0
							/* also, copy corresponding ipo-curve to ipo-block if applicable */
							if(me->key->ipo && key->ipo) {
								// FIXME... this is a luxury item!
								puts("FIXME: ignoring IPO's when joining shapekeys on Meshes for now...");
							}
#endif
						}
					}
				}
			}
		}
	}
	CTX_DATA_END;
	
	/* setup new data for destination mesh */
	memset(&vdata, 0, sizeof(vdata));
	memset(&edata, 0, sizeof(edata));
	memset(&fdata, 0, sizeof(fdata));
	
	mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
	medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
	mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);

	vertofs= 0;
	edgeofs= 0;
	faceofs= 0;
	
	/* inverse transform for all selected meshes in this object */
	invert_m4_m4(imat, ob->obmat);
	
	CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
		/* only join if this is a mesh */
		if(base->object->type==OB_MESH) {
			me= base->object->data;
			
			if(me->totvert) {
				/* standard data */
				CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
				CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert);
				
				/* vertex groups */
				dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT);
				
				/* NB: vertex groups here are new version */
				if(dvert) {
					for(i=0; i<me->totvert; i++) {
						for(j=0; j<dvert[i].totweight; j++) {
							/*	Find the old vertex group */
							odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr);
							if(odg) {
								/*	Search for a match in the new object, and set new index */
								for(dg=ob->defbase.first, index=0; dg; dg=dg->next, index++) {
									if(!strcmp(dg->name, odg->name)) {
										dvert[i].dw[j].def_nr = index;
										break;
									}
								}
							}
						}
					}
				}
				
				/* if this is the object we're merging into, no need to do anything */
				if(base->object != ob) {
					/* watch this: switch matmul order really goes wrong */
					mul_m4_m4m4(cmat, base->object->obmat, imat);
					
					/* transform vertex coordinates into new space */
					for(a=0, mv=mvert; a < me->totvert; a++, mv++) {
						mul_m4_v3(cmat, mv->co);
					}
					
					/* for each shapekey in destination mesh:
					 *	- if there's a matching one, copy it across (will need to transform vertices into new space...)
					 *	- otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
					 */
					if(key) {
						/* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
						for(kb= key->block.first; kb; kb= kb->next) {
							/* get pointer to where to write data for this mesh in shapekey's data array */
							fp1= ((float *)kb->data) + (vertofs*3);	
							
							/* check if this mesh has such a shapekey */
							okb= key_get_named_keyblock(me->key, kb->name);
							if(okb) {
								/* copy this mesh's shapekey to the destination shapekey (need to transform first) */
								fp2= ((float *)(okb->data));
								for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) {
									VECCOPY(fp1, fp2);
									mul_m4_v3(cmat, fp1);
								}
							}
							else {
								/* copy this mesh's vertex coordinates to the destination shapekey */
								mv= mvert;
								for(a=0; a < me->totvert; a++, fp1+=3, mv++) {
									VECCOPY(fp1, mv->co);
								}
							}
						}
					}
				}
				else {
					/* for each shapekey in destination mesh:
					 *	- if it was an 'original', copy the appropriate data from nkey
					 *	- otherwise, copy across plain coordinates (no need to transform coordinates)
					 */
					if(key) {
						for(kb= key->block.first; kb; kb= kb->next) {
							/* get pointer to where to write data for this mesh in shapekey's data array */
							fp1= ((float *)kb->data) + (vertofs*3);	
							
							/* check if this was one of the original shapekeys */
							okb= key_get_named_keyblock(nkey, kb->name);
							if(okb) {
								/* copy this mesh's shapekey to the destination shapekey */
								fp2= ((float *)(okb->data));
								for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) {
									VECCOPY(fp1, fp2);
								}
							}
							else {
								/* copy base-coordinates to the destination shapekey */
								mv= mvert;
								for(a=0; a < me->totvert; a++, fp1+=3, mv++) {
									VECCOPY(fp1, mv->co);
								}
							}
						}
					}
				}
				
				/* advance mvert pointer to end of base mesh's data */
				mvert+= me->totvert;
			}
			
			if(me->totface) {
				/* make mapping for materials */
				for(a=1; a<=base->object->totcol; a++) {
					ma= give_current_material(base->object, a);

					for(b=0; b<totcol; b++) {
						if(ma == matar[b]) {
							matmap[a-1]= b;
							break;
						}
					}
				}
				
				if(base->object!=ob)
					multiresModifier_prepare_join(scene, base->object, ob);

				CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
				CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface);
				
				for(a=0; a<me->totface; a++, mface++) {
					mface->v1+= vertofs;
					mface->v2+= vertofs;
					mface->v3+= vertofs;
					if(mface->v4) mface->v4+= vertofs;
					
					if (matmap)
						mface->mat_nr= matmap[(int)mface->mat_nr];
					else 
						mface->mat_nr= 0;
				}
				
				faceofs += me->totface;
			}
			
			if(me->totedge) {
				CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
				CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge);
				
				for(a=0; a<me->totedge; a++, medge++) {
					medge->v1+= vertofs;
					medge->v2+= vertofs;
				}
				
				edgeofs += me->totedge;
			}
			
			/* vertofs is used to help newly added verts be reattached to their edge/face 
			 * (cannot be set earlier, or else reattaching goes wrong)
			 */
			vertofs += me->totvert;
			
			/* free base, now that data is merged */
			if(base->object != ob)
				ED_base_object_free_and_unlink(bmain, scene, base);
		}
	}
	CTX_DATA_END;
	
	/* return to mesh we're merging to */
	me= ob->data;
	
	CustomData_free(&me->vdata, me->totvert);
	CustomData_free(&me->edata, me->totedge);
	CustomData_free(&me->fdata, me->totface);

	me->totvert= totvert;
	me->totedge= totedge;
	me->totface= totface;
	
	me->vdata= vdata;
	me->edata= edata;
	me->fdata= fdata;

	mesh_update_customdata_pointers(me);
	
	/* old material array */
	for(a=1; a<=ob->totcol; a++) {
		ma= ob->mat[a-1];
		if(ma) ma->id.us--;
	}
	for(a=1; a<=me->totcol; a++) {
		ma= me->mat[a-1];
		if(ma) ma->id.us--;
	}
	if(ob->mat) MEM_freeN(ob->mat);
	if(ob->matbits) MEM_freeN(ob->matbits);
	if(me->mat) MEM_freeN(me->mat);
	ob->mat= me->mat= NULL;
	ob->matbits= NULL;
	
	if(totcol) {
		me->mat= matar;
		ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar");
		ob->matbits= MEM_callocN(sizeof(char)*totcol, "join obmatbits");
	}
	else
		MEM_freeN(matar);
	
	ob->totcol= me->totcol= totcol;
	ob->colbits= 0;

	if (matmap) MEM_freeN(matmap);
	
	/* other mesh users */
	test_object_materials((ID *)me);
	
	/* free temp copy of destination shapekeys (if applicable) */
	if(nkey) {
		// XXX 2.5 Animato
#if 0
		/* free it's ipo too - both are not actually freed from memory yet as ID-blocks */
		if(nkey->ipo) {
			free_ipo(nkey->ipo);
			BLI_remlink(&bmain->ipo, nkey->ipo);
			MEM_freeN(nkey->ipo);
		}
#endif
		
		free_key(nkey);
		BLI_remlink(&bmain->key, nkey);
		MEM_freeN(nkey);
	}
	
	DAG_scene_sort(bmain, scene);	// removed objects, need to rebuild dag before editmode call

#if 0
	ED_object_enter_editmode(C, EM_WAITCURSOR);
	ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR|EM_DO_UNDO);
#else
	/* toggle editmode using lower level functions so this can be called from python */
	make_editMesh(scene, ob);
	load_editMesh(scene, ob);
	free_editMesh(me->edit_mesh);
	MEM_freeN(me->edit_mesh);
	me->edit_mesh= NULL;
	DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA);
#endif
	WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);

	return OPERATOR_FINISHED;
}
コード例 #14
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);
}
コード例 #15
0
/* do not free editmesh itself here */
void free_editMesh(EditMesh *em)
{
	if(em==NULL) return;

	if(em->verts.first) free_vertlist(em, &em->verts);
	if(em->edges.first) free_edgelist(em, &em->edges);
	if(em->faces.first) free_facelist(em, &em->faces);
	if(em->selected.first) BLI_freelistN(&(em->selected));

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

	if(em->derivedFinal) {
		if (em->derivedFinal!=em->derivedCage) {
			em->derivedFinal->needsFree= 1;
			em->derivedFinal->release(em->derivedFinal);
		}
		em->derivedFinal= NULL;
	}
	if(em->derivedCage) {
		em->derivedCage->needsFree= 1;
		em->derivedCage->release(em->derivedCage);
		em->derivedCage= NULL;
	}

	/* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */
#if 0
	if(em->hashedgetab) {
		HashEdge *he, *hen;
		int a, used=0, max=0, nr;
		he= em->hashedgetab;
		for(a=0; a<EDHASHSIZE; a++, he++) {
			if(he->eed) used++;
			hen= he->next;
			nr= 0;
			while(hen) {
				nr++;
				hen= hen->next;
			}
			if(max<nr) max= nr;
		}
		printf("hastab used %d max %d\n", used, max);
	}
#endif
	if(em->hashedgetab) MEM_freeN(em->hashedgetab);
	em->hashedgetab= NULL;
	
	if(em->allverts) MEM_freeN(em->allverts);
	if(em->alledges) MEM_freeN(em->alledges);
	if(em->allfaces) MEM_freeN(em->allfaces);
	
	em->allverts= em->curvert= NULL;
	em->alledges= em->curedge= NULL;
	em->allfaces= em->curface= NULL;
	
	mesh_octree_table(NULL, NULL, NULL, 'e');
	mesh_mirrtopo_table(NULL, 'e');

	em->totvert= em->totedge= em->totface= 0;

	em->act_face = NULL;
}
コード例 #16
0
void BKE_mesh_calc_edges(Mesh *mesh, int update)
{
	CustomData edata;
	EdgeHashIterator *ehi;
	MFace *mf = mesh->mface;
	MEdge *med, *med_orig;
	EdgeHash *eh = BLI_edgehash_new();
	int i, totedge, totface = mesh->totface;

	if(mesh->totedge==0)
		update= 0;

	if(update) {
		/* assume existing edges are valid
		 * useful when adding more faces and generating edges from them */
		med= mesh->medge;
		for(i= 0; i<mesh->totedge; i++, med++)
			BLI_edgehash_insert(eh, med->v1, med->v2, med);
	}

	for (i = 0; i < totface; i++, mf++) {
		if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
			BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
		if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
			BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);

		if (mf->v4) {
			if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
				BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
			if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
				BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
		} else {
			if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
				BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
		}
	}

	totedge = BLI_edgehash_size(eh);

	/* write new edges into a temporary CustomData */
	memset(&edata, 0, sizeof(edata));
	CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);

	ehi = BLI_edgehashIterator_new(eh);
	med = CustomData_get_layer(&edata, CD_MEDGE);
	for(i = 0; !BLI_edgehashIterator_isDone(ehi);
		BLI_edgehashIterator_step(ehi), ++i, ++med) {

		if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) {
			*med= *med_orig; /* copy from the original */
		} else {
			BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
			med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */
		}
	}
	BLI_edgehashIterator_free(ehi);

	/* free old CustomData and assign new one */
	CustomData_free(&mesh->edata, mesh->totedge);
	mesh->edata = edata;
	mesh->totedge = totedge;

	mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);

	BLI_edgehash_free(eh, NULL);
}
コード例 #17
0
ファイル: mesh_convert.c プロジェクト: wangyxuan/blender
/* 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);
  }
}