[Bf-committers] UnlimitedClay in 3,2,1

raulf at info.upr.edu.cu raulf at info.upr.edu.cu
Wed Apr 27 19:50:50 CEST 2011


Hi all :)

As promised yesterday here is the UnlimitedClay patch against an old
revision (32564), is a heavy patch where I move data a lot among files,
basically due to the need to expose editmesh functionality to the sculpt
module and viceversa, remember that UnlimietdClay is more like a hybrid of
both modes , also there are some incomplete features or temporal solutions
there (like drawing functions).

There are several smoothing algorithm that I have earlier release as a
cleaner patch,  and rewritten to to avoid introducing new terms , so they
can be used here just for testing purposes, I don't recomend to integrate
them as they are in this patch, if any dev is interesting in them please
search the Blender patch tracker where the correct patch is floating.

A new rewrite must be done for the new BMesh and also to implement better
PBVH support, I'm preparing a PDF where I explains the basic for dynamic
subdivision sculpting that will ease the task :)

I'm sure all the issues will be overcome soon. Enough of talk ;)

PS: Forgive me for pasting the patch here but PasteAll.org takes ages to
load for me O.o!

//------ UnlimitedClay alpha 2 patch -------------------------------------

Index: release/scripts/ui/properties_data_modifier.py
===================================================================
--- release/scripts/ui/properties_data_modifier.py	(revision 32564)
+++ release/scripts/ui/properties_data_modifier.py	(working copy)
@@ -568,6 +568,13 @@
     def SOFT_BODY(self, layout, ob, md):
         layout.label(text="See Soft Body panel.")

+    def UCLAY(self, layout, ob, md):
+          split = layout.split()
+          col = split.column()
+          col.prop(md, "detail")
+          col.prop(md, "smoothness")
+          col.prop(md, "relax")
+
     def SOLIDIFY(self, layout, ob, md):

         split = layout.split()
Index: source/blender/blenkernel/BKE_cdderivedmesh.h
===================================================================
--- source/blender/blenkernel/BKE_cdderivedmesh.h	(revision 32564)
+++ source/blender/blenkernel/BKE_cdderivedmesh.h	(working copy)
@@ -50,7 +50,7 @@
    calculate normals as those functions will automtically create new
    data to not overwrite the original */
 struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh, struct Object *ob);
-
+struct DerivedMesh *CDDM_from_editmesh_select(struct EditMesh *em, struct
Mesh *me);
 /* creates a CDDerivedMesh from the given EditMesh */
 struct DerivedMesh *CDDM_from_editmesh(struct EditMesh *em, struct Mesh
*me);

@@ -114,3 +114,4 @@
 struct MFace *CDDM_get_faces(struct DerivedMesh *dm);
 #endif

+
Index: source/blender/blenkernel/BKE_DerivedMesh.h
===================================================================
--- source/blender/blenkernel/BKE_DerivedMesh.h	(revision 32564)
+++ source/blender/blenkernel/BKE_DerivedMesh.h	(working copy)
@@ -62,6 +62,7 @@
 struct GPUDrawObject;
 struct ListBase;
 struct PBVH;
+struct UClayModifierData;

 /* number of sub-elements each mesh element has (for interpolation) */
 #define SUB_ELEMS_VERT 0
@@ -122,6 +123,14 @@
 	struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
 	struct MFace *(*getFaceArray)(DerivedMesh *dm);

+	/* return a pointer to the entire list of editverts/editedges/editface
from the
+	 * derived mesh.
+	 */
+	struct EditVert *(*getEditVerts)(DerivedMesh *dm);
+	struct EditEdge *(*getEditEdges)(DerivedMesh *dm);
+	struct EditFace *(*getEditFaces)(DerivedMesh *dm);
+
+
 	/* copy all verts/edges/faces from the derived mesh into
 	 * *{vert/edge/face}_r (must point to a buffer large enough)
 	 */
@@ -542,5 +551,24 @@
 /* Set object's bounding box based on DerivedMesh min/max data */
 void DM_set_object_boundbox(struct Object *ob, DerivedMesh *dm);

+typedef struct EditMeshDerivedMesh{
+	struct DerivedMesh dm;
+
+	struct EditMesh *em;
+	float (*vertexCos)[3];
+	float (*vertexNos)[3];
+	float (*faceNos)[3];
+
+	struct PBVH *pbvh;
+	unsigned int pbvh_draw, modified;
+
+	//struct UClayModifierData *ucmd;
+	struct Scene *scene;
+	struct Object *ob;
+	int numverts, numedges, numfaces;
+} EditMeshDerivedMesh;
+
+DerivedMesh *uclay_dm_create_from_derived(struct UClayModifierData *ucmd,
int local_ucmd, DerivedMesh *dm,struct Object *ob,struct Scene
*scene,float radius, int useRenderParams,int isFinalCalc);
 #endif

+
Index: source/blender/blenkernel/BKE_modifier.h
===================================================================
--- source/blender/blenkernel/BKE_modifier.h	(revision 32564)
+++ source/blender/blenkernel/BKE_modifier.h	(working copy)
@@ -311,6 +311,7 @@
 int           modifiers_isSoftbodyEnabled(struct Object *ob);
 int           modifiers_isClothEnabled(struct Object *ob);
 int           modifiers_isParticleEnabled(struct Object *ob);
+int 	      modifiers_isUClayEnabled(struct Object *ob);

 struct Object *modifiers_isDeformedByArmature(struct Object *ob);
 struct Object *modifiers_isDeformedByLattice(struct Object *ob);
@@ -340,3 +341,4 @@

 #endif

+
Index: source/blender/blenkernel/BKE_multires.h
===================================================================
--- source/blender/blenkernel/BKE_multires.h	(revision 32564)
+++ source/blender/blenkernel/BKE_multires.h	(working copy)
@@ -39,8 +39,10 @@
 struct Object;

 void multires_mark_as_modified(struct Object *ob);
+void uclay_mark_as_modified(struct Object *ob); //Mio Eventually moved

 void multires_force_update(struct Object *ob);
+void uclay_force_update(struct Object *ob);
 void multires_force_render_update(struct Object *ob);
 void multires_force_external_reload(struct Object *ob);

@@ -73,3 +75,4 @@

 #endif

+
Index: source/blender/blenkernel/BKE_paint.h
===================================================================
--- source/blender/blenkernel/BKE_paint.h	(revision 32564)
+++ source/blender/blenkernel/BKE_paint.h	(working copy)
@@ -38,8 +38,66 @@
 struct Paint;
 struct PBVH;
 struct Scene;
-struct StrokeCache;

+typedef struct StrokeCache {
+	/* Invariants */
+	float initial_radius;
+	float scale[3];
+	int flag;
+	float clip_tolerance[3];
+	float initial_mouse[2];
+
+	/* Variants */
+	float radius;
+	float radius_squared;
+	//float traced_location[3];
+	float true_location[3];
+	float location[3];
+
+	float pen_flip;
+	float invert;
+	float pressure;
+	float mouse[2];
+	float bstrength;
+	float tex_mouse[2];
+
+	/* The rest is temporary storage that isn't saved as a property */
+
+	int first_time; /* Beginning of stroke may do some things special */
+
+	struct bglMats *mats;
+
+	/* Clean this up! */
+	struct ViewContext *vc;
+	struct Brush *brush;
+
+	float (*face_norms)[3]; /* Copy of the mesh faces' normals */
+	float special_rotation; /* Texture rotation (radians) for anchored and
rake modes */
+	int pixel_radius, previous_pixel_radius;
+	float grab_delta[3], grab_delta_symmetry[3];
+	float old_grab_location[3], orig_grab_location[3];
+
+	int symmetry; /* Symmetry index between 0 and 7 bit combo 0 is Brush only;
+		1 is X mirror; 2 is Y mirror; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is
XYZ */
+	int mirror_symmetry_pass; /* the symmetry pass we are currently on
between 0 and 7*/
+	float true_view_normal[3];
+	float view_normal[3];
+	float last_area_normal[3];
+	float last_center[3];
+	int radial_symmetry_pass;
+	float symm_rot_mat[4][4];
+	float symm_rot_mat_inv[4][4];
+	float last_rake[2]; /* Last location of updating rake rotation */
+	int original;
+
+	float vertex_rotation;
+
+	char saved_active_brush_name[24];
+	int alt_smooth;
+
+	float plane_trim_squared;
+} StrokeCache;
+
 extern const char PAINT_CURSOR_SCULPT[3];
 extern const char PAINT_CURSOR_VERTEX_PAINT[3];
 extern const char PAINT_CURSOR_WEIGHT_PAINT[3];
@@ -63,8 +121,9 @@
 typedef struct SculptSession {
 	struct ProjVert *projverts;

-	/* Mesh data (not copied) can come either directly from a Mesh, or from
a MultiresDM */
+	/* Mesh data (not copied) can come either directly from a Mesh, from a
MultiresDM or EditMeshDM */
 	struct MultiresModifierData *multires; /* Special handling for multires
meshes */
+	struct UClayModifierData *uclay; /* Special handling for uclay meshes */
 	struct MVert *mvert;
 	struct MFace *mface;
 	int totvert, totface;
Index: source/blender/blenkernel/intern/cdderivedmesh.c
===================================================================
--- source/blender/blenkernel/intern/cdderivedmesh.c	(revision 32564)
+++ source/blender/blenkernel/intern/cdderivedmesh.c	(working copy)
@@ -222,7 +222,7 @@
 		BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
 				   me->totface, me->totvert);
 	}
-
+
 	return cddm->pbvh;
 }

@@ -1617,6 +1617,106 @@
 	return dm;
 }

+DerivedMesh *CDDM_from_editmesh_select(EditMesh *em, Mesh *me)
+{
+	DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
+							   BLI_countlist(&em->edges),
+							   BLI_countlist(&em->faces));
+	CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+	EditVert *eve;
+	EditEdge *eed;
+	EditFace *efa;
+	MVert *mvert = cddm->mvert;
+	MEdge *medge = cddm->medge;
+	MFace *mface = cddm->mface;
+	int i, *index;
+
+	dm->deformedOnly = 1;
+
+	CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
+					 CD_CALLOC, dm->numVertData);
+	/* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
+					 CD_CALLOC, dm->numEdgeData); */
+	CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
+					 CD_CALLOC, dm->numFaceData);
+
+	/* set eve->hash to vert index */
+	for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
+		eve->tmp.l = i;
+
+	/* Need to be able to mark loose edges */
+	for(eed = em->edges.first; eed; eed = eed->next) {
+		eed->f2 = 0;
+	}
+	for(efa = em->faces.first; efa; efa = efa->next) {
+		efa->e1->f2 = 1;
+		efa->e2->f2 = 1;
+		efa->e3->f2 = 1;
+		if(efa->e4) efa->e4->f2 = 1;
+	}
+
+	index = dm->getVertDataArray(dm, CD_ORIGINDEX);
+	for(i = 0, eve = em->verts.first; i < dm->numVertData;
+		i++, eve = eve->next, index++) {
+		MVert *mv = &mvert[i];
+
+		VECCOPY(mv->co, eve->co);
+
+		mv->no[0] = eve->no[0] * 32767.0;
+		mv->no[1] = eve->no[1] * 32767.0;
+		mv->no[2] = eve->no[2] * 32767.0;
+		mv->bweight = (unsigned char) (eve->bweight * 255.0f);
+
+		mv->mat_nr = 0;
+		if (eve->f & SELECT) mv->flag |= SELECT;
+			else mv->flag = 0;//Mio
+
+		*index = i;
+
+		CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
+	}
+
+	index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
+	for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
+		i++, eed = eed->next, index++) {
+		MEdge *med = &medge[i];
+
+		med->v1 = eed->v1->tmp.l;
+		med->v2 = eed->v2->tmp.l;
+		med->crease = (unsigned char) (eed->crease * 255.0f);
+		med->bweight = (unsigned char) (eed->bweight * 255.0f);
+		med->flag = ME_EDGEDRAW|ME_EDGERENDER;
+
+		if(eed->seam) med->flag |= ME_SEAM;
+		if(eed->sharp) med->flag |= ME_SHARP;
+		if(!eed->f2) med->flag |= ME_LOOSEEDGE;
+
+		*index = i;
+
+		/* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
+	}
+
+	index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+	for(i = 0, efa = em->faces.first; i < dm->numFaceData;
+		i++, efa = efa->next, index++) {
+		MFace *mf = &mface[i];
+
+		mf->v1 = efa->v1->tmp.l;
+		mf->v2 = efa->v2->tmp.l;
+		mf->v3 = efa->v3->tmp.l;
+		mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
+		mf->mat_nr = efa->mat_nr;
+		mf->flag = efa->flag;
+
+		*index = i;
+
+		CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
+		test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
+	}
+
+	return dm;
+}
+
 DerivedMesh *CDDM_from_curve(Object *ob)
 {
 	return CDDM_from_curve_customDB(ob, &((Curve *)ob->data)->disp);
@@ -1914,3 +2014,4 @@
 	return ((CDDerivedMesh*)dm)->mface;
 }

+
Index: source/blender/blenkernel/intern/DerivedMesh.c
===================================================================
--- source/blender/blenkernel/intern/DerivedMesh.c	(revision 32564)
+++ source/blender/blenkernel/intern/DerivedMesh.c	(working copy)
@@ -66,6 +66,7 @@

 ///////////////////////////////////
 ///////////////////////////////////
+#include
"C:\Blender_Build\blenderSVN\source\blender\editors\include\ED_mesh.h"
//temporal hack, find a better way to reference the resource :P

 static MVert *dm_getVertArray(DerivedMesh *dm)
 {
@@ -445,15 +446,6 @@

 ///

-typedef struct {
-	DerivedMesh dm;
-
-	EditMesh *em;
-	float (*vertexCos)[3];
-	float (*vertexNos)[3];
-	float (*faceNos)[3];
-} EditMeshDerivedMesh;
-
 static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void
*userData, int index, float *co, float *no_f, short *no_s), void
*userData)
 {
 	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -519,8 +511,9 @@
 }
 static void emDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges),
int UNUSED(drawAllEdges))
 {
-	emDM_drawMappedEdges(dm, NULL, NULL);
+	emDM_drawMappedEdges(dm, NULL, NULL);
 }
+
 static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int
(*setDrawOptions)(void *userData, int index), void
(*setDrawInterpOptions)(void *userData, int index, float t), void
*userData)
 {
 	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1057,7 +1050,7 @@
 	EditVert *eve;
 	int i;

-	if (emdm->em->verts.first) {
+	 if (emdm->em->verts.first) {
 		for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
 			if (emdm->vertexCos) {
 				DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
@@ -1067,27 +1060,27 @@
 		}
 	} else {
 		min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
-	}
+	}
 }
 static int emDM_getNumVerts(DerivedMesh *dm)
 {
 	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;

-	return BLI_countlist(&emdm->em->verts);
+	return emdm->numverts; //BLI_countlist(&emdm->em->verts);
 }

 static int emDM_getNumEdges(DerivedMesh *dm)
 {
 	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;

-	return BLI_countlist(&emdm->em->edges);
+	return emdm->numedges; //BLI_countlist(&emdm->em->edges);
 }

 static int emDM_getNumFaces(DerivedMesh *dm)
 {
 	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;

-	return BLI_countlist(&emdm->em->faces);
+	return emdm->numfaces; //BLI_countlist(&emdm->em->faces);
 }

 static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
@@ -1220,19 +1213,20 @@
 		vert_r->mat_nr = 0;
 		vert_r->flag = 0;
 		vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
+
+		/* store vertex indices in tmp union */
+		ev->tmp.l = (intptr_t) i; //Mio
 	}
 }

-static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
 {
 	EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
 	EditEdge *ee = em->edges.first;
-	EditVert *ev;
-	int i;
-
+
 	/* store vertex indices in tmp union */
-	for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
-		ev->tmp.l = (intptr_t) i;
+	//for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
+	//	ev->tmp.l = (intptr_t) i;

 	for( ; ee; ee = ee->next, ++edge_r) {
 		edge_r->crease = (unsigned char) (ee->crease*255.0f);
@@ -1255,12 +1249,10 @@
 {
 	EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
 	EditFace *ef = em->faces.first;
-	EditVert *ev;
-	int i;
-
+
 	/* store vertexes indices in tmp union */
-	for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
-		ev->tmp.l = (intptr_t) i;
+	//for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
+	//	ev->tmp.l = (intptr_t) i;

 	for( ; ef; ef = ef->next, ++face_r) {
 		face_r->mat_nr = ef->mat_nr;
@@ -1316,24 +1308,377 @@
 static void emDM_release(DerivedMesh *dm)
 {
 	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-
-	if (DM_release(dm)) {
+
+	if (DM_release(dm)) { //check the fact that emDM release is called a lot
and multires no, have to do with multires needs free
+		if (emdm->modified){ //if is in sculpt mode
+				//ccgdm->multires.update(dm);
+				//load_editMesh(emdm->scene, emdm->ob); //apply editmesh to mesh
+				//not needed?
+				//BLI_pbvh_free(emdm->pbvh);
+				//MEM_freeN(emdm->pbvh);
+				//emdm->pbvh = NULL;
+			}
+
 		if (emdm->vertexCos) {
 			MEM_freeN(emdm->vertexCos);
 			MEM_freeN(emdm->vertexNos);
-			MEM_freeN(emdm->faceNos);
-		}
+			MEM_freeN(emdm->faceNos);
+		}

 		MEM_freeN(emdm);
 	}
 }
+//----
+static int em_can_pbvh_draw(Object *ob, DerivedMesh *dm)
+{
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *) dm;
+	Mesh *me= (ob)? ob->data: NULL;

+
+	if(ob->sculpt->modifiers_active) return 0;
+
+	return 1; //?(emdm->em->allverts == me->mvert) || ob->sculpt->kb;
+}
+
+
+static int can_pbvh_draw_uclay(Object *ob, DerivedMesh *dm)
+{
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh*) dm;
+	Mesh *me= (ob)? ob->data: NULL;
+	EditMesh *em;
+	em = (EditMesh *)me->edit_mesh;
+
+	if(ob->sculpt->modifiers_active) return 0;
+
+	return 1; //(emdm->em == em) || ob->sculpt->kb;
+}
+
+static struct PBVH *emDM_getPBVH(Object *ob, DerivedMesh *dm) //check why
this is called several times more than other methods, performance eater
+{
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *) dm;
+	EditFace *efa = NULL;
+	EditMesh *em;
+	Mesh *me;
+	int i = 0, totface = 0, totvert= 0;
+
+	if(!ob) {
+		emdm->pbvh= NULL;
+		return NULL;
+	}
+
+	if(!ob->sculpt)
+		return NULL;
+
+	if(ob->sculpt->pbvh) {
+		emdm->pbvh= ob->sculpt->pbvh;
+		emdm->pbvh_draw = can_pbvh_draw_uclay(ob, dm);
+	}
+
+	me= (ob)? ob->data: NULL;
+	em = ((struct EditMesh *)emdm->em);
+
+	if (em->faces.first) totface = emdm->numfaces;
+	if (em->verts.first) totvert = emdm->numverts;
+
+	//if(emdm->pbvh){ //handle here topology changes, updates
+	//	BLI_pbvh_update_editmesh(emdm->pbvh, em->faces.first,
em->verts.first, totface, totvert);
+
+	//	emdm->pbvh_draw = can_pbvh_draw_uclay(ob, dm);
+	//} else {
+		/* no pbvh exists yet, we need to create one. only in case of unlimited
clay
+	   we build a pbvh over the modified mesh, in other cases the base mesh
+	   is being sculpted, so we build a pbvh from that. */
+		emdm->pbvh = BLI_pbvh_new();
+		BLI_pbvh_build_editmesh(emdm->pbvh, em->faces.first, em->verts.first,
totface, totvert);
+		emdm->pbvh_draw = can_pbvh_draw_uclay(ob, dm);
+	//}
+	return emdm->pbvh;
+}
+
+static void emDM_drawVerts(DerivedMesh *dm) //implementarla mejor despues
+{
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *) dm;
+	EditVert *eve;
+
+	if( GPU_buffer_legacy(dm) ) {
+		glBegin(GL_POINTS);
+		for(eve= emdm->em->verts.first; eve; eve= eve->next)
+			glVertex3fv(eve->co);
+		glEnd();
+	}
+	else {	/* use OpenGL VBOs or Vertex Arrays instead for better, faster
rendering */
+		GPU_vertex_setup(dm);
+		if( !GPU_buffer_legacy(dm) ) {
+			if(dm->drawObject->nelements)	glDrawArrays(GL_POINTS,0,
dm->drawObject->nelements);
+			else							glDrawArrays(GL_POINTS,0, dm->drawObject->nlooseverts);
+		}
+		GPU_buffer_unbind();
+	}
+}
+
+static void emDM_drawLooseEdges(DerivedMesh *dm)
+{
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *) dm;
+	EditEdge *eed;
+	int i;
+	i=0;
+	if( GPU_buffer_legacy(dm) ) {
+		DEBUG_VBO( "Using legacy code. emDM_drawLooseEdges\n" );
+		glBegin(GL_LINES);
+		for(eed= emdm->em->edges.first; eed; eed= eed->next) {
+			if(eed->f&ME_LOOSEEDGE) { //?
+				glVertex3fv(eed->v1->co);
+				glVertex3fv(eed->v2->co);
+			}
+		}
+		glEnd();
+	}
+	else {	/* use OpenGL VBOs or Vertex Arrays instead for better, faster
rendering */
+		int prevstart = 0;
+		int prevdraw = 1;
+		int draw = 1;
+
+		GPU_edge_setup(dm);
+		if( !GPU_buffer_legacy(dm) ) {
+			for(eed= emdm->em->edges.first; eed; eed= eed->next) {
+				if(eed->f&ME_LOOSEEDGE) {
+					draw = 1;
+				}
+				else {
+					draw = 0;
+				}
+				if( prevdraw != draw ) {
+					if( prevdraw > 0 && (i-prevstart) > 0) {
+						GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES,
prevstart*2, (i-prevstart)*2  );
+					}
+					prevstart = i;
+				}
+				prevdraw = draw;
+			}
+			if( prevdraw > 0 && (i-prevstart) > 0 ) {
+				GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES,
prevstart*2, (i-prevstart)*2  );
+			}
+		}
+		GPU_buffer_unbind();
+	}
+}
+
+static void emDM_drawFacesSolid(DerivedMesh *dm, float
(*partial_redraw_planes)[4], int fast, int (*setMaterial)(int, void
*attribs)) {
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *) dm;
+	EditVert *eve = emdm->em->verts.first;
+	EditFace *efa = emdm->em->faces.first;
+	float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
+	int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
+
+	if(emdm->pbvh && emdm->pbvh_draw) {
+		if(dm->numFaceData) {
+			float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+
+			glShadeModel((efa->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
+			BLI_pbvh_draw(emdm->pbvh, partial_redraw_planes, face_nors, (efa->flag
& ME_SMOOTH)); //implement this?¿
+			glShadeModel(GL_FLAT);
+		}
+		return;
+	}
+
+	if( GPU_buffer_legacy(dm) ) {
+		DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
+		glBegin(glmode = GL_QUADS);
+		for(efa= emdm->em->faces.first; efa; efa= efa->next) {
+			int new_glmode, new_matnr, new_shademodel;
+
+			new_glmode = efa->v4?GL_QUADS:GL_TRIANGLES;
+			new_matnr = 1; //mface->mat_nr + 1;
+			new_shademodel = (efa->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
+
+			if(new_glmode != glmode || new_matnr != matnr
+			   || new_shademodel != shademodel) {
+				glEnd();
+
+				drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
+
+				glShadeModel(shademodel = new_shademodel);
+				glBegin(glmode = new_glmode);
+			}
+
+			if(drawCurrentMat) {
+				if(shademodel == GL_FLAT) {
+					if (nors) {
+						glNormal3fv(nors);
+					}
+					else {
+						/* TODO make this better (cache facenormals as layer?) */
+						float nor[3];
+						if(efa->v4) {
+							normal_quad_v3( nor, efa->v1->co, efa->v2->co, efa->v3->co,
efa->v4->co);
+						} else {
+							normal_tri_v3( nor,efa->v1->co, efa->v2->co, efa->v3->co);
+						}
+						glNormal3fv(nor);
+					}
+				}
+				glNormal3fv(efa->v1->no);
+				glVertex3fv(efa->v1->co);
+
+				glNormal3fv(efa->v2->no);
+				glVertex3fv(efa->v2->co);
+
+				glNormal3fv(efa->v3->no);
+				glVertex3fv(efa->v3->co);
+
+				if(efa->v4) {
+					glNormal3fv(efa->v4->no);
+					glVertex3fv(efa->v4->co);
+				}
+			}
+
+			if(nors) nors += 3;
+		}
+		glEnd();
+	}
+	else {	/* use OpenGL VBOs or Vertex Arrays instead for better, faster
rendering */
+		GPU_vertex_setup( dm );
+		GPU_normal_setup( dm );
+		if( !GPU_buffer_legacy(dm) ) {
+			glShadeModel(GL_SMOOTH);
+			for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
+				if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
+					glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
+			}
+		}
+		GPU_buffer_unbind( );
+	}
+
+#undef PASSVERT
+	glShadeModel(GL_FLAT);
+}
+
+static DerivedMesh *getEditMeshDerivedMesh_uclay(EditMesh *em, Object
*ob, float (*vertexCos)[3])
+{
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh
*)MEM_callocN(sizeof(EditMeshDerivedMesh), "emdm");
+	emdm->numverts = BLI_countlist(&em->verts);
+	emdm->numedges = BLI_countlist(&em->edges);
+	emdm->numfaces = BLI_countlist(&em->faces);
+
+	DM_init(&emdm->dm, DM_TYPE_EDITMESH, emdm->numverts , emdm->numedges,
emdm->numfaces);
+	/*/---
+	ccgdm->dm.getVertCo = ccgDM_getFinalVertCo;
+	ccgdm->dm.getVertNo = ccgDM_getFinalVertNo;
+
+	ccgdm->dm.getFaceMap = ccgDM_getFaceMap;
+	ccgdm->dm.getVertCos = ccgdm_getVertCos;
+	ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
+	//---*/
+
+	emdm->dm.drawFacesSolid = emDM_drawFacesSolid;
+	emdm->dm.drawVerts = emDM_drawVerts; //mio
+	emdm->dm.getPBVH = emDM_getPBVH; //mio
+	emdm->dm.drawLooseEdges = emDM_drawLooseEdges; //mio, needed?
+
+	emdm->dm.getMinMax = emDM_getMinMax;
+
+	emdm->dm.getNumVerts = emDM_getNumVerts; //ok
+	emdm->dm.getNumEdges = emDM_getNumEdges; //ok
+	emdm->dm.getNumFaces = emDM_getNumFaces; //ok
+
+	//emdm->dm.getVertCos = emDM_getVertCos;
+
+	//emdm->dm.getVert = emDM_getVert;
+	//emdm->dm.getEdge = emDM_getEdge;
+	//emdm->dm.getFace = emDM_getFace;
+	emdm->dm.copyVertArray = emDM_copyVertArray; //needed
+	emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
+	emdm->dm.copyFaceArray = emDM_copyFaceArray;
+
+	//emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
+
+	//emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
+	//emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
+	//emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
+
+	emdm->dm.drawEdges = emDM_drawEdges;
+	emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
+	emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
+	emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
+	emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
+	emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
+	emdm->dm.drawFacesTex = emDM_drawFacesTex;
+	emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
+	emdm->dm.drawUVEdges = emDM_drawUVEdges;
+
+	emdm->dm.release = emDM_release;
+
+//	emdm->dm.getEditEdges = emDM_getEditEdges;
+//	emdm->dm.getEditVerts = emDM_getEditVerts;
+//	emdm->dm.getEditFaces = emDM_getEditFaces;
+
+	emdm->em = em;
+//	emdm->vertexCos = vertexCos;
+
+	if(CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
+		EditVert *eve;
+		int i;
+
+		DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
+
+		for(eve = em->verts.first, i = 0; eve; eve = eve->next, ++i)
+			DM_set_vert_data(&emdm->dm, i, CD_MDEFORMVERT,
+							 CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT));
+	}
+
+	if(vertexCos) {
+		EditVert *eve;
+		EditFace *efa;
+		int totface = BLI_countlist(&em->faces);
+		int i;
+
+		for (i=0,eve=em->verts.first; eve; eve= eve->next)
+			eve->tmp.l = (intptr_t) i++;
+
+		emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
+		emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
+
+		for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
+			float *v1 = vertexCos[(int) efa->v1->tmp.l];
+			float *v2 = vertexCos[(int) efa->v2->tmp.l];
+			float *v3 = vertexCos[(int) efa->v3->tmp.l];
+			float *no = emdm->faceNos[i];
+
+			if(efa->v4) {
+				float *v4 = vertexCos[(int) efa->v4->tmp.l];
+
+				normal_quad_v3( no,v1, v2, v3, v4);
+				add_v3_v3(emdm->vertexNos[(int) efa->v4->tmp.l], no);
+			}
+			else {
+				normal_tri_v3( no,v1, v2, v3);
+			}
+			add_v3_v3(emdm->vertexNos[(int) efa->v1->tmp.l], no);
+			add_v3_v3(emdm->vertexNos[(int) efa->v2->tmp.l], no);
+			add_v3_v3(emdm->vertexNos[(int) efa->v3->tmp.l], no);
+		}
+
+		for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
+			float *no = emdm->vertexNos[i];
+			/* following Mesh convention; we use vertex coordinate itself
+			 * for normal in this case */
+			if (normalize_v3(no)==0.0) {
+				normalize_v3_v3(no, vertexCos[i]);
+			}
+		}
+	}
+	return (DerivedMesh*) emdm;
+}
+
 static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float
(*vertexCos)[3])
 {
-	EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh
*)MEM_callocN(sizeof(EditMeshDerivedMesh), "emdm"); //?
+	emdm->numverts = BLI_countlist(&em->verts);
+	emdm->numedges = BLI_countlist(&em->edges);
+	emdm->numfaces = BLI_countlist(&em->faces);

-	DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts),
-					 BLI_countlist(&em->edges), BLI_countlist(&em->faces));
+	DM_init(&emdm->dm, DM_TYPE_EDITMESH, emdm->numverts,
+					 emdm->numedges, emdm->numfaces);

 	emdm->dm.getMinMax = emDM_getMinMax;

@@ -1416,16 +1761,17 @@

 		for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
 			float *no = emdm->vertexNos[i];
-			/* following Mesh convention; we use vertex coordinate itself
+			/* following Mesh convention; we use vertex coordinate itself
 			 * for normal in this case */
 			if (normalize_v3(no)==0.0) {
-				normalize_v3_v3(no, vertexCos[i]);
+				VECCOPY(no, vertexCos[i]);
+				normalize_v3(no);
 			}
 		}
 	}

 	return (DerivedMesh*) emdm;
-}
+}

 /***/

@@ -2729,7 +3075,550 @@
 	dm->getMinMax(dm, min, max);

 	if(!ob->bb)
-		ob->bb= MEM_callocN(sizeof(BoundBox), "bb");
+		ob->bb= (BoundBox *)MEM_callocN(sizeof(BoundBox), "bb");

 	boundbox_set_from_min_max(ob->bb, min, max);
 }
+
+
+//------------------------------------------
+void set_border_flag(struct EditMesh *em){
+	EditFace *efa;
+	EditEdge *eed;
+
+	/* clear flag */
+	for (efa=em->faces.first;efa;efa=efa->next){
+		efa->e1->f2 = 0;
+		efa->e2->f2 = 0;
+		efa->e3->f2 = 0;
+		if (efa->e4) efa->e4->f2 = 0;
+	}
+	/* find frontier edges, not shared by other faces */
+	for (efa=em->faces.first;efa;efa=efa->next){
+		efa->e1->f2++;
+		efa->e2->f2++;
+		efa->e3->f2++;
+		if (efa->e4) efa->e4->f2++;
+	}
+
+	/* clear flag verts */
+	for (eed = em->edges.first; eed; eed = eed->next){
+			eed->v1->f2 = 0;
+			eed->v2->f2 = 0;
+	}
+	/* propagate fromtier selection to verts */
+	for (eed = em->edges.first; eed; eed = eed->next){
+		if (eed->f2 == 1){ //is frontier
+			eed->v1->f2 = 1;
+			eed->v2->f2 = 1;
+		}
+	}
+}
+
+void tensate(struct EditMesh *em, float spring_k, float dampfac, float
dtime, float detail){
+	EditFace *efa;
+	float diff[3], dist1, dist2, dist3, dist4, dist5, dist6,
D1,D2,D3,D4,D5,D6, L= 0.f;
+	float k = dtime * spring_k;
+	float end[3]={0.f,0.f,0.f};
+	float delta[3]={0.f,0.f,0.f};
+	float v1[3], v2[3], v3[3], v4[3];
+	float prev_co1[3], prev_co2[3], prev_co3[3], prev_co4[3];
+	int i=0;
+
+	set_border_flag(em);
+
+	for (efa=em->faces.first;efa;efa=efa->next){
+		int fourth_vert_selected = 0;
+		if (efa->v4)
+			if (efa->v4->f & SELECT) fourth_vert_selected = 1;
+
+		//if ((efa->v1->f & SELECT) | (efa->v2->f & SELECT) | (efa->v3->f &
SELECT) | fourth_vert_selected){ //if selected
+				//sub_v3_v3v3(diff, efa->v1->co, efa->v2->co);
+				//dist1 = len_v3(diff);
+
+				//sub_v3_v3v3(diff, efa->v2->co, efa->v3->co);
+				//dist2 = len_v3(diff);
+
+				//sub_v3_v3v3(diff, efa->v3->co, efa->v1->co);
+				//dist3 = len_v3(diff);
+
+				L= 0.f; //0.3333f * (dist1+dist2+dist3);
+
+				for (i=0; i<10; i++){ //first only tris
+					zero_v3(v1); zero_v3(v2); zero_v3(v3), zero_v3(v4);
+
+					copy_v3_v3(prev_co1,efa->v1->co);
+					copy_v3_v3(prev_co2,efa->v2->co);
+					copy_v3_v3(prev_co3,efa->v3->co);
+					if (efa->v4) copy_v3_v3(prev_co4,efa->v4->co);
+
+					//find distance among verts 1-2-3
+					sub_v3_v3v3(diff, prev_co1, prev_co2);
+					dist1 = len_v3(diff);
+
+					sub_v3_v3v3(diff, prev_co2, prev_co3);
+					dist2 = len_v3(diff);
+
+					sub_v3_v3v3(diff, prev_co3, prev_co1);
+					dist3 = len_v3(diff);
+
+					if (efa->v4){
+						sub_v3_v3v3(diff, prev_co1, prev_co4);
+						dist4 = len_v3(diff);
+
+						sub_v3_v3v3(diff, prev_co2, prev_co4);
+						dist5 = len_v3(diff);
+
+						sub_v3_v3v3(diff, prev_co3, prev_co4);
+						dist6 = len_v3(diff);
+
+						D4 =  k * (L - dist4);
+						D5 =  k * (L - dist5);
+						D6 =  k * (L - dist6);
+					}
+
+					D1 =  k * (L - dist1);
+					D2 =  k * (L - dist2);
+					D3 =  k * (L - dist3);
+
+					//v1
+					if (!efa->v1->f2 ){ //&& (efa->v1->f & SELECT)
+						sub_v3_v3v3(end, prev_co2, prev_co1);
+						normalize_v3(end);
+						madd_v3_v3fl(v1, end, -D1);
+
+						sub_v3_v3v3(end, prev_co3, prev_co1);
+						normalize_v3(end);
+						madd_v3_v3fl(v1, end, -D3);
+
+						if (efa->v4){
+							sub_v3_v3v3(end, prev_co4, prev_co1);
+							normalize_v3(end);
+							madd_v3_v3fl(v1, end, -D4);
+						}
+
+						madd_v3_v3fl(v1,v1,-dampfac);
+						madd_v3_v3v3fl(efa->v1->co, prev_co1, v1, dtime);
+
+						//remove movement along vertex normal
+						sub_v3_v3v3(delta, efa->v1->co,prev_co1);
+						project_v3_v3v3(delta, delta, efa->v1->no);
+						sub_v3_v3v3(efa->v1->co,efa->v1->co,delta);
+					}
+					//v2
+					if (!efa->v2->f2 ){ //&& (efa->v2->f & SELECT)
+						sub_v3_v3v3(end, prev_co1, prev_co2);
+						normalize_v3(end);
+						madd_v3_v3fl(v2, end, -D1);
+
+						sub_v3_v3v3(end, prev_co3, prev_co2);
+						normalize_v3(end);
+						madd_v3_v3fl(v2, end, -D2);
+
+						if (efa->v4){
+							sub_v3_v3v3(end, prev_co4, prev_co2);
+							normalize_v3(end);
+							madd_v3_v3fl(v2, end, -D5);
+						}
+
+						madd_v3_v3fl(v2,v2,-dampfac);
+						madd_v3_v3v3fl(efa->v2->co, prev_co2, v2, dtime);
+
+						//remove movement along vertex normal
+						sub_v3_v3v3(delta, efa->v2->co,prev_co2);
+						project_v3_v3v3(delta, delta, efa->v2->no);
+						sub_v3_v3v3(efa->v2->co,efa->v2->co,delta);
+					}
+					//v3
+					if (!efa->v3->f2 ){ //&& (efa->v3->f & SELECT)
+						sub_v3_v3v3(end, prev_co2, prev_co3);
+						normalize_v3(end);
+						madd_v3_v3fl(v3, end, -D2);
+
+						sub_v3_v3v3(end, prev_co1, prev_co3);
+						normalize_v3(end);
+						madd_v3_v3fl(v3, end, -D3);
+
+						if (efa->v4){
+							sub_v3_v3v3(end, prev_co4, prev_co3);
+							normalize_v3(end);
+							madd_v3_v3fl(v3, end, -D6);
+						}
+
+						madd_v3_v3fl(v3,v3,-dampfac);
+						madd_v3_v3v3fl(efa->v3->co, prev_co3, v3, dtime);
+
+						//remove movement along vertex normal
+						sub_v3_v3v3(delta, efa->v3->co,prev_co3);
+						project_v3_v3v3(delta, delta, efa->v3->no);
+						sub_v3_v3v3(efa->v3->co,efa->v3->co,delta);
+					}
+					//v4
+					if (efa->v4){
+						if (!efa->v4->f2 ){ //&& (efa->v4->f & SELECT)
+							sub_v3_v3v3(end, prev_co1, prev_co4);
+							normalize_v3(end);
+							madd_v3_v3fl(v4, end, -D4);
+
+							sub_v3_v3v3(end, prev_co2, prev_co4);
+							normalize_v3(end);
+							madd_v3_v3fl(v4, end, -D5);
+
+							sub_v3_v3v3(end, prev_co3, prev_co4);
+							normalize_v3(end);
+							madd_v3_v3fl(v4, end, -D6);
+
+							madd_v3_v3fl(v4,v4,-dampfac);
+							madd_v3_v3v3fl(efa->v4->co, prev_co4, v4, dtime);
+
+							//remove movement along vertex normal
+							sub_v3_v3v3(delta, efa->v4->co,prev_co4);
+							project_v3_v3v3(delta, delta, efa->v4->no);
+							sub_v3_v3v3(efa->v4->co,efa->v4->co,delta);
+						}
+					}
+				//-----------*/
+				}
+			//}
+	}
+}
+
+void laplacian_relaxation(struct EditMesh *em, float spring_k, float
dampfac, float dtime, float detail){
+	EditEdge *eed;
+	EditVert *eve;
+	float k = dtime * spring_k;
+	float end[3]={0.f,0.f,0.f};
+	float delta[3]={0.f,0.f,0.f};
+	float prev_co[3];
+	int i=0;
+
+	for (i = 0; i<3 ; i++){
+	//set_border_flag(em); //Optional, user defined
+
+	/* clear editvert old_co*/
+	for (eve = em->verts.first; eve; eve = eve->next){
+		zero_v3(eve->old_co);
+		eve->v = 0.f;
+		eve->count = 0;
+	}
+
+	for (eed=em->edges.first;eed;eed=eed->next){
+		if ((!eed->v1->f2 && (eed->v1->f1 == 1)) || (!eed->v2->f2 &&
(eed->v2->f1 == 1)) ){
+		madd_v3_v3fl(eed->v1->old_co, eed->v2->co, 1.f);
+		madd_v3_v3fl(eed->v2->old_co, eed->v1->co, 1.f);
+
+		eed->v1->count += 1.f;
+		eed->v2->count += 1.f;
+		}
+	}
+
+
+	for (eve = em->verts.first; eve; eve = eve->next){
+		if (!eve->f2 && (eve->f1 == SELECT) ){//
+			copy_v3_v3(prev_co,eve->co);
+			mul_v3_fl(eve->old_co, 1.f/eve->count);
+			copy_v3_v3(eve->co, eve->old_co);
+
+			//remove movement along vertex normal
+			sub_v3_v3v3(delta, eve->co,prev_co);
+			project_v3_v3v3(delta, delta, eve->no);
+			sub_v3_v3v3(eve->co,eve->co,delta);
+		}
+	} //*/
+
+	}//for i
+}
+
+void revised_ideal_length_relaxation(struct EditMesh *em, float spring_k,
float dampfac, float dtime, float detail){
+	EditEdge *eed;
+	EditVert *eve;
+	float diff[3], dist1,  L= 0.f;
+	float k = dtime * spring_k;
+	float end[3]={0.f,0.f,0.f};
+	float delta[3]={0.f,0.f,0.f};
+
+	int i=0;
+
+	set_border_flag(em);
+
+	/* clear editvert old_co*/
+	for (i = 0; i<1 ; i++){
+	for (eve = em->verts.first; eve; eve = eve->next){
+		zero_v3(eve->sum_co); zero_v3(eve->old_co);
+		eve->v = 0.f;
+		eve->count = 0;
+		eve->w = 0;
+		eve->sum_dist = 0.f;
+	}
+
+	for (eed=em->edges.first;eed;eed=eed->next){
+		sub_v3_v3v3(diff, eed->v1->co, eed->v2->co);
+		dist1 = len_v3(diff);
+
+		eed->v1->sum_dist +=dist1; //accumulate dist from verts
+		eed->v2->sum_dist +=dist1;
+
+		eed->v1->count += 1.f; //count verts
+		eed->v2->count += 1.f;
+	}
+
+	for (eve = em->verts.first; eve; eve = eve->next){
+		eve->sum_dist = eve->sum_dist/eve->count;
+	}
+
+	for (eed=em->edges.first;eed;eed=eed->next){
+		float a = 0.f;
+
+		sub_v3_v3v3(diff, eed->v1->co, eed->v2->co);
+		dist1 = len_v3(diff);
+
+		a = 2.f * dist1/(eed->v1->sum_dist + eed->v2->sum_dist);
+
+		eed->v1->w += a/eed->v1->count;
+		eed->v2->w += a/eed->v2->count;
+	}
+
+	for (eed=em->edges.first;eed;eed=eed->next){
+		sub_v3_v3v3(diff, eed->v1->co, eed->v2->co);
+		dist1 = len_v3(diff);
+
+		eed->v1->sum_co[0] += (dist1 - (eed->v1->sum_dist + eed->v2->sum_dist)
* 0.5f * eed->v1->w) * (eed->v2->co[0] - eed->v1->co[0])/dist1;
+		eed->v1->sum_co[1] += (dist1 - (eed->v1->sum_dist + eed->v2->sum_dist)
* 0.5f * eed->v1->w) * (eed->v2->co[1] - eed->v1->co[1])/dist1;
+		eed->v1->sum_co[2] += (dist1 - (eed->v1->sum_dist + eed->v2->sum_dist)
* 0.5f * eed->v1->w) * (eed->v2->co[2] - eed->v1->co[2])/dist1;
+
+		eed->v2->sum_co[0] += (dist1 - (eed->v1->sum_dist + eed->v2->sum_dist)
* 0.5f * eed->v2->w) * (eed->v1->co[0] - eed->v2->co[0])/dist1;
+		eed->v2->sum_co[1] += (dist1 - (eed->v1->sum_dist + eed->v2->sum_dist)
* 0.5f * eed->v2->w) * (eed->v1->co[1] - eed->v2->co[1])/dist1;
+		eed->v2->sum_co[2] += (dist1 - (eed->v1->sum_dist + eed->v2->sum_dist)
* 0.5f * eed->v2->w) * (eed->v1->co[2] - eed->v2->co[2])/dist1;
+
+		madd_v3_v3fl(eed->v1->old_co, eed->v2->co, 1.f);
+		madd_v3_v3fl(eed->v2->old_co, eed->v1->co, 1.f);
+	}
+
+	for (eve = em->verts.first; eve; eve = eve->next){
+		if (!eve->f2){
+			eve->co[0] = (eve->old_co[0] - eve->sum_co[0])/eve->count;
+			eve->co[1] = (eve->old_co[1] - eve->sum_co[1])/eve->count;
+			eve->co[2] = (eve->old_co[2] - eve->sum_co[2])/eve->count;
+		}
+	}
+
+
+	}//for i
+}
+//----------------------
+void HC_relaxation(struct EditMesh *em, float spring_k, float dampfac,
float dtime, float detail){
+	EditEdge *eed;
+	EditVert *eve;
+	float k = dtime * spring_k;
+	float end[3]={0.f,0.f,0.f};
+	float delta[3]={0.f,0.f,0.f};
+	float diff[3];
+	int i=0;
+	float a = 0.1f;
+	float b = 0.6f;
+
+	set_border_flag(em);
+
+	/* clear editvert old_co*/
+	for (eve = em->verts.first; eve; eve = eve->next){
+		copy_v3_v3(eve->old_co, eve->co);
+		eve->v = 0.f;
+		eve->count = 0;
+		zero_v3(eve->p); zero_v3(eve->b);
+		zero_v3(eve->sum_co); zero_v3(eve->sum_b);
+	}
+
+	/* counting neighbors */
+	for (eed = em->edges.first; eed; eed = eed->next){
+		eed->v1->count++;
+		eed->v2->count++;
+	}
+
+	for (i = 0; i< 4 ; i++){
+		for (eve = em->verts.first; eve; eve = eve->next){
+			zero_v3(eve->sum_co);
+			zero_v3(eve->sum_b);
+			zero_v3(eve->p); zero_v3(eve->b);
+		}
+
+		for (eed = em->edges.first; eed; eed = eed->next){
+			add_v3_v3(eed->v1->sum_co, eed->v2->co);
+			add_v3_v3(eed->v2->sum_co, eed->v1->co);
+		}
+
+		//1rst pass
+		for (eve = em->verts.first; eve; eve = eve->next){
+			copy_v3_v3(diff,eve->sum_co);
+			mul_v3_fl(diff,1.f/eve->count); //diff new position
+
+			copy_v3_v3(eve->p,diff);
+
+			eve->b[0] = diff[0] - (a*eve->old_co[0] + (1.f-a)*eve->co[0]);
+			eve->b[1] = diff[1] - (a*eve->old_co[1] + (1.f-a)*eve->co[1]);
+			eve->b[2] = diff[2] - (a*eve->old_co[2] + (1.f-a)*eve->co[2]);
+		}
+
+		for (eed = em->edges.first; eed; eed = eed->next){
+			add_v3_v3(eed->v1->sum_b, eed->v2->b);
+			add_v3_v3(eed->v2->sum_b, eed->v1->b);
+		}
+		//2nd pass
+		for (eve = em->verts.first; eve; eve = eve->next){
+			if (!eve->f2){ // && (eve->f & SELECT)
+				eve->co[0] = eve->p[0] - (b*eve->b[0] + (1-b)*eve->sum_b[0]/eve->count);
+				eve->co[1] = eve->p[1] - (b*eve->b[1] + (1-b)*eve->sum_b[1]/eve->count);
+				eve->co[2] = eve->p[2] - (b*eve->b[2] + (1-b)*eve->sum_b[2]/eve->count);
+			}
+		}
+
+	}//for i
+}
+//----------------------
+void select_edges_uclay(struct EditMesh *em, float radius, float detail,
int repeat, int edge_treshold){//edge_treshold: fator to trigger edge
splitting
+	EditFace *efa;
+	float diff[3];
+	int i = 0;
+	float dist1, dist2, dist3, s, d;
+
+	for(efa= em->faces.first; efa; efa= efa->next){
+		if (efa->f & SELECT)
+		{
+			float bigger = 0.f;
+			sub_v3_v3v3(diff, efa->e1->v1->co, efa->e1->v2->co);
+			dist1 = len_v3(diff);
+			bigger = dist1;
+
+			sub_v3_v3v3(diff, efa->e2->v1->co, efa->e2->v2->co);
+			dist2 = len_v3(diff);
+			if (bigger < dist2) bigger = dist2;
+
+			sub_v3_v3v3(diff, efa->e3->v1->co, efa->e3->v2->co);
+			dist3 = len_v3(diff);
+			if (bigger < dist3) bigger = dist3;
+
+			s = (dist1 + dist2 + dist3) * 0.5f; //area =
sqrtf(s*(s-dist1)*(s-dist2)*(s-dist3)); r = area/s; /* incircle radius */
+			d = 2.f * sqrtf((s-dist1)*(s-dist2)*(s-dist3)/s);
+
+			if (d > detail){
+				//if (bigger == dist1) efa->e1->f |= SELECT;
+				//else if (bigger == dist2) efa->e2->f |= SELECT;
+				//else efa->e3->f |= SELECT;
+
+				if ((efa->v1->count <= edge_treshold) && (efa->v2->count <=
edge_treshold) && (efa->v3->count <= edge_treshold)){
+				efa->e1->f |= SELECT;
+				efa->e2->f |= SELECT;
+				efa->e3->f |= SELECT;
+				if (efa->e4) efa->e4->f |= SELECT;
+				}
+			}
+		} //if (efa->f & SELECT)
+		if ((efa->v1->count > edge_treshold) || (efa->v2->count >
edge_treshold) || (efa->v3->count > edge_treshold)){
+			float bigger = 0.f;
+			sub_v3_v3v3(diff, efa->e1->v1->co, efa->e1->v2->co);
+			dist1 = len_v3(diff);
+			bigger = dist1;
+
+			sub_v3_v3v3(diff, efa->e2->v1->co, efa->e2->v2->co);
+			dist2 = len_v3(diff);
+			if (bigger < dist2) bigger = dist2;
+
+			sub_v3_v3v3(diff, efa->e3->v1->co, efa->e3->v2->co);
+			dist3 = len_v3(diff);
+			if (bigger < dist3) bigger = dist3;
+
+			s = (dist1 + dist2 + dist3) * 0.5f; //area =
sqrtf(s*(s-dist1)*(s-dist2)*(s-dist3)); r = area/s;
+			d = 2.f * sqrtf((s-dist1)*(s-dist2)*(s-dist3)/s);
+
+			if (d > detail){
+				if (efa->v1->count > edge_treshold) { //efa->e2->f &= ~SELECT;
+					efa->e1->f |= SELECT;
+					efa->e3->f |= SELECT;
+					efa->e2->f &= ~SELECT;
+				}
+
+				if (efa->v2->count > edge_treshold) {
+					efa->e1->f |= SELECT;
+					efa->e2->f |= SELECT;
+					efa->e3->f &= ~SELECT;
+				}
+				if (efa->v3->count > edge_treshold) {
+					efa->e2->f |= SELECT;
+					efa->e3->f |= SELECT;
+					efa->e1->f &= ~SELECT;
+				}
+			} //if (d > detail)
+		} //if ((efa->v1->count > edge_treshold) || (efa->v2-> ....*/
+	} //for(efa= em->faces.first...
+} //*/
+
+DerivedMesh *uclay_dm_create_from_derived(struct UClayModifierData *ucmd,
int local_ucmd, DerivedMesh *dm,struct Object *ob,struct Scene
*scene,float radius, int useRenderParams,int isFinalCalc)
+{
+	EditMesh *em;
+	EditMeshDerivedMesh *emdm;
+	DerivedMesh *result;
+	EditVert *eve;
+	float detail = radius * ucmd->detail;	//fix this parameter
+	int toteditface = 0, repeat = ucmd->relax;
+	Mesh *me = (Mesh *)ob->data;
+	int mark = 0, i = 0;
+	int edge_treshold = 9; //fator to trigger edge splitting
+
+	//LinkNode *listeditedges = NULL;
+	//LinkData *iter = NULL;
+
+	if (!me->edit_mesh)
+		make_editMesh(scene,ob);
+	em = me->edit_mesh;
+
+	/* em = (EditMesh *)ucmd->emCache;
+	if (!em) {
+		ucmd->emCache = (struct EditMesh *) MEM_callocN(sizeof(struct
EditMesh), "editmesh from derivedmesh");
+		em = (EditMesh *)ucmd->emCache;
+		make_editMesh_from_DerivedMesh(scene,ob,dm, em);
+		} // OK :) */
+
+
+	//select_edges_uclay(em, radius, detail, repeat, edge_treshold);
+	esubdivideflag_local(ob, em, SELECT,ucmd->smoothness,0,B_SMOOTH,1,
SUBDIV_CORNER_INNERVERT, 0);
+	//convert_to_triface_all(em,0); //find a way to allways enforce this
from subdivission
+	laplacian_relaxation(em, 0.5f, 0.1f, 0.1f, detail); //fix conflict with
esubd .. issues with flags
+
+	//recalc_editnormals(em);
+	//try to achieve even faces
+	//for (efa=em->faces.first;efa; efa =efa->next){
+	//	if (efa->e1->f & SELECT)
+	//}
+
+	// we could combine any amount of editmesh tools here ;)!
+
+	//for (i=0; i<repeat; i++) {
+	//	smooth_vertex_editmesh(ob,em); //OK
+	 //}
+
+	/* clear selection */
+	//for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT;
+	//for (eed= em->edges.first; eed; eed= eed->next)
+	//	eed->f &= ~SELECT;
+	EM_clear_flag_all(em, SELECT); //*/
+	for (eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0; //smooth flag
+
+	result = getEditMeshDerivedMesh_uclay(em, ob, NULL); //OK
CDDM_from_mesh(me, ob);
+	emdm = (EditMeshDerivedMesh *)result;
+
+	/* build here the array from editfaces*/
+	//toteditface = emdm->numfaces;
+	//pbvh = emdm->pbvh;
+	//i = 0;
+	emdm->scene = scene;
+	emdm->ob = ob;
+
+	/* if(ob->sculpt && ob->sculpt->pbvh) {
+		if(!ob->sculpt->cache) {
+			BLI_pbvh_free(ob->sculpt->pbvh);
+			ob->sculpt->pbvh= NULL;
+		}
+	}
+
+//	BLI_linklist_free(listeditedges,NULL); //*/
+	return result;
+}
Index: source/blender/blenkernel/intern/multires.c
===================================================================
--- source/blender/blenkernel/intern/multires.c	(revision 32564)
+++ source/blender/blenkernel/intern/multires.c	(working copy)
@@ -116,12 +116,26 @@
 	ccgdm->multires.modified = 1;
 }

+//Mio, eventually moved
+static void uclay_dm_mark_as_modified(DerivedMesh *dm)
+{
+	EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
+	emdm->modified = 1;
+}
+
 void multires_mark_as_modified(Object *ob)
 {
 	if(ob && ob->derivedFinal)
 		multires_dm_mark_as_modified(ob->derivedFinal);
 }

+//mio Eventually moved
+void uclay_mark_as_modified(Object *ob)
+{
+	if(ob && ob->derivedFinal)
+		uclay_dm_mark_as_modified(ob->derivedFinal);
+}
+
 void multires_force_update(Object *ob)
 {
 	if(ob) {
@@ -137,6 +151,22 @@
 	}
 }

+/* temporal here buy eventually movd toa correct place*/
+void uclay_force_update(Object *ob)
+{
+	if(ob) {
+		if(ob->derivedFinal) {
+			ob->derivedFinal->needsFree =1;
+			ob->derivedFinal->release(ob->derivedFinal);
+			ob->derivedFinal = NULL;
+		}
+		if(ob->sculpt && ob->sculpt->pbvh) {
+			BLI_pbvh_free(ob->sculpt->pbvh);
+			ob->sculpt->pbvh= NULL;
+		}
+	}
+}
+
 void multires_force_external_reload(Object *ob)
 {
 	Mesh *me = get_mesh(ob);
@@ -678,7 +708,7 @@
 	mmd = ccgdm->multires.mmd;
 	multires_set_tot_mdisps(me, mmd->totlvl);
 	CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
-	mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
+	mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);

 	if(mdisps) {
 		int lvl = ccgdm->multires.lvl;
@@ -782,7 +812,7 @@
 DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd,
int local_mmd, DerivedMesh *dm, Object *ob,
 							int useRenderParams, int UNUSED(isFinalCalc))
 {
-	Mesh *me= ob->data;
+	Mesh *me= (Mesh *)ob->data;
 	DerivedMesh *result;
 	CCGDerivedMesh *ccgdm;
 	DMGridData **gridData, **subGridData;
@@ -811,16 +841,16 @@
 	gridSize = result->getGridSize(result);
 	gridData = result->getGridData(result);

-	subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*");
+	subGridData = (DMGridData **)MEM_callocN(sizeof(DMGridData*)*numGrids,
"subGridData*");

 	for(i = 0; i < numGrids; i++) {
-		subGridData[i] = MEM_callocN(sizeof(DMGridData)*gridSize*gridSize,
"subGridData");
+		subGridData[i] = (DMGridData
*)MEM_callocN(sizeof(DMGridData)*gridSize*gridSize, "subGridData");
 		memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize);
 	}

 	multires_set_tot_mdisps(me, mmd->totlvl);
 	CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
-	multiresModifier_disp_run(result, ob->data, 0, 0, subGridData,
mmd->totlvl);
+	multiresModifier_disp_run(result, (Mesh *)ob->data, 0, 0, subGridData,
mmd->totlvl);

 	for(i = 0; i < numGrids; i++)
 		MEM_freeN(subGridData[i]);
@@ -1385,3 +1415,4 @@
 	me->mr= NULL;
 }

+
Index: source/blender/blenkernel/intern/subsurf_ccg.c
===================================================================
--- source/blender/blenkernel/intern/subsurf_ccg.c	(revision 32564)
+++ source/blender/blenkernel/intern/subsurf_ccg.c	(working copy)
@@ -70,6 +70,7 @@
 static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);

 static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
+static int edDM_use_uclay_pbvh(EditMeshDerivedMesh *emdm); //mio,
eventually moved

 ///

@@ -1971,8 +1972,8 @@
 			if(!ccgdm->multires.local_mmd &&
BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) <
0)
 				ccgdm->multires.mmd = NULL;
 			if(ccgdm->multires.mmd)
-				ccgdm->multires.update(dm);
-		}
+				ccgdm->multires.update(dm);
+		}

 		if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
 		if(ccgdm->gridData) MEM_freeN(ccgdm->gridData);
@@ -1988,6 +1989,7 @@
 		MEM_freeN(ccgdm->faceMap);
 		MEM_freeN(ccgdm);
 	}
+
 }

 static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
@@ -2752,3 +2754,4 @@
 	dm->release(dm);
 }

+
Index: source/blender/blenlib/BLI_editVert.h
===================================================================
--- source/blender/blenlib/BLI_editVert.h	(revision 32564)
+++ source/blender/blenlib/BLI_editVert.h	(working copy)
@@ -60,8 +60,19 @@
 	} tmp;
 	float no[3]; /*vertex normal */
 	float co[3]; /*vertex location */
+	float v; /* vertex speed */
 	short xs, ys; /* used to store a screenspace 2d projection of the verts */
+
+	float old_co[3]; /* original position */
+	float sum_b[3]; /* accumulated factor*/
+	float sum_co[3]; //HC relax
+	float p[3];  //HC relax
+	float b[3]; // HC relax
+	int count; /* number of neighbours */
+	float sum_dist; /* accumulated neighbours */
+	float w; /* accumulated weigth */

+
 	/* f stores selection eg. if (eve->f & SELECT) {...
 	h for hidden. if (!eve->h) {...
 	f1 and f2 can be used for temp data, clear them first*/
@@ -150,8 +161,8 @@
 typedef struct EditMesh
 {
 	ListBase verts, edges, faces;
-	ListBase selected; /*EditSelections. Used to store the order in which
things are selected.*/
-	HashEdge *hashedgetab;
+	ListBase selected; /*EditSelections. Used to store the order in which
things are selected.*/
+	HashEdge *hashedgetab;

 	/* this is for the editmesh_fastmalloc */
 	EditVert *allverts, *curvert;
Index: source/blender/blenlib/BLI_math_geom.h
===================================================================
--- source/blender/blenlib/BLI_math_geom.h	(revision 32564)
+++ source/blender/blenlib/BLI_math_geom.h	(working copy)
@@ -94,6 +94,8 @@
 	float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float
threshold);
 int isect_ray_tri_epsilon_v3(float p1[3], float d[3],
 	float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float
epsilon);
+int fast_discard_tri(float center[3], float R, float v1[3], float v2[3],
float v3[3]);
+int FastRayTri(float orig[3], float dir[3], float v0[3], float v1[3],
float v2[3]);

 /* point in polygon */
 int isect_point_tri_v2(float p[2], float a[2], float b[2], float c[2]);
Index: source/blender/blenlib/BLI_pbvh.h
===================================================================
--- source/blender/blenlib/BLI_pbvh.h	(revision 32564)
+++ source/blender/blenlib/BLI_pbvh.h	(working copy)
@@ -32,7 +32,12 @@
 struct PBVH;
 struct PBVHNode;
 struct ListBase;
+struct EditMesh;
+struct EditVert;
+struct EditFace;
+struct DMGridData;

+
 typedef struct PBVH PBVH;
 typedef struct PBVHNode PBVHNode;

@@ -53,11 +58,13 @@
 PBVH *BLI_pbvh_new(void);
 void BLI_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert
*verts,
 			int totface, int totvert);
+void BLI_pbvh_build_editmesh(PBVH *bvh, struct EditFace *editfaces,
struct EditVert *editverts, int toteditface, int toteditvert);
 void BLI_pbvh_build_grids(PBVH *bvh, struct DMGridData **grids,
 	struct DMGridAdjacency *gridadj, int totgrid,
 	int gridsize, void **gridfaces);
 void BLI_pbvh_free(PBVH *bvh);

+
 /* Hierarchical Search in the BVH, two methods:
    * for each hit calling a callback
    * gather nodes in an array (easy to multithread) */
@@ -107,6 +114,7 @@
 	int *uniquevert, int *totvert);
 void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node,
 	int **vert_indices, struct MVert **verts);
+void BLI_pbvh_node_get_editverts(PBVH *bvh, PBVHNode *node, int
*toteditvert);

 void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
 void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float
bb_max[3]);
@@ -121,6 +129,7 @@
 void BLI_pbvh_grids_update(PBVH *bvh, struct DMGridData **grids,
 	struct DMGridAdjacency *gridadj, void **gridfaces);

+
 /* vertex deformer */
 float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3];
 void BLI_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
@@ -133,6 +142,7 @@
    - allow the compiler to eliminate dead code and variables
    - spend most of the time in the relatively simple inner loop */

+
 #define PBVH_ITER_ALL		0
 #define PBVH_ITER_UNIQUE	1

@@ -146,6 +156,10 @@
 	int gy;
 	int i;

+	/* EditMesh Mio*/
+	struct EditVert *editvert;
+	int toteditvert;
+
 	/* grid */
 	struct DMGridData **grids;
 	struct DMGridData *grid;
@@ -166,6 +180,89 @@
 	float *fno;
 } PBVHVertexIter;

+/* Axis-aligned bounding box */
+typedef struct {
+	float bmin[3], bmax[3];
+} BB;
+
+/* Axis-aligned bounding box with centroid */
+typedef struct {
+	float bmin[3], bmax[3], bcentroid[3];
+} BBC;
+
+struct PBVHNode {
+	/* Opaque handle for drawing code */
+	void *draw_buffers;
+
+	int *vert_indices;
+
+	/* Voxel bounds */
+	BB vb;
+	BB orig_vb;
+
+	/* For internal nodes */
+	int children_offset;
+
+	/* Pointer into bvh prim_indices */
+	int *prim_indices;
+	int *face_vert_indices;
+
+	/* EditVert  */
+	unsigned int toteditverts;
+	struct EditVert **editverts;
+
+	unsigned int totprim;
+	unsigned int uniq_verts, face_verts;
+
+	char flag;
+
+	float tmin; // used for raycasting, is how close bb is to the ray point
+
+	int proxy_count;
+	PBVHProxyNode* proxies;
+};
+/* Bitmap */
+typedef char* BLI_bitmap;
+
+struct PBVH {
+	PBVHNode *nodes;
+	int node_mem_count, totnode;
+
+	int *prim_indices;
+	int totprim;
+	int totvert;
+
+	int leaf_limit;
+
+	/* Mesh data */
+	struct MVert *verts;
+	struct MFace *faces;
+
+	/* Grid Data */
+	struct DMGridData **grids;
+	struct DMGridAdjacency *gridadj;
+	void **gridfaces;
+	int totgrid;
+	int gridsize;
+
+	/*EditMesh Data*/
+	struct EditFace **editfaces; /* not all editfaces, just node*/
+
+
+	/* Only used during BVH build and update,
+	   don't need to remain valid after */
+	BLI_bitmap vert_bitmap;
+
+#ifdef PERFCNTRS
+	int perf_modified;
+#endif
+
+	/* flag are verts/faces deformed */
+	int deformed;
+};
+
+#define STACK_FIXED_DEPTH	100
+
 #ifdef _MSC_VER
 #pragma warning (disable:4127) // conditional expression is constant
 #endif
@@ -174,22 +271,25 @@
 	{ \
 		struct DMGridData **grids; \
 		struct MVert *verts; \
-		int *grid_indices, totgrid, gridsize, *vert_indices, uniq_verts,
totvert; \
+		int *grid_indices, totgrid, gridsize, *vert_indices, uniq_verts,
totvert, toteditvert; \
 		\
 		vi.grid= 0; \
 		vi.no= 0; \
 		vi.fno= 0; \
 		vi.mvert= 0; \
 		vi.skip= 0; \
+		vi.editvert= 0; \
 		\
 		BLI_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL,
&gridsize, &grids, NULL); \
 		BLI_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert); \
 		BLI_pbvh_node_get_verts(bvh, node, &vert_indices, &verts); \
+		BLI_pbvh_node_get_editverts(bvh, node, &toteditvert); \
 		\
 		vi.grids= grids; \
 		vi.grid_indices= grid_indices; \
 		vi.totgrid= (grids)? totgrid: 1; \
 		vi.gridsize= gridsize; \
+		vi.toteditvert= toteditvert; \
 		\
 		if(mode == PBVH_ITER_ALL) \
 			vi.totvert = totvert; \
@@ -226,13 +326,18 @@
 					vi.fno= vi.grid->no; \
 					vi.grid++; \
 				} \
+				else if (vi.toteditvert) { \
+					vi.editvert = node->editverts[vi.gx]; \
+					vi.co= vi.editvert->co; \
+					vi.fno= vi.editvert->no; \
+				} \
 				else { \
 					vi.mvert= &vi.mverts[vi.vert_indices[vi.gx]]; \
 					vi.co= vi.mvert->co; \
 					vi.no= vi.mvert->no; \
 				} \

-#define BLI_pbvh_vertex_iter_end \
+#define BLI_pbvh_vertex_iter_end(vi) \
 			} \
 		} \
 	}
@@ -247,3 +352,4 @@

 #endif /* BLI_PBVH_H */

+

Index: source/blender/blenlib/intern/math_geom.c
===================================================================
--- source/blender/blenlib/intern/math_geom.c	(revision 32564)
+++ source/blender/blenlib/intern/math_geom.c	(working copy)
@@ -420,6 +420,31 @@
 	return 1;
 }

+int fast_discard_tri(float center[3], float R, float v1[3], float v2[3],
float v3[3]){
+	float deltha1, deltha2;
+	deltha1 = center[0] - R;
+	if ((v1[0] < deltha1) && (v2[0] < deltha1) && (v3[0] < deltha1)) return 0;
+
+	deltha2 = center[0] + R;
+	if ((v1[0] > deltha2) && (v2[0] > deltha2) && (v3[0] > deltha2)) return 0;
+
+	//----discarding Y axis---------
+	deltha1 = center[1] - R;
+	if ((v1[1] < deltha1) && (v2[1] < deltha1) && (v3[1] < deltha1)) return 0;
+
+	deltha2 = center[1] + R;
+	if ((v1[1] > deltha2) && (v2[1] > deltha2) && (v3[1] > deltha2)) return 0;
+
+	//----discarding Z axis---------
+	deltha1 = center[2] - R;
+	if ((v1[2] < deltha1) && (v2[2] < deltha1) && (v3[2] < deltha1)) return 0;
+
+	deltha2 = center[2] + R;
+	if ((v1[2] > deltha2) && (v2[2] > deltha2) && (v3[2] > deltha2)) return 0;
+
+	return 1;
+}
+
 /* moved from effect.c
    test if the ray starting at p1 going in d direction intersects the
triangle v0..v2
    return non zero if it does
@@ -459,12 +484,45 @@

 	return 1;
 }
+//With Culling
+int FastRayTri(float orig[3], float dir[3], float v0[3], float v1[3],
float v2[3]){
+	float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
+	double det, inv_det, t, u, v;

+		//find vectors for two edges sharing vert
+		sub_v3_v3v3(edge1,v1,v2);
+		sub_v3_v3v3(edge2,v2,v0);
+
+		//begin calculating determinant also used to calculate U parameter
+		cross_v3_v3v3(pvec,dir,edge2);
+
+		//if determinant is near zero ray lies in plane of triangle
+		det = dot_v3v3(edge1, pvec);
+
+		if (det < 0.00001f) return 0;
+
+		//calculate distance from vertex to ray origin
+		sub_v3_v3v3(tvec,orig,v0);
+
+		//calculate U parameter and test bounds
+		u = dot_v3v3(tvec,pvec);
+		if ( u < 0.0f || u > det) return 0;
+
+
+		//prepare to test V parameter
+		cross_v3_v3v3(qvec,tvec,edge1);
+
+		//calculate V parameter and test bounds
+		v = dot_v3v3(dir,qvec);
+		if ( v < 0.0f || u + v > det) return 0;
+		return 1;
+	}
+
 int isect_ray_tri_epsilon_v3(float p1[3], float d[3], float v0[3], float
v1[3], float v2[3], float *lambda, float *uv, float epsilon)
 {
     float p[3], s[3], e1[3], e2[3], q[3];
     float a, f, u, v;
-
+
     sub_v3_v3v3(e1, v1, v0);
     sub_v3_v3v3(e2, v2, v0);

@@ -491,7 +549,7 @@
         uv[1]= v;
     }

-    return 1;
+	return 1;
 }

 int isect_ray_tri_threshold_v3(float p1[3], float d[3], float v0[3],
float v1[3], float v2[3], float *lambda, float *uv, float threshold)
Index: source/blender/blenlib/intern/pbvh.c
===================================================================
--- source/blender/blenlib/intern/pbvh.c	(revision 32564)
+++ source/blender/blenlib/intern/pbvh.c	(working copy)
@@ -29,6 +29,7 @@
 #include "BLI_math.h"
 #include "BLI_ghash.h"
 #include "BLI_pbvh.h"
+#include "BLI_editVert.h"

 #include "BKE_DerivedMesh.h"
 #include "BKE_mesh.h" /* for mesh_calc_normals */
@@ -38,11 +39,12 @@

 #define LEAF_LIMIT 10000

+#include
"C:\Blender_Build\blenderSVN\source\blender\editors\include\ED_mesh.h"
+
 //#define PERFCNTRS

-/* Bitmap */
-typedef char* BLI_bitmap;

+
 BLI_bitmap BLI_bitmap_new(int tot)
 {
 	return MEM_callocN((tot >> 3) + 1, "BLI bitmap");
@@ -63,79 +65,8 @@
 	b[index >> 3] &= ~(1 << (index & 7));
 }

-/* Axis-aligned bounding box */
-typedef struct {
-	float bmin[3], bmax[3];
-} BB;

-/* Axis-aligned bounding box with centroid */
-typedef struct {
-	float bmin[3], bmax[3], bcentroid[3];
-} BBC;

-struct PBVHNode {
-	/* Opaque handle for drawing code */
-	void *draw_buffers;
-
-	int *vert_indices;
-
-	/* Voxel bounds */
-	BB vb;
-	BB orig_vb;
-
-	/* For internal nodes */
-	int children_offset;
-
-	/* Pointer into bvh prim_indices */
-	int *prim_indices;
-	int *face_vert_indices;
-
-	unsigned int totprim;
-	unsigned int uniq_verts, face_verts;
-
-	char flag;
-
-	float tmin; // used for raycasting, is how close bb is to the ray point
-
-	int proxy_count;
-	PBVHProxyNode* proxies;
-};
-
-struct PBVH {
-	PBVHNode *nodes;
-	int node_mem_count, totnode;
-
-	int *prim_indices;
-	int totprim;
-	int totvert;
-
-	int leaf_limit;
-
-	/* Mesh data */
-	MVert *verts;
-	MFace *faces;
-
-	/* Grid Data */
-	DMGridData **grids;
-	DMGridAdjacency *gridadj;
-	void **gridfaces;
-	int totgrid;
-	int gridsize;
-
-	/* Only used during BVH build and update,
-	   don't need to remain valid after */
-	BLI_bitmap vert_bitmap;
-
-#ifdef PERFCNTRS
-	int perf_modified;
-#endif
-
-	/* flag are verts/faces deformed */
-	int deformed;
-};
-
-#define STACK_FIXED_DEPTH	100
-
 typedef struct PBVHStack {
 	PBVHNode *node;
 	int revisiting;
@@ -222,7 +153,7 @@
 		BLI_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL) {
 			BB_expand(&vb, vd.co);
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 	else {
 		BB_expand_with_bb(&vb,
@@ -383,6 +314,40 @@
 	BLI_ghash_free(map, NULL, NULL);
 }

+static void build_editmesh_leaf_node(PBVH *bvh, PBVHNode *node){
+	int i, totface, toteditverts = 0;
+	int counter = 0;
+	GHash *gh;
+	GHashIterator* ghi;
+
+	gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp,
"editverts gh");
+
+	totface= node->totprim;
+
+	/* avoid duplicated editverts using a GHash */
+	for(i = 0; i < totface; i++) {
+		EditFace *f = bvh->editfaces[node->prim_indices[i]];
+
+		if (!BLI_ghash_haskey(gh,f->v1)) BLI_ghash_insert(gh, f->v1, NULL);
+		if (!BLI_ghash_haskey(gh,f->v2)) BLI_ghash_insert(gh, f->v2, NULL);
+		if (!BLI_ghash_haskey(gh,f->v3)) BLI_ghash_insert(gh, f->v3, NULL);
+		if (f->v4) if (!BLI_ghash_haskey(gh,f->v4)) BLI_ghash_insert(gh, f->v4,
NULL); //*/
+
+	}
+	toteditverts = BLI_ghash_size(gh);
+	node->toteditverts = toteditverts;
+	node->editverts = MEM_callocN(toteditverts * sizeof(EditVert *), "node
EditVert array");
+
+	ghi = BLI_ghashIterator_new(gh);
+	for(i = 0; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi),
i++){
+		node->editverts[i]=BLI_ghashIterator_getKey(ghi);
+	}
+
+	node->flag |= PBVH_UpdateDrawBuffers;
+	BLI_ghashIterator_free(ghi);
+	BLI_ghash_free(gh, NULL, NULL);
+}
+
 static void build_grids_leaf_node(PBVH *bvh, PBVHNode *node)
 {
 	if(!G.background) {
@@ -393,6 +358,7 @@
 	node->flag |= PBVH_UpdateDrawBuffers;
 }

+
 /* Recursively build a node in the tree

    vb is the voxel box around all of the primitives contained in
@@ -428,8 +394,11 @@

 		if(bvh->faces)
 			build_mesh_leaf_node(bvh, bvh->nodes + node_index);
-		else
+		else if (bvh->grids)
 			build_grids_leaf_node(bvh, bvh->nodes + node_index);
+		else if (bvh->editfaces)
+			build_editmesh_leaf_node(bvh, bvh->nodes + node_index);
+
 		bvh->nodes[node_index].orig_vb= bvh->nodes[node_index].vb;

 		/* Done with this subtree */
@@ -479,7 +448,7 @@
 	if(totprim != bvh->totprim) {
 		bvh->totprim = totprim;
 		if(bvh->nodes) MEM_freeN(bvh->nodes);
-		if(bvh->prim_indices) MEM_freeN(bvh->prim_indices);
+		if(bvh->prim_indices) MEM_freeN(bvh->prim_indices);
 		bvh->prim_indices = MEM_callocN(sizeof(int) * totprim,
 						"bvh prim indices");
 		for(i = 0; i < totprim; ++i)
@@ -497,7 +466,8 @@
 	build_sub(bvh, 0, cb, prim_bbc, 0, totprim);
 }

-/* Do a full rebuild with on Mesh data structure */
+
+/* Do a full rebuild with on Mesh data structure, reestructurar aqui*/
 void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int
totface, int totvert)
 {
 	BBC *prim_bbc = NULL;
@@ -514,7 +484,7 @@

 	/* For each face, store the AABB and the AABB centroid */
 	prim_bbc = MEM_mallocN(sizeof(BBC) * totface, "prim_bbc");
-
+
 	for(i = 0; i < totface; ++i) {
 		MFace *f = faces + i;
 		const int sides = f->v4 ? 4 : 3;
@@ -537,6 +507,67 @@
 	MEM_freeN(bvh->vert_bitmap);
 }

+
+
+/* Do a full rebuild with on EditMesh data structure */
+void BLI_pbvh_build_editmesh(PBVH *bvh, EditFace *editfaces, EditVert
*editverts, int toteditface, int toteditvert)
+{
+	BBC *prim_bbc = NULL;
+	BB cb;
+	int i = 0;
+	EditFace *efa;
+
+	bvh->leaf_limit = LEAF_LIMIT;
+
+	BB_reset(&cb);
+
+	/* For each editface, store the AABB and the AABB centroid */
+	prim_bbc = (BBC *)MEM_mallocN(sizeof(BBC) * toteditface, "prim_bbc");
+
+	bvh->editfaces = (EditFace *)MEM_callocN(toteditface * sizeof(EditFace
*),"EditFace array");
+
+	for(efa= editfaces; efa; efa= efa->next){
+		BBC *bbc = prim_bbc + i;
+		BB_reset((BB*)bbc);
+
+		BB_expand((BB*)bbc, efa->v1->co);
+		BB_expand((BB*)bbc, efa->v2->co);
+		BB_expand((BB*)bbc, efa->v3->co);
+
+		if (efa->v4) BB_expand((BB*)bbc, efa->v4->co);
+
+		BBC_update_centroid(bbc);
+		BB_expand(&cb, bbc->bcentroid);
+		bvh->editfaces[i]= efa;
+		i++;
+	}
+
+	/* prim_bbc = (BBC *)MEM_mallocN(sizeof(BBC) * toteditvert, "prim_bbc");
+	i = 0;
+
+	 for (eve = editverts; eve; eve = eve->next){
+		BBC *bbc = prim_bbc + i;
+		BB_reset((BB*)bbc);
+
+		BB_expand((BB*)bbc, eve->co);
+
+		BBC_update_centroid(bbc);
+		BB_expand(&cb, bbc->bcentroid);
+		++i;
+		} //*/
+
+	if(toteditface)
+		pbvh_build(bvh, &cb, prim_bbc, toteditface);
+	//if(toteditvert)
+	//	pbvh_build(bvh, &cb, prim_bbc, toteditvert);
+
+	MEM_freeN(prim_bbc);
+}
+
+void BLI_pbvh_update_editmesh(PBVH *bvh, EditFace *editfaces, EditVert
*editverts, int toteditface, int toteditvert){
+
+}
+
 /* Do a full rebuild with on Grids data structure */
 void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, DMGridAdjacency
*gridadj,
 	int totgrid, int gridsize, void **gridfaces)
@@ -579,7 +610,7 @@

 PBVH *BLI_pbvh_new(void)
 {
-	PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
+	PBVH *bvh = (PBVH *)MEM_callocN(sizeof(PBVH), "pbvh");

 	return bvh;
 }
@@ -599,18 +630,23 @@
 				MEM_freeN(node->vert_indices);
 			if(node->face_vert_indices)
 				MEM_freeN(node->face_vert_indices);
+			if (node->editverts)
+				MEM_freeN(node->editverts);
 		}
 	}

 	if (bvh->deformed) {
 		if (bvh->verts) {
 			/* if pbvh was deformed, new memory was allocated for verts/faces --
free it */
-
 			MEM_freeN(bvh->verts);
-			MEM_freeN(bvh->faces);
-		}
+			MEM_freeN(bvh->faces);
+		}
 	}

+	if (bvh->editfaces){
+			MEM_freeN(bvh->editfaces);
+		}
+
 	MEM_freeN(bvh->nodes);
 	MEM_freeN(bvh->prim_indices);
 	MEM_freeN(bvh);
@@ -890,12 +926,97 @@
 static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
 	int totnode, float (*face_nors)[3])
 {
+	EditVert *eve;
 	float (*vnor)[3];
 	int n;

 	if(bvh->grids)
 		return;
+	if (bvh->editfaces){
+		return;
+		/* vnor= MEM_callocN(sizeof(float)*3*bvh->toteditvert, "bvh temp vnors");

+		#pragma omp parallel for private(n) schedule(static)
+		for(n = 0; n < totnode; n++) {
+			PBVHNode *node= nodes[n];
+
+			if((node->flag & PBVH_UpdateNormals)) {
+				int i, j, toteditface, *faces;
+
+				faces= node->prim_indices;
+				toteditface= node->totprim;
+
+				for(i = 0; i < toteditface; ++i) {
+					EditFace *f= bvh->editfaces[faces[i]];
+					float fn[3];
+					unsigned int *fv = &f->v1;
+					int sides= (f->v4)? 4: 3;
+
+					if(f->v4)
+						normal_quad_v3(fn, f->v1->co, f->v2->co,
+									   f->v3->co, f->v4->co);
+					else
+						normal_tri_v3(fn, f->v1->co, f->v2->co,
+									  f->v3->co);
+
+					for(j = 0; j < sides; ++j) {
+						int v= fv[j];
+
+						//if(bvh->editverts[v].flag & ME_VERT_PBVH_UPDATE) {
+							/* this seems like it could be very slow but profile
+							does not show this, so just leave it for now?
+							#pragma omp atomic
+							vnor[v][0] += fn[0];
+							#pragma omp atomic
+							vnor[v][1] += fn[1];
+							#pragma omp atomic
+							vnor[v][2] += fn[2];
+						//}
+					}
+
+					if(face_nors)
+						copy_v3_v3(face_nors[faces[i]], fn);
+				}
+			}
+		}
+		//----------
+		#pragma omp parallel for private(n) schedule(static)
+		for(n = 0; n < totnode; n++) {
+			PBVHNode *node= nodes[n];
+
+			if(node->flag & PBVH_UpdateNormals) {
+				int i, *verts, totvert;
+
+				verts= node->editvert_indices;
+				totvert= node->toteditverts;
+
+				for(i = 0; i < totvert; ++i) {
+					const int v = verts[i];
+					EditVert *eve= &bvh->editverts[v];
+
+					//if(eve->flag & ME_VERT_PBVH_UPDATE) {
+						float no[3];
+
+						copy_v3_v3(no, vnor[v]);
+						normalize_v3(no);
+
+						eve->no[0] = no[0];
+						eve->no[1] = no[1];
+						eve->no[2] = no[2];
+
+						//eve->flag &= ~ME_VERT_PBVH_UPDATE;
+					//}
+				}
+
+				node->flag &= ~PBVH_UpdateNormals;
+			}
+		}
+
+		MEM_freeN(vnor);
+		return;
+		//-----------//*/
+	}
+
 	/* could be per node to save some memory, but also means
 	   we have to store for each vertex which node it is in */
 	vnor= MEM_callocN(sizeof(float)*3*bvh->totvert, "bvh temp vnors");
@@ -1020,7 +1141,7 @@
 	for(n = 0; n < totnode; n++) {
 		node= nodes[n];

-		if(node->flag & PBVH_UpdateDrawBuffers) {
+		if(node->flag & PBVH_UpdateDrawBuffers) { //Mio, put here
bvh->editverts code
 			if(bvh->grids) {
 				GPU_update_grid_buffers(node->draw_buffers,
 						   bvh->grids,
@@ -1029,6 +1150,14 @@
 						   bvh->gridsize,
 						   smooth);
 			}
+			else if (bvh->editfaces){ //Mio
+				//GPU_update_editmesh_buffers(node->draw_buffers,
+				//		   bvh->grids,
+				//		   node->vert_indices,
+				//		   node->toteditvert,
+				//		   bvh->gridsize,
+				//		   smooth);
+			}
 			else {
 				GPU_update_mesh_buffers(node->draw_buffers,
 						   bvh->verts,
@@ -1184,10 +1313,14 @@
 		if(totvert) *totvert= node->totprim*bvh->gridsize*bvh->gridsize;
 		if(uniquevert) *uniquevert= *totvert;
 	}
-	else {
+	else if (bvh->verts){
 		if(totvert) *totvert= node->uniq_verts + node->face_verts;
 		if(uniquevert) *uniquevert= node->uniq_verts;
 	}
+	else if (bvh->editfaces){
+		if (totvert) *totvert = node->toteditverts;
+		if (uniquevert) *uniquevert = *totvert;
+	}
 }

 void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int
**grid_indices, int *totgrid, int *maxgrid, int *gridsize, DMGridData
***griddata, DMGridAdjacency **gridadj)
@@ -1210,6 +1343,16 @@
 	}
 }

+void BLI_pbvh_node_get_editverts(PBVH *bvh, PBVHNode *node, int
*toteditvert)
+{
+	if(bvh->editfaces) {
+		if (toteditvert) *toteditvert = node->toteditverts;
+	}
+	else {
+		if (toteditvert) *toteditvert = 0;
+	}
+}
+
 void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
 {
 	copy_v3_v3(bb_min, node->vb.bmin);
@@ -1311,7 +1454,6 @@
 				 float *fdist)
 {
     float dist;
-
     if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2,
&dist, NULL, 0.1f) && dist < *fdist) ||
         (t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2,
t3, &dist, NULL, 0.1f) && dist < *fdist))
     {
@@ -1358,7 +1500,7 @@
 			}
 		}
 	}
-	else {
+	else if (bvh->grids){
 		int totgrid= node->totprim;
 		int gridsize= bvh->gridsize;
 		int i, x, y;
@@ -1393,8 +1535,37 @@
 				origco += gridsize*gridsize;
 		}
 	}
-
-	return hit;
+	else if (bvh->editfaces){
+		int toteditface= node->totprim;
+		int *faces= node->prim_indices;
+		int i= 0;
+		int isect;
+
+		for(i = 0; i < toteditface; i++) {
+			EditFace *f = bvh->editfaces[faces[i]];
+			f->f = 0; /* first clear UClay flags */
+			isect =0;
+			if(origco) {
+				/* intersect with backuped original coordinates
+				hit |= ray_face_intersection(ray_start, ray_normal,
+							 origco[face_verts[i*4+0]],
+							 origco[face_verts[i*4+1]],
+							 origco[face_verts[i*4+2]],
+							 f->v4? origco[face_verts[i*4+3]]: NULL,
+							 dist); */
+				//Mio, to be implemented yet
+			}
+			else {
+				/* intersect with current coordinates, here implement for local faces
only not all */
+				isect = ray_face_intersection(ray_start, ray_normal, f->v1->co,
f->v2->co, f->v3->co, f->v4 ? f->v4->co : NULL, dist);
+				hit |= isect;
+				if (isect) {
+					if (dot_v3v3(ray_normal,f->n) < 0.f) f->f |= 1; /* only detect and
subdivide front faces */	 //
+				}
+			}
+		}
+	}
+	return hit;
 }

 //#include <GL/glew.h>
@@ -1481,6 +1652,7 @@
 	bvh->gridfaces= gridfaces;
 }

+
 float (*BLI_pbvh_get_vertCos(PBVH *pbvh))[3]
 {
 	int a;
@@ -1553,8 +1725,10 @@

 		if (bvh->grids)
 			totverts = node->totprim*bvh->gridsize*bvh->gridsize;
-		else
+		else if (bvh->verts)
 			totverts = node->uniq_verts;
+		else if (bvh->editfaces)
+			totverts = node->toteditverts;

 		node->proxies[index].co= MEM_callocN(sizeof(float[3])*totverts,
"PBVHNodeProxy.co");
 	}
Index: source/blender/editors/include/ED_mesh.h
===================================================================
--- source/blender/editors/include/ED_mesh.h	(revision 32564)
+++ source/blender/editors/include/ED_mesh.h	(working copy)
@@ -102,6 +102,10 @@
 void		ED_spacetypes_init(void);
 void		ED_keymap_mesh(struct wmKeyConfig *keyconf);

+void 		make_editMeshDM(struct Scene *scene, struct Object *ob, struct
EditMesh *em);
+void 		make_editMesh_from_DerivedMesh(struct Scene *scene,struct Object
*ob,struct DerivedMesh *dm,struct EditMesh *em);
+void 		load_editMesh_external(struct Scene *scene,struct Object
*ob,struct EditMesh *em);
+void  		make_editmesh_arrays(struct EditMesh *em,struct MVert
*mvert,struct MFace *mface);
 void		make_editMesh(struct Scene *scene, struct Object *ob);
 void		load_editMesh(struct Scene *scene, struct Object *ob);
 void		remake_editMesh(struct Scene *scene, struct Object *ob);
@@ -230,9 +234,140 @@
 int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct
Object *ob, struct Mesh *me, const char *name, int active_set);
 int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct
Mesh *me);

+
+struct bContext;
+struct wmOperatorType;
+struct wmOperator;
+
+
+#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
+
+/* ******************** editface.c */
+
+int edgetag_context_check(struct Scene *scene, struct EditEdge *eed);
+void edgetag_context_set(struct Scene *scene,struct EditEdge *eed, int val);
+int edgetag_shortest_path(struct Scene *scene,struct EditMesh *em,struct
EditEdge *source,struct EditEdge *target);
+
+/* ******************* editmesh.c */
+
+extern void free_editvert(struct EditMesh *em,struct EditVert *eve);
+extern void free_editedge(struct EditMesh *em,struct EditEdge *eed);
+extern void free_editface(struct EditMesh *em,struct EditFace *efa);
+void free_editMesh(struct EditMesh *em);
+
+extern void free_vertlist(struct EditMesh *em,struct ListBase *edve);
+extern void free_edgelist(struct EditMesh *em,struct ListBase *lb);
+extern void free_facelist(struct EditMesh *em,struct ListBase *lb);
+
+extern void remedge(struct EditMesh *em,struct EditEdge *eed);
+
+extern struct EditVert *addvertlist(struct EditMesh *em, float *vec,
struct EditVert *example);
+extern struct EditEdge *addedgelist(struct EditMesh *em, struct EditVert
*v1, struct EditVert *v2, struct EditEdge *example);
+extern struct EditFace *addfacelist(struct EditMesh *em, struct EditVert
*v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct
EditFace *example, struct EditFace *exampleEdges);
+extern struct EditEdge *findedgelist(struct EditMesh *em, struct EditVert
*v1, struct EditVert *v2);
+
+void em_setup_viewcontext(struct bContext *C,struct ViewContext *vc);
+/* ******************* editmesh_lib.c */
+void EM_stats_update(struct EditMesh *em);
+
+extern void EM_fgon_flags(struct EditMesh *em);
+extern void EM_hide_reset(struct EditMesh *em);
+
+extern int faceselectedOR(struct EditFace *efa, int flag);
+extern int faceselectedAND(struct EditFace *efa, int flag);
+
+void EM_remove_selection(struct EditMesh *em, void *data, int type);
+void EM_clear_flag_all(struct EditMesh *em, int flag);
+void EM_set_flag_all(struct EditMesh *em, int flag);
+void EM_set_flag_all_selectmode(struct EditMesh *em, int flag);
+
+void EM_data_interp_from_verts(struct EditMesh *em,struct EditVert
*v1,struct EditVert *v2,struct EditVert *eve, float fac);
+void EM_data_interp_from_faces(struct EditMesh *em,struct EditFace
*efa1,struct EditFace *efa2,struct EditFace *efan, int i1, int i2, int i3,
int i4);
+
+int EM_nvertices_selected(struct EditMesh *em);
+int EM_nedges_selected(struct EditMesh *em);
+int EM_nfaces_selected(struct EditMesh *em);
+
+float EM_face_perimeter(struct EditFace *efa);
+
+void EM_store_selection(struct EditMesh *em, void *data, int type);
+
+extern struct EditFace *exist_face(struct EditMesh *em,struct EditVert
*v1,struct EditVert *v2,struct EditVert *v3,struct EditVert *v4);
+extern void flipface(struct EditMesh *em,struct EditFace *efa); // flips
for normal direction
+extern int compareface(struct EditFace *vl1,struct EditFace *vl2);
+
+/* flag for selection bits, *nor will be filled with normal for extrusion
constraint */
+/* return value defines if such normal was set */
+extern short extrudeflag_face_indiv(struct EditMesh *em, short flag,
float *nor);
+extern short extrudeflag_verts_indiv(struct EditMesh *em, short flag,
float *nor);
+extern short extrudeflag_edges_indiv(struct EditMesh *em, short flag,
float *nor);
+extern short extrudeflag_vert(struct Object *obedit,struct EditMesh *em,
short flag, float *nor, int all);
+extern short extrudeflag(struct Object *obedit,struct EditMesh *em, short
flag, float *nor, int all);
+
+extern void adduplicateflag(struct EditMesh *em, int flag);
+extern void delfaceflag(struct EditMesh *em, int flag);
+
+extern void rotateflag(struct EditMesh *em, short flag, float *cent,
float rotmat[][3]);
+extern void translateflag(struct EditMesh *em, short flag, float *vec);
+
+
+extern struct EditFace *EM_face_from_faces(struct EditMesh *em, struct
EditFace *efa1,
+										   struct EditFace *efa2, int i1, int i2, int i3, int i4);
+
+extern int EM_view3d_poll(struct bContext *C);
+
+/* ******************* editmesh_loop.c */
+
+#define LOOP_SELECT	1
+#define LOOP_CUT	2
+extern struct EditEdge *findnearestedge(struct ViewContext *vc, int *dist);
+extern void EM_automerge(struct Scene *scene,struct Object *obedit, int
update);
+void editmesh_select_by_material(struct EditMesh *em, int index);
+void EM_recalc_normal_direction(struct EditMesh *em, int inside, int
select);	/* makes faces righthand turning */
+void EM_select_more(struct EditMesh *em);
+void selectconnected_mesh_all(struct EditMesh *em);
+void faceloop_select(struct EditMesh *em,struct EditEdge *startedge, int
select);
+
+/**
+ * findnearestvert
+ *
+ * dist (in/out): minimal distance to the nearest and at the end, actual
distance
+ * sel: selection bias
+ * 		if SELECT, selected vertice are given a 5 pixel bias to make them
farter than unselect verts
+ * 		if 0, unselected vertice are given the bias
+ * strict: if 1, the vertice corresponding to the sel parameter are
ignored and not just biased
+ */
+extern struct EditVert *findnearestvert(struct ViewContext *vc, int
*dist, short sel, short strict);
+
+
+/* ******************* editmesh_tools.c */
+
+#define SUBDIV_SELECT_ORIG      0
+#define SUBDIV_SELECT_INNER     1
+#define SUBDIV_SELECT_INNER_SEL 2
+#define SUBDIV_SELECT_LOOPCUT 3
+
+/* edge subdivide corner cut types */
+#define SUBDIV_CORNER_PATH		0
+#define SUBDIV_CORNER_INNERVERT	1
+#define SUBDIV_CORNER_FAN		2
+
+
+void join_triangles(struct EditMesh *em);
+int removedoublesflag(struct EditMesh *em, short flag, short automerge,
float limit);		/* return amount */
+void esubdivideflag(struct Object *obedit,struct EditMesh *em, int flag,
float smooth, float fractal, int beautify, int numcuts, int
corner_pattern, int seltype);
+void esubdivideflag_local(struct Object *obedit,struct EditMesh *em, int
flag, float smooth, float fractal, int beautify, int numcuts, int
corner_pattern, int seltype);
+int smooth_vertex_editmesh(struct Object *obedit,struct EditMesh *em);
+void beautify_fill(struct EditMesh *em);
+void convert_to_triface_all(struct EditMesh *em, int direction);
+void fill_mesh(struct EditMesh *em);
+void addedgeface_mesh_uclay(struct EditMesh *em);
+
 #ifdef __cplusplus
 }
 #endif

+
 #endif /* ED_MESH_H */

+
Index: source/blender/editors/mesh/editmesh.c
===================================================================
--- source/blender/editors/mesh/editmesh.c	(revision 32564)
+++ source/blender/editors/mesh/editmesh.c	(working copy)
@@ -914,6 +914,431 @@
 	}
 }

+/* turns Mesh into editmesh */
+void make_editMeshDM(Scene *scene, Object *ob,struct EditMesh *em)
+{
+	Mesh *me= ob->data;
+	MFace *mface;
+	MVert *mvert;
+	MSelect *mselect;
+	KeyBlock *actkey;
+	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;
+
+	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(!paint_facesel_test(ob))
+			eve->f |= (mvert->flag & 1);
+
+		if (mvert->flag & ME_HIDE) eve->h= 1;
+		eve->no[0]= mvert->no[0]/32767.0;
+		eve->no[1]= mvert->no[1]/32767.0;
+		eve->no[2]= mvert->no[2]/32767.0;
+
+		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) {
+				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 & SELECT) eed->f |= SELECT;
+				if(medge->flag & ME_FGON) eed->h= EM_FGON;	// 2 different defines!
+				if(medge->flag & ME_HIDE) eed->h |= 1;
+				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 {
+					if (a==me->act_face) {
+						EM_set_actFace(em, efa);
+					}
+
+					/* dont allow hidden and selected */
+					if(mface->flag & ME_FACE_SEL) {
+						efa->f |= SELECT;
+
+						if(paint_facesel_test(ob)) {
+							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 */
+	}
+
+}
+
+/* turns DerivedMesh into EditMesh */
+void make_editMesh_from_DerivedMesh(struct Scene *scene,struct Object
*ob,struct DerivedMesh *dm, struct EditMesh *em)
+{
+	//Mesh *me= ob->data;
+	MFace *mface;
+	MVert *mvert;
+	KeyBlock *actkey;
+	EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
+	EditFace *efa, *efa_last_sel= NULL;
+	EditEdge *eed;
+	float *co, (*keyco)[3]= NULL;
+	int tot, a, totvert,totedge,totface, eekadoodle= 0;
+
+	totvert = dm->getNumVerts(dm);
+	totedge = dm->getNumEdges(dm);
+	totface = dm->getNumFaces(dm);
+
+	em->selectmode= scene->toolsettings->selectmode; // warning needs to be
synced
+	em->act_face = NULL;
+	em->totvert= tot= dm->getNumVerts(dm);
+	em->totedge= dm->getNumEdges(dm);
+	em->totface= dm->getNumFaces(dm);
+
+
+	if(tot==0) {
+		return;
+	}
+
+	if(ob->actcol > 0)
+		em->mat_nr= ob->actcol-1;
+
+	/* initialize fastmalloc for editmesh */
+	init_editmesh_fastmalloc(em, totvert, totedge, 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(&(dm->vertData), &em->vdata, CD_MASK_EDITMESH,
CD_CALLOC, 0); //Aqui?
+	mvert= dm->getVertArray(dm); //Aqui
+
+	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(!paint_facesel_test(ob))
+			eve->f |= (mvert->flag & 1);
+
+		if (mvert->flag & ME_HIDE) eve->h= 1;
+		eve->no[0]= mvert->no[0]/32767.0;
+		eve->no[1]= mvert->no[1]/32767.0;
+		eve->no[2]= mvert->no[2]/32767.0;
+
+		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(&(dm->vertData), &em->vdata, a, &eve->data); //Aqui
+	}
+
+	if(actkey && actkey->totelem!=totvert); //Aqui
+	else {
+		MEdge *medge= dm->getEdgeArray(dm); //Aqui
+
+		CustomData_copy(&(dm->edgeData), &em->edata, CD_MASK_EDITMESH,
CD_CALLOC, 0); //Aqui
+		/* make edges */
+		for(a=0; a<totedge; a++, medge++) { //Aqui
+			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) {
+				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 & SELECT) eed->f |= SELECT;
+				if(medge->flag & ME_FGON) eed->h= EM_FGON;	// 2 different defines!
+				if(medge->flag & ME_HIDE) eed->h |= 1;
+				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(&(dm->edgeData),&em->edata, a, &eed->data);
//Aqui
+			}
+		}
+
+		CustomData_copy(&(dm->faceData), &em->fdata, CD_MASK_EDITMESH,
CD_CALLOC, 0); //Aqui
+
+		/* make faces */
+		mface= dm->getFaceArray(dm); //Aqui
+
+		for(a=0; a<totface; a++, mface++) { //Aqui
+			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(&(dm->faceData), &em->fdata, a, &efa->data);
//Aqui
+
+				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 {
+					//if (a==me->act_face) {
+					//	EM_set_actFace(em, efa);
+					//}
+
+					/* dont allow hidden and selected */
+					if(mface->flag & ME_FACE_SEL) {
+						efa->f |= SELECT;
+
+						if(paint_facesel_test(ob)) {
+							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){ //Aqui
+		//restore editselections
+		EM_init_index_arrays(em, 1,1,1);
+		mselect = me->mselect;	//Aqui
+
+		for(a=0; a<me->totselect; a++, mselect++){ //Aqui
+			/*check if recorded selection is still valid, if so copy into
editmesh/ //Aqui
+			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 */
+	}
+
+}
+
+void  make_editmesh_arrays(EditMesh *em, MVert *mvert, MFace *mface){
+	MFace *mfaceindex;
+	MVert *mvertindex;
+	EditFace *efa;
+	float nor[3];
+
+	int i =0;
+	int a= 0;
+
+	EditVert *eve = em->verts.first;
+	while(eve) {
+		mvertindex = &((MVert *) mvert)[i];
+		VECCOPY(mvertindex->co, eve->co);
+
+		mvertindex->mat_nr= 32767;  /* what was this for, halos? */
+
+		/* vertex normal */
+		VECCOPY(nor, eve->no);
+		mul_v3_fl(nor, 32767.0);
+		VECCOPY(mvertindex->no, nor);
+
+		//eve->tmp.l = a++;  /* counter */
+
+		mvertindex->flag= 0;
+		mvertindex->flag |= (eve->f & SELECT);
+		if (eve->h) mvertindex->flag |= ME_HIDE;
+
+		mvertindex->bweight= (char)(255.0*eve->bweight);
+
+		eve= eve->next;
+		i++;
+	}
+
+	/* the faces , taken from lead_editMesh*/
+	i = 0;
+
+	efa = em->faces.first;
+	while(efa) {
+		mfaceindex = &((MFace *) mface)[i];
+
+		mfaceindex->v1= (unsigned int) efa->v1->tmp.l;
+		mfaceindex->v2= (unsigned int) efa->v2->tmp.l;
+		mfaceindex->v3= (unsigned int) efa->v3->tmp.l;
+		if (efa->v4) mfaceindex->v4 = (unsigned int) efa->v4->tmp.l;
+
+		mfaceindex->mat_nr= efa->mat_nr;
+		mfaceindex->flag= efa->flag;
+
+		i++;
+		efa= efa->next;
+	}
+	//mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+}
+
 /* makes Mesh out of editmesh */
 void load_editMesh(Scene *scene, Object *ob)
 {
@@ -1307,6 +1732,399 @@
 	mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
 }

+/* makes Mesh out of editmesh */
+void load_editMesh_external(Scene *scene, Object *ob, EditMesh *em)
+{
+	Mesh *me= ob->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, nor[3];
+	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);
+
+		mvert->mat_nr= 32767;  /* what was this for, halos? */
+
+		/* vertex normal */
+		VECCOPY(nor, eve->no);
+		mul_v3_fl(nor, 32767.0);
+		VECCOPY(mvert->no, nor);
+
+		/* 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.0*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.0*eed->crease);
+		medge->bweight= (char)(255.0*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;
+		}
+
+		/* mat_nr in vertex */
+		if(me->totcol>1) {
+			mvert= me->mvert+mface->v1;
+			if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr;
+			mvert= me->mvert+mface->v2;
+			if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr;
+			mvert= me->mvert+mface->v3;
+			if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr;
+			if(mface->v4) {
+				mvert= me->mvert+mface->v4;
+				if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr;
+			}
+		}
+
+		/* 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 i,j;
+
+		for (ob=G.main->object.first; ob; ob=ob->id.next) {
+			if (ob->parent==ob && 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 */
+				i=0;
+				ofs= MEM_callocN(sizeof(float) * 3 * em->totvert,  "currkey->data");
+				eve= em->verts.first;
+				mvert = me->mvert;
+				while(eve) {
+					VECSUB(ofs[i], mvert->co, oldverts[eve->keyindex].co);
+					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);
+}
+
 void remake_editMesh(Scene *scene, Object *ob)
 {
 	make_editMesh(scene, ob);
Index: source/blender/editors/mesh/editmesh_add.c
===================================================================
--- source/blender/editors/mesh/editmesh_add.c	(revision 32564)
+++ source/blender/editors/mesh/editmesh_add.c	(working copy)
@@ -824,7 +824,124 @@
 		recalc_editnormals(em);
 	}
 	}
+
+void addedgeface_mesh_uclay(EditMesh *em)
+{
+	EditVert *eve, *neweve[4];
+	EditEdge *eed;
+	EditFace *efa;
+	short amount=0;

+	/* how many selected ? */
+	if(em->selectmode & SCE_SELECT_EDGE) {
+		/* in edge mode finding selected vertices means flushing down edge
codes... */
+		/* can't make face with only edge selection info... */
+		EM_selectmode_set(em);
+	}
+
+	for(eve= em->verts.first; eve; eve= eve->next) {
+		if(eve->f & SELECT) {
+			amount++;
+			if(amount>4) break;
+			neweve[amount-1]= eve;
+		}
+	}
+
+	if(amount==2) {
+		eed= addedgelist(em, neweve[0], neweve[1], NULL);
+		EM_select_edge(eed, 1);
+
+		// XXX		DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+		return;
+	}
+	else if(amount > 4) {
+		addfaces_from_edgenet(em);
+		return;
+	}
+	else if(amount<2) {
+	//	BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make
an edge/face");
+		return;
+	}
+
+	efa= NULL; // check later
+
+	if(amount==3) {
+
+		if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], NULL)==0) {
+			efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
+			EM_select_face(efa, 1);
+		}
+	//	else BKE_report(op->reports, RPT_ERROR, "The selected vertices
already form a face");
+	}
+	else if(amount==4) {
+		/* this test survives when theres 2 triangles */
+		if(exist_face(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+			int tria= 0;
+
+			/* remove trias if they exist, 4 cases.... */
+			if(exist_face(em, neweve[0], neweve[1], neweve[2], NULL)) tria++;
+			if(exist_face(em, neweve[0], neweve[1], neweve[3], NULL)) tria++;
+			if(exist_face(em, neweve[0], neweve[2], neweve[3], NULL)) tria++;
+			if(exist_face(em, neweve[1], neweve[2], neweve[3], NULL)) tria++;
+
+			if(tria==2) join_triangles(em);
+			else if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2],
neweve[3])==0) {
+				 /* If there are 4 Verts, But more selected edges, we need to call
addfaces_from_edgenet */
+					EditEdge *eedcheck;
+					int count;
+					count = 0;
+					for(eedcheck= em->edges.first; eedcheck; eedcheck= eedcheck->next) {
+						if(eedcheck->f & SELECT) {
+							count++;
+						}
+					}
+
+				if(count++ > 4){
+					addfaces_from_edgenet(em);
+					return;
+				} else {
+				/* if 4 edges exist, we just create the face, convex or not */
+					efa= addface_from_edges(em);
+					if(efa==NULL) {
+
+						/* the order of vertices can be anything, 6 cases to check */
+						if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co,
neweve[3]->co) ) {
+							efa= addfacelist(em, neweve[0], neweve[1], neweve[2], neweve[3],
NULL, NULL);
+						}
+						else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co,
neweve[1]->co) ) {
+							efa= addfacelist(em, neweve[0], neweve[2], neweve[3], neweve[1],
NULL, NULL);
+						}
+						else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co,
neweve[3]->co) ) {
+							efa= addfacelist(em, neweve[0], neweve[2], neweve[1], neweve[3],
NULL, NULL);
+						}
+						else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co,
neweve[2]->co) ) {
+							efa= addfacelist(em, neweve[0], neweve[1], neweve[3], neweve[2],
NULL, NULL);
+						}
+						else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co,
neweve[1]->co) ) {
+							efa= addfacelist(em, neweve[0], neweve[3], neweve[2], neweve[1],
NULL, NULL);
+						}
+						else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co,
neweve[2]->co) ) {
+							efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2],
NULL, NULL);
+						}
+					//	else BKE_report(op->reports, RPT_ERROR, "cannot find nice quad
from concave set of vertices");
+
+					}
+				}
+			}
+		//	else BKE_report(op->reports, RPT_ERROR, "The selected vertices
already form a face");
+		}
+	//	else BKE_report(op->reports, RPT_ERROR, "The selected vertices
already form a face");
+	}
+
+	if(efa) {
+		EM_select_face(efa, 1);
+
+		fix_new_face(em, efa);
+
+		recalc_editnormals(em);
+	}
+	}
+
 static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
 {
 	Object *obedit= CTX_data_edit_object(C);
Index: source/blender/editors/mesh/editmesh_mods.c
===================================================================
--- source/blender/editors/mesh/editmesh_mods.c	(revision 32564)
+++ source/blender/editors/mesh/editmesh_mods.c	(working copy)
@@ -4425,6 +4425,144 @@
 	RNA_def_boolean(ot->srna, "zaxis", 1, "Z-Axis", "Smooth along the Z
axis.");
 }

+int smooth_vertex_editmesh(Object *obedit, EditMesh *em) //Mio
+{
+	EditVert *eve, *eve_mir = NULL;
+	EditEdge *eed;
+	float *adror, *adr, fac;
+	float fvec[3];
+	int teller=0;
+	ModifierData *md;
+	int index;
+
+	/* count */
+	eve= em->verts.first;
+	while(eve) {
+		teller++; //if(eve->f & SELECT)
+		eve= eve->next;
+	}
+	if(teller==0) {
+		BKE_mesh_end_editmesh(obedit->data, em);
+		return OPERATOR_CANCELLED;
+	}
+
+	adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
+	eve= em->verts.first;
+	while(eve) {
+		 { //if(eve->f & SELECT)
+			eve->tmp.p = (void*)adr;
+			eve->f1= 0;
+			eve->f2= 0;
+			adr+= 3;
+		}
+		eve= eve->next;
+	}
+
+	/* if there is a mirror modifier with clipping, flag the verts that
+	 * are within tolerance of the plane(s) of reflection
+	 */
+	for(md=obedit->modifiers.first; md; md=md->next) {
+		if(md->type==eModifierType_Mirror) {
+			MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+			if(mmd->flag & MOD_MIR_CLIPPING) {
+				for (eve= em->verts.first; eve; eve= eve->next) {
+					 { //if(eve->f & SELECT)
+
+						switch(mmd->axis){
+							case 0:
+								if (fabs(eve->co[0]) < mmd->tolerance)
+									eve->f2 |= 1;
+								break;
+							case 1:
+								if (fabs(eve->co[1]) < mmd->tolerance)
+									eve->f2 |= 2;
+								break;
+							case 2:
+								if (fabs(eve->co[2]) < mmd->tolerance)
+									eve->f2 |= 4;
+								break;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	eed= em->edges.first;
+	while(eed) { //count selected times
+		 { //if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) )
+			fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
+			fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
+			fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
+
+			if( eed->v1->f1<255) { //(eed->v1->f & SELECT) &&
+				eed->v1->f1++;
+				add_v3_v3(eed->v1->tmp.p, fvec);
+			}
+			if( eed->v2->f1<255) { //(eed->v2->f & SELECT) &&
+				eed->v2->f1++;
+				add_v3_v3(eed->v2->tmp.p, fvec);
+			}
+		}
+		eed= eed->next;
+	}
+
+	index= 0;
+	eve= em->verts.first;
+	while(eve) {
+		 { //if(eve->f & SELECT)
+			if(eve->f1) {
+
+
+				if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
+					eve_mir= editmesh_get_x_mirror_vert(obedit, em, eve, eve->co, index);
+				}
+
+				adr = eve->tmp.p;
+				fac= 0.5/(float)eve->f1;
+
+				eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
+				eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
+				eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
+
+				/* clip if needed by mirror modifier */
+				if (eve->f2) {
+					if (eve->f2 & 1) {
+						eve->co[0]= 0.0f;
+					}
+					if (eve->f2 & 2) {
+						eve->co[1]= 0.0f;
+					}
+					if (eve->f2 & 4) {
+						eve->co[2]= 0.0f;
+					}
+				}
+
+				if (eve_mir) {
+					eve_mir->co[0]=-eve->co[0];
+					eve_mir->co[1]= eve->co[1];
+					eve_mir->co[2]= eve->co[2];
+				}
+
+			}
+			eve->tmp.p= NULL;
+		}
+		index++;
+		eve= eve->next;
+	}
+	MEM_freeN(adror);
+
+	recalc_editnormals(em);
+
+	BKE_mesh_end_editmesh(obedit->data, em);
+
+	//DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+	//WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+	return OPERATOR_FINISHED;
+}
+
 void vertexnoise(Object *obedit, EditMesh *em)
 {
 	Material *ma;
@@ -4612,3 +4750,4 @@
 	RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
 }

+
Index: source/blender/editors/mesh/editmesh_tools.c
===================================================================
--- source/blender/editors/mesh/editmesh_tools.c	(revision 32564)
+++ source/blender/editors/mesh/editmesh_tools.c	(working copy)
@@ -171,6 +171,44 @@

 }

+void convert_to_triface_all(EditMesh *em, int direction)
+{
+	EditFace *efa, *efan, *next;
+	float fac;
+
+	efa= em->faces.last;
+	while(efa) {
+		next= efa->prev;
+		if(efa->v4) {
+			//if(efa->f & SELECT) {
+				/* choose shortest diagonal for split */
+				fac= len_v3v3(efa->v1->co, efa->v3->co) - len_v3v3(efa->v2->co,
efa->v4->co);
+				/* this makes sure exact squares get split different in both cases */
+				if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
+					efan= EM_face_from_faces(em, efa, NULL, 0, 1, 2, -1);
+					if(efa->f & SELECT) EM_select_face(efan, 1);
+					efan= EM_face_from_faces(em, efa, NULL, 0, 2, 3, -1);
+					if(efa->f & SELECT) EM_select_face(efan, 1);
+				}
+				else {
+					efan= EM_face_from_faces(em, efa, NULL, 0, 1, 3, -1);
+					if(efa->f & SELECT) EM_select_face(efan, 1);
+					efan= EM_face_from_faces(em, efa, NULL, 1, 2, 3, -1);
+					if(efa->f & SELECT) EM_select_face(efan, 1);
+				}
+
+				BLI_remlink(&em->faces, efa);
+				free_editface(em, efa);
+			//}
+		}
+		efa= next;
+	}
+
+	EM_fgon_flags(em);	// redo flags and indices for fgons
+
+
+}
+
 int removedoublesflag(EditMesh *em, short flag, short automerge, float
limit)		/* return amount */
 {
 	/*
@@ -2967,6 +3005,165 @@
 	recalc_editnormals(em);
 }

+//------------
+void esubdivideflag_local(Object *obedit, EditMesh *em, int flag, float
smooth, float fractal, int beauty, int numcuts, int corner_pattern, int
seltype)
+{
+	EditFace *ef;
+	EditEdge *eed, *cedge;
+	EditVert **templist;
+	struct GHash *gh;
+	int i,edgecount, facetype;
+	ModifierData *md= obedit->modifiers.first;
+	int ctrl= 0; // XXX
+
+	// We store an array of verts for each edge that is subdivided,
+	// we put this array as a value in a ghash which is keyed by the EditEdge*
+
+	gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp,
"subdivideedgenum gh");
+	//Flush vertex flags upward to the edges
+	// So for each edge, if it is selected, we allocate an array of size cuts+2
+	// so we can have a place for the v1, the new verts and v2
+	for(eed = em->edges.first;eed;eed = eed->next) {
+		eed->f2 = 0;
+		if(eed->f & flag) {
+			eed->f2	|= EDGEOLD;
+
+			templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
+			templist[0] = eed->v1;
+			for(i=0;i<numcuts;i++) {
+				// This function creates the new vert and returns it back
+				// to the array
+				templist[i+1] = subdivideedgenum(em, eed, i+1, numcuts, smooth,
fractal, beauty);
+				//while we are here, we can copy edge info from the original edge
+				cedge = addedgelist(em, templist[i],templist[i+1],eed);
+				// Also set the edge f2 to EDGENEW so that we can use this info later
+				templist[i+1]->f1 = SELECT; //set for uclay smooth
+				cedge->f2 = EDGENEW;
+			}
+			templist[i+1] = eed->v2;
+			//Do the last edge too
+			cedge = addedgelist(em, templist[i],templist[i+1],eed);
+			cedge->f2 = EDGENEW;
+			// Now that the edge is subdivided, we can put its verts in the ghash
+			BLI_ghash_insert(gh, eed, templist);
+		}
+	}
+
+	/*/ Now for each face in the mesh we need to figure out How many edges
were cut
+	// and which filling method to use for that face */
+	for(ef = em->faces.first;ef;ef = ef->next) {
+		edgecount = 0;
+		facetype = 3;
+		if(ef->e1->f & flag) {edgecount++;}
+		if(ef->e2->f & flag) {edgecount++;}
+		if(ef->e3->f & flag) {edgecount++;}
+		if(ef->v4) {
+			facetype = 4;
+			if(ef->e4->f & flag) {edgecount++;}
+		}
+		if(facetype == 4) {
+			switch(edgecount) {
+				case 0:
+					break;
+
+				case 1:
+					ef->f1 = SELECT;
+					fill_quad_single(em, ef, gh, numcuts, seltype);
+					break;
+				case 2: ef->f1 = SELECT;
+					// if there are 2, we check if edge 1 and 3 are either both on or
off that way
+					// we can tell if the selected pair is Adjacent or Opposite of each
other
+					if((ef->e1->f & flag && ef->e3->f & flag) ||
+					   (ef->e2->f & flag && ef->e4->f & flag)) {
+						fill_quad_double_op(em, ef, gh, numcuts);
+					}else{
+						switch(corner_pattern) {
+							case 0:	fill_quad_double_adj_path(em, ef, gh, numcuts); break;
+							case 1:	fill_quad_double_adj_inner(em, ef, gh, numcuts); break;
+							case 2:	fill_quad_double_adj_fan(em, ef, gh, numcuts); break;
+						}
+					}
+					break;
+				case 3: ef->f1 = SELECT;
+					fill_quad_triple(em, ef, gh, numcuts);
+					break;
+				case 4: ef->f1 = SELECT;
+					fill_quad_quadruple(em, ef, gh, numcuts, smooth, fractal, beauty);
+					break;
+			}
+		} else {
+			switch(edgecount) {
+				case 0: break;
+				case 1: ef->f1 = SELECT;
+					fill_tri_single(em, ef, gh, numcuts, seltype);
+					break;
+				case 2: ef->f1 = SELECT;
+					fill_tri_double(em, ef, gh, numcuts);
+					break;
+				case 3: ef->f1 = SELECT;
+					fill_tri_triple(em, ef, gh, numcuts, smooth, fractal, beauty);
+					break;
+			}
+		}
+	}
+
+	// Delete Old Edges and Faces
+	for(eed = em->edges.first;eed;eed = eed->next) {
+		if(BLI_ghash_haskey(gh,eed)) {
+			eed->f1 = SELECT;
+		} else {
+			eed->f1 = 0;
+		}
+	}
+	free_tagged_edges_faces(em, em->edges.first, em->faces.first);
+
+	if(seltype == SUBDIV_SELECT_ORIG  && !ctrl) {
+		// bugfix: vertex could get flagged as "not-selected"
+		// solution: clear flags before, not at the same time as setting SELECT
flag -dg
+
+		for(eed = em->edges.first;eed;eed = eed->next) {
+			if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) {
+				eed->f &= !flag;
+				EM_select_edge(eed,0);
+			}
+		}
+		for(eed = em->edges.first;eed;eed = eed->next) {
+			if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) {
+				eed->f |= flag;
+				EM_select_edge(eed,1);
+			}
+		}
+	} else if ((seltype == SUBDIV_SELECT_INNER || seltype ==
SUBDIV_SELECT_INNER_SEL)|| ctrl) {
+		for(eed = em->edges.first;eed;eed = eed->next) {
+			if(eed->f2 & EDGEINNER) {
+				eed->f |= flag;
+				EM_select_edge(eed,1);
+				if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT;
+				if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT;
+			}else{
+				eed->f &= !flag;
+				EM_select_edge(eed,0);
+			}
+		}
+	} else if(seltype == SUBDIV_SELECT_LOOPCUT){
+		for(eed = em->edges.first;eed;eed = eed->next) {
+			if(eed->f2 & DOUBLEOPFILL){
+				eed->f |= flag;
+				EM_select_edge(eed,1);
+			}else{
+				eed->f &= !flag;
+				EM_select_edge(eed,0);
+			}
+		}
+	}
+
+	// Free the ghash and call MEM_freeN on all the value entries to return
+	// that memory
+	BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+
+	recalc_editnormals(em);
+}
+
 static int count_selected_edges(EditEdge *ed)
 {
 	int totedge = 0;
@@ -3123,7 +3320,7 @@
 }

 /** remove and free list of tagged edges and faces */
-static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace
*efa)
+void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa)
 {
 	EditEdge *nexted;
 	EditFace *nextvl;
@@ -6778,7 +6975,7 @@

 /* note; the EM_selectmode_set() calls here illustrate how badly
constructed it all is... from before the
 edge/face flags, with very mixed results.... */
-static void beautify_fill(EditMesh *em)
+void beautify_fill(EditMesh *em)
 {
 	EditVert *v1, *v2, *v3, *v4;
 	EditEdge *eed, *nexted;
@@ -6942,7 +7139,7 @@

 /* Got this from scanfill.c. You will need to juggle around the
 * callbacks for the scanfill.c code a bit for this to work. */
-static void fill_mesh(EditMesh *em)
+void fill_mesh(EditMesh *em)
 {
 	EditVert *eve,*v1;
 	EditEdge *eed,*e1,*nexted;
Index: source/blender/editors/mesh/mesh_intern.h
===================================================================
--- source/blender/editors/mesh/mesh_intern.h	(revision 32564)
+++ source/blender/editors/mesh/mesh_intern.h	(working copy)
@@ -32,39 +32,9 @@
 #ifndef MESH_INTERN_H
 #define MESH_INTERN_H

-struct bContext;
-struct wmOperatorType;
-struct wmOperator;
+extern EnumPropertyItem corner_type_items[];


-#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
-
-/* ******************** editface.c */
-
-int edgetag_context_check(Scene *scene, EditEdge *eed);
-void edgetag_context_set(Scene *scene, EditEdge *eed, int val);
-int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source,
EditEdge *target);
-
-/* ******************* editmesh.c */
-
-extern void free_editvert(EditMesh *em, EditVert *eve);
-extern void free_editedge(EditMesh *em, EditEdge *eed);
-extern void free_editface(EditMesh *em, EditFace *efa);
-void free_editMesh(EditMesh *em);
-
-extern void free_vertlist(EditMesh *em, ListBase *edve);
-extern void free_edgelist(EditMesh *em, ListBase *lb);
-extern void free_facelist(EditMesh *em, ListBase *lb);
-
-extern void remedge(EditMesh *em, EditEdge *eed);
-
-extern struct EditVert *addvertlist(EditMesh *em, float *vec, struct
EditVert *example);
-extern struct EditEdge *addedgelist(EditMesh *em, struct EditVert *v1,
struct EditVert *v2, struct EditEdge *example);
-extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1,
struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct
EditFace *example, struct EditFace *exampleEdges);
-extern struct EditEdge *findedgelist(EditMesh *em, struct EditVert *v1,
struct EditVert *v2);
-
-void em_setup_viewcontext(struct bContext *C, ViewContext *vc);
-
 void MESH_OT_separate(struct wmOperatorType *ot);

 /* ******************* editmesh_add.c */
@@ -85,61 +55,7 @@
 void MESH_OT_fgon_make(struct wmOperatorType *ot);
 void MESH_OT_fgon_clear(struct wmOperatorType *ot);

-/* ******************* editmesh_lib.c */
-void EM_stats_update(EditMesh *em);

-extern void EM_fgon_flags(EditMesh *em);
-extern void EM_hide_reset(EditMesh *em);
-
-extern int faceselectedOR(EditFace *efa, int flag);
-extern int faceselectedAND(EditFace *efa, int flag);
-
-void EM_remove_selection(EditMesh *em, void *data, int type);
-void EM_clear_flag_all(EditMesh *em, int flag);
-void EM_set_flag_all(EditMesh *em, int flag);
-void EM_set_flag_all_selectmode(EditMesh *em, int flag);
-
-void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2,
EditVert *eve, float fac);
-void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace
*efa2, EditFace *efan, int i1, int i2, int i3, int i4);
-
-int EM_nvertices_selected(EditMesh *em);
-int EM_nedges_selected(EditMesh *em);
-int EM_nfaces_selected(EditMesh *em);
-
-float EM_face_perimeter(EditFace *efa);
-
-void EM_store_selection(EditMesh *em, void *data, int type);
-
-extern EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2,
EditVert *v3, EditVert *v4);
-extern void flipface(EditMesh *em, EditFace *efa); // flips for normal
direction
-extern int compareface(EditFace *vl1, EditFace *vl2);
-
-/* flag for selection bits, *nor will be filled with normal for extrusion
constraint */
-/* return value defines if such normal was set */
-extern short extrudeflag_face_indiv(EditMesh *em, short flag, float *nor);
-extern short extrudeflag_verts_indiv(EditMesh *em, short flag, float *nor);
-extern short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor);
-extern short extrudeflag_vert(Object *obedit, EditMesh *em, short flag,
float *nor, int all);
-extern short extrudeflag(Object *obedit, EditMesh *em, short flag, float
*nor, int all);
-
-extern void adduplicateflag(EditMesh *em, int flag);
-extern void delfaceflag(EditMesh *em, int flag);
-
-extern void rotateflag(EditMesh *em, short flag, float *cent, float
rotmat[][3]);
-extern void translateflag(EditMesh *em, short flag, float *vec);
-
-extern int convex(float *v1, float *v2, float *v3, float *v4);
-
-extern struct EditFace *EM_face_from_faces(EditMesh *em, struct EditFace
*efa1,
-										   struct EditFace *efa2, int i1, int i2, int i3, int i4);
-
-extern int EM_view3d_poll(struct bContext *C);
-
-/* ******************* editmesh_loop.c */
-
-#define LOOP_SELECT	1
-#define LOOP_CUT	2
-
 void MESH_OT_knife_cut(struct wmOperatorType *ot);

 /* ******************* editmesh_mods.c */
@@ -169,46 +85,9 @@
 void MESH_OT_solidify(struct wmOperatorType *ot);
 void MESH_OT_select_nth(struct wmOperatorType *ot);

+int EdgeSlide(struct EditMesh *em, struct wmOperator *op, short
immediate, float imperc);
+extern int convex(float *v1, float *v2, float *v3, float *v4);

-extern EditEdge *findnearestedge(ViewContext *vc, int *dist);
-extern void EM_automerge(Scene *scene, Object *obedit, int update);
-void editmesh_select_by_material(EditMesh *em, int index);
-void EM_recalc_normal_direction(EditMesh *em, int inside, int select);	/*
makes faces righthand turning */
-void EM_select_more(EditMesh *em);
-void selectconnected_mesh_all(EditMesh *em);
-void faceloop_select(EditMesh *em, EditEdge *startedge, int select);
-
-/**
- * findnearestvert
- *
- * dist (in/out): minimal distance to the nearest and at the end, actual
distance
- * sel: selection bias
- * 		if SELECT, selected vertice are given a 5 pixel bias to make them
farter than unselect verts
- * 		if 0, unselected vertice are given the bias
- * strict: if 1, the vertice corresponding to the sel parameter are
ignored and not just biased
- */
-extern EditVert *findnearestvert(ViewContext *vc, int *dist, short sel,
short strict);
-
-
-/* ******************* editmesh_tools.c */
-
-#define SUBDIV_SELECT_ORIG      0
-#define SUBDIV_SELECT_INNER     1
-#define SUBDIV_SELECT_INNER_SEL 2
-#define SUBDIV_SELECT_LOOPCUT 3
-
-/* edge subdivide corner cut types */
-#define SUBDIV_CORNER_PATH		0
-#define SUBDIV_CORNER_INNERVERT	1
-#define SUBDIV_CORNER_FAN		2
-
-extern EnumPropertyItem corner_type_items[];
-
-void join_triangles(EditMesh *em);
-int removedoublesflag(EditMesh *em, short flag, short automerge, float
limit);		/* return amount */
-void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth,
float fractal, int beautify, int numcuts, int corner_pattern, int
seltype);
-int EdgeSlide(EditMesh *em, struct wmOperator *op, short immediate, float
imperc);
-
 void MESH_OT_merge(struct wmOperatorType *ot);
 void MESH_OT_subdivide(struct wmOperatorType *ot);
 void MESH_OT_remove_doubles(struct wmOperatorType *ot);
@@ -258,3 +137,4 @@

 #endif // MESH_INTERN_H

+
Index: source/blender/editors/sculpt_paint/sculpt.c
===================================================================
--- source/blender/editors/sculpt_paint/sculpt.c	(revision 32564)
+++ source/blender/editors/sculpt_paint/sculpt.c	(working copy)
@@ -127,12 +127,38 @@
 	return NULL;
 }

+/* Sculpt mode handles unlimited clay differently from regular meshes,
but only if
+   it's the last modifier on the stack and it is not on the first level */
+struct UClayModifierData *sculpt_uclay_active(Scene *scene, Object *ob)
+{
+	Mesh *me= (Mesh*)ob->data;
+	ModifierData *md, *nmd;
+
+	for(md= modifiers_getVirtualModifierList(ob); md; md= md->next) {
+		if(md->type == eModifierType_UClay) {
+			UClayModifierData *ucmd= (UClayModifierData*)md;
+
+			/* Check if any of the modifiers after multires are active
+			 * if not it can use the multires struct */
+			for(nmd= md->next; nmd; nmd= nmd->next)
+				if(modifier_isEnabled(scene, nmd, eModifierMode_Realtime))
+					break;
+
+			if(!nmd )
+				return ucmd;
+		}
+	}
+
+	return NULL;
+}
+
+
 /* Checks whether full update mode (slower) needs to be used to work with
modifiers */
 int sculpt_modifiers_active(Scene *scene, Object *ob)
 {
 	ModifierData *md;
 	MultiresModifierData *mmd= sculpt_multires_active(scene, ob);
-
+
 	/* check if there are any modifiers after what we are sculpting,
 	   for a multires modifier with a deform modifier in front, we
 	   do no need to recalculate the modifier stack. note that this
@@ -167,65 +193,8 @@

    For descriptions of these settings, check the operator properties.
 */
-typedef struct StrokeCache {
-	/* Invariants */
-	float initial_radius;
-	float scale[3];
-	int flag;
-	float clip_tolerance[3];
-	float initial_mouse[2];

-	/* Variants */
-	float radius;
-	float radius_squared;
-	//float traced_location[3];
-	float true_location[3];
-	float location[3];

-	float pen_flip;
-	float invert;
-	float pressure;
-	float mouse[2];
-	float bstrength;
-	float tex_mouse[2];
-
-	/* The rest is temporary storage that isn't saved as a property */
-
-	int first_time; /* Beginning of stroke may do some things special */
-
-	bglMats *mats;
-
-	/* Clean this up! */
-	ViewContext *vc;
-	Brush *brush;
-
-	float (*face_norms)[3]; /* Copy of the mesh faces' normals */
-	float special_rotation; /* Texture rotation (radians) for anchored and
rake modes */
-	int pixel_radius, previous_pixel_radius;
-	float grab_delta[3], grab_delta_symmetry[3];
-	float old_grab_location[3], orig_grab_location[3];
-
-	int symmetry; /* Symmetry index between 0 and 7 bit combo 0 is Brush only;
-		1 is X mirror; 2 is Y mirror; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is
XYZ */
-	int mirror_symmetry_pass; /* the symmetry pass we are currently on
between 0 and 7*/
-	float true_view_normal[3];
-	float view_normal[3];
-	float last_area_normal[3];
-	float last_center[3];
-	int radial_symmetry_pass;
-	float symm_rot_mat[4][4];
-	float symm_rot_mat_inv[4][4];
-	float last_rake[2]; /* Last location of updating rake rotation */
-	int original;
-
-	float vertex_rotation;
-
-	char saved_active_brush_name[24];
-	int alt_smooth;
-
-	float plane_trim_squared;
-} StrokeCache;
-
 /* ===== OPENGL =====
  *
  * Simple functions to get data from the GL
@@ -891,7 +860,7 @@
 					add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BLI_pbvh_vertex_iter_end(vd);
 		}
 		else {
 			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -907,7 +876,7 @@
 					}
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BLI_pbvh_vertex_iter_end(vd);
 		}

 		#pragma omp critical
@@ -1039,11 +1008,10 @@

 			sculpt_clip(sd, ss, vd.co, val);

-			if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+			if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 		}
 	}
-	BLI_pbvh_vertex_iter_end;
+	BLI_pbvh_vertex_iter_end(vd);
 }

 static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss,
PBVHNode *node, float bstrength)
@@ -1195,7 +1163,9 @@
 	int n;

 	calc_sculpt_normal(sd, ss, area_normal, nodes, totnode);
+

+
 	/* offset with as much as possible factored in already */
 	mul_v3_v3fl(offset, area_normal, ss->cache->radius);
 	mul_v3_v3(offset, ss->cache->scale);
@@ -1218,13 +1188,12 @@
 				/* offset vertex */
 				float fade = tex_strength(ss, brush, vd.co,
test.dist)*frontface(brush, area_normal, vd.no, vd.fno);

-				mul_v3_v3fl(proxy[vd.i], offset, fade);
-
-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				mul_v3_v3fl(proxy[vd.i], offset, fade);
+
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1283,11 +1252,10 @@

 				add_v3_v3v3(proxy[vd.i], val1, val2);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1315,11 +1283,10 @@
 				sub_v3_v3v3(val, test.location, vd.co);
 				mul_v3_v3fl(proxy[vd.i], val, fade);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 				}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1367,11 +1334,10 @@

 				mul_v3_v3fl(proxy[vd.i], grab_delta, fade);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1407,11 +1373,10 @@

 				mul_v3_v3fl(proxy[vd.i], cono, fade);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1455,11 +1420,10 @@

 				mul_v3_v3fl(proxy[vd.i], grab_delta, fade);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1502,11 +1466,10 @@

 				mul_v3_v3fl(proxy[vd.i], cono, fade);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1549,11 +1512,10 @@
 				sub_v3_v3(proxy[vd.i], origco[vd.i]);
 				mul_v3_fl(proxy[vd.i], fade);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1620,11 +1582,10 @@

 				sculpt_clip(sd, ss, vd.co, val);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1655,11 +1616,10 @@
 				mul_v3_fl(val, fade * ss->cache->radius);
 				mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale);

-				if(vd.mvert)
-					vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+				if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -1691,7 +1651,7 @@
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BLI_pbvh_vertex_iter_end(vd);
 		}
 		else {
 			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -1700,7 +1660,7 @@
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BLI_pbvh_vertex_iter_end(vd);
 		}

 		#pragma omp critical
@@ -1760,7 +1720,7 @@
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BLI_pbvh_vertex_iter_end(vd);
 		}
 		else {
 			BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -1781,7 +1741,7 @@
 					private_count++;
 				}
 			}
-			BLI_pbvh_vertex_iter_end;
+			BLI_pbvh_vertex_iter_end(vd);
 		}

 		#pragma omp critical
@@ -1978,12 +1938,11 @@

 					mul_v3_v3fl(proxy[vd.i], val, fade);

-					if(vd.mvert)
-						vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+					if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -2050,13 +2009,12 @@

 						mul_v3_v3fl(proxy[vd.i], val, fade);

-						if(vd.mvert)
-							vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+						if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 					}
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -2140,13 +2098,12 @@

 						mul_v3_v3fl(proxy[vd.i], val, fade);

-						if(vd.mvert)
-							vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+						if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 					}
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -2200,13 +2157,12 @@

 						mul_v3_v3fl(proxy[vd.i], val, fade);

-						if(vd.mvert)
-							vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+						if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 					}
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -2260,13 +2216,12 @@

 						mul_v3_v3fl(proxy[vd.i], val, fade);

-						if(vd.mvert)
-							vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+						if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 					}
 				}
 			}
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}
 }

@@ -2332,16 +2287,158 @@
 	}
 }

+float circle_eval(float circle_center[3], float radius_squared, float
co[3]){
+	return (circle_center[0]-co[0])*(circle_center[0]-co[0]) +
(circle_center[1]-co[1])*(circle_center[1]-co[1]) +
(circle_center[2]-co[2])*(circle_center[2]-co[2]) - radius_squared;
+}
+
+int circle_segment_test(float circle_center[3], float radius_squared,
float seg1[3], float seg2[3]){
+	float a = (seg1[0] - seg2[0])*(seg1[0] - seg2[0]) + (seg1[1] -
seg2[1])*(seg1[1] - seg2[1]) + (seg1[2] - seg2[2])*(seg1[2] - seg2[2]);
+	float b = 2.f * ( (seg2[0]-seg1[0])*(seg1[0]-circle_center[0]) +
(seg2[1]-seg1[1])*(seg1[1]-circle_center[1]) +
(seg2[2]-seg1[2])*(seg1[2]-circle_center[2]) );
+	float c = circle_center[0]*circle_center[0] +
circle_center[1]*circle_center[1] + circle_center[2]*circle_center[2] +
seg1[0]*seg1[0] + seg1[1]*seg1[1] + seg1[2]*seg1[2] - 2.f *
(circle_center[0]*seg1[0] + circle_center[1]*seg1[1] +
circle_center[2]*seg1[2]) - radius_squared;
+	float D = b*b - 4.f * a *c;
+	float u1,u2;
+
+	if ( D >= 0) {
+		u1 = (-b + sqrtf(D))/(2.f * a);
+		u2 = (-b - sqrtf(D))/(2.f * a);
+		if ((u1 >= 0.f && u1<= 1.f) || (u2 >= 0.f && u2 <= 1.f)) return 1;
//segment intersect at two points the sphere or one point is inside the
sphere
+		if ((u1 < 0.f && u2 >1.f) || (u2 < 0.f && u1 >1.f)) return 1; //segment
inside the sphere
+	}
+	else return 0;
+}
+
+static int circle_face_intersection(float circle_center[3], float radius,
struct EditFace *f){
+	if (circle_eval(circle_center, radius, f->v1->co) <= 0) return 1;
+	if (circle_eval(circle_center, radius, f->v2->co) <= 0) return 1;
+	if (circle_eval(circle_center, radius, f->v3->co) <= 0) return 1;
+	if (f->v4) if (circle_eval(circle_center, radius, f->v4->co) <= 0)
return 1;
+
+	if (circle_segment_test(circle_center, radius,
f->e1->v1->co,f->e1->v2->co) == 1) return 1;
+	if (circle_segment_test(circle_center, radius,
f->e2->v1->co,f->e2->v2->co) == 1) return 1;
+	if (circle_segment_test(circle_center, radius,
f->e3->v1->co,f->e3->v2->co) == 1) return 1;
+	if (f->e4) if (circle_segment_test(circle_center, radius,
f->e4->v1->co,f->e4->v2->co) == 1) return 1;
+
+	return 0;
+}
+
+#define SELECT 1
+static void mark_subdiv_faces(SculptSession *ss, PBVHNode *node, float
ext_radius, int edge_treshold){
+	int toteditface= node->totprim;
+	int *faces= node->prim_indices;
+	int i, isect = 0;
+
+	//extend selections, more select iterations means more derivates =
smooth detail transitions,
+	for(i = 0; i < toteditface; i++){
+		EditFace *f = ss->pbvh->editfaces[faces[i]];
+
+		if (fast_discard_tri(ss->cache->location, ext_radius , f->v1->co,
f->v2->co, f->v3->co)){ //does not work properly
+		//isect = circle_face_intersection(ss->cache->location, ext_radius , f);
+		//if (isect) {
+			f->f |= SELECT;
+
+			f->v1->f |= SELECT;
+			f->v2->f |= SELECT;
+			f->v3->f |= SELECT;
+			if (f->v4) f->v4->f |= SELECT;
+
+			f->v1->f1 = SELECT;
+			f->v2->f1 = SELECT;
+			f->v3->f1 = SELECT;
+			if (f->v4) f->v4->f1 = SELECT;
+		//} //faces, verts, f1
+		}//if (fast_discard_face
+	}
+
+	// second pass, extend selected verts, more iterations means more derivates
+	for(i = 0; i < toteditface; i++){
+		EditFace *f = ss->pbvh->editfaces[faces[i]];
+		int has_v4 = 0;
+		if (f->v4) if (f->v4->f1 == SELECT) has_v4 = 1;
+
+		if ((f->v1->f1 == SELECT) || (f->v2->f1 == SELECT) || (f->v3->f1 ==
SELECT) || has_v4){
+			if ((f->v1->count > edge_treshold) || (f->v2->count > edge_treshold)
|| (f->v3->count > edge_treshold))
+				f->f |= SELECT;
+			if (f->v4) if (f->v4->count > edge_treshold) f->f |= SELECT;
+
+			f->v1->f |= SELECT;
+			f->v2->f |= SELECT;
+			f->v3->f |= SELECT;
+			if (f->v4) f->v4->f |= SELECT;
+		} //f1->verts
+	}
+
+	// third pass, extend selected verts
+	for(i = 0; i < toteditface; i++){
+		EditFace *f = ss->pbvh->editfaces[faces[i]];
+		int has_v4 = 0;
+		if (f->v4) if (f->v4->f & SELECT) has_v4 = 1;
+
+		if ((f->v1->f & SELECT) | (f->v2->f & SELECT) | (f->v3->f & SELECT) |
has_v4) {
+			if ((f->v1->count > edge_treshold) || (f->v2->count > edge_treshold)
|| (f->v3->count > edge_treshold))
+				f->f |= SELECT;
+			if (f->v4) if (f->v4->count > edge_treshold) f->f |= SELECT;
+
+			f->v1->f1 = SELECT;
+			f->v2->f1 = SELECT;
+			f->v3->f1 = SELECT;
+			if (f->v4) f->v4->f1 = SELECT;
+		} //verts->f1
+	}
+}
+
+void sculpt_select_edges_uclay(SculptSession *ss, PBVHNode *node, float
ext_radius, float detail, int repeat, int edge_treshold){//edge_treshold:
fator to trigger edge splitting
+	int toteditface= node->totprim;
+	int *faces= node->prim_indices;
+
+	float diff[3];
+	float edgeLength;
+	int i = 0;
+	float dist1, dist2, dist3, s, d;
+
+	for(i = 0; i < toteditface; i++){
+		EditFace *f = ss->pbvh->editfaces[faces[i]];
+		if (f->f & SELECT)
+		{
+			float bigger = 0.f;
+			sub_v3_v3v3(diff, f->e1->v1->co, f->e1->v2->co);
+			dist1 = len_v3(diff);
+			bigger = dist1;
+
+			sub_v3_v3v3(diff, f->e2->v1->co, f->e2->v2->co);
+			dist2 = len_v3(diff);
+			if (bigger < dist2) bigger = dist2;
+
+			sub_v3_v3v3(diff, f->e3->v1->co, f->e3->v2->co);
+			dist3 = len_v3(diff);
+			if (bigger < dist3) bigger = dist3;
+
+			s = (dist1 + dist2 + dist3) * 0.5f; //area =
sqrtf(s*(s-dist1)*(s-dist2)*(s-dist3)); r = area/s; /* incircle radius */
+			d = 2.f * sqrtf((s-dist1)*(s-dist2)*(s-dist3)/s);
+
+			if (d > detail){
+				if (bigger == dist1) f->e1->f |= SELECT; //
+				else if (bigger == dist2) f->e2->f |= SELECT; //
+				else f->e3->f |= SELECT;	//
+			}
+		} //if (efa->f & SELECT)
+	} //for(i = 0; i < toteditface; i++)....
+}
+
 static void do_brush_action(Sculpt *sd, SculptSession *ss, Brush *brush)
 {
 	SculptSearchSphereData data;
 	PBVHNode **nodes = NULL;
 	int n, totnode;
+	float ext_radius = 0.f;

 	/* Build a list of all nodes that are potentially within the brush's
area of influence */
 	data.ss = ss;
 	data.sd = sd;
 	data.radius_squared = ss->cache->radius_squared;
+	if (ss->uclay) {
+		data.radius_squared *= ss->uclay->offset;
+		ext_radius = data.radius_squared;
+	}
 	data.original = ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB,
SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB, SCULPT_TOOL_LAYER);
 	BLI_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes,
&totnode);

@@ -2351,8 +2448,15 @@
 		for (n= 0; n < totnode; n++) {
 			sculpt_undo_push_node(ss, nodes[n]);
 			BLI_pbvh_node_mark_update(nodes[n]);
-		}
+			if (ss->uclay) {
+				float detail = 0.25f * (1.f - ss->uclay->detail + 0.2f) *
sqrtf(ext_radius); //nice radius detail function
+				int repeat = ss->uclay->relax;

+				mark_subdiv_faces(ss, nodes[n], ext_radius, 9);
+				sculpt_select_edges_uclay(ss, nodes[n], ext_radius, detail, repeat, 9);
+			}
+		}
+
 		/* Apply one type of brush action */
 		switch(brush->sculpt_tool){
 		case SCULPT_TOOL_DRAW:
@@ -2465,7 +2569,7 @@

 					sculpt_clip(sd, ss, vd.co, val);
 				}
-				BLI_pbvh_vertex_iter_end;
+				BLI_pbvh_vertex_iter_end(vd);

 				BLI_pbvh_node_free_proxies(nodes[n]);
 			}
@@ -2503,7 +2607,7 @@

 					sculpt_clip(sd, ss, vd.co, val);
 				}
-				BLI_pbvh_vertex_iter_end;
+				BLI_pbvh_vertex_iter_end(vd);

 				BLI_pbvh_node_free_proxies(nodes[n]);

@@ -2636,7 +2740,8 @@
 {
 	DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
 	SculptSession *ss = ob->sculpt;
-	MultiresModifierData *mmd= sculpt_multires_active(scene, ob);
+	MultiresModifierData *mmd= sculpt_multires_active(scene, ob);
+	UClayModifierData *ucmd = sculpt_uclay_active(scene,ob); //Mio

 	ss->ob= ob;

@@ -2652,7 +2757,17 @@
 		ss->mvert= NULL;
 		ss->mface= NULL;
 		ss->face_normals= NULL;
+		ss->uclay = NULL;
 	}
+	if (ucmd){
+		ss->uclay = ucmd;
+		ss->totvert = dm->getNumVerts(dm);
+		ss->totface = dm->getNumFaces(dm);
+		ss->mvert= NULL;
+		ss->mface= NULL;
+		ss->face_normals= NULL;
+		ss->multires = NULL;
+	}
 	else {
 		Mesh *me = get_mesh(ob);
 		ss->totvert = me->totvert;
@@ -2661,8 +2776,8 @@
 		ss->mface = me->mface;
 		ss->face_normals = NULL;
 		ss->multires = NULL;
-	}
-
+		ss->uclay = NULL;
+	}
 	ss->pbvh = dm->getPBVH(ob, dm);
 	ss->fmap = (need_fmap && dm->getFaceMap)? dm->getFaceMap(ob, dm): NULL;

@@ -3008,6 +3123,7 @@
 {
 	StrokeCache *cache = ss->cache;
 	Brush *brush = paint_brush(&sd->paint);
+	UClayModifierData *ucmd = ss->uclay;

 	int dx, dy;

@@ -3038,10 +3154,11 @@
 	if(cache->first_time) {
 		if (!brush_use_locked_size(brush)) {
 			cache->initial_radius= unproject_brush_radius(ss->ob, cache->vc,
cache->true_location, brush_size(brush));
-			brush_set_unprojected_radius(brush, cache->initial_radius);
+			brush_set_unprojected_radius(brush, cache->initial_radius);
+
 		}
 		else {
-			cache->initial_radius= brush_unprojected_radius(brush);
+			cache->initial_radius= brush_unprojected_radius(brush);
 		}

 		if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK))
@@ -3147,7 +3264,7 @@
 	if(ss->modifiers_active) {
 		Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
 		Brush *brush = paint_brush(&sd->paint);
-
+
 		sculpt_update_mesh_elements(CTX_data_scene(C), ss->ob,
brush->sculpt_tool == SCULPT_TOOL_SMOOTH);
 	}
 }
@@ -3278,9 +3395,9 @@
 					if(vd.no) VECCOPY(vd.no, unode->no[vd.i])
 					else normal_short_to_float_v3(vd.fno, unode->no[vd.i]);

-					if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+					if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
 				}
-				BLI_pbvh_vertex_iter_end;
+				BLI_pbvh_vertex_iter_end(vd);

 				BLI_pbvh_node_mark_update(nodes[n]);
 			}
@@ -3303,9 +3420,13 @@
 	SculptSession *ss = ob->sculpt;
 	ARegion *ar = CTX_wm_region(C);
 	MultiresModifierData *mmd = ss->multires;
+	UClayModifierData *ucmd = ss->uclay;

 	if(mmd)
 		multires_mark_as_modified(ob);
+	if(ucmd)
+		uclay_mark_as_modified(ob);
+
 	if(ob->derivedFinal) /* VBO no longer valid */
 		GPU_drawobject_free(ob->derivedFinal);

@@ -3582,18 +3703,26 @@
 	ToolSettings *ts = CTX_data_tool_settings(C);
 	Object *ob = CTX_data_active_object(C);
 	MultiresModifierData *mmd= sculpt_multires_active(scene, ob);
+	UClayModifierData *ucmd= sculpt_uclay_active(scene, ob);
 	int flush_recalc= 0;

 	(void)unused;

 	/* multires in sculpt mode could have different from object mode
subdivision level */
 	flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl;
+
+	/* unlimited clay in sculpt mode could have different topology from
object mode  */
+	flush_recalc |= (ucmd != NULL);
+
 	/* if object has got active modifiers, it's dm could be different in
sculpt mode  */
 	//flush_recalc |= sculpt_modifiers_active(scene, ob);

 	if(ob->mode & OB_MODE_SCULPT) {
 		if(mmd)
 			multires_force_update(ob);
+
+		if(ucmd)
+			uclay_force_update(ob);

 		if(flush_recalc)
 			DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@@ -3655,3 +3784,4 @@
 	WM_operatortype_append(SCULPT_OT_set_persistent_base);
 }

+
Index: source/blender/editors/sculpt_paint/sculpt_intern.h
===================================================================
--- source/blender/editors/sculpt_paint/sculpt_intern.h	(revision 32564)
+++ source/blender/editors/sculpt_paint/sculpt_intern.h	(working copy)
@@ -53,6 +53,7 @@
 void sculpt_stroke_draw(struct SculptStroke *);
 void sculpt_radialcontrol_start(int mode);
 struct MultiresModifierData *sculpt_multires_active(struct Scene *scene,
struct Object *ob);
+struct UClayModifierData *sculpt_uclay_active(struct Scene *scene, struct
Object *ob);

 struct Brush *sculptmode_brush(void);
 //void do_symmetrical_brush_actions(struct Sculpt *sd, struct wmOperator
*wm, struct BrushAction *a, short *, short *);
@@ -108,6 +109,7 @@
 void sculpt_undo_push_end(void);

 struct MultiresModifierData *sculpt_multires_active(struct Scene *scene,
struct Object *ob);
+struct UClayModifierData *sculpt_uclay_active(struct Scene *scene, struct
Object *ob);
 int sculpt_modifiers_active(Scene *scene, Object *ob);
 void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]);

Index: source/blender/editors/sculpt_paint/sculpt_undo.c
===================================================================
--- source/blender/editors/sculpt_paint/sculpt_undo.c	(revision 32564)
+++ source/blender/editors/sculpt_paint/sculpt_undo.c	(working copy)
@@ -35,6 +35,7 @@
 #include "BLI_math.h"
 #include "BLI_ghash.h"
 #include "BLI_threads.h"
+#include "BLI_editVert.h"

 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
@@ -73,6 +74,7 @@
 	SculptUndoNode *unode;
 	MVert *mvert;
 	MultiresModifierData *mmd;
+	UClayModifierData *ucmd;
 	int *index;
 	int i, j, update= 0;

@@ -154,9 +156,28 @@
 					swap_v3_v3(grid[i].co, co[0]);
 			}
 		}
+		/* else if(unode->toteditvert){
+		/* EditMesh (UClay) restore
+			EditVert *editvert = NULL;
+			float (*co)[3];
+
+			/* regular mesh restore
+			if(ss->totvert != unode->maxvert)
+				continue;

+			index= unode->index;
+			editvert= dm->getEditVerts(dm);
+
+			for(i=0; i<unode->toteditvert; i++) {
+				swap_v3_v3(editvert->co, unode->co[i]);
+				editvert = editvert->next;
+				//editvert->.flag |= ME_VERT_PBVH_UPDATE;
+			}
+		} //*/
+
 		update= 1;
 	}
+

 	if(update) {
 		/* we update all nodes still, should be more clever, but also
@@ -167,6 +188,9 @@

 		if((mmd=sculpt_multires_active(scene, ob)))
 			multires_mark_as_modified(ob);
+
+		if((ucmd=sculpt_uclay_active(scene, ob)))
+			uclay_mark_as_modified(ob); //Mio

 		if(ss->modifiers_active || ((Mesh*)ob->data)->id.us > 1)
 			DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@@ -186,6 +210,8 @@
 			MEM_freeN(unode->index);
 		if(unode->grids)
 			MEM_freeN(unode->grids);
+	//	if(unode->editverts) //Mio
+	//		MEM_freeN(unode->editverts);
 		if(unode->layer_disp)
 			MEM_freeN(unode->layer_disp);
 	}
@@ -211,8 +237,8 @@
 	ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
 	Object *ob= ss->ob;
 	SculptUndoNode *unode;
-	int totvert, allvert, totgrid, maxgrid, gridsize, *grids;
-
+	int totvert, allvert, totgrid, maxgrid, gridsize, *grids, toteditvert,
*editverts;
+
 	/* list is manipulated by multiple threads, so we lock */
 	BLI_lock_thread(LOCK_CUSTOM1);

@@ -228,6 +254,7 @@
 	BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
 	BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
 		&maxgrid, &gridsize, NULL, NULL);
+	BLI_pbvh_node_get_editverts(ss->pbvh, node, &toteditvert, NULL,
&editverts); //Mio ver aqui

 	unode->totvert= totvert;
 	/* we will use this while sculpting, is mapalloc slow to access then? */
@@ -235,7 +262,7 @@
 	unode->no= MEM_mapallocN(sizeof(short)*3*allvert, "SculptUndoNode.no");
 	undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float)*3 +
sizeof(short)*3 + sizeof(int))*allvert);
 	BLI_addtail(lb, unode);
-
+
 	if(maxgrid) {
 		/* multires */
 		unode->maxgrid= maxgrid;
@@ -250,18 +277,18 @@
 	}

 	BLI_unlock_thread(LOCK_CUSTOM1);
-
+
 	/* copy threaded, hopefully this is the performance critical part */
 	{
 		PBVHVertexIter vd;

-		BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
+		BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
 			copy_v3_v3(unode->co[vd.i], vd.co);
 			if(vd.no) VECCOPY(unode->no[vd.i], vd.no)
 			else normal_float_to_short_v3(unode->no[vd.i], vd.fno);
-			if(vd.vert_indices) unode->index[vd.i]= vd.vert_indices[vd.i];
+			if(vd.vert_indices) unode->index[vd.i]= vd.vert_indices[vd.i];
 		}
-		BLI_pbvh_vertex_iter_end;
+		BLI_pbvh_vertex_iter_end(vd);
 	}

 	if(unode->grids)
Index: source/blender/editors/space_outliner/outliner.c
===================================================================
--- source/blender/editors/space_outliner/outliner.c	(revision 32564)
+++ source/blender/editors/space_outliner/outliner.c	(working copy)
@@ -4351,6 +4351,8 @@
 						UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
 					case eModifierType_Screw:
 						UI_icon_draw(x, y, ICON_MOD_SCREW); break;
+					case eModifierType_UClay:
+						UI_icon_draw(x, y, ICON_MOD_PHYSICS); break;
 					default:
 						UI_icon_draw(x, y, ICON_DOT); break;
 				}
@@ -5691,3 +5693,4 @@
 	soops->storeflag &= ~SO_TREESTORE_REDRAW;
 }

+
Index: source/blender/gpu/GPU_buffers.h
===================================================================
--- source/blender/gpu/GPU_buffers.h	(revision 32564)
+++ source/blender/gpu/GPU_buffers.h	(working copy)
@@ -142,6 +142,8 @@
 	int *grid_indices, int totgrid, int gridsize);
 void GPU_update_grid_buffers(void *buffers_v, struct DMGridData **grids,
 	int *grid_indices, int totgrid, int gridsize, int smooth);
+void GPU_update_editmesh_buffers(void *buffers_v,struct EditVert
*editverts, int *editvert_indices, int toteditvert);
+void *GPU_build_editmesh_buffers(struct EditVert *editverts,struct
EditFace **editfaces, int toteditface, int toteditvert);
 void GPU_draw_buffers(void *buffers);
 void GPU_free_buffers(void *buffers);

Index: source/blender/gpu/intern/gpu_buffers.c
===================================================================
--- source/blender/gpu/intern/gpu_buffers.c	(revision 32564)
+++ source/blender/gpu/intern/gpu_buffers.c	(working copy)
@@ -41,6 +41,7 @@
 #include "BLI_ghash.h"
 #include "BLI_math.h"
 #include "BLI_threads.h"
+#include "BLI_editVert.h"

 #include "DNA_meshdata_types.h"

@@ -421,6 +422,11 @@
 	int totgrid;
 	int gridsize;

+	/* editmesh pointers */
+	EditFace **editfaces;
+	EditVert *editverts;
+	int toteditface;
+
 	unsigned int tot_tri, tot_quad;
 } GPU_Buffers;

@@ -682,6 +688,121 @@
 	return buffers;
 }

+
+void GPU_update_editmesh_buffers(void *buffers_v,struct EditVert *editverts,
+			int *editvert_indices, int toteditvert)
+{
+	GPU_Buffers *buffers = buffers_v;
+	VertexBufferFormat *vert_data;
+	int i;
+	EditVert *eve;
+
+	if(buffers->vert_buf) {
+		/* Build VBO , issues here*/
+		glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
+		glBufferDataARB(GL_ARRAY_BUFFER_ARB,
+				 sizeof(VertexBufferFormat) * toteditvert,
+				 NULL, GL_STATIC_DRAW_ARB);
+		vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+
+		if(vert_data) {
+			for(eve= editverts; eve; eve= eve->next) {
+				//MVert *v = editvert + editvert_indices[i];
+				VertexBufferFormat *out = vert_data + i;
+
+				copy_v3_v3(out->co, eve->co);
+				memcpy(out->no, eve->no, sizeof(short) * 3);
+				i++;
+			}
+
+			glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+		}
+		else {
+			glDeleteBuffersARB(1, &buffers->vert_buf);
+			buffers->vert_buf = 0;
+		}
+
+		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+	}
+
+	buffers->editverts = editverts;
+}
+
+void *GPU_build_editmesh_buffers(struct EditVert *editverts,struct
EditFace **editfaces, int toteditface, int toteditvert)
+{
+	GPU_Buffers *buffers; //improve this
+	unsigned short *tri_data;
+	int i, j, k, tottri = 0;
+
+	EditFace *efa;
+	EditVert *eve;
+
+	buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers");
+	buffers->index_type = GL_UNSIGNED_SHORT;
+
+	/* Count the number of triangles */
+	for(efa= editfaces; efa; efa= efa->next)
+		tottri += efa->v4 ? 2 : 1;
+
+
+	if(GL_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO))
+		glGenBuffersARB(1, &buffers->index_buf);
+
+	if(buffers->index_buf) {
+		/* Generate index buffer object */
+		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
+		glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
+				 sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB);
+
+		/* Fill the triangle buffer */
+		tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+		if(tri_data) {
+			for(efa= editfaces; efa; efa= efa->next) {
+				int v[3] = {efa->v1->co, efa->v2->co, efa->v3->co};
+
+				for(j = 0; j < (efa->v4 ? 2 : 1); ++j) {
+					for(k = 0; k < 3; ++k) {
+					//	void *value, *key = SET_INT_IN_POINTER(v[k]);
+						int vbo_index;
+
+					//	value = BLI_ghash_lookup(map, key);
+						vbo_index = 1; //GET_INT_FROM_POINTER(value);
+
+					//	if(vbo_index < 0) {
+					//		vbo_index = -vbo_index +
+					//			tot_uniq_verts - 1;
+					//	}
+
+						*tri_data = vbo_index;
+						++tri_data;
+					}
+					v[0] = efa->v4->co;
+					v[1] = efa->v1->co;
+					v[2] = efa->v3->co;
+				}
+			}
+			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+		}
+		else {
+			glDeleteBuffersARB(1, &buffers->index_buf);
+			buffers->index_buf = 0;
+		}
+
+		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+	}
+
+	if(buffers->index_buf)
+		glGenBuffersARB(1, &buffers->vert_buf);
+	//GPU_update_editmesh_buffers(buffers, editverts, toteditvert);
+
+	buffers->tot_tri = tottri;
+
+	buffers->editfaces = editfaces;
+	buffers->toteditface = toteditface;
+
+	return buffers;
+}
+
 void GPU_draw_buffers(void *buffers_v)
 {
 	GPU_Buffers *buffers = buffers_v;
@@ -754,6 +875,26 @@
 			}
 		}
 	}
+	else if (buffers->toteditface){
+		/* fallback if we are out of memory */
+		int i;
+		for(i = 0; i < buffers->toteditface; ++i) {
+			EditFace *f = buffers->editfaces[buffers->face_indices[i]];
+
+			glBegin((f->v4)? GL_QUADS: GL_TRIANGLES);
+			glNormal3sv(f->v1->no);
+			glVertex3fv(f->v1->co);
+			glNormal3sv(f->v2->no);
+			glVertex3fv(f->v2->co);
+			glNormal3sv(f->v3->no);
+			glVertex3fv(f->v3->co);
+			if(f->v4) {
+				glNormal3sv(f->v4->no);
+				glVertex3fv(f->v4->co);
+			}
+			glEnd();
+		}
+	}
 }

 void GPU_free_buffers(void *buffers_v)
Index: source/blender/imbuf/intern/tiff.c
===================================================================
--- source/blender/imbuf/intern/tiff.c	(revision 32564)
+++ source/blender/imbuf/intern/tiff.c	(working copy)
@@ -2,7 +2,7 @@
  * tiff.c
  *
  * $Id$
- *
+ *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -31,10 +31,10 @@
  * already loaded the file into a memory buffer.  libtiff is not well
  * configured to handle files in memory, so a client wrapper is written to
  * surround the memory and turn it into a virtual file.  Currently, reading
- * of TIFF files is done using libtiff's RGBAImage support.  This is a
+ * of TIFF files is done using libtiff's RGBAImage support.  This is a
  * high-level routine that loads all images as 32-bit RGBA, handling all the
  * required conversions between many different TIFF types internally.
- *
+ *
  * Saving supports RGB, RGBA and BW (greyscale) images correctly, with
  * 8 bits per channel in all cases.  The "deflate" compression algorithm is
  * used to compress images.
@@ -45,7 +45,7 @@
 #include <string.h>

 #include "imbuf.h"
-
+
 #include "BKE_global.h"
 #include "BKE_utildefines.h"

@@ -58,11 +58,9 @@
 #include "IMB_allocimbuf.h"
 #include "IMB_filetype.h"
 #include "IMB_filter.h"
-
 #include "tiffio.h"


-
 /***********************
  * Local declarations. *
  ***********************/
@@ -98,7 +96,7 @@
 	(void)size;
 }

-static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t* pbase, toff_t*
psize)
+static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t* pbase, toff_t*
psize)
 {
 	(void)fd;
 	(void)pbase;
@@ -136,10 +134,10 @@
 		nRemaining = 0;
 	else
 		nRemaining = mfile->size - mfile->offset;
-
+
 	if(nCopy > nRemaining)
 		nCopy = nRemaining;
-
+
 	/* on EOF, return immediately and read (copy) nothing */
 	if(nCopy <= 0)
 		return (0);
@@ -207,7 +205,7 @@
 			break;
 		default:
 			/* no other types are supported - return an error */
-			fprintf(stderr,
+			fprintf(stderr,
 				"imb_tiff_SeekProc: "
 				"Unsupported TIFF SEEK type.\n");
 			return (-1);
@@ -242,12 +240,12 @@
 		fprintf(stderr,"imb_tiff_CloseProc: !mfile || !mfile->mem!\n");
 		return (0);
 	}
-
+
 	/* virtually close the file */
 	mfile->mem    = NULL;
 	mfile->offset = 0;
 	mfile->size   = 0;
-
+
 	return (0);
 }

@@ -280,7 +278,7 @@
 	memFile->offset = 0;
 	memFile->size = size;

-	return TIFFClientOpen("(Blender TIFF Interface Layer)",
+	return TIFFClientOpen("(Blender TIFF Interface Layer)",
 		"r", (thandle_t)(memFile),
 		imb_tiff_ReadProc, imb_tiff_WriteProc,
 		imb_tiff_SeekProc, imb_tiff_CloseProc,
@@ -349,9 +347,9 @@
 }


-/*
+/*
  * Use the libTIFF scanline API to read a TIFF image.
- * This method is most flexible and can handle multiple different bit depths
+ * This method is most flexible and can handle multiple different bit depths
  * and RGB channel orderings.
  */
 static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
@@ -363,12 +361,12 @@
 	int ib_flag=0, row, chan;
 	float *fbuf=NULL;
 	unsigned short *sbuf=NULL;
-
+
 	TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample);
 	TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);		/* number of
'channels' */
 	TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config);
 	scanline = TIFFScanlineSize(image);
-
+
 	if (bitspersample == 32) {
 		ib_flag = IB_rectfloat;
 		fbuf = (float *)_TIFFmalloc(scanline);
@@ -378,9 +376,9 @@
 	} else {
 		ib_flag = IB_rect;
 	}
-
+
 	tmpibuf= IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->depth, ib_flag);
-
+
 	/* simple RGBA image */
 	if (!(bitspersample == 32 || bitspersample == 16)) {
 		success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0);
@@ -389,11 +387,11 @@
 	else if (config == PLANARCONFIG_CONTIG) {
 		for (row = 0; row < ibuf->y; row++) {
 			int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1);
-
+
 			if (bitspersample == 32) {
 				success |= TIFFReadScanline(image, fbuf, row, 0);
 				scanline_contig_32bit(tmpibuf->rect_float+ib_offset, fbuf, ibuf->x,
spp);
-
+
 			} else if (bitspersample == 16) {
 				success |= TIFFReadScanline(image, sbuf, row, 0);
 				scanline_contig_16bit(tmpibuf->rect_float+ib_offset, sbuf, ibuf->x,
spp);
@@ -401,32 +399,32 @@
 		}
 	/* separate channels: RRRGGGBBB */
 	} else if (config == PLANARCONFIG_SEPARATE) {
-
+
 		/* imbufs always have 4 channels of data, so we iterate over all of them
 		 * but only fill in from the TIFF scanline where necessary. */
 		for (chan = 0; chan < 4; chan++) {
 			for (row = 0; row < ibuf->y; row++) {
 				int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1);
-
+
 				if (bitspersample == 32) {
 					if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */
 						memset(fbuf, 1.0, sizeof(fbuf));
 					else
 						success |= TIFFReadScanline(image, fbuf, row, chan);
 					scanline_separate_32bit(tmpibuf->rect_float+ib_offset, fbuf,
ibuf->x, chan);
-
+
 				} else if (bitspersample == 16) {
 					if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */
 						memset(sbuf, 65535, sizeof(sbuf));
 					else
 						success |= TIFFReadScanline(image, sbuf, row, chan);
 					scanline_separate_16bit(tmpibuf->rect_float+ib_offset, sbuf,
ibuf->x, chan);
-
+
 				}
 			}
 		}
 	}
-
+
 	if (bitspersample == 32)
 		_TIFFfree(fbuf);
 	else if (bitspersample == 16)
@@ -434,27 +432,27 @@

 	if(success) {
 		ibuf->profile = (bitspersample==32)?IB_PROFILE_LINEAR_RGB:IB_PROFILE_SRGB;
-
+
 		if(ENDIAN_ORDER == B_ENDIAN)
 			IMB_convert_rgba_to_abgr(tmpibuf);
 		if(premul) {
 			IMB_premultiply_alpha(tmpibuf);
 			ibuf->flags |= IB_premul;
 		}
-
+
 		/* assign rect last */
 		if (tmpibuf->rect_float)
 			ibuf->rect_float= tmpibuf->rect_float;
-		else
+		else
 			ibuf->rect= tmpibuf->rect;
 		ibuf->mall |= ib_flag;
 		ibuf->flags |= ib_flag;
-
+
 		tmpibuf->mall &= ~ib_flag;
 	}

 	IMB_freeImBuf(tmpibuf);
-
+
 	return success;
 }

@@ -505,15 +503,15 @@
 	TIFFGetField(image, TIFFTAG_IMAGEWIDTH,  &width);
 	TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
 	TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);
-
+
 	ib_depth = (spp==3)?24:32;
-
+
 	ibuf = IMB_allocImBuf(width, height, ib_depth, 0);
 	if(ibuf) {
 		ibuf->ftype = TIF;
 	}
 	else {
-		fprintf(stderr,
+		fprintf(stderr,
 			"imb_loadtiff: could not allocate memory for TIFF " \
 			"image.\n");
 		TIFFClose(image);
@@ -629,7 +627,7 @@
 /**
  * Saves a TIFF file.
  *
- * ImBuf structures with 1, 3 or 4 bytes per pixel (GRAY, RGB, RGBA
+ * ImBuf structures with 1, 3 or 4 bytes per pixel (GRAY, RGB, RGBA
  * respectively) are accepted, and interpreted correctly.  Note that the
TIFF
  * convention is to use pre-multiplied alpha, which can be achieved within
  * Blender by setting "Premul" alpha handling.  Other alpha conventions are
@@ -653,15 +651,15 @@
 	float *fromf = NULL;
 	int x, y, from_i, to_i, i;
 	int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
-

+
 	/* check for a valid number of bytes per pixel.  Like the PNG writer,
 	 * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
 	 * to gray, RGB, RGBA respectively. */
 	samplesperpixel = (uint16)((ibuf->depth + 7) >> 3);
 	if((samplesperpixel > 4) || (samplesperpixel == 2)) {
 		fprintf(stderr,
-			"imb_savetiff: unsupported number of bytes per "
+			"imb_savetiff: unsupported number of bytes per "
 			"pixel: %d\n", samplesperpixel);
 		return (0);
 	}
@@ -675,7 +673,7 @@
 	if(flags & IB_mem) {
 		/* bork at the creation of a TIFF in memory */
 		fprintf(stderr,
-			"imb_savetiff: creation of in-memory TIFF files is "
+			"imb_savetiff: creation of in-memory TIFF files is "
 			"not yet supported.\n");
 		return (0);
 	}
@@ -723,7 +721,7 @@
 		/* RGBA images */
 		TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
 				extraSampleTypes);
-		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
+		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
 				PHOTOMETRIC_RGB);
 	}
 	else if(samplesperpixel == 3) {
@@ -746,7 +744,7 @@
 			if(pixels16) {
 				/* convert from float source */
 				float rgb[3];
-
+
 				if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
 					linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
 				else
@@ -756,7 +754,7 @@
 				to16[to_i+1] = FTOUSHORT(rgb[1]);
 				to16[to_i+2] = FTOUSHORT(rgb[2]);
 				to_i += 3; from_i+=3;
-
+
 				if (samplesperpixel == 4) {
 					to16[to_i+3] = FTOUSHORT(fromf[from_i+3]);
 					to_i++; from_i++;
Index: source/blender/makesdna/DNA_modifier_types.h
===================================================================
--- source/blender/makesdna/DNA_modifier_types.h	(revision 32564)
+++ source/blender/makesdna/DNA_modifier_types.h	(working copy)
@@ -66,9 +66,10 @@
 	eModifierType_ShapeKey,
 	eModifierType_Solidify,
 	eModifierType_Screw,
+	eModifierType_UClay,
 	/* placeholder, keep this so durian files load in
 	 * trunk with the correct modifier once its merged */
-	eModifierType_Warp,
+	eModifierType_Warp,
 	NUM_MODIFIER_TYPES
 } ModifierType;

@@ -442,6 +443,15 @@
 	ModifierData modifier;
 } SoftbodyModifierData;

+typedef struct UClayModifierData {
+	ModifierData modifier;
+
+	float detail, offset;
+	float smoothness;
+	int relax;
+
+} UClayModifierData;
+
 typedef struct ClothModifierData {
 	ModifierData		modifier;

Index: source/blender/makesrna/intern/rna_modifier.c
===================================================================
--- source/blender/makesrna/intern/rna_modifier.c	(revision 32564)
+++ source/blender/makesrna/intern/rna_modifier.c	(working copy)
@@ -85,6 +85,7 @@
 	{eModifierType_Smoke, "SMOKE", ICON_MOD_SMOKE, "Smoke", ""},
 	{eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""},
 	{eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""},
+	{eModifierType_UClay, "UCLAY", ICON_MOD_SOFT, "UClay", ""},
 	{0, NULL, 0, NULL, NULL}};

 #ifdef RNA_RUNTIME
@@ -175,6 +176,8 @@
 			return &RNA_SolidifyModifier;
 		case eModifierType_Screw:
 			return &RNA_ScrewModifier;
+		case eModifierType_UClay:
+			return &RNA_UClayModifier;
 		default:
 			return &RNA_Modifier;
 	}
@@ -2085,6 +2088,36 @@
 	RNA_def_struct_ui_icon(srna, ICON_MOD_PHYSICS);
 }

+static void rna_def_modifier_uclay(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+
+	srna= RNA_def_struct(brna, "UClayModifier", "Modifier");
+	RNA_def_struct_ui_text(srna, "Unlimited Clay Modifier", "Unlimited Clay
Modifier for sculpting");
+	RNA_def_struct_sdna(srna, "UClayModifierData");
+	RNA_def_struct_ui_icon(srna, ICON_MOD_PHYSICS);
+
+	prop= RNA_def_property(srna, "detail", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_range(prop, 0.001, 1.0);
+	RNA_def_property_ui_range(prop, 0.005, 1.0, 0.5, 3);
+	RNA_def_property_ui_text(prop, "Detail", "");
+	RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+	prop= RNA_def_property(srna, "smoothness", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "smoothness");
+	RNA_def_property_range(prop, 0.0, 100.0);
+	RNA_def_property_ui_range(prop, 0.0, 10, 0.25, 2);
+	RNA_def_property_ui_text(prop, "Smoothness", "Subdivission smoothness");
+	RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+	prop= RNA_def_property(srna, "relax", PROP_INT, PROP_NONE);
+	RNA_def_property_range(prop, 0, 1000);
+	RNA_def_property_ui_range(prop, 0, 1000, 0, 0);
+	RNA_def_property_ui_text(prop, "Relax", "Vertex relaxing iteration");
+	RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
 static void rna_def_modifier_solidify(BlenderRNA *brna)
 {
 	StructRNA *srna;
@@ -2333,6 +2366,7 @@
 	rna_def_modifier_smoke(brna);
 	rna_def_modifier_solidify(brna);
 	rna_def_modifier_screw(brna);
+	rna_def_modifier_uclay(brna);
 }

 #endif
Index: source/blender/makesrna/intern/rna_sequencer.c
===================================================================
--- source/blender/makesrna/intern/rna_sequencer.c	(revision 32564)
+++ source/blender/makesrna/intern/rna_sequencer.c	(working copy)
@@ -48,7 +48,7 @@

 static float to_dB(float x)
 {
-	return logf(x * x + 1e-30f) * 4.34294480f;
+	return 4.34294480f * logf(x * x + 1e-30f) ;
 }

 static float from_dB(float x)
Index: source/blender/makesrna/RNA_access.h
===================================================================
--- source/blender/makesrna/RNA_access.h	(revision 32564)
+++ source/blender/makesrna/RNA_access.h	(working copy)
@@ -562,6 +562,7 @@
 extern StructRNA RNA_WorldTextureSlot;
 extern StructRNA RNA_XnorController;
 extern StructRNA RNA_XorController;
+extern StructRNA RNA_UClayModifier;


 /* Pointer
@@ -939,3 +940,4 @@

 #endif /* RNA_ACCESS */

+
Index: source/blender/modifiers/intern/MOD_uclay.c
===================================================================
--- source/blender/modifiers/intern/MOD_uclay.c	(revision 0)
+++ source/blender/modifiers/intern/MOD_uclay.c	(revision 0)
@@ -0,0 +1,135 @@
+/*
+* $Id: MOD_uclay.c 28152 2010-5-24 farsthary $
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software  Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Raul Fernandez Hernandez
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+
+#include "DNA_scene_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_particle.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BKE_multires.h"
+#include "BKE_paint.h"
+
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_pbvh.h"
+
+#include "MOD_modifiertypes.h"
+
+//---------
+#include "BKE_brush.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+//-----------
+
+#include
"C:\Blender_Build\blenderSVN\source\blender\editors\include\ED_mesh.h"
+
+struct StrokeCache;
+
+
+static void initData(ModifierData *md)
+{
+	UClayModifierData *ucmd = (UClayModifierData*) md;
+
+	ucmd->detail = 0.5f;
+	ucmd->smoothness = 0.25f;
+	ucmd->relax = 0;
+	ucmd->offset = 1.5f;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+	UClayModifierData *ucmd = (UClayModifierData*) md;
+	UClayModifierData *tucmd = (UClayModifierData*) target;
+
+	tucmd->detail = ucmd->detail;
+	tucmd->smoothness = ucmd->smoothness;
+	tucmd->relax = ucmd->relax;
+	tucmd->offset = ucmd->offset;
+}
+
+static DerivedMesh *applyModifier(
+	ModifierData *md, Object *ob, DerivedMesh *dm,
+  int useRenderParams, int isFinalCalc)
+{
+	SculptSession *ss= ob->sculpt;
+	int sculpting= (ob->mode & OB_MODE_SCULPT) && ss;
+	float radius = 10.f; //A big threshold to ensure that theres no
subdivission if no sculpting, odd?
+	UClayModifierData *ucmd = (UClayModifierData*)md;
+	DerivedMesh *result = NULL;
+	if(sculpting && ss->cache != NULL) radius = ss->cache->radius;
+
+	result = uclay_dm_create_from_derived(ucmd, 0, dm, ob, md->scene,
radius, useRenderParams, isFinalCalc);
+
+	if(result == dm)
+		return dm;
+
+	if(useRenderParams || !isFinalCalc) {
+		DerivedMesh *cddm= CDDM_copy(result);
+		result->release(result);
+		result= cddm;
+	} else if(sculpting)
+		ss->pbvh= result->getPBVH(ob, result);
+
+	return result;
+}
+
+
+ModifierTypeInfo modifierType_UClay = {
+	/* name */              "UClay",
+	/* structName */        "UClayModifierData",
+	/* structSize */        sizeof(UClayModifierData),
+	/* type */              eModifierTypeType_Constructive,
+	/* flags */             eModifierTypeFlag_AcceptsMesh
+							| eModifierTypeFlag_RequiresOriginalData,
+	/* copyData */          copyData,
+	/* deformVerts */       0,
+	/* deformVertsEM */     0,
+	/* deformMatricesEM */  0,
+	/* applyModifier */     applyModifier,
+	/* applyModifierEM */   0,
+	/* initData */          initData,
+	/* requiredDataMask */  0,
+	/* freeData */          0,
+	/* isDisabled */        0,
+	/* updateDepgraph */    0,
+	/* dependsOnTime */     0,
+	/* foreachObjectLink */ 0,
+	/* foreachIDLink */     0,
+};
Index: source/blender/modifiers/intern/MOD_util.c
===================================================================
--- source/blender/modifiers/intern/MOD_util.c	(revision 32564)
+++ source/blender/modifiers/intern/MOD_util.c	(working copy)
@@ -182,5 +182,6 @@
 	INIT_TYPE(ShapeKey);
 	INIT_TYPE(Solidify);
 	INIT_TYPE(Screw);
+	INIT_TYPE(UClay);
 #undef INIT_TYPE
 }
Index: source/blender/modifiers/MOD_modifiertypes.h
===================================================================
--- source/blender/modifiers/MOD_modifiertypes.h	(revision 32564)
+++ source/blender/modifiers/MOD_modifiertypes.h	(working copy)
@@ -67,6 +67,7 @@
 extern ModifierTypeInfo modifierType_ShapeKey;
 extern ModifierTypeInfo modifierType_Solidify;
 extern ModifierTypeInfo modifierType_Screw;
+extern ModifierTypeInfo modifierType_UClay;

 /* MOD_util.c */
 void modifier_type_init(ModifierTypeInfo *types[]);


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- Participe en Universidad 2012, del 13 al 17 de febrero de 2012. Habana. Cuba. http://www.congresouniversidad.cu

- Consulte la Enciclopedia Colaborativa Cubana. http://www.ecured.cu


More information about the Bf-committers mailing list