* new vertex editing mode, preserving non modified vertices (=adding/removing faces automatically)

with debug prints
This commit is contained in:
Garux 2018-12-10 17:50:40 +03:00
parent 6b8b568fd2
commit 435c41b73b
3 changed files with 246 additions and 9 deletions

View File

@ -83,10 +83,10 @@ struct Skew{
Skew( std::size_t index_, float amount_ ) : index( index_ ), amount( amount_ ){ Skew( std::size_t index_, float amount_ ) : index( index_ ), amount( amount_ ){
} }
bool operator!= ( const Skew& other ) const { bool operator!= ( const Skew& other ) const {
return index != other.index || amount != other.amount; return !( *this == other );
} }
bool operator== ( const Skew& other ) const { bool operator== ( const Skew& other ) const {
return index == other.index && amount == other.amount; return ( amount == 0 && other.amount == 0 ) || ( index == other.index && amount == other.amount );
} }
}; };

View File

@ -106,6 +106,9 @@ inline bool Brush_isBounded( const Brush& brush ){
} }
void Brush::buildBRep(){ void Brush::buildBRep(){
globalOutputStream() << " buildBRep() \n";
const bool _vertexModeOn = m_vertexModeOn;
bool degenerate = buildWindings(); bool degenerate = buildWindings();
std::size_t faces_size = 0; std::size_t faces_size = 0;
@ -119,6 +122,7 @@ void Brush::buildBRep(){
} }
if ( degenerate || faces_size < 4 || faceVerticesCount != ( faceVerticesCount >> 1 ) << 1 ) { // sum of vertices for each face of a valid polyhedron is always even if ( degenerate || faces_size < 4 || faceVerticesCount != ( faceVerticesCount >> 1 ) << 1 ) { // sum of vertices for each face of a valid polyhedron is always even
globalOutputStream() << degenerate << " degenerate\n";
m_uniqueVertexPoints.resize( 0 ); m_uniqueVertexPoints.resize( 0 );
vertex_clear(); vertex_clear();
@ -305,6 +309,18 @@ void Brush::buildBRep(){
m_faceCentroidPoints[i] = pointvertex_for_windingpoint( m_faces[i]->centroid(), colour_vertex ); m_faceCentroidPoints[i] = pointvertex_for_windingpoint( m_faces[i]->centroid(), colour_vertex );
} }
} }
globalOutputStream() << _vertexModeOn << " _vertexModeOn\n";
globalOutputStream() << m_vertexModeOn << " m_vertexModeOn\n";
// :faceleg: start move end
// m_vertexModeOn 1 1 0
// _vertexModeOn 0 1 1
if( _vertexModeOn || m_vertexModeOn ){
if( !( !m_vertexModeOn && _vertexModeOn && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) ) //don't select in the end of g_bTmpComponentMode
for( const auto& i : m_vertexModeVertices )
if( i.m_selected )
for ( Observers::iterator o = m_observers.begin(); o != m_observers.end(); ++o )
( *o )->vertex_select( i.m_vertexTransformed );
}
} }
} }
@ -387,3 +403,140 @@ bool brush_filtered( Brush& brush ){
} }
return false; return false;
} }
class VertexModePlane
{
public:
Plane3 m_plane;
const Face* m_face;
const Brush::VertexModeVertex* const m_v[3];
bool m_transformed;
VertexModePlane( const Plane3& plane, const Face* face,
const Brush::VertexModeVertex* v1, const Brush::VertexModeVertex* v2, const Brush::VertexModeVertex* v3,
bool transformed ) : m_plane( plane ), m_face( face ), m_v{ v1, v2, v3 }, m_transformed( transformed ){
}
};
class VertexModePlanes
{
typedef std::vector<VertexModePlane> Planes;
Planes m_planes;
public:
typedef Planes::const_iterator const_iterator;
typedef Planes::iterator iterator;
void push_back( const VertexModePlane& plane ){
m_planes.push_back( plane );
}
iterator find( const Plane3& plane ){
iterator i = begin();
for( ; i != end(); ++i )
if( plane3_equal( plane, i->m_plane ) )
break;
return i;
}
const_iterator begin() const {
return m_planes.begin();
}
const_iterator end() const {
return m_planes.end();
}
iterator begin() {
return m_planes.begin();
}
iterator end() {
return m_planes.end();
}
std::size_t size() const {
return m_planes.size();
}
};
const Face* vertex_mode_find_common_face( const Brush::VertexModeVertex& v1, const Brush::VertexModeVertex& v2, const Brush::VertexModeVertex& v3 ){
const Face* face = 0;
for( const auto& i : v1.m_faces ){
if( std::find( v2.m_faces.begin(), v2.m_faces.end(), i ) != v2.m_faces.end()
&& std::find( v3.m_faces.begin(), v3.m_faces.end(), i ) != v3.m_faces.end() ){
face = i;
break;
}
}
return face;
}
#include "quickhull/QuickHull.hpp"
void Brush::vertexModeTransform( const Matrix4& matrix ){
globalOutputStream() << " vertexModeTransform\n";
quickhull::QuickHull<double> quickhull;
std::vector<quickhull::Vector3<double>> pointCloud;
pointCloud.reserve( m_vertexModeVertices.size() );
for( auto& i : m_vertexModeVertices ){
if( i.m_selected )
i.m_vertexTransformed = matrix4_transformed_point( matrix, i.m_vertex );
pointCloud.push_back( quickhull::Vector3<double>( static_cast<double>( i.m_vertexTransformed.x() ),
static_cast<double>( i.m_vertexTransformed.y() ),
static_cast<double>( i.m_vertexTransformed.z() ) ) );
}
auto hull = quickhull.getConvexHull( pointCloud, false, true, 0.0001 );
const auto& indexBuffer = hull.getIndexBuffer();
const size_t triangleCount = indexBuffer.size() / 3;
VertexModePlanes vertexModePlanes;
for( size_t i = 0; i < triangleCount; ++i ) {
const Brush::VertexModeVertex* v[3];
bool transformed = false;
for( size_t j = 0; j < 3; ++j ){
v[j] = &m_vertexModeVertices[indexBuffer[i * 3 + j]];
transformed |= v[j]->m_selected;
}
const Plane3 plane = plane3_for_points( v[0]->m_vertexTransformed, v[1]->m_vertexTransformed, v[2]->m_vertexTransformed );
if( plane3_valid( plane ) ){
VertexModePlanes::iterator it = vertexModePlanes.find( plane );
if( it == vertexModePlanes.end() ){ //not found, add new plane
const Face* face = vertex_mode_find_common_face( *v[0], *v[1], *v[2] );
if( !face ){ //no common face, use some
face = v[0]->m_faces[0];
transformed = true;
}
if( vector3_dot( plane.normal(), face->getPlane().plane3().normal() ) < 0 ){ //likely reversed plane
transformed = true;
}
vertexModePlanes.push_back( VertexModePlane( plane, face, v[0], v[2], v[1], transformed ) );
}
else{
it->m_transformed |= transformed;
}
}
}
if( vertexModePlanes.size() >=4 ){ //avoid obvious transform to degenerate
clear();
for( const auto& i : vertexModePlanes ){
const Face& face = *i.m_face;
if( i.m_transformed ){
if( g_brush_textureVertexlock_enabled ){
Matrix4 local2tex;
Texdef_Construct_local2tex( face.getTexdef().m_projection, face.getShader().width(), face.getShader().height(), face.getPlane().plane3().normal(), local2tex );
const DoubleVector3 st[3]{ matrix4_transformed_point( local2tex, i.m_v[0]->m_vertex ),
matrix4_transformed_point( local2tex, i.m_v[1]->m_vertex ),
matrix4_transformed_point( local2tex, i.m_v[2]->m_vertex ) };
const DoubleVector3 points[3]{ i.m_v[0]->m_vertexTransformed, i.m_v[1]->m_vertexTransformed, i.m_v[2]->m_vertexTransformed };
TextureProjection projection;
Texdef_from_ST( projection, points, st, face.getShader().width(), face.getShader().height() );
projection.m_brushprimit_texdef.removeScale( face.getShader().width(), face.getShader().height() );
addPlane( i.m_v[0]->m_vertexTransformed, i.m_v[1]->m_vertexTransformed, i.m_v[2]->m_vertexTransformed, face.GetShader(), projection );
Brush_textureChanged();
}
else{
addPlane( i.m_v[0]->m_vertexTransformed, i.m_v[1]->m_vertexTransformed, i.m_v[2]->m_vertexTransformed, face.GetShader(), face.getTexdef().normalised() );
}
}
else{
addFace( face );
}
}
globalOutputStream() << m_faces.size() << " m_faces.size()\n";
}
}

View File

@ -1550,6 +1550,8 @@ virtual void edge_push_back( SelectableEdge& edge ) = 0;
virtual void vertex_clear() = 0; virtual void vertex_clear() = 0;
virtual void vertex_push_back( SelectableVertex& vertex ) = 0; virtual void vertex_push_back( SelectableVertex& vertex ) = 0;
virtual void vertex_select( const Vector3& vertex ) = 0;
virtual void DEBUG_verify() const = 0; virtual void DEBUG_verify() const = 0;
}; };
@ -1800,6 +1802,7 @@ void transformChanged(){
//m_transformChanged = true; //m_transformChanged = true;
planeChanged(); planeChanged();
m_transformChanged = true; //experimental fix of cyclic dependency m_transformChanged = true; //experimental fix of cyclic dependency
globalOutputStream() << m_planeChanged << " m_planeChanged\n";
} }
typedef MemberCaller<Brush, &Brush::transformChanged> TransformChangedCaller; typedef MemberCaller<Brush, &Brush::transformChanged> TransformChangedCaller;
@ -1858,18 +1861,51 @@ void snapto( float snap ){
} }
} }
void revertTransform(){ void revertTransform(){
globalOutputStream() << " revertTransform\n";
for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
{ {
( *i )->revertTransform(); ( *i )->revertTransform();
} }
} }
void freezeTransform(){ void freezeTransform(){
globalOutputStream() << " freezeTransform\n";
for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
{ {
( *i )->freezeTransform(); ( *i )->freezeTransform();
} }
} }
class VertexModeVertex
{
public:
const Vector3 m_vertex;
Vector3 m_vertexTransformed;
const bool m_selected;
std::vector<Face*> m_faces;
VertexModeVertex( const Vector3& vertex, const bool selected ) : m_vertex( vertex ), m_vertexTransformed( vertex ), m_selected( selected ) {
}
};
typedef std::vector<VertexModeVertex> VertexModeVertices;
VertexModeVertices m_vertexModeVertices;
bool m_vertexModeOn{false};
void vertexModeInit(){
globalOutputStream() << " vertexModeInit(){\n";
m_vertexModeOn = true;
m_vertexModeVertices.clear();
undoSave();
}
void vertexModeFree(){
globalOutputStream() << " vertexModeFree(){\n";
m_vertexModeOn = false;
// m_vertexModeVertices.clear(); //keep, as it is required by buildBRep() after this call
}
void vertexModeTransform( const Matrix4& matrix );
/// \brief Returns the absolute index of the \p faceVertex. /// \brief Returns the absolute index of the \p faceVertex.
std::size_t absoluteIndex( FaceVertexId faceVertex ){ std::size_t absoluteIndex( FaceVertexId faceVertex ){
std::size_t index = 0; std::size_t index = 0;
@ -2374,6 +2410,9 @@ bool buildWindings(){
{ {
m_aabb_local = AABB(); m_aabb_local = AABB();
if( m_faces.size() )
m_faces[0]->plane3(); //force evaluateTransform() first, as m_faces is changed during vertexModeTransform
for ( std::size_t i = 0; i < m_faces.size(); ++i ) for ( std::size_t i = 0; i < m_faces.size(); ++i )
{ {
Face& f = *m_faces[i]; Face& f = *m_faces[i];
@ -3145,6 +3184,21 @@ void selectVerticesOnFaces( const FaceInstances_ptrs& faceinstances ){
} }
while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() ); while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() );
} }
void gather( Brush::VertexModeVertices& vertexModeVertices ) const {
vertexModeVertices.push_back( Brush::VertexModeVertex( m_vertex->getFace().getWinding()[m_vertex->m_faceVertex.getVertex()].vertex, isSelected() ) );
FaceVertexId faceVertex = m_vertex->m_faceVertex;
do
{
vertexModeVertices.back().m_faces.push_back( &m_faceInstances[faceVertex.getFace()].getFace() );
faceVertex = next_vertex( m_vertex->m_faces, faceVertex );
}
while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() );
}
void vertex_select( const Vector3& vertex ){
if( vector3_length_squared( vertex - m_vertex->getFace().getWinding()[m_vertex->m_faceVertex.getVertex()].vertex ) < ( 0.1 * 0.1 ) ){
setSelected( true );
}
}
}; };
class BrushInstanceVisitor class BrushInstanceVisitor
@ -3341,6 +3395,16 @@ void vertex_push_back( SelectableVertex& vertex ){
m_vertexInstances.push_back( VertexInstance( m_faceInstances, vertex ) ); m_vertexInstances.push_back( VertexInstance( m_faceInstances, vertex ) );
} }
void vertex_select( const Vector3& vertex ){
for( auto& i : m_vertexInstances )
i.vertex_select( vertex );
for ( const auto& i : m_faceInstances )
if( i.selectedComponents( SelectionSystem::eVertex ) ) //got something selected, okay
return;
if( !m_vertexInstances.empty() )
m_vertexInstances[0].setSelected( true ); //select at least something to prevent transform interruption after removing all selected vertices during vertexModeTransform
}
void DEBUG_verify() const { void DEBUG_verify() const {
ASSERT_MESSAGE( m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch" ); ASSERT_MESSAGE( m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch" );
} }
@ -3715,10 +3779,25 @@ void snapComponents( float snap ){
} }
} }
void evaluateTransform(){ void evaluateTransform(){
if( m_transform.m_transformFrozen && !m_transform.isIdentity() ){ globalOutputStream() << " evaluateTransform\n";
if( m_transform.m_transformFrozen )
m_brush.vertexModeFree();
if( m_transform.m_transformFrozen && !m_transform.isIdentity() ){ /* new transform */
m_transform.m_transformFrozen = false; m_transform.m_transformFrozen = false;
for( auto& i : m_faceInstances ) for( auto& i : m_faceInstances )
i.getFace().cacheCentroid(); i.getFace().cacheCentroid();
if( m_transform.getType() == TRANSFORM_COMPONENT ){
for ( const auto& i : m_faceInstances ){
if( i.selectedComponents( SelectionSystem::eVertex ) ){
m_brush.vertexModeInit();
for ( const auto& i : m_vertexInstances ){
i.gather( m_brush.m_vertexModeVertices );
}
break;
}
}
}
} }
const Matrix4 matrix( m_transform.calculateTransform() ); const Matrix4 matrix( m_transform.calculateTransform() );
@ -3728,12 +3807,17 @@ void evaluateTransform(){
} }
else else
{ {
const bool tmp = g_brush_texturelock_enabled; if( m_brush.m_vertexModeOn ){
/* do not want texture projection transformation while resizing brush */ m_brush.vertexModeTransform( matrix );
if( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) }
g_brush_texturelock_enabled = false; else{
transformComponents( matrix ); const bool tmp = g_brush_texturelock_enabled;
g_brush_texturelock_enabled = tmp; /* do not want texture projection transformation while resizing brush */
if( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive )
g_brush_texturelock_enabled = false;
transformComponents( matrix );
g_brush_texturelock_enabled = tmp;
}
} }
} }
void applyTransform(){ void applyTransform(){