#pragma region License /****************************************************************************** This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ #pragma endregion #include "IndexedSurfacePatch.h" using namespace std; namespace PolyVox { IndexedSurfacePatch::IndexedSurfacePatch() { m_iTimeStamp = -1; } IndexedSurfacePatch::~IndexedSurfacePatch() { } const std::vector& IndexedSurfacePatch::getIndices(void) const { return m_vecTriangleIndices; } uint32_t IndexedSurfacePatch::getNoOfIndices(void) const { return m_vecTriangleIndices.size(); } uint32_t IndexedSurfacePatch::getNoOfNonUniformTrianges(void) const { uint32_t result = 0; for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) { if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) { } else { result++; } } return result; } uint32_t IndexedSurfacePatch::getNoOfUniformTrianges(void) const { uint32_t result = 0; for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) { if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) { result++; } } return result; } uint32_t IndexedSurfacePatch::getNoOfVertices(void) const { return m_vecVertices.size(); } std::vector& IndexedSurfacePatch::getRawVertexData(void) { return m_vecVertices; } const std::vector& IndexedSurfacePatch::getVertices(void) const { return m_vecVertices; } void IndexedSurfacePatch::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) { m_vecTriangleIndices.push_back(index0); m_vecTriangleIndices.push_back(index1); m_vecTriangleIndices.push_back(index2); } uint32_t IndexedSurfacePatch::addVertex(const SurfaceVertex& vertex) { m_vecVertices.push_back(vertex); return m_vecVertices.size() - 1; } void IndexedSurfacePatch::clear(void) { m_vecVertices.clear(); m_vecTriangleIndices.clear(); } const bool IndexedSurfacePatch::isEmpty(void) const { return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); } void IndexedSurfacePatch::smooth(float fAmount, bool bIncludeEdgeVertices) { if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... { return; } std::vector vecOriginalVertices = m_vecVertices; Vector3DFloat offset = static_cast(m_Region.getLowerCorner()); for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) { SurfaceVertex& v0 = vecOriginalVertices[*iterIndex]; SurfaceVertex& v0New = m_vecVertices[*iterIndex]; iterIndex++; SurfaceVertex& v1 = vecOriginalVertices[*iterIndex]; SurfaceVertex& v1New = m_vecVertices[*iterIndex]; iterIndex++; SurfaceVertex& v2 = vecOriginalVertices[*iterIndex]; SurfaceVertex& v2New = m_vecVertices[*iterIndex]; iterIndex++; //FIXME - instead of finding these opposite points (Opp) we could just use the midpoint? Vector3DFloat v0Opp = (v1.position + v2.position) / 2.0f; Vector3DFloat v1Opp = (v0.position + v2.position) / 2.0f; Vector3DFloat v2Opp = (v0.position + v1.position) / 2.0f; Vector3DFloat v0ToOpp = v0Opp - v0.position; v0ToOpp.normalise(); Vector3DFloat v1ToOpp = v1Opp - v1.position; v1ToOpp.normalise(); Vector3DFloat v2ToOpp = v2Opp - v2.position; v2ToOpp.normalise(); Vector3DFloat n0 = v0.getNormal(); n0.normalise(); Vector3DFloat n1 = v1.getNormal(); n1.normalise(); Vector3DFloat n2 = v2.getNormal(); n2.normalise(); if(m_Region.containsPoint(v0.getPosition() + offset, 0.001)) { v0New.position += (n0 * (n0.dot(v0ToOpp)) * fAmount); } if(m_Region.containsPoint(v1.getPosition() + offset, 0.001)) { v1New.position += (n1 * (n1.dot(v1ToOpp)) * fAmount); } if(m_Region.containsPoint(v2.getPosition() + offset, 0.001)) { v2New.position += (n2 * (n2.dot(v2ToOpp)) * fAmount); } } } void IndexedSurfacePatch::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices) { Vector3DFloat offset = static_cast(m_Region.getLowerCorner()); for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) { if(m_Region.containsPoint(iterVertex->getPosition() + offset, 0.001)) { iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f)); } } for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) { SurfaceVertex& v0 = m_vecVertices[*iterIndex]; iterIndex++; SurfaceVertex& v1 = m_vecVertices[*iterIndex]; iterIndex++; SurfaceVertex& v2 = m_vecVertices[*iterIndex]; iterIndex++; Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition()); if(m_Region.containsPoint(v0.getPosition() + offset, 0.001)) { v0.setNormal(v0.getNormal() + triangleNormal); } if(m_Region.containsPoint(v1.getPosition() + offset, 0.001)) { v1.setNormal(v1.getNormal() + triangleNormal); } if(m_Region.containsPoint(v2.getPosition() + offset, 0.001)) { v2.setNormal(v2.getNormal() + triangleNormal); } } if(bNormalise) { for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) { Vector3DFloat normal = iterVertex->getNormal(); normal.normalise(); iterVertex->setNormal(normal); } } } POLYVOX_SHARED_PTR IndexedSurfacePatch::extractSubset(std::set setMaterials) { POLYVOX_SHARED_PTR result(new IndexedSurfacePatch); if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... { return result; } for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) { SurfaceVertex& v0 = m_vecVertices[*iterIndex]; iterIndex++; SurfaceVertex& v1 = m_vecVertices[*iterIndex]; iterIndex++; SurfaceVertex& v2 = m_vecVertices[*iterIndex]; iterIndex++; if( (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || (setMaterials.find(v2.getMaterial()) != setMaterials.end())) { uint32_t i0 = result->addVertex(v0); uint32_t i1 = result->addVertex(v1); uint32_t i2 = result->addVertex(v2); result->addTriangle(i0,i1,i2); } } return result; } }