Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreEdgeListBuilder.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2004 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreStableHeaders.h"
00026 #include "OgreEdgeListBuilder.h"
00027 #include "OgreLogManager.h"
00028 #include "OgreStringConverter.h"
00029 #include "OgreVertexIndexData.h"
00030 #include "OgreException.h"
00031 
00032 namespace Ogre {
00033 
00034     void EdgeData::log(Log* l)
00035     {
00036         EdgeGroupList::iterator i, iend;
00037         EdgeList::iterator ei, eiend;
00038         TriangleList::iterator ti, tiend;
00039         tiend = triangles.end();
00040         l->logMessage("Edge Data");
00041         l->logMessage("---------");
00042         size_t num = 0;
00043         for (ti = triangles.begin(); ti != tiend; ++ti, ++num)
00044         {
00045             Triangle& t = *ti;
00046             l->logMessage("Triangle " + StringConverter::toString(num) + " = {" +
00047                 "indexSet=" + StringConverter::toString(t.indexSet) + ", " + 
00048                 "vertexSet=" + StringConverter::toString(t.vertexSet) + ", " + 
00049                 "v0=" + StringConverter::toString(t.vertIndex[0]) + ", " + 
00050                 "v1=" + StringConverter::toString(t.vertIndex[1]) + ", " + 
00051                 "v2=" + StringConverter::toString(t.vertIndex[2]) + "}"); 
00052         }
00053         iend = edgeGroups.end();
00054         for (i = edgeGroups.begin(); i != iend; ++i)
00055         {
00056             num = 0;
00057             eiend = i->edges.end();
00058             l->logMessage("Edge Group vertexSet=" + StringConverter::toString(i->vertexSet));
00059             for (ei = i->edges.begin(); ei != eiend; ++ei, ++num)
00060             {
00061                 Edge& e = *ei;
00062                 l->logMessage(
00063                     "Edge " + StringConverter::toString(num) + " = {\n" + 
00064                     "  tri0=" + StringConverter::toString(e.triIndex[0]) + ", \n" + 
00065                     "  tri1=" + StringConverter::toString(e.triIndex[1]) + ", \n" + 
00066                     "  v0=" + StringConverter::toString(e.vertIndex[0]) + ", \n" + 
00067                     "  v1=" + StringConverter::toString(e.vertIndex[1]) + ", \n"
00068                     "  degenerate=" + StringConverter::toString(e.degenerate) + " \n"
00069                     "}"); 
00070             }
00071         }
00072     }
00073     //---------------------------------------------------------------------
00074     EdgeListBuilder::EdgeListBuilder()
00075         : mEdgeData(0), mWeldVertices(true), mWeldVerticesAcrossVertexSets(true), 
00076         mWeldVerticesAcrossIndexSets(true)
00077     {
00078     }
00079     //---------------------------------------------------------------------
00080     EdgeListBuilder::~EdgeListBuilder()
00081     {
00082     }
00083     //---------------------------------------------------------------------
00084     void EdgeListBuilder::addVertexData(const VertexData* vertexData)
00085     {
00086         mVertexDataList.push_back(vertexData);
00087     }
00088     //---------------------------------------------------------------------
00089     void EdgeListBuilder::addIndexData(const IndexData* indexData, 
00090         size_t vertexSet, RenderOperation::OperationType opType)
00091     {
00092         mIndexDataList.push_back(indexData);
00093         mIndexDataVertexDataSetList.push_back(vertexSet);
00094         mOperationTypeList.push_back(opType);
00095     }
00096     //---------------------------------------------------------------------
00097     EdgeData* EdgeListBuilder::build(void)
00098     {
00099         /* Ok, here's the algorithm:
00100         For each set of indices in turn
00101           // First pass, create triangles and create edges
00102           For each set of 3 indexes
00103             Create a new Triangle entry in the list
00104             For each vertex referenced by the tri indexes
00105               Get the position of the vertex as a Vector3 from the correct vertex buffer
00106               Attempt to locate this position in the existing common vertex set
00107               If not found
00108                 Create a new common vertex entry in the list
00109               End If
00110               Populate the original vertex index and common vertex index 
00111             Next vertex
00112             If commonIndex[0] < commonIndex[1]
00113                 Create a new edge 
00114             End If
00115             If commonIndex[1] < commonIndex[2]
00116                 Create a new edge 
00117             End If
00118             If commonIndex[2] < commonIndex[0]
00119                 Create a new edge 
00120             End If
00121           Next set of 3 indexes
00122         Next index set
00123         // Identify shared edges (works across index sets)
00124         For each triangle in the common triangle list
00125         If commonIndex[0] > commonIndex[1]
00126             Find existing edge and update with second side
00127         End If
00128         If commonIndex[1] > commonIndex[2]
00129             Find existing edge and update with second side
00130         End If
00131         If commonIndex[2] > commonIndex[0]
00132             Find existing edge and update with second side
00133         End If
00134         Next triangle
00135 
00136         Note that all edges 'belong' to the index set which originally caused them
00137         to be created, which also means that the 2 vertices on the edge are both referencing the 
00138         vertex buffer which this index set uses.
00139         */
00140 
00141 
00142         /* 
00143         There is a major consideration: 'What is a common vertex'? This is a
00144         crucial decision, since to form a completely close hull, you need to treat
00145         vertices which are not physically the same as equivalent. This is because
00146         there will be 'seams' in the model, where discrepancies in vertex components
00147         other than position (such as normals or texture coordinates) will mean
00148         that there are 2 vertices in the same place, and we MUST 'weld' them
00149         into a single common vertex in order to have a closed hull. Just looking
00150         at the unique vertex indices is not enough, since these seams would render
00151         the hull invalid.
00152 
00153         So, we look for positions which are the same across vertices, and treat 
00154         those as as single vertex for our edge calculation. However, this has
00155         it's own problems. There are OTHER vertices which may have a common 
00156         position that should not be welded. Imagine 2 cubes touching along one
00157         single edge. The common vertices on that edge, if welded, will cause 
00158         an ambiguous hull, since the edge will have 4 triangles attached to it,
00159         whilst a manifold mesh should only have 2 triangles attached to each edge.
00160         This is a problem.
00161 
00162         We deal with this with fallback techniques. We try the following approaches,
00163         in order, falling back on the next approach if the current one results in
00164         an ambiguous hull:
00165         
00166         1. Weld all vertices at the same position across all vertex and index sets. 
00167         2. Weld vertices at the same position if they are in the same vertex set, 
00168            but regardless of the index set
00169         3. Weld vertices at the same position if they were first referred to in 
00170            the same index set, but regardless of the vertex set.
00171         4. Weld vertices only if they are in the same vertex set AND they are first
00172            referenced in the same index set.
00173         5. Never weld vertices at the same position. This will only result in a
00174            valid hull if there are no seams in the mesh (perfect vertex sharing)
00175 
00176         If all these techniques fail, the hull cannot be built. 
00177 
00178         Therefore, when you have a model which has a potentially ambiguous hull,
00179         (meeting at edges), you MUST EITHER:
00180 
00181            A. differentiate the individual sub-hulls by separating them by 
00182               vertex set or by index set.
00183         or B. ensure that you have no seams, ie you have perfect vertex sharing.
00184               This is typically only feasible when you have no textures and 
00185               completely smooth shading
00186         */
00187 
00188         ushort technique = 1;
00189         bool validHull= false;
00190 
00191         while (!validHull && technique <= 5)
00192         {
00193             switch (technique)
00194             {
00195             case 1: // weld across everything
00196                 mWeldVertices = true;
00197                 mWeldVerticesAcrossVertexSets = true;
00198                 mWeldVerticesAcrossIndexSets = true;
00199                 break;
00200             case 2: // weld across index sets only
00201                 mWeldVertices = true;
00202                 mWeldVerticesAcrossVertexSets = false;
00203                 mWeldVerticesAcrossIndexSets = true;
00204                 break;
00205             case 3: // weld across vertex sets only
00206                 mWeldVertices = true;
00207                 mWeldVerticesAcrossVertexSets = true;
00208                 mWeldVerticesAcrossIndexSets = false;
00209                 break;
00210             case 4: // weld within same index & vertex set only
00211                 mWeldVertices = true;
00212                 mWeldVerticesAcrossVertexSets = false;
00213                 mWeldVerticesAcrossIndexSets = false;
00214                 break;
00215             case 5: // never weld
00216                 mWeldVertices = false;
00217                 mWeldVerticesAcrossVertexSets = false;
00218                 mWeldVerticesAcrossIndexSets = false;
00219                 break;
00220             };
00221 
00222             // Log alternate techniques
00223             if (technique > 1)
00224             {
00225                 LogManager::getSingleton().logMessage(
00226                     "Trying alternate edge building technique " + 
00227                     StringConverter::toString(technique));
00228             }
00229 
00230             try 
00231             {
00232                 attemptBuild();
00233                 // if we got here with no exceptions, we're done 
00234                 validHull = true;
00235             }
00236             catch (Exception& e) 
00237             {
00238                 if (e.getNumber() == Exception::ERR_DUPLICATE_ITEM)
00239                 {
00240                     // Ambiguous hull, try next technique
00241                     ++technique;
00242                 }
00243                 else
00244                 {
00245                     throw;
00246                 }
00247 
00248             }
00249         }
00250 
00251         return mEdgeData;
00252 
00253     }        
00254     //---------------------------------------------------------------------
00255     void EdgeListBuilder::attemptBuild(void)
00256     {
00257         // reset
00258         mVertices.clear();
00259         mUniqueEdges.clear();
00260         if (mEdgeData)
00261         {
00262             mEdgeData->triangles.clear();
00263             EdgeData::EdgeGroupList::iterator egi, egiend;
00264             egiend = mEdgeData->edgeGroups.end();
00265             for(egi = mEdgeData->edgeGroups.begin(); egi != egiend; ++egi)
00266             {
00267                 egi->edges.clear();
00268             }
00269         }
00270         else
00271         {
00272             mEdgeData = new EdgeData();
00273         }
00274         // resize the edge group list to equal the number of vertex sets
00275         mEdgeData->edgeGroups.resize(mVertexDataList.size());
00276         // Initialise edge group data
00277         for (unsigned short vSet = 0; vSet < mVertexDataList.size(); ++vSet)
00278         {
00279             mEdgeData->edgeGroups[vSet].vertexSet = vSet;
00280             mEdgeData->edgeGroups[vSet].vertexData = mVertexDataList[vSet];
00281         }
00282 
00283         IndexDataList::iterator i, iend;
00284         std::vector<size_t>::iterator mapi, mapiend;
00285         mapiend = mIndexDataVertexDataSetList.end();
00286         mapi = mIndexDataVertexDataSetList.begin();
00287         iend = mIndexDataList.end();
00288         // Stage 1, build triangles and initial edge list
00289         size_t indexSet = 0;
00290         for (i = mIndexDataList.begin(); i != iend; ++i, ++mapi, ++indexSet)
00291         {
00292             buildTrianglesEdges(indexSet, *mapi);
00293         }
00294         // Stage 2, link edges
00295         connectEdges();
00296 
00297         // Log
00298         //log(LogManager::getSingleton().createLog("EdgeListBuilder.log"));
00299 
00300     }
00301     //---------------------------------------------------------------------
00302     void EdgeListBuilder::buildTrianglesEdges(size_t indexSet, size_t vertexSet)
00303     {
00304         const IndexData* indexData = mIndexDataList[indexSet];
00305         RenderOperation::OperationType opType = mOperationTypeList[indexSet];
00306 
00307         size_t iterations;
00308         
00309         switch (opType)
00310         {
00311         case RenderOperation::OT_TRIANGLE_LIST:
00312             iterations = indexData->indexCount / 3;
00313             break;
00314         case RenderOperation::OT_TRIANGLE_FAN:
00315         case RenderOperation::OT_TRIANGLE_STRIP:
00316             iterations = indexData->indexCount - 2;
00317             break;
00318         default:
00319             break;
00320         };
00321 
00322 
00323 
00324         // locate position element & the buffer to go with it
00325         const VertexData* vertexData = mVertexDataList[vertexSet];
00326         const VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
00327         HardwareVertexBufferSharedPtr vbuf = 
00328             vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
00329         // lock the buffer for reading
00330         unsigned char* pBaseVertex = static_cast<unsigned char*>(
00331             vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
00332 
00333         // Get the indexes ready for reading
00334         unsigned short* p16Idx;
00335         unsigned int* p32Idx;
00336 
00337         if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
00338         {
00339             p32Idx = static_cast<unsigned int*>(
00340                 indexData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
00341         }
00342         else
00343         {
00344             p16Idx = static_cast<unsigned short*>(
00345                 indexData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
00346         }
00347 
00348         // Iterate over all the groups of 3 indexes
00349         Real* pReal;
00350         // Get the triangle start, if we have more than one index set then this
00351         // will not be zero
00352         size_t triStart = mEdgeData->triangles.size();
00353         // Pre-reserve memory for less thrashing
00354         mEdgeData->triangles.reserve(triStart + iterations);
00355         for (size_t t = 0; t < iterations; ++t)
00356         {
00357             EdgeData::Triangle tri;
00358             tri.indexSet = indexSet;
00359             tri.vertexSet = vertexSet;
00360 
00361             unsigned int index[3];
00362             Vector3 v[3];
00363             for (size_t i = 0; i < 3; ++i)
00364             {
00365                 // Standard 3-index read for tri list or first tri in strip / fan
00366                 if (opType == RenderOperation::OT_TRIANGLE_LIST ||
00367                     t == 0)
00368                 {
00369                     if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
00370                     {
00371                         index[i] = *p32Idx++;
00372                     }
00373                     else
00374                     {
00375                         index[i] = *p16Idx++;
00376                     }
00377                 }
00378                 else
00379                 {
00380                     // Strips and fans are formed from last 2 indexes plus the 
00381                     // current one for triangles after the first
00382                     if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
00383                     {
00384                         index[i] = p32Idx[i-2];
00385                     }
00386                     else
00387                     {
00388                         index[i] = p16Idx[i-2];
00389                     }
00390                     // Perform single-index increment at the last tri index
00391                     if (i == 2)
00392                     {
00393                         if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
00394                         {
00395                             p32Idx++;
00396                         }
00397                         else
00398                         {
00399                             p16Idx++;
00400                         }
00401 
00402                     }
00403 
00404                 }
00405 
00406                 // Populate tri original vertex index
00407                 tri.vertIndex[i] = index[i];
00408 
00409                 // Retrieve the vertex position
00410                 unsigned char* pVertex = pBaseVertex + (index[i] * vbuf->getVertexSize());
00411                 posElem->baseVertexPointerToElement(pVertex, &pReal);
00412                 v[i].x = *pReal++;
00413                 v[i].y = *pReal++;
00414                 v[i].z = *pReal++;
00415                 // find this vertex in the existing vertex map, or create it
00416                 tri.sharedVertIndex[i] = 
00417                     findOrCreateCommonVertex(v[i], vertexSet, indexSet, index[i]);
00418             }
00419             // Calculate triangle normal (NB will require recalculation for 
00420             // skeletally animated meshes)
00421             tri.normal = Math::calculateFaceNormal(v[0], v[1], v[2]);
00422             // Add triangle to list
00423             mEdgeData->triangles.push_back(tri);
00424             // Create edges from common list
00425             try {
00426                 if (tri.sharedVertIndex[0] < tri.sharedVertIndex[1])
00427                 {
00428                     createEdge(vertexSet, triStart + t, 
00429                         tri.vertIndex[0], tri.vertIndex[1], 
00430                         tri.sharedVertIndex[0], tri.sharedVertIndex[1]);
00431                 }
00432                 if (tri.sharedVertIndex[1] < tri.sharedVertIndex[2])
00433                 {
00434                     createEdge(vertexSet, triStart + t, 
00435                         tri.vertIndex[1], tri.vertIndex[2], 
00436                         tri.sharedVertIndex[1], tri.sharedVertIndex[2]);
00437                 }
00438                 if (tri.sharedVertIndex[2] < tri.sharedVertIndex[0])
00439                 {
00440                     createEdge(vertexSet, triStart + t, 
00441                         tri.vertIndex[2], tri.vertIndex[0], 
00442                         tri.sharedVertIndex[2], tri.sharedVertIndex[0]);
00443                 }
00444             }
00445             catch (Exception& e)
00446             {
00447                 // unlock buffers so this is repeatable if required
00448                 indexData->indexBuffer->unlock();
00449                 vbuf->unlock();
00450                 throw;
00451             }
00452 
00453         }
00454         indexData->indexBuffer->unlock();
00455         vbuf->unlock();
00456 
00457 
00458 
00459 
00460     }
00461     //---------------------------------------------------------------------
00462     void EdgeListBuilder::createEdge(size_t vertexSet, size_t triangleIndex, 
00463         size_t vertIndex0, size_t vertIndex1, size_t sharedVertIndex0, 
00464         size_t sharedVertIndex1)
00465     {
00466         // Check unique on shared vertices
00467         std::pair<size_t, size_t> vertPair;
00468         vertPair.first = sharedVertIndex0;
00469         vertPair.second = sharedVertIndex1;
00470         UniqueEdgeSet::iterator ui = mUniqueEdges.find(vertPair);
00471         if (ui != mUniqueEdges.end())
00472         {
00473             Except(Exception::ERR_DUPLICATE_ITEM, 
00474                 "Edge is shared by too many triangles", 
00475                 "EdgeListBuilder::createEdge");
00476         }
00477         mUniqueEdges.insert(vertPair);
00478 
00479         EdgeData::Edge e;
00480         e.degenerate = true; // initialise as degenerate
00481 
00482         // Set only first tri, the other will be completed in connectEdges
00483         e.triIndex[0] = triangleIndex;
00484         e.sharedVertIndex[0] = sharedVertIndex0;
00485         e.sharedVertIndex[1] = sharedVertIndex1;
00486         e.vertIndex[0] = vertIndex0;
00487         e.vertIndex[1] = vertIndex1;
00488         mEdgeData->edgeGroups[vertexSet].edges.push_back(e);
00489 
00490     }
00491     //---------------------------------------------------------------------
00492     size_t EdgeListBuilder::findOrCreateCommonVertex(const Vector3& vec, 
00493         size_t vertexSet, size_t indexSet, size_t originalIndex)
00494     {
00495         // Iterate over existing list
00496         CommonVertexList::iterator i, iend;
00497         iend = mVertices.end();
00498         size_t index = 0;
00499         for (i = mVertices.begin(); i != iend; ++i, ++index)
00500         {
00501             const CommonVertex& commonVec = *i;
00502             // weld common vertex by position
00503             if (Math::RealEqual(vec.x, commonVec.position.x, 1e-04) && 
00504                 Math::RealEqual(vec.y, commonVec.position.y, 1e-04) && 
00505                 Math::RealEqual(vec.z, commonVec.position.z, 1e-04) && 
00506                 (commonVec.vertexSet == vertexSet || mWeldVerticesAcrossVertexSets) && 
00507                 (commonVec.indexSet == indexSet || mWeldVerticesAcrossIndexSets) && 
00508                 (commonVec.originalIndex == originalIndex || mWeldVertices))
00509             {
00510                 return index;
00511             }
00512             
00513 
00514         }
00515         // Not found, insert
00516         CommonVertex newCommon;
00517         newCommon.index = mVertices.size();
00518         newCommon.position = vec;
00519         newCommon.vertexSet = vertexSet;
00520         newCommon.indexSet = indexSet;
00521         newCommon.originalIndex = originalIndex;
00522         mVertices.push_back(newCommon);
00523         return newCommon.index;
00524     }
00525     //---------------------------------------------------------------------
00526     void EdgeListBuilder::connectEdges(void)
00527     {
00528         // Iterate over existing triangles
00529         EdgeData::TriangleList::iterator ti, tiend;
00530         tiend = mEdgeData->triangles.end();
00531         size_t triIndex = 0;
00532         for (ti = mEdgeData->triangles.begin(); ti != tiend; ++ti, ++triIndex)
00533         {
00534             EdgeData::Triangle& tri = *ti;
00535             EdgeData::Edge* e;
00536             if (tri.sharedVertIndex[0] > tri.sharedVertIndex[1])
00537             {
00538                 e = findEdge(tri.sharedVertIndex[1], tri.sharedVertIndex[0]);
00539                 if (e)
00540                 {
00541                     e->triIndex[1] = triIndex;
00542                     e->degenerate = false;
00543                 }
00544             }
00545             if (tri.sharedVertIndex[1] > tri.sharedVertIndex[2])
00546             {
00547                 // Find the existing edge (should be reversed order)
00548                 e = findEdge(tri.sharedVertIndex[2], tri.sharedVertIndex[1]);
00549                 if (e)
00550                 {
00551                     e->triIndex[1] = triIndex;
00552                     e->degenerate = false;
00553                 }
00554             }
00555             if (tri.sharedVertIndex[2] > tri.sharedVertIndex[0])
00556             {
00557                 e = findEdge(tri.sharedVertIndex[0], tri.sharedVertIndex[2]);
00558                 if (e)
00559                 {
00560                     e->triIndex[1] = triIndex;
00561                     e->degenerate = false;
00562                 }
00563             }
00564 
00565         }
00566 
00567 
00568     }
00569     //---------------------------------------------------------------------
00570     EdgeData::Edge* EdgeListBuilder::findEdge(size_t sharedIndex1, size_t sharedIndex2)
00571     {
00572         // Iterate over the existing edges
00573         EdgeData::EdgeGroupList::iterator i, iend;
00574         EdgeData::EdgeList::iterator ei, eiend;
00575 
00576         iend = mEdgeData->edgeGroups.end();
00577         for (i = mEdgeData->edgeGroups.begin(); i != iend; ++i)
00578         {
00579             eiend = i->edges.end();
00580             for (ei = i->edges.begin(); ei != eiend; ++ei)
00581             {
00582                 EdgeData::Edge& e = *ei;
00583                 if (e.sharedVertIndex[0] == sharedIndex1 && e.sharedVertIndex[1] == sharedIndex2)
00584                 {
00585                     return &(*ei);
00586                 }
00587             }
00588         }
00589         
00590         // no edge
00591         return 0;
00592 
00593     }
00594     //---------------------------------------------------------------------
00595     //---------------------------------------------------------------------
00596     void EdgeData::updateTriangleLightFacing(const Vector4& lightPos)
00597     {
00598         // Iterate over the triangles, and determine if they are light facing
00599         EdgeData::TriangleList::iterator ti, tiend;
00600         tiend = triangles.end();
00601         Vector3 vertToLight;
00602         for (ti = triangles.begin(); ti != tiend; ++ti)
00603         {
00604             EdgeData::Triangle& t = *ti;
00605             // Get pointer to positions, and reference the first position
00606 
00607             Real dp = t.normal.dotProduct(lightPos);
00608             t.lightFacing = (dp > 0);
00609 
00610         }
00611 
00612     }
00613     //---------------------------------------------------------------------
00614     void EdgeData::updateFaceNormals(size_t vertexSet, 
00615         HardwareVertexBufferSharedPtr positionBuffer)
00616     {
00617         assert (positionBuffer->getVertexSize() == sizeof(Real) * 3
00618             && "Position buffer should contain only positions!");
00619 
00620         // Lock buffer for reading
00621         Real* pVert = static_cast<Real*>(
00622             positionBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
00623 
00624         // Iterate over the triangles
00625         EdgeData::TriangleList::iterator i, iend;
00626         iend = triangles.end();
00627         for (i = triangles.begin(); i != iend; ++i)
00628         {
00629             Triangle& t = *i;
00630             // Only update tris which are using this vertex set
00631             if (t.vertexSet == vertexSet)
00632             {
00633                 size_t offset = t.vertIndex[0]*3;
00634                 Vector3 v1(pVert + offset);
00635 
00636                 offset = t.vertIndex[1]*3;
00637                 Vector3 v2(pVert + offset);
00638 
00639                 offset = t.vertIndex[2]*3;
00640                 Vector3 v3(pVert + offset);
00641 
00642                 t.normal = Math::calculateFaceNormal(v1, v2, v3);
00643             }
00644         }
00645 
00646 
00647         // unlock the buffer
00648         positionBuffer->unlock();
00649     }
00650     //---------------------------------------------------------------------
00651     void EdgeListBuilder::log(Log* l)
00652     {
00653         l->logMessage("EdgeListBuilder Log");
00654         l->logMessage("-------------------");
00655         l->logMessage("Number of vertex sets: " + StringConverter::toString(mVertexDataList.size()));
00656         l->logMessage("Number of index sets: " + StringConverter::toString(mIndexDataList.size()));
00657         
00658         size_t i, j;
00659         // Log original vertex data
00660         for(i = 0; i < mVertexDataList.size(); ++i)
00661         {
00662             const VertexData* vData = mVertexDataList[i];
00663             l->logMessage(".");
00664             l->logMessage("Original vertex set " + 
00665                 StringConverter::toString(i) + " - vertex count " + 
00666                 StringConverter::toString(vData->vertexCount));
00667             const VertexElement* posElem = vData->vertexDeclaration->findElementBySemantic(VES_POSITION);
00668             HardwareVertexBufferSharedPtr vbuf = 
00669                 vData->vertexBufferBinding->getBuffer(posElem->getSource());
00670             // lock the buffer for reading
00671             unsigned char* pBaseVertex = static_cast<unsigned char*>(
00672                 vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
00673             Real* pReal;
00674             for (j = 0; j < vData->vertexCount; ++j)
00675             {
00676                 posElem->baseVertexPointerToElement(pBaseVertex, &pReal);
00677                 l->logMessage("Vertex " + StringConverter::toString(j) + 
00678                     ": (" + StringConverter::toString(pReal[0]) + 
00679                     ", " + StringConverter::toString(pReal[1]) + 
00680                     ", " + StringConverter::toString(pReal[2]) + ")");
00681                 pBaseVertex += vbuf->getVertexSize();
00682             }
00683             vbuf->unlock();
00684         }
00685 
00686         // Log original index data
00687         for(i = 0; i < mIndexDataList.size(); i++)
00688         {
00689             const IndexData* iData = mIndexDataList[i];
00690             l->logMessage(".");
00691             l->logMessage("Original triangle set " + 
00692                 StringConverter::toString(i) + " - index count " + 
00693                 StringConverter::toString(iData->indexCount) + " - " + 
00694             "vertex set " + StringConverter::toString(mIndexDataVertexDataSetList[i]) + " - " + 
00695             "operationType " + StringConverter::toString(mOperationTypeList[i]));
00696             // Get the indexes ready for reading
00697             unsigned short* p16Idx;
00698             unsigned int* p32Idx;
00699 
00700             if (iData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
00701             {
00702                 p32Idx = static_cast<unsigned int*>(
00703                     iData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
00704             }
00705             else
00706             {
00707                 p16Idx = static_cast<unsigned short*>(
00708                     iData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
00709             }
00710 
00711             for (j = 0; j < iData->indexCount;  )
00712             {
00713                 if (iData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
00714                 {
00715                     if (mOperationTypeList[i] == RenderOperation::OT_TRIANGLE_LIST
00716                         || j == 0)
00717                     {
00718                         l->logMessage("Triangle " + StringConverter::toString(j) + 
00719                             ": (" + StringConverter::toString(*p32Idx++) + 
00720                             ", " + StringConverter::toString(*p32Idx++) + 
00721                             ", " + StringConverter::toString(*p32Idx++) + ")");
00722                         j += 3;
00723                     }
00724                     else
00725                     {
00726                         l->logMessage("Triangle " + StringConverter::toString(j) + 
00727                             ": (" + StringConverter::toString(*p32Idx++) + ")");
00728                         j++;
00729                     }
00730                 }
00731                 else
00732                 {
00733                     if (mOperationTypeList[i] == RenderOperation::OT_TRIANGLE_LIST
00734                         || j == 0)
00735                     {
00736                         l->logMessage("Index " + StringConverter::toString(j) + 
00737                             ": (" + StringConverter::toString(*p16Idx++) + 
00738                             ", " + StringConverter::toString(*p16Idx++) + 
00739                             ", " + StringConverter::toString(*p16Idx++) + ")");
00740                         j += 3;
00741                     }
00742                     else
00743                     {
00744                         l->logMessage("Triangle " + StringConverter::toString(j) + 
00745                             ": (" + StringConverter::toString(*p16Idx++) + ")");
00746                         j++;
00747                     }
00748                 }
00749 
00750 
00751             }
00752 
00753             iData->indexBuffer->unlock();
00754 
00755 
00756             // Log common vertex list
00757             l->logMessage(".");
00758             l->logMessage("Common vertex list - vertex count " + 
00759                 StringConverter::toString(mVertices.size()));
00760             for (i = 0; i < mVertices.size(); ++i)
00761             {
00762                 CommonVertex& c = mVertices[i];
00763                 l->logMessage("Common vertex " + StringConverter::toString(i) + 
00764                     ": (vertexSet=" + StringConverter::toString(c.vertexSet) + 
00765                     ", originalIndex=" + StringConverter::toString(c.originalIndex) + 
00766                     ", position=" + StringConverter::toString(c.position));
00767             }
00768         }
00769 
00770     }
00771 
00772 
00773 
00774 }
00775 

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:23 2004