GrpcPrint/PrintS/external/vl/include/vlGraphics/TriangleIterator.hpp

632 lines
19 KiB
C++
Raw Normal View History

2024-03-19 17:45:12 +08:00
/**************************************************************************************/
/* */
/* Visualization Library */
/* http://visualizationlibrary.org */
/* */
/* Copyright (c) 2005-2020, Michele Bosi */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or without modification, */
/* are permitted provided that the following conditions are met: */
/* */
/* - Redistributions of source code must retain the above copyright notice, this */
/* list of conditions and the following disclaimer. */
/* */
/* - Redistributions in binary form must reproduce the above copyright notice, this */
/* list of conditions and the following disclaimer in the documentation and/or */
/* other materials provided with the distribution. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/**************************************************************************************/
#ifndef TriangleIterator_INCLUDE_ONCE
#define TriangleIterator_INCLUDE_ONCE
#include <vlGraphics/Array.hpp>
#include <vlCore/vlnamespace.hpp>
namespace vl
{
//-----------------------------------------------------------------------------
// TriangleIteratorAbstract
//-----------------------------------------------------------------------------
/** For internal use only. See vl::TriangleIterator instead. */
class TriangleIteratorAbstract: public Object
{
VL_INSTRUMENT_ABSTRACT_CLASS(vl::TriangleIteratorAbstract, Object)
public:
virtual bool next() = 0;
virtual bool hasNext() const = 0;
virtual int a() const = 0;
virtual int b() const = 0;
virtual int c() const = 0;
};
//-----------------------------------------------------------------------------
// TriangleIteratorIndexed
//-----------------------------------------------------------------------------
/** For internal use only. See vl::TriangleIterator instead. */
template<class TArray>
class TriangleIteratorIndexed: public TriangleIteratorAbstract
{
VL_INSTRUMENT_CLASS(vl::TriangleIteratorIndexed<TArray>, TriangleIteratorAbstract)
public:
TriangleIteratorIndexed()
{
VL_DEBUG_SET_OBJECT_NAME()
mCurrentIndex = 0;
mEnd = 0;
mA = mB = mC = -1;
mEven = true;
mIndex0 = 0;
mArray = NULL;
mPrimRestartIndex = (unsigned int)-1;
mPrimRestartOn = false;
mBaseVertex = 0;
mPrimType = PT_UNKNOWN;
}
TriangleIteratorIndexed(const TArray* idx_array, EPrimitiveType prim_type, int base_vert, bool prim_restart_on, unsigned int prim_restart_idx)
{
VL_DEBUG_SET_OBJECT_NAME()
mCurrentIndex = 0;
mEnd = 0;
mA = mB = mC = -1;
mEven = true;
mIndex0 = 0;
mArray = idx_array;
mPrimRestartIndex = prim_restart_idx;
mPrimRestartOn = prim_restart_on;
mBaseVertex = base_vert;
mPrimType = prim_type;
}
bool hasNext() const { return mCurrentIndex != mEnd; }
virtual int a() const { return mA; }
virtual int b() const { return mB; }
virtual int c() const { return mC; }
void initialize(int start=0, int end=-1)
{
VL_CHECK( start >= 0 )
VL_CHECK( end <= (int)mArray->size() )
if (end == -1)
end = (int)mArray->size();
mCurrentIndex = end; // end
mA = mB = mC = -1;
mEven = true;
mIndex0 = start;
mEnd = end;
if (mArray->size())
{
switch(mPrimType)
{
case PT_TRIANGLES:
mCurrentIndex = start;
mA = mArray->at(start+0);
mB = mArray->at(start+1);
mC = mArray->at(start+2);
break;
case PT_TRIANGLES_ADJACENCY:
mCurrentIndex = start;
mA = mArray->at(start+0);
mB = mArray->at(start+2);
mC = mArray->at(start+4);
break;
case PT_TRIANGLE_STRIP:
mCurrentIndex = start;
mA = mArray->at(start+0);
mB = mArray->at(start+1);
mC = mArray->at(start+2);
break;
case PT_TRIANGLE_FAN:
case PT_POLYGON:
mCurrentIndex = start + 1;
mA = mArray->at(start+0);
mB = mArray->at(start+1);
mC = mArray->at(start+2);
break;
case PT_QUADS:
// VL_CHECK( (end-start) % 4 == 0 ) /* primitive restart might screw up this */
mCurrentIndex = start;
mA = mArray->at(start+0);
mB = mArray->at(start+1);
mC = mArray->at(start+2);
break;
case PT_QUAD_STRIP:
// VL_CHECK( (end-start) % 2 == 0 ) /* primitive restart might screw up this */
mCurrentIndex = start;
mA = mArray->at(start+0);
mB = mArray->at(start+1);
mC = mArray->at(start+2);
break;
default:
Log::error( Say("TriangleIteratorIndexed::initialize(): unsupported primitive type %n.\n") << mPrimType );
VL_TRAP();
break;
}
}
// if we are not at the end then add base vertices
if ( mCurrentIndex != mEnd )
{
mA += mBaseVertex;
mB += mBaseVertex;
mC += mBaseVertex;
}
else
{
mA = mB = mC = -1;
}
}
bool next()
{
// reached the end
if ( mCurrentIndex == mEnd )
return false;
switch(mPrimType)
{
case PT_TRIANGLES:
mCurrentIndex += 3;
// check for the end
if ( mCurrentIndex >= mEnd )
mCurrentIndex = mEnd;
else
if ( isPrimRestart(mCurrentIndex) )
{
mCurrentIndex += 1;
mA = mArray->at(mCurrentIndex + 0);
mB = mArray->at(mCurrentIndex + 1);
mC = mArray->at(mCurrentIndex + 2);
}
else
{
mA = mArray->at(mCurrentIndex + 0);
mB = mArray->at(mCurrentIndex + 1);
mC = mArray->at(mCurrentIndex + 2);
}
break;
case PT_TRIANGLES_ADJACENCY:
mCurrentIndex += 6;
// check for the end
if ( mCurrentIndex >= mEnd )
mCurrentIndex = mEnd;
else
if ( isPrimRestart(mCurrentIndex) )
{
mCurrentIndex += 1;
mA = mArray->at(mCurrentIndex + 0);
mB = mArray->at(mCurrentIndex + 2);
mC = mArray->at(mCurrentIndex + 4);
}
else
{
mA = mArray->at(mCurrentIndex + 0);
mB = mArray->at(mCurrentIndex + 2);
mC = mArray->at(mCurrentIndex + 4);
}
break;
case PT_QUAD_STRIP:
case PT_TRIANGLE_STRIP:
mCurrentIndex += 1;
if ( mCurrentIndex + 2 >= mEnd )
mCurrentIndex = mEnd;
else
if ( isPrimRestart(mCurrentIndex + 2) )
{
mCurrentIndex += 3;
mEven = true;
mA = mArray->at(mCurrentIndex + 0);
mB = mArray->at(mCurrentIndex + 1);
mC = mArray->at(mCurrentIndex + 2);
}
else
{
mEven = !mEven;
if (mEven)
{
mA = mArray->at(mCurrentIndex + 0);
mB = mArray->at(mCurrentIndex + 1);
mC = mArray->at(mCurrentIndex + 2);
}
else
{
mA = mArray->at(mCurrentIndex + 0);
mB = mArray->at(mCurrentIndex + 2);
mC = mArray->at(mCurrentIndex + 1);
}
}
break;
case PT_TRIANGLE_FAN:
case PT_POLYGON:
mCurrentIndex += 1;
if ( mCurrentIndex + 1 >= mEnd )
{
mCurrentIndex = mEnd;
}
else
if ( isPrimRestart(mCurrentIndex + 1) )
{
mIndex0 = mCurrentIndex + 2;
mCurrentIndex = mIndex0 + 1;
mA = mArray->at(mIndex0);
mB = mArray->at(mCurrentIndex + 0);
mC = mArray->at(mCurrentIndex + 1);
}
else
{
mA = mArray->at(mIndex0);
mB = mArray->at(mCurrentIndex + 0);
mC = mArray->at(mCurrentIndex + 1);
}
break;
case PT_QUADS:
mCurrentIndex += 2;
if ( mCurrentIndex >= mEnd )
{
mCurrentIndex = mEnd;
}
else
if ( isPrimRestart(mCurrentIndex) )
{
mCurrentIndex += 1;
mEven = true;
mA = mArray->at(mCurrentIndex+0);
mB = mArray->at(mCurrentIndex+1);
mC = mArray->at(mCurrentIndex+2);
}
else
{
mEven = !mEven;
if ( mEven )
{
mA = mArray->at(mCurrentIndex+0);
mB = mArray->at(mCurrentIndex+1);
mC = mArray->at(mCurrentIndex+2);
}
else
{
mA = mArray->at(mCurrentIndex+0);
mB = mArray->at(mCurrentIndex+1);
mC = mArray->at(mCurrentIndex-2);
}
}
break;
default:
VL_TRAP();
break;
}
// if we are not at the end then add base vertices
if (mCurrentIndex != mEnd)
{
mA += mBaseVertex;
mB += mBaseVertex;
mC += mBaseVertex;
return true;
}
else
{
mA = mB = mC = -1;
return false;
}
}
void setBaseVertex(int base_vert) { mBaseVertex = base_vert; }
int baseVertex() const { return mBaseVertex; }
private:
bool isPrimRestart(int i) const { return mPrimRestartOn && mArray->at(i) == mPrimRestartIndex; }
private:
const TArray* mArray;
EPrimitiveType mPrimType;
int mA, mB, mC;
int mCurrentIndex;
int mIndex0;
int mEnd;
int mBaseVertex;
unsigned int mPrimRestartIndex;
bool mPrimRestartOn;
bool mEven;
};
//-----------------------------------------------------------------------------
// TriangleIteratorDirect
//-----------------------------------------------------------------------------
/** For internal use only. See vl::TriangleIterator instead. */
class TriangleIteratorDirect: public TriangleIteratorAbstract
{
VL_INSTRUMENT_CLASS(vl::TriangleIteratorDirect, TriangleIteratorAbstract)
public:
TriangleIteratorDirect(EPrimitiveType prim_type=PT_UNKNOWN)
{
VL_DEBUG_SET_OBJECT_NAME()
mCurrentIndex = mStart = mEnd = 0;
mA = mB = mC = -1;
mPrimType = prim_type;
mEven = true;
}
bool hasNext() const { return mCurrentIndex != mEnd; }
virtual int a() const { return mA; }
virtual int b() const { return mB; }
virtual int c() const { return mC; }
void initialize(int start, int end)
{
VL_CHECK(end >= start)
mStart = start;
mCurrentIndex = mEnd = end;
mA = mB = mC = -1;
mEven = true;
switch(mPrimType)
{
case PT_TRIANGLES:
// VL_CHECK( (end - start) % 3 == 0 ) /* primitive restart might screw up this */
mCurrentIndex = start;
mA = start + 0;
mB = start + 1;
mC = start + 2;
break;
case PT_TRIANGLE_STRIP:
mCurrentIndex = start;
mA = start + 0;
mB = start + 1;
mC = start + 2;
break;
case PT_TRIANGLE_FAN:
case PT_POLYGON:
mCurrentIndex = start + 1;
mA = start + 0;
mB = start + 1;
mC = start + 2;
break;
case PT_QUADS:
// VL_CHECK( (end - start) % 4 == 0 ) /* primitive restart might screw up this */
mCurrentIndex = start;
mA = start + 0;
mB = start + 1;
mC = start + 2;
break;
case PT_QUAD_STRIP:
// VL_CHECK( (end - start) % 2 == 0 ) /* primitive restart might screw up this */
mCurrentIndex = start;
mA = start + 0;
mB = start + 1;
mC = start + 2;
break;
default:
break;
}
}
bool next()
{
// reached the end
if ( mCurrentIndex == mEnd )
return false;
switch(mPrimType)
{
case PT_TRIANGLES:
mCurrentIndex += 3;
// check for the end
if ( mCurrentIndex >= mEnd )
mCurrentIndex = mEnd;
else
{
mA = mCurrentIndex + 0;
mB = mCurrentIndex + 1;
mC = mCurrentIndex + 2;
}
break;
case PT_QUAD_STRIP:
case PT_TRIANGLE_STRIP:
mCurrentIndex += 1;
if ( mCurrentIndex + 2 >= mEnd )
mCurrentIndex = mEnd;
else
{
mEven = !mEven;
if (mEven)
{
mA = mCurrentIndex + 0;
mB = mCurrentIndex + 1;
mC = mCurrentIndex + 2;
}
else
{
mA = mCurrentIndex + 0;
mB = mCurrentIndex + 2;
mC = mCurrentIndex + 1;
}
}
break;
case PT_TRIANGLE_FAN:
case PT_POLYGON:
mCurrentIndex += 1;
if ( mCurrentIndex + 1 >= mEnd )
{
mCurrentIndex = mEnd;
}
else
{
mA = mStart;
mB = mCurrentIndex+0;
mC = mCurrentIndex+1;
}
break;
case PT_QUADS:
mCurrentIndex += 2;
if ( mCurrentIndex >= mEnd )
{
mCurrentIndex = mEnd;
}
else
{
mEven = !mEven;
if ( mEven )
{
mA = mCurrentIndex+0;
mB = mCurrentIndex+1;
mC = mCurrentIndex+2;
}
else
{
mA = mCurrentIndex+0;
mB = mCurrentIndex+1;
mC = mCurrentIndex-2;
}
}
break;
default:
VL_TRAP();
break;
}
// if we are not at the end then add base vertices
if (mCurrentIndex == mEnd)
{
mA = mB = mC = -1;
return false;
}
else
return true;
}
private:
EPrimitiveType mPrimType;
int mA, mB, mC;
int mCurrentIndex;
int mStart;
int mEnd;
bool mEven;
};
//-----------------------------------------------------------------------------
// TriangleIteratorMulti
//-----------------------------------------------------------------------------
/** For internal use only. See vl::TriangleIterator instead. */
template<class TArray>
class TriangleIteratorMulti: public TriangleIteratorIndexed<TArray>
{
VL_INSTRUMENT_CLASS(vl::TriangleIteratorMulti<class TArray>, TriangleIteratorIndexed<TArray>)
public:
TriangleIteratorMulti( const std::vector<GLint>* p_base_vertices, const std::vector<GLsizei>* p_count_vector, const TArray* idx_array, EPrimitiveType prim_type, bool prim_restart_on, int prim_restart_idx)
:TriangleIteratorIndexed<TArray>( idx_array, prim_type, 0, prim_restart_on, prim_restart_idx)
{
VL_DEBUG_SET_OBJECT_NAME()
mpBaseVertices = p_base_vertices;
mpCountVector = p_count_vector;
mStart = 0;
mCurPrim = 0;
}
void initialize()
{
VL_CHECK( mpBaseVertices->size() == mpCountVector->size() )
if ( (*mpBaseVertices).size() )
TriangleIteratorIndexed<TArray>::setBaseVertex( (*mpBaseVertices)[mCurPrim] );
int end = mStart + (*mpCountVector)[mCurPrim];
TriangleIteratorIndexed<TArray>::initialize( mStart, end );
// abort if could not initialize (primitive not supported)
if ( !TriangleIteratorIndexed<TArray>::hasNext() )
mCurPrim = (int)(*mpCountVector).size()-1;
}
bool next()
{
if ( TriangleIteratorIndexed<TArray>::next() )
return true;
else
if ( mCurPrim < (int)(*mpCountVector).size()-1 )
{
mStart += (*mpCountVector)[mCurPrim];
mCurPrim++;
initialize();
return true;
}
else
return false;
}
bool hasNext() const
{
if ( !TriangleIteratorIndexed<TArray>::hasNext() && mCurPrim == (int)(*mpCountVector).size()-1 )
return false;
else
return true;
}
protected:
const std::vector<GLint>* mpBaseVertices;
const std::vector<GLsizei>* mpCountVector;
int mCurPrim;
int mStart;
};
//-----------------------------------------------------------------------------
// TriangleIterator
//-----------------------------------------------------------------------------
/** Iterator used to extract the indices of every single triangle of a DrawCall
* regardless of the primitive type.
* \sa DrawCall::triangles() */
class TriangleIterator
{
public:
TriangleIterator(TriangleIteratorAbstract* it): mIterator(it) { }
/** Requires the next triangle. Returns \p false the iterator reached the end of the triangle list. */
bool next() { return mIterator->next(); }
bool operator++() { return next(); }
/** Returns false if the iterator has reached the end of the triangle list. In this case a(), b() and c() return -1. */
bool hasNext() { return mIterator->hasNext(); }
/** First index of the triangle. */
int a() const { return mIterator->a(); }
/** First index of the triangle. */
int b() const { return mIterator->b(); }
/** First index of the triangle. */
int c() const { return mIterator->c(); }
protected:
ref<TriangleIteratorAbstract> mIterator;
};
//-----------------------------------------------------------------------------
}
#endif