Przeglądaj źródła

- IFC: avoid artifacts in high-curvature regions (or the boundaries thereof) of IfcSweptDiskSolid elements.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1299 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 13 lat temu
rodzic
commit
15c0b8b955
1 zmienionych plików z 47 dodań i 20 usunięć
  1. 47 20
      code/IFCGeometry.cpp

+ 47 - 20
code/IFCGeometry.cpp

@@ -581,6 +581,8 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv
 	startvec.y = 1.0f;
 	startvec.y = 1.0f;
 	startvec.z = 1.0f;
 	startvec.z = 1.0f;
 
 
+	unsigned int last_dir = 0;
+
 	// generate circles at the sweep positions
 	// generate circles at the sweep positions
 	for(size_t i = 0; i < samples; ++i) {
 	for(size_t i = 0; i < samples; ++i) {
 
 
@@ -596,24 +598,34 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv
 		// figure out an arbitrary point q so that (p-q) * d = 0,
 		// figure out an arbitrary point q so that (p-q) * d = 0,
 		// try to maximize ||(p-q)|| * ||(p_last-q_last)|| 
 		// try to maximize ||(p-q)|| * ||(p_last-q_last)|| 
 		IfcVector3 q;
 		IfcVector3 q;
-		if (abs(d.x) > 1e-6) {
-			q.y = startvec.y;
-			q.z = startvec.z;
-			q.x = -(d.y * q.y + d.z * q.z) / d.x;
-		}
-		else if (abs(d.y) > 1e-6) {
-			q.x = startvec.x;
-			q.z = startvec.z;
-			q.y = -(d.x * q.x + d.z * q.z) / d.y;
-		}
-		else { // if (abs(d.z) > 1e-6) 
-			q.y = startvec.y;
-			q.x = startvec.x;
-			q.z = -(d.y * q.y + d.x * q.x) / d.z;
+		bool take_any = false;
+
+		for (unsigned int i = 0; i < 2; ++i, take_any = true) {
+			if ((last_dir == 0 || take_any) && abs(d.x) > 1e-6) {
+				q.y = startvec.y;
+				q.z = startvec.z;
+				q.x = -(d.y * q.y + d.z * q.z) / d.x;
+				last_dir = 0;
+				break;
+			}
+			else if ((last_dir == 1 || take_any) && abs(d.y) > 1e-6) {
+				q.x = startvec.x;
+				q.z = startvec.z;
+				q.y = -(d.x * q.x + d.z * q.z) / d.y;
+				last_dir = 1;
+				break;
+			}
+			else if ((last_dir == 2 && abs(d.z) > 1e-6) || take_any) { 
+				q.y = startvec.y;
+				q.x = startvec.x;
+				q.z = -(d.y * q.y + d.x * q.x) / d.z;
+				last_dir = 2;
+				break;
+			}
 		}
 		}
 
 
-		startvec = q;
 		q *= solid.Radius / q.Length();
 		q *= solid.Radius / q.Length();
+		startvec = q;
 
 
 		// generate a rotation matrix to rotate q around d
 		// generate a rotation matrix to rotate q around d
 		IfcMatrix4 rot;
 		IfcMatrix4 rot;
@@ -630,12 +642,27 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv
 	// make quads
 	// make quads
 	for(size_t i = 0; i < samples - 1; ++i) {
 	for(size_t i = 0; i < samples - 1; ++i) {
 
 
-		for (unsigned int seg = 0; seg < cnt_segments - 1; ++seg) {
+		const aiVector3D& this_start = points[ i * cnt_segments ];
+
+		// locate corresponding point on next sample ring
+		unsigned int best_pair_offset = 0;
+		float best_distance_squared = 1e10f;
+		for (unsigned int seg = 0; seg < cnt_segments; ++seg) {
+			const aiVector3D& p = points[ (i+1) * cnt_segments + seg];
+			const float l = (p-this_start).SquareLength();
+
+			if(l < best_distance_squared) {
+				best_pair_offset = seg;
+				best_distance_squared = l;
+			}
+		}
+
+		for (unsigned int seg = 0; seg < cnt_segments; ++seg) {
 
 
-			result.verts.push_back(points[ i * cnt_segments + seg]);
-			result.verts.push_back(points[ i * cnt_segments + seg + 1]);
-			result.verts.push_back(points[ (i+1) * cnt_segments + seg + 1]);
-			result.verts.push_back(points[ (i+1) * cnt_segments + seg]);
+			result.verts.push_back(points[ i * cnt_segments + (seg % cnt_segments)]);
+			result.verts.push_back(points[ i * cnt_segments + (seg + 1) % cnt_segments]);
+			result.verts.push_back(points[ (i+1) * cnt_segments + ((seg + 1 + best_pair_offset) % cnt_segments)]);
+			result.verts.push_back(points[ (i+1) * cnt_segments + ((seg + best_pair_offset) % cnt_segments)]);
 
 
 			result.vertcnt.push_back(4);
 			result.vertcnt.push_back(4);
 		}
 		}