KeosMesh.cpp

Go to the documentation of this file.
00001 /*
00002  * This source file is part of KEOS (Free 3D Engine)
00003  * For the latest info, see http://www.keosengine.org/
00004  * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
00005  *
00006  * This program is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License as published by the Free Software
00008  * Foundation; either version 2 of the License, or (at your option) any later
00009  * version.
00010  *
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00018  * http://www.gnu.org/copyleft/lesser.txt.
00019  *
00020  */
00021 
00022 #include "KeosMesh.h"
00023 #include "KeosException.h"
00024 #include "KeosRoot.h"
00025 #include "KeosRenderSystem.h"
00026 #include "KeosUtil.h"
00027 
00028 namespace Keos
00029 {
00030 #define Renderer CRoot::Instance().GetRenderSystem()
00031 
00032 
00033   //=======================================================================
00034   // CMesh implementation
00035   //=======================================================================
00036 
00037   //-----------------------------------------------------------------------
00038   CMesh::CMesh()
00039   {}
00040 
00041   //-----------------------------------------------------------------------
00042   CMesh::~CMesh()
00043   {
00044     std::for_each(m_MeshGeomList.begin(), m_MeshGeomList.end(), Delete());
00045     std::for_each(m_MaterialList.begin(), m_MaterialList.end(), Delete());
00046   }
00047 
00048   //-----------------------------------------------------------------------
00049   void CMesh::Render() const
00050   {
00051     CMeshGeom* pTemp;
00052     for (uint i = 0; i < m_MeshGeomList.size(); i++)
00053     {
00054       pTemp = m_MeshGeomList[i];
00055       if (pTemp->GetMaterialIndex() != -1)
00056       {
00057         CMaterial* pMaterial = m_MaterialList[pTemp->GetMaterialIndex()];
00058         if (pMaterial->HasTexture()) // For the moment only the texture is used
00059         {
00060           //Renderer->SetupTextureUnit(0, TXO_COLOR_FIRSTARG, TXA_TEXTURE);
00061           //Renderer->SetupTextureUnit(0, TXO_ALPHA_FIRSTARG, TXA_TEXTURE);
00062           Renderer->SetTexture(0, pMaterial->GetTexture()->GetTextureBase());
00063         }
00064         else Renderer->SetTexture(0, NULL);
00065       }
00066       Renderer->SetDeclaration(pTemp->m_pDeclaration);
00067       if (pTemp->m_bUseSharedVertexBuffer)
00068         Renderer->SetVertexBuffer(0, m_SharedVertexBuffer);
00069       else Renderer->SetVertexBuffer(0, pTemp->m_VertexBuffer);
00070       Renderer->SetIndexBuffer(pTemp->m_IndexBuffer);
00071       Renderer->DrawIndexedPrimitives(pTemp->m_PrimitiveType, 0, pTemp->m_nPrimitivesCount);
00072 
00073     }
00074   }
00075 
00076   //-----------------------------------------------------------------------
00077   uint CMesh::GetTrianglesCount(void)
00078   {
00079     uint nRes = 0;
00080     for (uint i = 0; i < m_MeshGeomList.size(); i++)
00081     {
00082       nRes += m_MeshGeomList[i]->GetTrianglesCount();
00083 
00084     }
00085     return nRes;
00086   }
00087 
00088   //-----------------------------------------------------------------------
00089   void CMesh::CreateSharedVertexBuffer(const CMeshGeom::TVertex* pVertices, ulong nVerticesCount)
00090   {
00091     Assert(pVertices != NULL);
00092     m_SharedVertexBuffer  = Renderer->CreateVertexBuffer(nVerticesCount, 0, pVertices);
00093   }
00094 
00095   //-----------------------------------------------------------------------
00096   void CMesh::ComputeNormals()
00097   {
00101 
00102     TVector3F vVector1, vVector2, vNormal, vPoly[3];
00103 
00104     // Calculate the face normals, then you take the average of all the normals around each
00105     // vertex.  It's just averaging.  That way you get a better approximation for that vertex.
00106 
00107     // Go through each of the MeshGeom to calculate their normals
00108     for (uint index = 0; index < m_MeshGeomList.size(); index++)
00109     {
00110       uint i;
00111 
00112       // Get the current MeshGeom
00113       CMeshGeom* pMeshGeom = m_MeshGeomList[index];
00114 
00115       // Here we allocate all the memory we need to calculate the normals
00116       TVector3F *pNormals  = new TVector3F [pMeshGeom->GetTrianglesCount()];
00117       TVector3F *pTempNormals = new TVector3F [pMeshGeom->GetTrianglesCount()];
00118 
00119       // Lock buffers
00120       uint nVertexBufferSize;
00121       CMeshGeom::TVertex* Vertices;
00122       if (pMeshGeom->m_bUseSharedVertexBuffer)
00123       {
00124         Vertices = m_SharedVertexBuffer.Lock(0, 0, LOCK_WRITEONLY);
00125         nVertexBufferSize = m_SharedVertexBuffer.GetCount();
00126       }
00127       else
00128       {
00129         Vertices = pMeshGeom->m_VertexBuffer.Lock(0, 0, LOCK_WRITEONLY);
00130         nVertexBufferSize = pMeshGeom->m_VertexBuffer.GetCount();
00131       }
00132       CMeshGeom::TIndex* Indicies = pMeshGeom->m_IndexBuffer.Lock(0, 0, LOCK_READONLY);
00133 
00134       // Go though all of the faces of this object
00135       for (i = 0; i < pMeshGeom->GetTrianglesCount(); i++)
00136       {
00137         // To cut down LARGE code, we extract the 3 points of this face
00138         vPoly[0] = Vertices[Indicies[i*3+0]].Position;
00139         vPoly[1] = Vertices[Indicies[i*3+1]].Position;
00140         vPoly[2] = Vertices[Indicies[i*3+2]].Position;
00141 
00142         // Now let's calculate the face normals (Get 2 vectors and find the cross product of those 2)
00143 
00144         vVector1 = VectorBetweenTwoPoints(vPoly[0], vPoly[2]);  // Get the vector of the polygon (we just need 2 sides for the normal)
00145         vVector2 = VectorBetweenTwoPoints(vPoly[2], vPoly[1]);  // Get a second vector of the polygon
00146 
00147         vNormal  = VectorCross(vVector1, vVector2);  // Return the cross product of the 2 vectors (normalize vector, but not a unit vector)
00148         pTempNormals[i] = vNormal;     // Save the un-normalized normal for the vertex normals
00149         vNormal.Normalize();    // Normalize the cross product to give us the polygons normal
00150 
00151         pNormals[i] = vNormal;      // Assign the normal to the list of normals
00152       }
00153 
00154       // Now Get The Vertex Normals
00155       TVector3F vSum = TVector3F(0.0, 0.0, 0.0);
00156       TVector3F vZero = vSum;
00157       int shared = 0;
00158 
00159       for (i = 0; i < nVertexBufferSize; i++)   // Go through all of the vertices
00160       {
00161         for (uint j = 0; j < pMeshGeom->GetTrianglesCount(); j++) // Go through all of the triangles
00162         {            // Check if the vertex is shared by another face
00163           if (Indicies[j*3+0] == i ||
00164               Indicies[j*3+1] == i ||
00165               Indicies[j*3+2] == i)
00166           {
00167             vSum += pTempNormals[j];// Add the un-normalized normal of the shared face
00168             shared++;    // Increase the number of shared triangles
00169           }
00170         }
00171 
00172         // Get the normal by dividing the sum by the shared.  We negate the shared so it has the normals pointing out.
00173         if (pMeshGeom->m_bUseSharedVertexBuffer && (Vertices[i].Normal.LengthSq() != 0))
00174           Vertices[i].Normal = (vSum + Vertices[i].Normal / float(-(shared + 1)));
00175         Vertices[i].Normal = (vSum / float(-shared));
00176 
00177         // Normalize the normal for the final vertex normal
00178         Vertices[i].Normal.Normalize();
00179 
00180         vSum = vZero;         // Reset the sum
00181         shared = 0;          // Reset the shared
00182       }
00183 
00184       // Unlock buffers
00185       if (pMeshGeom->m_bUseSharedVertexBuffer)
00186         m_SharedVertexBuffer.Unlock();
00187       else pMeshGeom->m_VertexBuffer.Unlock();
00188       pMeshGeom->m_IndexBuffer.Unlock();
00189 
00190       // Free our memory and start over on the next MeshGeom
00191       delete [] pTempNormals;
00192       delete [] pNormals;
00193     }
00194   }
00195 
00196   //-----------------------------------------------------------------------
00197   CMeshGeom* CMesh::GetMeshGeom(const String& strName) const
00198   {
00199     ushort nIndex = _GetMeshGeomIndex(strName);
00200     return GetMeshGeom(nIndex);
00201   }
00202 
00203   //-----------------------------------------------------------------------
00204   CMeshGeom* CMesh::GetMeshGeom(ushort nIndex) const
00205   {
00206     TMeshGeomList::const_iterator i = m_MeshGeomList.begin();
00207     return const_cast<CMeshGeom*>(i[nIndex]);
00208   }
00209 
00210   //---------------------------------------------------------------------
00211   ushort CMesh::_GetMeshGeomIndex(const String& strName) const
00212   {
00213     TMeshGeomNameMap::const_iterator i = m_MeshGeomNameMap.find(strName) ;
00214     if (i == m_MeshGeomNameMap.end())
00215       throw new CException("No MeshGeom named " + strName + " found.");
00216 
00217     return i->second;
00218   }
00219 
00220 } // namespace Keos

Generated on Fri Mar 9 14:29:02 2007 for Keos by  doxygen 1.5.1-p1