* improved CSGTool::Hollow::diagonal algorithm (reliable for complex brushes complete extrude, handle simple brushes deep partial extrude)
This commit is contained in:
parent
9f29864f50
commit
d664d15f17
109
radiant/csg.cpp
109
radiant/csg.cpp
|
|
@ -90,7 +90,7 @@ public:
|
||||||
const double dot = vector3_dot( face.getPlane().plane3().normal(), m_exclusionAxis );
|
const double dot = vector3_dot( face.getPlane().plane3().normal(), m_exclusionAxis );
|
||||||
return dot < m_mindot + 0.001 || dot > m_maxdot - 0.001;
|
return dot < m_mindot + 0.001 || dot > m_maxdot - 0.001;
|
||||||
}
|
}
|
||||||
else{
|
else{ // note: straight equality check: may explode, when used with modified faces (e.g. ePull tmpbrush offset faces forth and back) (works so far)
|
||||||
return std::find( m_exclude_vec.begin(), m_exclude_vec.end(), face.getPlane().plane3().normal() ) != m_exclude_vec.end();
|
return std::find( m_exclude_vec.begin(), m_exclude_vec.end(), face.getPlane().plane3().normal() ) != m_exclude_vec.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -213,84 +213,93 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( m_settings.m_hollowType == eDiag ) {
|
|
||||||
if( face.contributes() ) {
|
|
||||||
m_out.push_back( new Brush( m_brush ) );
|
|
||||||
m_out.back()->clear();
|
|
||||||
|
|
||||||
Face* newFace = m_out.back()->addFace( face );
|
|
||||||
if( newFace != 0 ) {
|
|
||||||
newFace->planeChanged();
|
|
||||||
}
|
}
|
||||||
newFace = m_out.back()->addFace( face );
|
|
||||||
|
|
||||||
if( newFace != 0 ) {
|
|
||||||
if( !m_settings.m_removeInner && m_settings.m_caulk ){
|
|
||||||
newFace->SetShader( GetCaulkShader() );
|
|
||||||
}
|
}
|
||||||
newFace->flipWinding();
|
};
|
||||||
newFace->getPlane().offset( m_settings.m_offset );
|
/* brush0, brush2 are supposed to have same amount of faces in the same order */
|
||||||
newFace->planeChanged();
|
void brush_extrudeDiag( const Brush& brush0, const Brush& brush2, brush_vector_t& m_out, const HollowSettings& m_settings ){
|
||||||
}
|
|
||||||
|
|
||||||
const Winding& winding = face.getWinding();
|
|
||||||
TextureProjection projection;
|
TextureProjection projection;
|
||||||
TexDef_Construct_Default( projection );
|
TexDef_Construct_Default( projection );
|
||||||
for( std::size_t index = 0; index < winding.numpoints; ++index ){
|
const char* shader = m_settings.m_caulk ? GetCaulkShader() : TextureBrowser_GetSelectedShader();
|
||||||
const std::size_t next = Winding_next( winding, index );
|
|
||||||
|
for( Brush::const_iterator i0 = brush0.begin(); i0 != brush0.end(); ++i0 ){
|
||||||
|
const Face& face0 = *( *i0 );
|
||||||
|
Brush::const_iterator i2 = brush2.begin();
|
||||||
|
std::advance( i2, std::distance( brush0.begin(), i0 ) );
|
||||||
|
const Face& face2 = *( *i2 );
|
||||||
|
if( !m_settings.faceExcluded( face0 ) ) {
|
||||||
|
if( face0.contributes() ) {
|
||||||
|
m_out.push_back( new Brush( brush0 ) );
|
||||||
|
m_out.back()->clear();
|
||||||
|
|
||||||
|
if( Face* newFace = m_out.back()->addFace( face0 ) ) {
|
||||||
|
if( !m_settings.m_removeInner && m_settings.m_caulk ){
|
||||||
|
newFace->SetShader( shader );
|
||||||
|
}
|
||||||
|
newFace->flipWinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( face2.contributes() ){ //sew two valid windings
|
||||||
|
m_out.back()->addFace( face2 );
|
||||||
|
|
||||||
|
const auto addSidePlanes = [&m_out, shader, &projection]( const Winding& winding0, const Winding& winding2, const DoubleVector3 normal, const bool swap ){
|
||||||
|
for( std::size_t index0 = 0; index0 < winding0.numpoints; ++index0 ){
|
||||||
|
const std::size_t next = Winding_next( winding0, index0 );
|
||||||
Vector3 BestPoint;
|
Vector3 BestPoint;
|
||||||
float bestdist = 999999;
|
double bestdot = -1;
|
||||||
|
|
||||||
const Face* parallel_face = nullptr;
|
|
||||||
for( const Face* f : m_brush ) {
|
|
||||||
if( vector3_equal_epsilon( face.getPlane().plane3().normal(), f->getPlane().plane3().normal(), c_PLANE_NORMAL_EPSILON ) ){
|
|
||||||
parallel_face = f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( parallel_face != nullptr ){
|
|
||||||
const Winding& winding2 = parallel_face->getWinding();
|
|
||||||
float bestdot = -1;
|
|
||||||
for( std::size_t index2 = 0; index2 < winding2.numpoints; ++index2 ){
|
for( std::size_t index2 = 0; index2 < winding2.numpoints; ++index2 ){
|
||||||
const float dot = vector3_dot(
|
const double dot = vector3_dot(
|
||||||
vector3_normalised(
|
vector3_normalised(
|
||||||
vector3_cross(
|
vector3_cross(
|
||||||
winding[index].vertex - winding[next].vertex,
|
winding0[index0].vertex - winding0[next].vertex,
|
||||||
winding[index].vertex - winding2[index2].vertex
|
winding0[index0].vertex - winding2[index2].vertex
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
face.getPlane().plane3().normal()
|
normal
|
||||||
);
|
);
|
||||||
if( dot > bestdot ) {
|
if( dot > bestdot ) {
|
||||||
bestdot = dot;
|
bestdot = dot;
|
||||||
BestPoint = winding2[index2].vertex;
|
BestPoint = winding2[index2].vertex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_out.back()->addPlane( winding0[swap? next : index0].vertex,
|
||||||
|
winding0[swap? index0 : next].vertex,
|
||||||
|
BestPoint,
|
||||||
|
shader,
|
||||||
|
projection );
|
||||||
}
|
}
|
||||||
else{
|
};
|
||||||
for( const Face* f : m_brush ) {
|
//insert side planes from each winding perspective, as their form may change after brush expansion
|
||||||
|
addSidePlanes( face0.getWinding(), face2.getWinding(), face0.getPlane().plane3().normal(), false );
|
||||||
|
addSidePlanes( face2.getWinding(), face0.getWinding(), face0.getPlane().plane3().normal(), true );
|
||||||
|
}
|
||||||
|
else{ //one valid winding: this way may produce garbage with complex brushes, extruded partially, but does preferred result with simple ones
|
||||||
|
const Winding& winding0 = face0.getWinding();
|
||||||
|
for( std::size_t index0 = 0; index0 < winding0.numpoints; ++index0 ){
|
||||||
|
const std::size_t next = Winding_next( winding0, index0 );
|
||||||
|
Vector3 BestPoint;
|
||||||
|
double bestdist = 999999;
|
||||||
|
for( const Face* f : brush2 ) {
|
||||||
const Winding& winding2 = f->getWinding();
|
const Winding& winding2 = f->getWinding();
|
||||||
for( std::size_t index2 = 0; index2 < winding2.numpoints; ++index2 ){
|
for( std::size_t index2 = 0; index2 < winding2.numpoints; ++index2 ){
|
||||||
const float testdist = vector3_length( winding[index].vertex - winding2[index2].vertex );
|
const double testdist = vector3_length( winding0[index0].vertex - winding2[index2].vertex );
|
||||||
if( testdist < bestdist ) {
|
if( testdist < bestdist && plane3_distance_to_point( face0.getPlane().plane3(), winding2[index2].vertex ) > .05 ) {
|
||||||
bestdist = testdist;
|
bestdist = testdist;
|
||||||
BestPoint = winding2[index2].vertex;
|
BestPoint = winding2[index2].vertex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
m_out.back()->addPlane( winding0[index0].vertex,
|
||||||
m_out.back()->addPlane( winding[next].vertex,
|
winding0[next].vertex,
|
||||||
winding[index].vertex,
|
|
||||||
BestPoint,
|
BestPoint,
|
||||||
m_settings.m_caulk ? GetCaulkShader() : TextureBrowser_GetSelectedShader(),
|
shader,
|
||||||
projection );
|
projection );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
class FaceOffset {
|
class FaceOffset {
|
||||||
const HollowSettings& m_settings;
|
const HollowSettings& m_settings;
|
||||||
|
|
@ -337,8 +346,8 @@ public:
|
||||||
else if( m_settings.m_hollowType == eDiag ) {
|
else if( m_settings.m_hollowType == eDiag ) {
|
||||||
Brush* tmpbrush = new Brush( *brush );
|
Brush* tmpbrush = new Brush( *brush );
|
||||||
Brush_forEachFace( *tmpbrush, FaceOffset( m_settings ) );
|
Brush_forEachFace( *tmpbrush, FaceOffset( m_settings ) );
|
||||||
tmpbrush->removeEmptyFaces();
|
tmpbrush->evaluateBRep();
|
||||||
Brush_forEachFace( *tmpbrush, FaceMakeBrush( *brush, out, m_settings ) );
|
brush_extrudeDiag( *brush, *tmpbrush, out, m_settings );
|
||||||
delete tmpbrush;
|
delete tmpbrush;
|
||||||
if( !m_settings.m_removeInner && m_settings.m_caulk ) {
|
if( !m_settings.m_removeInner && m_settings.m_caulk ) {
|
||||||
Brush_forEachFace( *brush, CaulkFace( m_settings ) );
|
Brush_forEachFace( *brush, CaulkFace( m_settings ) );
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user