refactor PatchEdgeIter, Patch_getClosestTriangle
This commit is contained in:
parent
cf8e0e1501
commit
7be3cbda79
|
|
@ -1574,116 +1574,87 @@ void TextureClipboard_textureSelected( const char* shader ){
|
||||||
|
|
||||||
class PatchEdgeIter
|
class PatchEdgeIter
|
||||||
{
|
{
|
||||||
protected:
|
public:
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
eRowForward, // iterate inside a row
|
||||||
|
eRowBack,
|
||||||
|
eColForward, // iterate inside a column
|
||||||
|
eColBack
|
||||||
|
};
|
||||||
|
private:
|
||||||
const PatchControl* const m_ctrl;
|
const PatchControl* const m_ctrl;
|
||||||
const int m_width;
|
const int m_width;
|
||||||
const int m_height;
|
const int m_height;
|
||||||
|
const Type m_type;
|
||||||
int m_row;
|
int m_row;
|
||||||
int m_col;
|
int m_col;
|
||||||
const PatchControl& ctrlAt( size_t row, size_t col ) const {
|
const PatchControl& ctrlAt( size_t row, size_t col ) const {
|
||||||
return m_ctrl[row * m_width + col];
|
return m_ctrl[row * m_width + col];
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
PatchEdgeIter( const PatchData& patch ) : m_ctrl( patch.data() ), m_width( patch.getWidth() ), m_height( patch.getHeight() ){
|
PatchEdgeIter( const PatchData& patch, Type type, int rowOrCol ) :
|
||||||
|
m_ctrl( patch.data() ),
|
||||||
|
m_width( patch.getWidth() ),
|
||||||
|
m_height( patch.getHeight() ),
|
||||||
|
m_type( type ),
|
||||||
|
m_row( type == eColForward? 0 : type == eColBack? patch.getHeight() - 1 : rowOrCol ),
|
||||||
|
m_col( type == eRowForward? 0 : type == eRowBack? patch.getWidth() - 1 : rowOrCol ) {
|
||||||
}
|
}
|
||||||
PatchEdgeIter( const PatchEdgeIter& other ) = default;
|
PatchEdgeIter( const PatchEdgeIter& other ) = default;
|
||||||
virtual ~PatchEdgeIter(){};
|
PatchEdgeIter( const PatchEdgeIter& other, Type type ) :
|
||||||
virtual std::unique_ptr<PatchEdgeIter> clone() const = 0;
|
m_ctrl( other.m_ctrl ),
|
||||||
|
m_width( other.m_width ),
|
||||||
|
m_height( other.m_height ),
|
||||||
|
m_type( type ),
|
||||||
|
m_row( other.m_row ),
|
||||||
|
m_col( other.m_col ) {
|
||||||
|
}
|
||||||
const PatchControl& operator*() const {
|
const PatchControl& operator*() const {
|
||||||
return ctrlAt( m_row, m_col );
|
return ctrlAt( m_row, m_col );
|
||||||
}
|
}
|
||||||
operator bool() const {
|
operator bool() const {
|
||||||
return m_row >=0 && m_row < m_height && m_col >=0 && m_col < m_width;
|
return m_row >=0 && m_row < m_height && m_col >=0 && m_col < m_width;
|
||||||
}
|
}
|
||||||
virtual void operator++() = 0;
|
void operator++(){
|
||||||
void operator+=( size_t inc ){
|
operator+=( 1 );
|
||||||
while( inc-- )
|
|
||||||
operator++();
|
|
||||||
}
|
}
|
||||||
std::unique_ptr<PatchEdgeIter> operator+( size_t inc ) const {
|
void operator+=( size_t inc ){
|
||||||
std::unique_ptr<PatchEdgeIter> it = clone();
|
switch ( m_type )
|
||||||
*it += inc;
|
{
|
||||||
|
case eRowForward:
|
||||||
|
m_col += inc;
|
||||||
|
break;
|
||||||
|
case eRowBack:
|
||||||
|
m_col -= inc;
|
||||||
|
break;
|
||||||
|
case eColForward:
|
||||||
|
m_row += inc;
|
||||||
|
break;
|
||||||
|
case eColBack:
|
||||||
|
m_row -= inc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PatchEdgeIter operator+( size_t inc ) const {
|
||||||
|
PatchEdgeIter it( *this );
|
||||||
|
it += inc;
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
virtual std::unique_ptr<PatchEdgeIter> getCrossIter() const = 0;
|
PatchEdgeIter getCrossIter() const {
|
||||||
};
|
switch ( m_type )
|
||||||
|
{
|
||||||
class PatchRowBackIter : public PatchEdgeIter
|
case eRowForward:
|
||||||
{
|
return PatchEdgeIter( *this, eColBack );
|
||||||
public:
|
case eRowBack:
|
||||||
PatchRowBackIter( const PatchData& patch, size_t row ) : PatchEdgeIter( patch ){
|
return PatchEdgeIter( *this, eColForward );
|
||||||
m_row = row;
|
case eColForward:
|
||||||
m_col = m_width - 1;
|
return PatchEdgeIter( *this, eRowForward );
|
||||||
}
|
case eColBack:
|
||||||
PatchRowBackIter( const PatchEdgeIter& base ) : PatchEdgeIter( base ){}
|
return PatchEdgeIter( *this, eRowBack );
|
||||||
std::unique_ptr<PatchEdgeIter> clone() const override {
|
}
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchRowBackIter( *this ) );
|
|
||||||
}
|
|
||||||
void operator++() override {
|
|
||||||
--m_col;
|
|
||||||
}
|
|
||||||
std::unique_ptr<PatchEdgeIter> getCrossIter() const override;
|
|
||||||
};
|
|
||||||
class PatchRowForwardIter : public PatchEdgeIter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PatchRowForwardIter( const PatchData& patch, size_t row ) : PatchEdgeIter( patch ){
|
|
||||||
m_row = row;
|
|
||||||
m_col = 0;
|
|
||||||
}
|
|
||||||
PatchRowForwardIter( const PatchEdgeIter& base ) : PatchEdgeIter( base ){}
|
|
||||||
std::unique_ptr<PatchEdgeIter> clone() const override {
|
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchRowForwardIter( *this ) );
|
|
||||||
}
|
|
||||||
void operator++() override {
|
|
||||||
++m_col;
|
|
||||||
}
|
|
||||||
std::unique_ptr<PatchEdgeIter> getCrossIter() const override;
|
|
||||||
};
|
|
||||||
class PatchColBackIter : public PatchEdgeIter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PatchColBackIter( const PatchData& patch, size_t col ) : PatchEdgeIter( patch ){
|
|
||||||
m_row = m_height - 1;
|
|
||||||
m_col = col;
|
|
||||||
}
|
|
||||||
PatchColBackIter( const PatchEdgeIter& base ) : PatchEdgeIter( base ){}
|
|
||||||
std::unique_ptr<PatchEdgeIter> clone() const override {
|
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchColBackIter( *this ) );
|
|
||||||
}
|
|
||||||
void operator++() override {
|
|
||||||
--m_row;
|
|
||||||
}
|
|
||||||
std::unique_ptr<PatchEdgeIter> getCrossIter() const override {
|
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchRowBackIter( *this ) );
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class PatchColForwardIter : public PatchEdgeIter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PatchColForwardIter( const PatchData& patch, size_t col ) : PatchEdgeIter( patch ){
|
|
||||||
m_row = 0;
|
|
||||||
m_col = col;
|
|
||||||
}
|
|
||||||
PatchColForwardIter( const PatchEdgeIter& base ) : PatchEdgeIter( base ){}
|
|
||||||
std::unique_ptr<PatchEdgeIter> clone() const override {
|
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchColForwardIter( *this ) );
|
|
||||||
}
|
|
||||||
void operator++() override {
|
|
||||||
++m_row;
|
|
||||||
}
|
|
||||||
std::unique_ptr<PatchEdgeIter> getCrossIter() const override {
|
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchRowForwardIter( *this ) );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unique_ptr<PatchEdgeIter> PatchRowBackIter::getCrossIter() const {
|
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchColForwardIter( *this ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<PatchEdgeIter> PatchRowForwardIter::getCrossIter() const {
|
|
||||||
return std::unique_ptr<PatchEdgeIter>( new PatchColBackIter( *this ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns 0 or 3 CW points
|
// returns 0 or 3 CW points
|
||||||
static std::vector<const PatchControl*> Patch_getClosestTriangle( const PatchData& patch, const Winding& w, const Plane3& plane ){
|
static std::vector<const PatchControl*> Patch_getClosestTriangle( const PatchData& patch, const Winding& w, const Plane3& plane ){
|
||||||
|
|
@ -1701,110 +1672,64 @@ static std::vector<const PatchControl*> Patch_getClosestTriangle( const PatchDat
|
||||||
|
|
||||||
const double eps = .25;
|
const double eps = .25;
|
||||||
|
|
||||||
const auto line_close = [eps]( const Line& line, const PatchControl& p ){
|
std::vector<const PatchControl*> ret;
|
||||||
return vector3_length_squared( line_closest_point( line, p.m_vertex ) - p.m_vertex ) < eps;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto ray_close = [eps]( const DoubleRay& ray, const PatchControl& p ){
|
const auto find_triangle = [&ret, &patch, triangle_ok, eps]( const auto& check_func ){
|
||||||
return ray_squared_distance_to_point( ray, p.m_vertex ) < eps;
|
for( auto& iter : {
|
||||||
};
|
PatchEdgeIter( patch, PatchEdgeIter::eRowBack, 0 ),
|
||||||
|
PatchEdgeIter( patch, PatchEdgeIter::eRowForward, patch.getHeight() - 1 ),
|
||||||
const auto plane_close = [eps]( const Plane3& plane, const PatchControl& p ){
|
PatchEdgeIter( patch, PatchEdgeIter::eColBack, patch.getWidth() - 1 ),
|
||||||
return std::pow( plane3_distance_to_point( plane, p.m_vertex ), 2 ) < eps;
|
PatchEdgeIter( patch, PatchEdgeIter::eColForward, 0 ) } )
|
||||||
|
{
|
||||||
|
for( PatchEdgeIter i0 = iter; i0; i0 += 2 ){
|
||||||
|
const PatchControl& p0 = *i0;
|
||||||
|
if( check_func( p0 ) ){
|
||||||
|
for( PatchEdgeIter i1 = i0 + size_t{ 2 }; i1; i1 += 2 ){
|
||||||
|
const PatchControl& p1 = *i1;
|
||||||
|
if( check_func( p1 )
|
||||||
|
&& vector3_length_squared( p1.m_vertex - p0.m_vertex ) > eps ){
|
||||||
|
for( PatchEdgeIter i2 = i0.getCrossIter() + size_t{ 1 }, i22 = i1.getCrossIter() + size_t{ 1 }; i2 && i22; ++i2, ++i22 ){
|
||||||
|
for( const PatchControl& p2 : { *i2, *i22 } ){
|
||||||
|
if( triangle_ok( p0, p1, p2 ) ){
|
||||||
|
ret = { &p0, &p1, &p2 };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* try patchControls-on-edge */
|
/* try patchControls-on-edge */
|
||||||
for ( std::size_t i = w.numpoints - 1, j = 0; j < w.numpoints; i = j, ++j ){
|
for ( std::size_t i = w.numpoints - 1, j = 0; j < w.numpoints && ret.empty(); i = j, ++j )
|
||||||
const Line line( w[i].vertex, w[j].vertex );
|
{
|
||||||
|
const auto line_close = [eps, line = Line( w[i].vertex, w[j].vertex )]( const PatchControl& p ){
|
||||||
for( auto& iter : {
|
return vector3_length_squared( line_closest_point( line, p.m_vertex ) - p.m_vertex ) < eps;
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchRowBackIter( patch, 0 ) ),
|
};
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchRowForwardIter( patch, patch.getHeight() - 1 ) ),
|
find_triangle( line_close );
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchColBackIter( patch, patch.getWidth() - 1 ) ),
|
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchColForwardIter( patch, 0 ) ) } )
|
|
||||||
{
|
|
||||||
for( const std::unique_ptr<PatchEdgeIter>& i0 = iter; *i0; *i0 += 2 ){
|
|
||||||
const PatchControl& p0 = **i0;
|
|
||||||
if( line_close( line, p0 ) ){
|
|
||||||
for( std::unique_ptr<PatchEdgeIter> i1 = *i0 + size_t{ 2 }; *i1; *i1 += 2 ){
|
|
||||||
const PatchControl& p1 = **i1;
|
|
||||||
if( line_close( line, p1 )
|
|
||||||
&& vector3_length_squared( p1.m_vertex - p0.m_vertex ) > eps ){
|
|
||||||
for( std::unique_ptr<PatchEdgeIter> i2 = *i0->getCrossIter() + size_t{ 1 }, i22 = *i1->getCrossIter() + size_t{ 1 }; *i2 && *i22; ++*i2, ++*i22 ){
|
|
||||||
for( const PatchControl& p2 : { **i2, **i22 } ){
|
|
||||||
if( triangle_ok( p0, p1, p2 ) ){
|
|
||||||
return { &p0, &p1, &p2 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try patchControls-on-edgeLine */
|
/* try patchControls-on-edgeLine */
|
||||||
for ( std::size_t i = w.numpoints - 1, j = 0; j < w.numpoints; i = j, ++j ){
|
for ( std::size_t i = w.numpoints - 1, j = 0; j < w.numpoints && ret.empty(); i = j, ++j )
|
||||||
const DoubleRay ray = ray_for_points( DoubleVector3( w[i].vertex ), DoubleVector3( w[j].vertex ) );
|
{
|
||||||
|
const auto ray_close = [eps, ray = ray_for_points( DoubleVector3( w[i].vertex ), DoubleVector3( w[j].vertex ) )]( const PatchControl& p ){
|
||||||
for( auto& iter : {
|
return ray_squared_distance_to_point( ray, p.m_vertex ) < eps;
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchRowBackIter( patch, 0 ) ),
|
};
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchRowForwardIter( patch, patch.getHeight() - 1 ) ),
|
find_triangle( ray_close );
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchColBackIter( patch, patch.getWidth() - 1 ) ),
|
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchColForwardIter( patch, 0 ) ) } )
|
|
||||||
{
|
|
||||||
for( const std::unique_ptr<PatchEdgeIter>& i0 = iter; *i0; *i0 += 2 ){
|
|
||||||
const PatchControl& p0 = **i0;
|
|
||||||
if( ray_close( ray, p0 ) ){
|
|
||||||
for( std::unique_ptr<PatchEdgeIter> i1 = *i0 + size_t{ 2 }; *i1; *i1 += 2 ){
|
|
||||||
const PatchControl& p1 = **i1;
|
|
||||||
if( ray_close( ray, p1 )
|
|
||||||
&& vector3_length_squared( p1.m_vertex - p0.m_vertex ) > eps ){
|
|
||||||
for( std::unique_ptr<PatchEdgeIter> i2 = *i0->getCrossIter() + size_t{ 1 }, i22 = *i1->getCrossIter() + size_t{ 1 }; *i2 && *i22; ++*i2, ++*i22 ){
|
|
||||||
for( const PatchControl& p2 : { **i2, **i22 } ){
|
|
||||||
if( triangle_ok( p0, p1, p2 ) ){
|
|
||||||
return { &p0, &p1, &p2 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try patchControls-on-facePlane */
|
/* try patchControls-on-facePlane */
|
||||||
{
|
if( ret.empty() ){
|
||||||
for( auto& iter : {
|
const auto plane_close = [eps, plane]( const PatchControl& p ){
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchRowBackIter( patch, 0 ) ),
|
return std::pow( plane3_distance_to_point( plane, p.m_vertex ), 2 ) < eps;
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchRowForwardIter( patch, patch.getHeight() - 1 ) ),
|
};
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchColBackIter( patch, patch.getWidth() - 1 ) ),
|
find_triangle( plane_close );
|
||||||
std::unique_ptr<PatchEdgeIter>( new PatchColForwardIter( patch, 0 ) ) } )
|
|
||||||
{
|
|
||||||
for( const std::unique_ptr<PatchEdgeIter>& i0 = iter; *i0; *i0 += 2 ){
|
|
||||||
const PatchControl& p0 = **i0;
|
|
||||||
if( plane_close( plane, p0 ) ){
|
|
||||||
for( std::unique_ptr<PatchEdgeIter> i1 = *i0 + size_t{ 2 }; *i1; *i1 += 2 ){
|
|
||||||
const PatchControl& p1 = **i1;
|
|
||||||
if( plane_close( plane, p1 )
|
|
||||||
&& vector3_length_squared( p1.m_vertex - p0.m_vertex ) > eps ){
|
|
||||||
for( std::unique_ptr<PatchEdgeIter> i2 = *i0->getCrossIter() + size_t{ 1 }, i22 = *i1->getCrossIter() + size_t{ 1 }; *i2 && *i22; ++*i2, ++*i22 ){
|
|
||||||
for( const PatchControl& p2 : { **i2, **i22 } ){
|
|
||||||
if( triangle_ok( p0, p1, p2 ) ){
|
|
||||||
return { &p0, &p1, &p2 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user