/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2006 Torus Knot Software Ltd Copyright (c) 2006 Matthias Fink, netAllied GmbH Also see acknowledgements in Readme.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. You may alternatively use this source under the terms of a specific version of the OGRE Unrestricted License provided you have obtained such a license from Torus Knot Software Ltd. ----------------------------------------------------------------------------- */ #include "OgreStableHeaders.h" #include "OgrePolygon.h" #include "OgreException.h" #include "OgreVector3.h" namespace Ogre { //----------------------------------------------------------------------- Polygon::Polygon() : mNormal( Vector3::ZERO ) , mIsNormalSet(false) { // reserve space for 6 vertices to reduce allocation cost mVertexList.reserve(6); } //----------------------------------------------------------------------- Polygon::~Polygon() { } //----------------------------------------------------------------------- Polygon::Polygon( const Polygon& cpy ) { mVertexList = cpy.mVertexList; mNormal = cpy.mNormal; mIsNormalSet = cpy.mIsNormalSet; } //----------------------------------------------------------------------- void Polygon::insertVertex(const Vector3& vdata, size_t vertex ) { // TODO: optional: check planarity OgreAssert(vertex <= getVertexCount(), "Insert position out of range" ); VertexList::iterator it = mVertexList.begin(); std::advance(it, vertex); mVertexList.insert(it, vdata); } //----------------------------------------------------------------------- void Polygon::insertVertex(const Vector3& vdata) { mVertexList.push_back(vdata); } //----------------------------------------------------------------------- const Vector3& Polygon::getVertex( size_t vertex ) const { OgreAssert(vertex < getVertexCount(), "Search position out of range"); return mVertexList[vertex]; } //----------------------------------------------------------------------- void Polygon::setVertex(const Vector3& vdata, size_t vertex ) { // TODO: optional: check planarity OgreAssert(vertex < getVertexCount(), "Search position out of range" ); // set new vertex mVertexList[ vertex ] = vdata; } //----------------------------------------------------------------------- void Polygon::removeDuplicates( void ) { for ( size_t i = 0; i < getVertexCount(); ++i ) { const Vector3& a = getVertex( i ); const Vector3& b = getVertex( (i + 1)%getVertexCount() ); if (a.positionEquals(b)) { deleteVertex(i); --i; } } } //----------------------------------------------------------------------- size_t Polygon::getVertexCount( void ) const { return mVertexList.size(); } //----------------------------------------------------------------------- const Vector3& Polygon::getNormal( void ) { OgreAssert( getVertexCount() >= 3, "Insufficient vertex count!" ); updateNormal(); return mNormal; } //----------------------------------------------------------------------- void Polygon::updateNormal( void ) { OgreAssert( getVertexCount() >= 3, "Insufficient vertex count!" ); if (mIsNormalSet) return; // vertex order is ccw const Vector3& a = getVertex( 0 ); const Vector3& b = getVertex( 1 ); const Vector3& c = getVertex( 2 ); // used method: Newell mNormal.x = 0.5f * ( (a.y - b.y) * (a.z + b.z) + (b.y - c.y) * (b.z + c.z) + (c.y - a.y) * (c.z + a.z)); mNormal.y = 0.5f * ( (a.z - b.z) * (a.x + b.x) + (b.z - c.z) * (b.x + c.x) + (c.z - a.z) * (c.x + a.x)); mNormal.z = 0.5f * ( (a.x - b.x) * (a.y + b.y) + (b.x - c.x) * (b.y + c.y) + (c.x - a.x) * (c.y + a.y)); mNormal.normalise(); mIsNormalSet = true; } //----------------------------------------------------------------------- void Polygon::deleteVertex( size_t vertex ) { OgreAssert( vertex < getVertexCount(), "Search position out of range" ); VertexList::iterator it = mVertexList.begin(); std::advance(it, vertex); mVertexList.erase( it ); } //----------------------------------------------------------------------- void Polygon::storeEdges( Polygon::EdgeMap *edgeMap ) const { OgreAssert( edgeMap != NULL, "EdgeMap ptr is NULL" ); size_t vertexCount = getVertexCount(); for ( size_t i = 0; i < vertexCount; ++i ) { edgeMap->insert( Edge( getVertex( i ), getVertex( ( i + 1 ) % vertexCount ) ) ); } } //----------------------------------------------------------------------- void Polygon::reset( void ) { // could use swap() to free memory here, but assume most may be reused so avoid realloc mVertexList.clear(); mIsNormalSet = false; } //----------------------------------------------------------------------- bool Polygon::operator == (const Polygon& rhs) const { if ( getVertexCount() != rhs.getVertexCount() ) return false; // Compare vertices. They may differ in its starting position. // find start size_t start; bool foundStart = false; for (size_t i = 0; i < getVertexCount(); ++i ) { if (getVertex(0).positionEquals(rhs.getVertex(i))) { start = i; foundStart = true; break; } } if (!foundStart) return false; for (size_t i = 0; i < getVertexCount(); ++i ) { const Vector3& vA = getVertex( i ); const Vector3& vB = rhs.getVertex( ( i + start) % getVertexCount() ); if (!vA.positionEquals(vB)) return false; } return true; } //----------------------------------------------------------------------- std::ostream& operator<< ( std::ostream& strm, const Polygon& poly ) { strm << "NUM VERTICES: " << poly.getVertexCount() << std::endl; for (size_t j = 0; j < poly.getVertexCount(); ++j ) { strm << "VERTEX " << j << ": " << poly.getVertex( j ) << std::endl; } return strm; } //----------------------------------------------------------------------- }