- 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
pull/6/merge
aramis_acg 2012-09-10 00:40:41 +00:00
parent a038288af9
commit 15c0b8b955
1 changed files with 47 additions and 20 deletions

View File

@ -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);
}