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 Vector3& getNear() 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 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;

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 ){
const Vector3 v( vector3_subtracted( line_closest_point( line, ( *i ).vertex ), ( *i ).vertex ) );
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 ) {
if ( vector3_dot( getFace().plane3().normal(), closest_point - ( *i ).vertex ) < 0.005 ) /* epsilon to prevent almost perpendicular faces pickup */
return false;
}
}
return true;
}
@ -3549,16 +3556,15 @@ void invertComponentSelection( SelectionSystem::EComponentMode mode ){
void selectPlanes( SelectionTest& test, FaceInstances_ptrs& bestInstances ){
test.BeginMesh( localToWorld() );
const Line line( test.getNear(), test.getFar() );
const Vector3 viewer( vector3_normalised( test.getNear() - test.getFar() ) );
const Vector3 viewdir( vector3_normalised( Vector3( test.getVolume().GetModelview()[2], test.getVolume().GetModelview()[6], test.getVolume().GetModelview()[10] ) ) );
double bestDot = 1;
for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
{
if( !( *i ).trySelectPlane( line ) ){
if( !( *i ).trySelectPlane( test ) ){
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;
if( diff > 0.03 ){
bestDot = dot;

View File

@ -2690,6 +2690,7 @@ const View& m_view;
clipcull_t m_cull;
Vector3 m_near;
Vector3 m_far;
Matrix4 m_screen2world;
public:
SelectionVolume( const View& view )
: m_view( view ){
@ -2706,6 +2707,10 @@ const Vector3& getFar() const {
return m_far;
}
const Matrix4& getScreen2world() const {
return m_screen2world;
}
void BeginMesh( const Matrix4& localToWorld, bool twoSided ){
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;
{
Matrix4 screen2world( matrix4_full_inverse( m_local2view ) );
m_screen2world = matrix4_full_inverse( m_local2view );
m_near = vector4_projected(
matrix4_transformed_vector4(
screen2world,
m_screen2world,
Vector4( 0, 0, -1, 1 )
)
);
m_far = vector4_projected(
matrix4_transformed_vector4(
screen2world,
m_screen2world,
Vector4( 0, 0, 1, 1 )
)
);