* DragExtrudeFaces: diagonal extruded brushes joints if extruding multiple faces per brush

This commit is contained in:
Garux 2020-03-08 17:23:02 +03:00
parent d664d15f17
commit 6e88e7b746
2 changed files with 167 additions and 31 deletions

View File

@ -216,7 +216,7 @@ public:
} }
} }
}; };
/* brush0, brush2 are supposed to have same amount of faces in the same order */ /* brush0, brush2 are supposed to have same amount of faces in the same order; brush2 bigger than brush0 */
void brush_extrudeDiag( const Brush& brush0, const Brush& brush2, brush_vector_t& m_out, const HollowSettings& m_settings ){ void brush_extrudeDiag( const Brush& brush0, const Brush& brush2, brush_vector_t& m_out, const HollowSettings& m_settings ){
TextureProjection projection; TextureProjection projection;
TexDef_Construct_Default( projection ); TexDef_Construct_Default( projection );

View File

@ -811,6 +811,15 @@ public:
BrushInstance* m_brushInstance; BrushInstance* m_brushInstance;
struct InFaceOutBrush{ Face* m_face; PlanePoints m_planepoints; Brush* m_outBrush; }; struct InFaceOutBrush{ Face* m_face; PlanePoints m_planepoints; Brush* m_outBrush; };
std::vector<InFaceOutBrush> m_faces; std::vector<InFaceOutBrush> m_faces;
std::vector<InFaceOutBrush>::iterator faceFind( const Face* face ){
return std::find_if( m_faces.begin(), m_faces.end(), [face]( const InFaceOutBrush& infaceoutbrush ){ return face == infaceoutbrush.m_face; } );
}
std::vector<InFaceOutBrush>::const_iterator faceFind( const Face* face ) const {
return std::find_if( m_faces.begin(), m_faces.end(), [face]( const InFaceOutBrush& infaceoutbrush ){ return face == infaceoutbrush.m_face; } );
}
bool faceExcluded( const Face* face ) const {
return faceFind( face ) == m_faces.end();
}
}; };
std::vector<ExtrudeSource> m_extrudeSources; std::vector<ExtrudeSource> m_extrudeSources;
@ -891,6 +900,14 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const
} }
} }
for( ExtrudeSource& source : m_extrudeSources ){ for( ExtrudeSource& source : m_extrudeSources ){
Brush& brush0 = source.m_brushInstance->getBrush();
if( source.m_faces.size() > 1 ){
Brush* tmpbrush = new Brush( brush0 );
offsetFaces( source, *tmpbrush, offset );
brush_extrudeDiag( brush0, *tmpbrush, source );
delete tmpbrush;
}
else{
for( auto& infaceoutbrush : source.m_faces ){ for( auto& infaceoutbrush : source.m_faces ){
const Face* face = infaceoutbrush.m_face; const Face* face = infaceoutbrush.m_face;
Brush* brush = infaceoutbrush.m_outBrush; Brush* brush = infaceoutbrush.m_outBrush;
@ -906,9 +923,10 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const
for( const WindingVertex& vertex : face->getWinding() ){ for( const WindingVertex& vertex : face->getWinding() ){
if( vertex.adjacent != c_brush_maxFaces ){ if( vertex.adjacent != c_brush_maxFaces ){
Brush::const_iterator faceIt = source.m_brushInstance->getBrush().begin(); Brush::const_iterator faceIt = brush0.begin();
std::advance( faceIt, vertex.adjacent ); std::advance( faceIt, vertex.adjacent );
f = brush->addFace( **faceIt ); brush->addFace( **faceIt );
}
} }
} }
} }
@ -931,6 +949,15 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const
face->getPlane().copy( infaceoutbrush.m_planepoints ); face->getPlane().copy( infaceoutbrush.m_planepoints );
face->planeChanged(); face->planeChanged();
} }
if( source.m_faces.size() > 1 ){
Brush* tmpbrush = new Brush( brush0 );
tmpbrush->evaluateBRep();
offsetFaces( source, brush0, offset );
if( brush0.hasContributingFaces() )
brush_extrudeDiag( brush0, *tmpbrush, source );
delete tmpbrush;
}
else{
for( auto& infaceoutbrush : source.m_faces ){ for( auto& infaceoutbrush : source.m_faces ){
Face* face = infaceoutbrush.m_face; Face* face = infaceoutbrush.m_face;
Brush* brush = infaceoutbrush.m_outBrush; Brush* brush = infaceoutbrush.m_outBrush;
@ -939,24 +966,133 @@ void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const
brush->copy( brush0 ); brush->copy( brush0 );
Face* f = brush->addFace( *face ); Face* f = brush->addFace( *face );
face->assign_planepts( infaceoutbrush.m_planepoints );
f->getPlane().offset( offset ); f->getPlane().offset( offset );
f->getPlane().reverse(); f->getPlane().reverse();
f->planeChanged(); f->planeChanged();
brush->removeEmptyFaces(); brush->removeEmptyFaces();
// modify original brush // modify original brush
face->getPlane().copy( infaceoutbrush.m_planepoints );
face->getPlane().offset( offset ); face->getPlane().offset( offset );
face->planeChanged(); face->planeChanged();
} }
} }
} }
} }
}
void set0( const Vector3& start, const Plane3& planeSelected ){ void set0( const Vector3& start, const Plane3& planeSelected ){
m_0 = start; m_0 = start;
m_planeSelected = planeSelected; m_planeSelected = planeSelected;
} }
private:
void offsetFaces( const ExtrudeSource& source, Brush& brush, const float offset ){
const Brush& brush0 = source.m_brushInstance->getBrush();
for( Brush::const_iterator i0 = brush0.begin(); i0 != brush0.end(); ++i0 ){
const Face& face0 = *( *i0 );
if( !source.faceExcluded( &face0 ) ){
Brush::const_iterator i = brush.begin();
std::advance( i, std::distance( brush0.begin(), i0 ) );
Face& face = *( *i );
face.getPlane().offset( offset );
face.planeChanged();
}
}
brush.evaluateBRep();
}
/* brush0, brush2 are supposed to have same amount of faces in the same order; brush2 bigger than brush0 */
void brush_extrudeDiag( const Brush& brush0, const Brush& brush2, ExtrudeSource& source ){
TextureProjection projection;
TexDef_Construct_Default( projection );
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 );
auto infaceoutbrush_iter = source.faceFind( &face0 ); // brush0 = source.m_brushInstance->getBrush()
if( infaceoutbrush_iter != source.m_faces.end() ) {
if( face0.contributes() || face2.contributes() ) {
const char* shader = face0.GetShader();
Brush* outBrush = ( *infaceoutbrush_iter ).m_outBrush;
outBrush->clear();
if( face0.contributes() ){
if( Face* newFace = outBrush->addFace( face0 ) ) {
newFace->flipWinding();
}
}
if( face2.contributes() ){
outBrush->addFace( face2 );
}
if( face0.contributes() && face2.contributes() ){ //sew two valid windings
const auto addSidePlanes = [&outBrush, 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;
double bestdot = -1;
for( std::size_t index2 = 0; index2 < winding2.numpoints; ++index2 ){
const double dot = vector3_dot(
vector3_normalised(
vector3_cross(
winding0[index0].vertex - winding0[next].vertex,
winding0[index0].vertex - winding2[index2].vertex
)
),
normal
);
if( dot > bestdot ) {
bestdot = dot;
BestPoint = winding2[index2].vertex;
}
}
outBrush->addPlane( winding0[swap? next : index0].vertex,
winding0[swap? index0 : next].vertex,
BestPoint,
shader,
projection );
}
};
//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 auto addSidePlanes = [&outBrush, shader, &projection]( const Winding& winding0, const Brush& brush2, const Plane3 plane, const bool swap ){
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();
for( std::size_t index2 = 0; index2 < winding2.numpoints; ++index2 ){
const double testdist = vector3_length( winding0[index0].vertex - winding2[index2].vertex );
if( testdist < bestdist && plane3_distance_to_point( plane, winding2[index2].vertex ) > .05 ) {
bestdist = testdist;
BestPoint = winding2[index2].vertex;
}
}
}
outBrush->addPlane( winding0[swap? next : index0].vertex,
winding0[swap? index0 : next].vertex,
BestPoint,
shader,
projection );
}
};
if( face0.contributes() )
addSidePlanes( face0.getWinding(), brush2, face0.getPlane().plane3(), false );
else if( face2.contributes() )
addSidePlanes( face2.getWinding(), brush0, plane3_flipped( face2.getPlane().plane3() ), true );
}
outBrush->removeEmptyFaces();
}
}
}
}
}; };