* new vertex editing mode, preserving non modified vertices (=adding/removing faces automatically)
with debug prints
This commit is contained in:
parent
6b8b568fd2
commit
435c41b73b
|
|
@ -83,10 +83,10 @@ struct Skew{
|
|||
Skew( std::size_t index_, float amount_ ) : index( index_ ), amount( amount_ ){
|
||||
}
|
||||
bool operator!= ( const Skew& other ) const {
|
||||
return index != other.index || amount != other.amount;
|
||||
return !( *this == other );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,9 @@ inline bool Brush_isBounded( const Brush& brush ){
|
|||
}
|
||||
|
||||
void Brush::buildBRep(){
|
||||
globalOutputStream() << " buildBRep() \n";
|
||||
const bool _vertexModeOn = m_vertexModeOn;
|
||||
|
||||
bool degenerate = buildWindings();
|
||||
|
||||
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
|
||||
globalOutputStream() << degenerate << " degenerate\n";
|
||||
m_uniqueVertexPoints.resize( 0 );
|
||||
|
||||
vertex_clear();
|
||||
|
|
@ -305,6 +309,18 @@ void Brush::buildBRep(){
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1550,6 +1550,8 @@ virtual void edge_push_back( SelectableEdge& edge ) = 0;
|
|||
virtual void vertex_clear() = 0;
|
||||
virtual void vertex_push_back( SelectableVertex& vertex ) = 0;
|
||||
|
||||
virtual void vertex_select( const Vector3& vertex ) = 0;
|
||||
|
||||
virtual void DEBUG_verify() const = 0;
|
||||
};
|
||||
|
||||
|
|
@ -1800,6 +1802,7 @@ void transformChanged(){
|
|||
//m_transformChanged = true;
|
||||
planeChanged();
|
||||
m_transformChanged = true; //experimental fix of cyclic dependency
|
||||
globalOutputStream() << m_planeChanged << " m_planeChanged\n";
|
||||
}
|
||||
typedef MemberCaller<Brush, &Brush::transformChanged> TransformChangedCaller;
|
||||
|
||||
|
|
@ -1858,18 +1861,51 @@ void snapto( float snap ){
|
|||
}
|
||||
}
|
||||
void revertTransform(){
|
||||
globalOutputStream() << " revertTransform\n";
|
||||
for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
|
||||
{
|
||||
( *i )->revertTransform();
|
||||
}
|
||||
}
|
||||
void freezeTransform(){
|
||||
globalOutputStream() << " freezeTransform\n";
|
||||
for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i )
|
||||
{
|
||||
( *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.
|
||||
std::size_t absoluteIndex( FaceVertexId faceVertex ){
|
||||
std::size_t index = 0;
|
||||
|
|
@ -2374,6 +2410,9 @@ bool buildWindings(){
|
|||
{
|
||||
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 )
|
||||
{
|
||||
Face& f = *m_faces[i];
|
||||
|
|
@ -3145,6 +3184,21 @@ void selectVerticesOnFaces( const FaceInstances_ptrs& faceinstances ){
|
|||
}
|
||||
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
|
||||
|
|
@ -3341,6 +3395,16 @@ void vertex_push_back( SelectableVertex& 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 {
|
||||
ASSERT_MESSAGE( m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch" );
|
||||
}
|
||||
|
|
@ -3715,10 +3779,25 @@ void snapComponents( float snap ){
|
|||
}
|
||||
}
|
||||
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;
|
||||
for( auto& i : m_faceInstances )
|
||||
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() );
|
||||
|
|
@ -3728,6 +3807,10 @@ void evaluateTransform(){
|
|||
}
|
||||
else
|
||||
{
|
||||
if( m_brush.m_vertexModeOn ){
|
||||
m_brush.vertexModeTransform( matrix );
|
||||
}
|
||||
else{
|
||||
const bool tmp = g_brush_texturelock_enabled;
|
||||
/* do not want texture projection transformation while resizing brush */
|
||||
if( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive )
|
||||
|
|
@ -3736,6 +3819,7 @@ void evaluateTransform(){
|
|||
g_brush_texturelock_enabled = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
void applyTransform(){
|
||||
m_brush.revertTransform();
|
||||
evaluateTransform();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user