robust algorithm for indirect Brush faces selection

This commit is contained in:
Garux 2018-03-21 04:12:06 +03:00
parent ed50787ee8
commit 73605bf94b
3 changed files with 26 additions and 14 deletions

View File

@ -229,6 +229,7 @@ virtual void BeginMesh( const Matrix4& localToWorld, bool twoSided = false ) = 0
virtual const VolumeTest& getVolume() const = 0; virtual const VolumeTest& getVolume() const = 0;
virtual const Vector3& getNear() const = 0; virtual const Vector3& getNear() const = 0;
virtual const Vector3& getFar() const = 0; virtual const Vector3& getFar() const = 0;
virtual const Matrix4& getScreen2world() const = 0;
virtual void TestPoint( const Vector3& point, SelectionIntersection& best ) = 0; virtual void TestPoint( const Vector3& point, SelectionIntersection& best ) = 0;
virtual void TestPolygon( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best, const DoubleVector3 planepoints[3] ) = 0; virtual void TestPolygon( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best, const DoubleVector3 planepoints[3] ) = 0;
virtual void TestLineLoop( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ) = 0; virtual void TestLineLoop( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ) = 0;

View File

@ -2720,15 +2720,22 @@ void selectReversedPlane( Selector& selector, const SelectedPlanes& selectedPlan
} }
} }
bool trySelectPlane( const Line& line ){ bool trySelectPlane( const SelectionTest& test ){
const Vector3 projected = vector4_projected(
matrix4_transformed_vector4(
test.getVolume().GetViewMatrix(),
Vector4( getFace().centroid(), 1 )
)
);
const Vector3 closest_point = vector4_projected(
matrix4_transformed_vector4(
test.getScreen2world(),
Vector4( 0, 0, projected[2], 1 )
)
);
for ( Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i ){ for ( Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i ){
const Vector3 v( vector3_subtracted( line_closest_point( line, ( *i ).vertex ), ( *i ).vertex ) ); if ( vector3_dot( getFace().plane3().normal(), closest_point - ( *i ).vertex ) < 0.005 ) /* epsilon to prevent almost perpendicular faces pickup */
const double dot = vector3_dot( getFace().plane3().normal(), v );
// globalOutputStream() << getFace().plane3().normal()[0] << " " << getFace().plane3().normal()[1] << " " << getFace().plane3().normal()[2] << " DOT " << dot << "\n";
//epsilon to prevent almost perpendicular faces pickup
if ( dot < 0.005 ) {
return false; return false;
}
} }
return true; return true;
} }
@ -3549,16 +3556,15 @@ void invertComponentSelection( SelectionSystem::EComponentMode mode ){
void selectPlanes( SelectionTest& test, FaceInstances_ptrs& bestInstances ){ void selectPlanes( SelectionTest& test, FaceInstances_ptrs& bestInstances ){
test.BeginMesh( localToWorld() ); test.BeginMesh( localToWorld() );
const Line line( test.getNear(), test.getFar() ); const Vector3 viewdir( vector3_normalised( Vector3( test.getVolume().GetModelview()[2], test.getVolume().GetModelview()[6], test.getVolume().GetModelview()[10] ) ) );
const Vector3 viewer( vector3_normalised( test.getNear() - test.getFar() ) );
double bestDot = 1; double bestDot = 1;
for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
{ {
if( !( *i ).trySelectPlane( line ) ){ if( !( *i ).trySelectPlane( test ) ){
continue; continue;
} }
const double dot = fabs( vector3_dot( ( *i ).getFace().plane3().normal(), viewer ) ); const double dot = fabs( vector3_dot( ( *i ).getFace().plane3().normal(), viewdir ) );
const double diff = bestDot - dot; const double diff = bestDot - dot;
if( diff > 0.03 ){ if( diff > 0.03 ){
bestDot = dot; bestDot = dot;

View File

@ -2690,6 +2690,7 @@ const View& m_view;
clipcull_t m_cull; clipcull_t m_cull;
Vector3 m_near; Vector3 m_near;
Vector3 m_far; Vector3 m_far;
Matrix4 m_screen2world;
public: public:
SelectionVolume( const View& view ) SelectionVolume( const View& view )
: m_view( view ){ : m_view( view ){
@ -2706,6 +2707,10 @@ const Vector3& getFar() const {
return m_far; return m_far;
} }
const Matrix4& getScreen2world() const {
return m_screen2world;
}
void BeginMesh( const Matrix4& localToWorld, bool twoSided ){ void BeginMesh( const Matrix4& localToWorld, bool twoSided ){
m_local2view = matrix4_multiplied_by_matrix4( m_view.GetViewMatrix(), localToWorld ); m_local2view = matrix4_multiplied_by_matrix4( m_view.GetViewMatrix(), localToWorld );
@ -2714,18 +2719,18 @@ void BeginMesh( const Matrix4& localToWorld, bool twoSided ){
m_cull = twoSided && !m_view.fill() ? eClipCullNone : ( matrix4_handedness( localToWorld ) == MATRIX4_RIGHTHANDED ) ? eClipCullCW : eClipCullCCW; m_cull = twoSided && !m_view.fill() ? eClipCullNone : ( matrix4_handedness( localToWorld ) == MATRIX4_RIGHTHANDED ) ? eClipCullCW : eClipCullCCW;
{ {
Matrix4 screen2world( matrix4_full_inverse( m_local2view ) ); m_screen2world = matrix4_full_inverse( m_local2view );
m_near = vector4_projected( m_near = vector4_projected(
matrix4_transformed_vector4( matrix4_transformed_vector4(
screen2world, m_screen2world,
Vector4( 0, 0, -1, 1 ) Vector4( 0, 0, -1, 1 )
) )
); );
m_far = vector4_projected( m_far = vector4_projected(
matrix4_transformed_vector4( matrix4_transformed_vector4(
screen2world, m_screen2world,
Vector4( 0, 0, 1, 1 ) Vector4( 0, 0, 1, 1 )
) )
); );