[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48373] branches/soc-2012-sushi/source/ blender: Fixed some bugs with vertex snapping, and re-implemented edge snapping.

luke frisken l.frisken at gmail.com
Thu Jun 28 15:11:20 CEST 2012


Revision: 48373
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48373
Author:   lfrisken
Date:     2012-06-28 13:11:06 +0000 (Thu, 28 Jun 2012)
Log Message:
-----------
Fixed some bugs with vertex snapping, and re-implemented edge snapping.
It's not quite working yet, but should be soon.

Modified Paths:
--------------
    branches/soc-2012-sushi/source/blender/blenkernel/BKE_snap.h
    branches/soc-2012-sushi/source/blender/blenkernel/intern/snap.c
    branches/soc-2012-sushi/source/blender/editors/transform/transform_snap.c

Modified: branches/soc-2012-sushi/source/blender/blenkernel/BKE_snap.h
===================================================================
--- branches/soc-2012-sushi/source/blender/blenkernel/BKE_snap.h	2012-06-28 12:32:06 UTC (rev 48372)
+++ branches/soc-2012-sushi/source/blender/blenkernel/BKE_snap.h	2012-06-28 13:11:06 UTC (rev 48373)
@@ -12,6 +12,8 @@
 	//perhaps more info later I might guess
 	float location[3];
 	float normal[3];
+	int r_dist;
+	float r_depth;
 }SnapPoint;
 
 typedef struct Snap Snap;
@@ -41,6 +43,7 @@
 
 int Snap_getretval(Snap* s);
 SnapPoint* Snap_getSnapPoint(Snap* s);
+void Snap_setClosestPoint(Snap* s, SnapPoint* sp);
 
 Snap* SnapMesh_create(	void* mesh_data,
 						SnapMesh_data_type data_type,

Modified: branches/soc-2012-sushi/source/blender/blenkernel/intern/snap.c
===================================================================
--- branches/soc-2012-sushi/source/blender/blenkernel/intern/snap.c	2012-06-28 12:32:06 UTC (rev 48372)
+++ branches/soc-2012-sushi/source/blender/blenkernel/intern/snap.c	2012-06-28 13:11:06 UTC (rev 48373)
@@ -35,6 +35,7 @@
 struct Snap{
 	int snap_found; //boolean whether snap point has been found
 	SnapPoint snap_point;
+	SnapPoint* closest_point; //previously calculated closest point to mouse and screen.
 
 	//TODO: all extra data in Snap should be subject to streamlining and change
 	//in the near future, as soon as I get something working. A lot of quick
@@ -53,7 +54,6 @@
 	float ray_start[3], ray_normal[3];
 	float ray_start_local[3], ray_normal_local[3];
 	int min_distance;
-	int r_dist;
 
 	//matrix storage
 	float imat[4][4];
@@ -86,8 +86,10 @@
 
 	s->min_distance = 30; //TODO: change to a user defined value;
 
+	s->closest_point = NULL;
+	s->snap_found = 0;
+
 	//TODO: pass the function pointers in as arguments
-	s->snap_found = 0;
 	s->run = NULL;
 	s->draw = NULL;
 	s->snap_data = NULL;
@@ -102,6 +104,17 @@
 	return s->retval;
 }
 
+//This function sets the closest previously calculated closest snap point. When the snap point calculation
+//for this object is run, it will compare what it finds to this point. If the point is not
+//closer to the mouse, and/or to the screen then it won't be counted as a valid snap point.
+//TODO: perhaps a deep copy of snap point might be/more intuitive better here (in case original goes out of scope
+//or is freed).
+//will work out further into the design when I start working out the best way
+//to optimise the snapping code.
+void Snap_setClosestPoint(Snap* s, SnapPoint* sp){
+	s->closest_point = sp;
+}
+
 SnapPoint* Snap_getSnapPoint(Snap* s){
 	return &(s->snap_point);
 }
@@ -162,6 +175,7 @@
 
 struct MeshData{
 	void* data;
+	int edit_mode;
 	int (*getNumVerts)(MeshData* md);
 	int (*getNumEdges)(MeshData* md);
 	int (*getNumFaces)(MeshData* md);
@@ -275,8 +289,8 @@
 	bme = EDBM_edge_at_index(em, index);
 	/* check whether edge is hidden and if either of its vertices are selected*/
 	if( BM_elem_flag_test(bme, BM_ELEM_HIDDEN) ||
-		BM_elem_flag_test(bme->v1, BM_ELEM_SELECT ||
-		BM_elem_flag_test(bme->v2, BM_ELEM_SELECT))){
+		BM_elem_flag_test(bme->v1, BM_ELEM_SELECT) ||
+		 BM_elem_flag_test(bme->v2, BM_ELEM_SELECT)){
 		return 0;
 	}
 	return 1;
@@ -314,9 +328,23 @@
 
 int MeshData_DerivedMesh_checkVert(MeshData *md, int index){
 	MVert *verts;
+	MVert *mv;
 	DerivedMesh* dm = (DerivedMesh*)md->data;
+	char hidden, selected;
 	verts = dm->getVertArray(dm);
-	if((verts[index].flag & 0) || (verts[index].flag & ME_HIDE)){
+	//TODO: remove these debugging variables mv and hidden
+	mv = &(verts[index]);
+	hidden =  (verts[index].flag & ME_HIDE);
+
+	//there is a weird bug where the selected flag is always on for meshes which aren't in editmode.
+	if(md->edit_mode){
+		selected = (verts[index].flag & 1);
+	}
+	else{
+		selected = 0;
+	}
+
+	if(hidden || selected){
 		return 0;
 	}
 	return 1;
@@ -344,13 +372,24 @@
 	MEdge* edges;
 	MVert* verts;
 	DerivedMesh* dm = (DerivedMesh*)md->data;
+	char hidden, v1_selected, v2_selected;
 	edges = dm->getEdgeArray(dm);
 	verts = dm->getVertArray(dm);
 	/* check whether edge is hidden and if either of its vertices (v1 and v2) are selected
 	When they are selected their flag will be 0? (if indeed it works similar to bmesh)*/
 	/* in this case v1 and v2 are integer indexes for the vertex array*/
-	if((verts[edges[index].v1].flag & 0) ||
-		(verts[edges[index].v2].flag & 0) ||
+
+	if(md->edit_mode){
+		v1_selected = verts[edges[index].v1].flag & 1;
+		v2_selected = verts[edges[index].v2].flag & 1;
+	}
+	else{
+		v1_selected = 0;
+		v2_selected = 0;
+	}
+
+	if(v1_selected ||
+		v2_selected ||
 		(edges[index].flag & ME_HIDE)){
 		return 0;
 	}
@@ -362,9 +401,11 @@
 }
 
 
-MeshData* MeshData_create(void* mesh_data, SnapMesh_data_type data_type){
+MeshData* SnapMesh_createMeshData(Snap* sm, void* mesh_data, SnapMesh_data_type data_type){
+	SnapMesh_data* sm_data = (SnapMesh_data*)sm->snap_data;
 	MeshData* md = (MeshData*)MEM_mallocN(sizeof(MeshData), "snapmesh_meshdata");
 	md->data = mesh_data;
+	md->edit_mode = (sm->ob->mode & OB_MODE_EDIT);//TODO: this variable might need to be updated if this thing is cached...
 	switch(data_type){
 	case SNAPMESH_DATA_TYPE_DerivedMesh:
 		md->getNumVerts = MeshData_DerivedMesh_getNumVerts;
@@ -413,7 +454,7 @@
 
 	//put an early exit flag somewhere here for the case when there is no geometry in mesh_data;
 	sm_data->data_type = data_type;
-	sm_data->mesh_data = MeshData_create(mesh_data, data_type);
+	sm_data->mesh_data = SnapMesh_createMeshData(sm, mesh_data, data_type);
 	sm_data->dm_index_array = NULL;
 
 	sm->snap_data = (void*)sm_data;
@@ -422,6 +463,7 @@
 }
 
 void SnapMesh_free(Snap* sm){
+	//TODO: there is some memory not getting freed somwhere in here...
 	SnapMesh_data *sm_data = sm->snap_data;
 	MEM_freeN(sm_data->mesh_data);
 	MEM_freeN(sm_data);
@@ -434,13 +476,6 @@
 
 /*TODO: ask Martin how this code works so I can comment it properly, and better understand it*/
 void SnapMesh_snap_vertex(Snap* sm){
-	/*There are a couple of bugs with my code for vertex snapping at the moment.
-	  1. When using a DerivedMesh in edit mode it is snapping to points in mid air, in a grid like fashion.
-	  2. When using a BMEditMesh or DerivedMesh in edit mode, with more than one mesh object in the scene,
-		 and the mouse is close to a vertex in the currently edited object, there are some weird
-		 false positions for the snap point location
-	TODO: solve these bugs! might be wise to wait until the changes to transform are made before doing this, because
-			they, especially the second bug are probably related to the transform side of things*/
 	int i, totvert;
 	SnapMesh_data* sm_data = (SnapMesh_data*)sm->snap_data;
 	MeshData* md = sm_data->mesh_data;
@@ -449,7 +484,6 @@
 	float location[3];
 	int new_dist;
 	float new_depth;
-	float r_depth;
 	int screen_loc[2];
 	MVert mv;
 
@@ -457,9 +491,6 @@
 
 	sm->retval = 0;
 
-	sm->r_dist = sm->min_distance; //TODO: investigate, does this r_dist value need to be stored in sm class?
-	r_depth = FLT_MAX;
-
 	md->index_init(md, SNAPMESH_DAT_vert); //should perhaps only be called once per mesh...
 	//was causing some segfault issues before with getVert.
 
@@ -483,7 +514,7 @@
 		project_int(sm->ar, location, screen_loc);
 		new_dist = abs(screen_loc[0] - sm->mval[0]) + abs(screen_loc[1] - sm->mval[1]);
 
-		if(new_dist > sm->r_dist || new_depth >= r_depth){//what is r_depth in original code? is it always FLT_MAX?
+		if(new_dist > sm->snap_point.r_dist || new_depth >= sm->snap_point.r_depth){//what is r_depth in original code? is it always FLT_MAX?
 			//I'm thinking this checks whether depth of snap point is the deeper than an existing point, if it is, then
 			//skip this vert. it also checks whether the distance between the mouse and the vert is small enough, if it
 			//isn't then skip this vert. it picks the closest one to the mouse, and the closest one to the screen.
@@ -491,15 +522,18 @@
 			continue;
 		}
 
-		r_depth = new_depth;
+		sm->snap_point.r_depth = new_depth;
 		sm->retval = 1;
+
 		copy_v3_v3(sm->snap_point.location, location);
 
+		printf("SnapPointInternal: %f, %f, %f\n", location[0], location[1], location[2]);
+
 		normal_short_to_float_v3(sm->snap_point.normal, mv.no);
 		mul_m3_v3(sm->timat, sm->snap_point.normal);
 		normalize_v3(sm->snap_point.normal);
 
-		sm->r_dist = new_dist;
+		sm->snap_point.r_dist = new_dist;
 	}
 }
 
@@ -512,14 +546,116 @@
 }
 
 void SnapMesh_snap_edge(Snap* sm){
-	int i, totedge;
+	int i, totedge, result, new_dist, r_dist;
+	int screen_loc[2];
+
+	float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
+	float edge_loc[3], vec[3], location[3];
+	float n1[3], n2[3];
+	float mul, new_depth, r_depth;
+
 	SnapMesh_data* sm_data = (SnapMesh_data*)sm->snap_data;
 	MeshData* md = sm_data->mesh_data;
+	MVert v1, v2;
 
+	copy_v3_v3(ray_end, sm->ray_normal_local);
+	mul_v3_fl(ray_end, 2000); //TODO: what!?
+	add_v3_v3v3(ray_end, sm->ray_start_local, ray_end);
+
+	sm->retval = 0;
+	r_depth = FLT_MAX;
+	r_dist = sm->min_distance;
+
 	md->index_init(md, SNAPMESH_DAT_edge); //should perhaps only be called once per mesh...
 
 	totedge = md->getNumEdges(md);
+	for(i=0;i<totedge;i++){
+		if(md->checkEdge(md, i) == 0){
+			continue;
+		}
 
+		md->getEdgeVerts(md, i, &v1, &v2);
+
+		//why don't we care about result?
+		result = isect_line_line_v3(v1.co, v2.co, sm->ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */
+		//intersect is closest point on line (beteween v1 and v2) to the line between ray_start_local and ray_end.
+		if(!result){
+			continue;
+		}
+
+		//dvec is calculated to be from mouse location to closest intersection point on line.
+		sub_v3_v3v3(dvec, intersect, sm->ray_start_local);
+
+		sub_v3_v3v3(edge_loc, v1.co, v2.co); //edge loc is vector representing line from v2 to v1.
+		sub_v3_v3v3(vec, intersect, v2.co); //vec is vector from v2 to intersect
+
+		//mul is value representing how large vec is compared to edge_loc.
+		//if vec is the same length and in the same direction as edge_loc, then mul == 1
+		mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc);
+
+		//this code constrains the intersect point on line to be lying on the edge_loc vector.
+		//because mul will be greater than 1 when vec is longer and in the same direction as edge_loc
+		//and mul will be less than 0 when it is going in the opposite direction to edge_loc.
+		if (mul > 1) {

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list