From bfc66aa6af4a6f8d35cb20f1cb7e8693b7210a71 Mon Sep 17 00:00:00 2001 From: Garux Date: Thu, 4 Apr 2019 17:34:08 +0300 Subject: [PATCH] * prevent resizing brushes to zero volume by faces drag, try to stop at minimal configuration --- radiant/brush.cpp | 46 +++++++++++++++++++++++++++ radiant/brush.h | 79 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 119 insertions(+), 6 deletions(-) diff --git a/radiant/brush.cpp b/radiant/brush.cpp index 51a8d168..820703f3 100644 --- a/radiant/brush.cpp +++ b/radiant/brush.cpp @@ -540,3 +540,49 @@ void Brush::vertexModeSnap( const float snap, bool all ){ vector3_snap( i.m_vertexTransformed, snap ); vertexModeBuildHull( all ); } + +#include "grid.h" +void BrushInstance::transformComponents( const Matrix4& matrix ){ + auto transform = [this]( const Matrix4& matrix ){ + for ( auto& fi : m_faceInstances ) + fi.transformComponents( matrix ); + }; + + transform( matrix ); + + const Vector3 translation = matrix4_get_translation_vec3( matrix ); + if( translation != g_vector3_identity ){ //has translation + Matrix4 ma( matrix ); + Vector3& tra = vector4_to_vector3( ma.t() ); + tra = g_vector3_identity; + if( g_matrix4_identity == ma ){ //only translation + for ( const auto& fi : m_faceInstances ){ + if( fi.isSelected() ){ //has faces selected + if( !m_brush.contributes() ){ //do binary search of worthy transform + for( std::size_t axis = 0; axis < 3; ++axis ){ + const float grid = translation[axis] < 0? -GetGridSize() : GetGridSize(); + int maxI = static_cast( translation[axis] / grid + .5f ); + int minI = 0; + while( maxI > minI ){ + const int curI = minI + ( maxI - minI + 1 ) / 2; + tra[axis] = curI * grid; + m_brush.revertTransform(); + transform( ma ); + if( m_brush.contributes() ){ + minI = curI; + } + else{ + maxI = curI - 1; + } + } + tra[axis] = minI * grid; + } + m_brush.revertTransform(); + transform( ma ); + } + break; + } + } + } + } +} diff --git a/radiant/brush.h b/radiant/brush.h index f7830a53..3becf4cf 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -1307,6 +1307,9 @@ const Plane3& plane3() const { m_observer->evaluateTransform(); return m_planeTransformed.plane3(); } +const Plane3& plane3_() const { + return m_planeTransformed.plane3(); +} FacePlane& getPlane(){ return m_plane; } @@ -2232,6 +2235,74 @@ void copy( const Brush& other ){ planeChanged(); } +/// for the only use to quickly check, if about to be transformed brush makes sense +bool contributes() const { + /* plane_unique() ripoff, calling no evaluation */ + auto plane_unique_ = [this]( std::size_t index ) -> bool { + // duplicate plane + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + if ( index != i && !plane3_inside( m_faces[index]->plane3_(), m_faces[i]->plane3_(), index < i ) ) { + return false; + } + } + return true; + }; + + /* windingForClipPlane() ripoff, calling no evaluation */ + auto windingForClipPlane_ = [this, &plane_unique_]( const Plane3& plane ) -> bool { + FixedWinding buffer[2]; + bool swap = false; + + // get a poly that covers an effectively infinite area + Winding_createInfinite( buffer[swap], plane, m_maxWorldCoord ); + + // chop the poly by all of the other faces + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + const Face& clip = *m_faces[i]; + + if ( plane3_equal( clip.plane3_(), plane ) + || !plane3_valid( clip.plane3_() ) || !plane_unique_( i ) + || plane3_opposing( plane, clip.plane3_() ) ) { + continue; + } + + if( buffer[swap].points.empty() ){ + break; + } + + buffer[!swap].clear(); + + { + // flip the plane, because we want to keep the back side + Plane3 clipPlane( vector3_negated( clip.plane3_().normal() ), -clip.plane3_().dist() ); + Winding_Clip( buffer[swap], plane, clipPlane, i, buffer[!swap] ); + } + swap = !swap; + } + + return buffer[swap].size() > 2; + }; + + + std::size_t contributing = 0; + + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + Face& f = *m_faces[i]; + + if ( plane3_valid( f.plane3_() ) && plane_unique_( i ) ) { + if( windingForClipPlane_( f.plane3_() ) ){ + ++contributing; + if( contributing > 3 ) + return true; + } + } + } + return false; +} + private: void edge_push_back( FaceVertexId faceVertex ){ m_select_edges.push_back( SelectableEdge( m_faces, faceVertex ) ); @@ -3782,12 +3853,8 @@ void selectVerticesOnTestedFaces( SelectionTest& test ){ } -void transformComponents( const Matrix4& matrix ){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).transformComponents( matrix ); - } -} +void transformComponents( const Matrix4& matrix ); + const AABB& getSelectedComponentsBounds() const { m_aabb_component = AABB();