diff --git a/code/IFCGeometry.cpp b/code/IFCGeometry.cpp index 525208abc..bb1fe35a1 100644 --- a/code/IFCGeometry.cpp +++ b/code/IFCGeometry.cpp @@ -581,6 +581,8 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv startvec.y = 1.0f; startvec.z = 1.0f; + unsigned int last_dir = 0; + // generate circles at the sweep positions 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, // try to maximize ||(p-q)|| * ||(p_last-q_last)|| 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(); + startvec = q; // generate a rotation matrix to rotate q around d IfcMatrix4 rot; @@ -630,12 +642,27 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv // make quads 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 ]; - 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]); + // 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 % 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); }