* prevent resizing brushes to zero volume by faces drag, try to stop at minimal configuration
This commit is contained in:
parent
2ef794539c
commit
bfc66aa6af
|
|
@ -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<int>( 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user