[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15059] branches/harmonic-skeleton/source/ blender: Retargetting

Martin Poirier theeth at yahoo.com
Fri May 30 19:42:02 CEST 2008


Revision: 15059
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15059
Author:   theeth
Date:     2008-05-30 19:42:02 +0200 (Fri, 30 May 2008)

Log Message:
-----------
Retargetting

More refined symmetry grouping (can take care of tails properly) and better matching between symmetry groups (based on relative length of arcs)

Modified Paths:
--------------
    branches/harmonic-skeleton/source/blender/blenlib/BLI_graph.h
    branches/harmonic-skeleton/source/blender/blenlib/intern/graph.c
    branches/harmonic-skeleton/source/blender/include/reeb.h
    branches/harmonic-skeleton/source/blender/src/autoarmature.c
    branches/harmonic-skeleton/source/blender/src/reeb.c

Modified: branches/harmonic-skeleton/source/blender/blenlib/BLI_graph.h
===================================================================
--- branches/harmonic-skeleton/source/blender/blenlib/BLI_graph.h	2008-05-30 14:56:23 UTC (rev 15058)
+++ branches/harmonic-skeleton/source/blender/blenlib/BLI_graph.h	2008-05-30 17:42:02 UTC (rev 15059)
@@ -52,6 +52,7 @@
 	float length;
 
 	int symmetry_level;
+	int symmetry_group;
 	int symmetry_flag;
 } BArc;
 
@@ -98,5 +99,6 @@
  * axial symetry sides */
 #define SYM_SIDE_POSITIVE		1
 #define SYM_SIDE_NEGATIVE		2
+/* Anything higher is the order in radial symmetry */
 
 #endif /*BLI_GRAPH_H_*/

Modified: branches/harmonic-skeleton/source/blender/blenlib/intern/graph.c
===================================================================
--- branches/harmonic-skeleton/source/blender/blenlib/intern/graph.c	2008-05-30 14:56:23 UTC (rev 15058)
+++ branches/harmonic-skeleton/source/blender/blenlib/intern/graph.c	2008-05-30 17:42:02 UTC (rev 15059)
@@ -23,6 +23,9 @@
  * graph.c: Common graph interface and methods
  */
 
+#include <float.h> 
+#include <math.h>
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_graph.h"
@@ -31,6 +34,12 @@
 
 #include "BKE_utildefines.h"
 
+static void testRadialSymmetry(BGraph *graph, BNode* root_node, RadialArc* ring, int total, float axis[3], float limit, int group);
+
+static void handleAxialSymmetry(BGraph *graph, BNode *root_node, int depth, float axis[3], float limit);
+static void testAxialSymmetry(BGraph *graph, BNode* root_node, BNode* node1, BNode* node2, BArc* arc1, BArc* arc2, float axis[3], float limit, int group);
+static void flagAxialSymmetry(BNode *root_node, BNode *end_node, BArc *arc, int group);
+
 void BLI_freeNode(BGraph *graph, BNode *node)
 {
 	if (node->arcs)
@@ -280,64 +289,19 @@
 	VecAddf(v, v, pv);
 }
 
-static void markRadialSymmetry(BGraph *graph, BNode *node, int depth, float axis[3], float limit)
+static void testRadialSymmetry(BGraph *graph, BNode* root_node, RadialArc* ring, int total, float axis[3], float limit, int group)
 {
-	RadialArc *ring = NULL;
-	RadialArc *unit;
 	int symmetric = 1;
-	int count = 0;
 	int i;
-
-	/* mark topological symmetry */
-	node->symmetry_flag |= SYM_TOPOLOGICAL;
-
-	/* count the number of arcs in the symmetry ring */
-	for (i = 0; i < node->degree; i++)
+	
+	/* sort ring by angle */
+	for (i = 0; i < total - 1; i++)
 	{
-		BArc *connectedArc = node->arcs[i];
-		
-		/* depth is store as a negative in flag. symmetry level is positive */
-		if (connectedArc->symmetry_level == -depth)
-		{
-			count++;
-		}
-	}
-
-	ring = MEM_callocN(sizeof(RadialArc) * count, "radial symmetry ring");
-	unit = ring;
-
-	/* fill in the ring */
-	for (unit = ring, i = 0; i < node->degree; i++)
-	{
-		BArc *connectedArc = node->arcs[i];
-		
-		/* depth is store as a negative in flag. symmetry level is positive */
-		if (connectedArc->symmetry_level == -depth)
-		{
-			BNode *otherNode = BLI_otherNode(connectedArc, node);
-			float vec[3];
-
-			unit->arc = connectedArc;
-
-			/* project the node to node vector on the symmetry plane */
-			VecSubf(unit->n, otherNode->p, node->p);
-			Projf(vec, unit->n, axis);
-			VecSubf(unit->n, unit->n, vec);
-
-			Normalize(unit->n);
-
-			unit++;
-		}
-	}
-
-	/* sort ring */
-	for (i = 0; i < count - 1; i++)
-	{
-		float minAngle = 3; /* arbitrary high value, higher than 2, at least */
+		float minAngle = FLT_MAX;
 		int minIndex = -1;
 		int j;
 
-		for (j = i + 1; j < count; j++)
+		for (j = i + 1; j < total; j++)
 		{
 			float angle = Inpf(ring[i].n, ring[j].n);
 
@@ -364,22 +328,22 @@
 		}
 	}
 
-	for (i = 0; i < count && symmetric; i++)
+	for (i = 0; i < total && symmetric; i++)
 	{
 		BNode *node1, *node2;
 		float tangent[3];
 		float normal[3];
 		float p[3];
-		int j = (i + 1) % count; /* next arc in the circular list */
+		int j = (i + 1) % total; /* next arc in the circular list */
 
 		VecAddf(tangent, ring[i].n, ring[j].n);
 		Crossf(normal, tangent, axis);
 		
-		node1 = BLI_otherNode(ring[i].arc, node);
-		node2 = BLI_otherNode(ring[j].arc, node);
+		node1 = BLI_otherNode(ring[i].arc, root_node);
+		node2 = BLI_otherNode(ring[j].arc, root_node);
 
 		VECCOPY(p, node2->p);
-		BLI_mirrorAlongAxis(p, node->p, normal);
+		BLI_mirrorAlongAxis(p, root_node->p, normal);
 		
 		/* check if it's within limit before continuing */
 		if (VecLenf(node1->p, p) > limit)
@@ -392,23 +356,192 @@
 	if (symmetric)
 	{
 		/* mark node as symmetric physically */
-		VECCOPY(node->symmetry_axis, axis);
-		node->symmetry_flag |= SYM_PHYSICAL;
-		node->symmetry_flag |= SYM_RADIAL;
+		VECCOPY(root_node->symmetry_axis, axis);
+		root_node->symmetry_flag |= SYM_PHYSICAL;
+		root_node->symmetry_flag |= SYM_RADIAL;
 		
+		/* FLAG SYMMETRY GROUP */
+		for (i = 0; i < total; i++)
+		{
+			ring[i].arc->symmetry_group = group;
+			ring[i].arc->symmetry_flag = i;
+		}
+
 		if (graph->radial_symmetry)
 		{
-			graph->radial_symmetry(node, ring, count);
+			graph->radial_symmetry(root_node, ring, total);
 		}
 	}
+}
 
+static void handleRadialSymmetry(BGraph *graph, BNode *root_node, int depth, float axis[3], float limit)
+{
+	RadialArc *ring = NULL;
+	RadialArc *unit;
+	int total = 0;
+	int group;
+	int first;
+	int i;
+
+	/* mark topological symmetry */
+	root_node->symmetry_flag |= SYM_TOPOLOGICAL;
+
+	/* total the number of arcs in the symmetry ring */
+	for (i = 0; i < root_node->degree; i++)
+	{
+		BArc *connectedArc = root_node->arcs[i];
+		
+		/* depth is store as a negative in flag. symmetry level is positive */
+		if (connectedArc->symmetry_level == -depth)
+		{
+			total++;
+		}
+	}
+
+	ring = MEM_callocN(sizeof(RadialArc) * total, "radial symmetry ring");
+	unit = ring;
+
+	/* fill in the ring */
+	for (unit = ring, i = 0; i < root_node->degree; i++)
+	{
+		BArc *connectedArc = root_node->arcs[i];
+		
+		/* depth is store as a negative in flag. symmetry level is positive */
+		if (connectedArc->symmetry_level == -depth)
+		{
+			BNode *otherNode = BLI_otherNode(connectedArc, root_node);
+			float vec[3];
+
+			unit->arc = connectedArc;
+
+			/* project the node to node vector on the symmetry plane */
+			VecSubf(unit->n, otherNode->p, root_node->p);
+			Projf(vec, unit->n, axis);
+			VecSubf(unit->n, unit->n, vec);
+
+			Normalize(unit->n);
+
+			unit++;
+		}
+	}
+
+	/* sort ring by arc length
+	 * using a rather bogus insertion sort
+	 * butrings will never get too big to matter
+	 * */
+	for (i = 0; i < total; i++)
+	{
+		int j;
+
+		for (j = i - 1; j >= 0; j--)
+		{
+			BArc *arc1, *arc2;
+			
+			arc1 = ring[j].arc;
+			arc2 = ring[j + 1].arc;
+			
+			if (arc1->length > arc2->length)
+			{
+				/* swap with smaller */
+				RadialArc tmp;
+				tmp = ring[j + 1];
+				ring[j + 1] = ring[j];
+				ring[j] = tmp;
+			}
+			else
+			{
+				break;
+			}
+		}
+	}
+
+	/* Dispatch to specific symmetry tests */
+	first = 0;
+	group = 0;
+	
+	for (i = 1; i < total; i++)
+	{
+		int dispatch = 0;
+		int last = i - 1;
+		
+		if (fabs(ring[first].arc->length - ring[i].arc->length) > limit)
+		{
+			dispatch = 1;
+		}
+
+		/* if not dispatching already and on last arc
+		 * Dispatch using current arc as last
+		 * */		
+		if (dispatch == 0 && i == total - 1)
+		{
+			last = i;
+			dispatch = 1;
+		} 
+		
+		if (dispatch)
+		{
+			int sub_total = last - first + 1; 
+
+			group += 1;
+
+			if (sub_total == 1)
+			{
+				printf("no dispatch\n");
+				/* NOTHING TO DO */
+			}
+			else if (sub_total == 2)
+			{
+				BArc *arc1, *arc2;
+				BNode *node1, *node2;
+				
+				printf("dispatch axial\n");
+
+				arc1 = ring[first].arc;
+				arc2 = ring[last].arc;
+				
+				node1 = BLI_otherNode(arc1, root_node);
+				node2 = BLI_otherNode(arc2, root_node);
+				
+				testAxialSymmetry(graph, root_node, node1, node2, arc1, arc2, axis, limit, group);
+			}
+			else if (sub_total != total) /* allocate a new sub ring if needed */
+			{
+				RadialArc *sub_ring = MEM_callocN(sizeof(RadialArc) * sub_total, "radial symmetry ring");
+				int sub_i;
+				
+				printf("dispatch radial sub ring\n");
+
+				/* fill in the sub ring */
+				for (sub_i = 0; sub_i < sub_total; sub_i++)
+				{
+					sub_ring[sub_i] = ring[first + sub_i];
+				}
+				
+				testRadialSymmetry(graph, root_node, sub_ring, sub_total, axis, limit, group);
+			
+				MEM_freeN(sub_ring);
+			}
+			else if (sub_total == total)
+			{
+				printf("dispatch radial full ring\n");
+
+				testRadialSymmetry(graph, root_node, ring, total, axis, limit, group);
+			}
+			
+			first = i;
+		}
+	}
+
+
 	MEM_freeN(ring);
 }
 
-static void setSideAxialSymmetry(BNode *root_node, BNode *end_node, BArc *arc)
+static void flagAxialSymmetry(BNode *root_node, BNode *end_node, BArc *arc, int group)
 {
 	float vec[3];
 	
+	arc->symmetry_group = group;
+	
 	VecSubf(vec, end_node->p, root_node->p);
 	
 	if (Inpf(vec, root_node->symmetry_axis) < 0)
@@ -421,20 +554,54 @@
 	}
 }
 
-static void markAxialSymmetry(BGraph *graph, BNode *node, int depth, float axis[3], float limit)
+static void testAxialSymmetry(BGraph *graph, BNode* root_node, BNode* node1, BNode* node2, BArc* arc1, BArc* arc2, float axis[3], float limit, int group)
 {
-	BArc *arc1 = NULL;
-	BArc *arc2 = NULL;
+	float nor[3], vec[3], p[3];
+
+	VecSubf(vec, node1->p, root_node->p);
+	Normalize(vec);
+	VecSubf(p, root_node->p, node2->p);
+	Normalize(p);
+	VecAddf(p, p, vec);
+
+	Crossf(vec, p, axis);
+	Crossf(nor, vec, axis);
+	
+	/* mirror node2 along axis */
+	VECCOPY(p, node2->p);
+	BLI_mirrorAlongAxis(p, root_node->p, nor);
+	
+	/* check if it's within limit before continuing */
+	if (VecLenf(node1->p, p) <= limit)
+	{
+		/* mark node as symmetric physically */
+		VECCOPY(root_node->symmetry_axis, nor);
+		root_node->symmetry_flag |= SYM_PHYSICAL;
+		root_node->symmetry_flag |= SYM_AXIAL;
+
+		/* flag side on arcs */
+		flagAxialSymmetry(root_node, node1, arc1, group);
+		flagAxialSymmetry(root_node, node2, arc2, group);
+		
+		if (graph->axial_symmetry)
+		{
+			graph->axial_symmetry(root_node, node1, node2, arc1, arc2);
+		}
+	}
+}
+
+static void handleAxialSymmetry(BGraph *graph, BNode *root_node, int depth, float axis[3], float limit)
+{
+	BArc *arc1 = NULL, *arc2 = NULL;
 	BNode *node1 = NULL, *node2 = NULL;
-	float nor[3], vec[3], p[3];
 	int i;
 	
 	/* mark topological symmetry */
-	node->symmetry_flag |= SYM_TOPOLOGICAL;
+	root_node->symmetry_flag |= SYM_TOPOLOGICAL;
 
-	for (i = 0; i < node->degree; i++)
+	for (i = 0; i < root_node->degree; i++)
 	{
-		BArc *connectedArc = node->arcs[i];
+		BArc *connectedArc = root_node->arcs[i];
 		
 		/* depth is store as a negative in flag. symmetry level is positive */

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list