Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreEdgeListBuilder.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 25.6 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreEdgeListBuilder.h"
31#include "OgreLogManager.h"
32#include "OgreStringConverter.h"
33#include "OgreVertexIndexData.h"
34#include "OgreException.h"
35#include "OgreOptimisedUtil.h"
36
37namespace Ogre {
38
39    void EdgeData::log(Log* l)
40    {
41        EdgeGroupList::iterator i, iend;
42        EdgeList::iterator ei, eiend;
43        TriangleList::iterator ti, tiend;
44        tiend = triangles.end();
45        l->logMessage("Edge Data");
46        l->logMessage("---------");
47        size_t num = 0;
48        for (ti = triangles.begin(); ti != tiend; ++ti, ++num)
49        {
50            Triangle& t = *ti;
51            l->logMessage("Triangle " + StringConverter::toString(num) + " = {" +
52                "indexSet=" + StringConverter::toString(t.indexSet) + ", " + 
53                "vertexSet=" + StringConverter::toString(t.vertexSet) + ", " + 
54                "v0=" + StringConverter::toString(t.vertIndex[0]) + ", " + 
55                "v1=" + StringConverter::toString(t.vertIndex[1]) + ", " + 
56                "v2=" + StringConverter::toString(t.vertIndex[2]) + "}"); 
57        }
58        iend = edgeGroups.end();
59        for (i = edgeGroups.begin(); i != iend; ++i)
60        {
61            num = 0;
62            eiend = i->edges.end();
63            l->logMessage("Edge Group vertexSet=" + StringConverter::toString(i->vertexSet));
64            for (ei = i->edges.begin(); ei != eiend; ++ei, ++num)
65            {
66                Edge& e = *ei;
67                l->logMessage(
68                    "Edge " + StringConverter::toString(num) + " = {\n" + 
69                    "  tri0=" + StringConverter::toString(e.triIndex[0]) + ", \n" + 
70                    "  tri1=" + StringConverter::toString(e.triIndex[1]) + ", \n" + 
71                    "  v0=" + StringConverter::toString(e.vertIndex[0]) + ", \n" + 
72                    "  v1=" + StringConverter::toString(e.vertIndex[1]) + ", \n"
73                    "  degenerate=" + StringConverter::toString(e.degenerate) + " \n"
74                    "}"); 
75            }
76        }
77    }
78    //---------------------------------------------------------------------
79    EdgeListBuilder::EdgeListBuilder()
80        : mEdgeData(0)
81    {
82    }
83    //---------------------------------------------------------------------
84    EdgeListBuilder::~EdgeListBuilder()
85    {
86    }
87    //---------------------------------------------------------------------
88    void EdgeListBuilder::addVertexData(const VertexData* vertexData)
89    {
90        if (vertexData->vertexStart != 0)
91        {
92            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
93                "The base vertex index of the vertex data must be zero for build edge list.",
94                "EdgeListBuilder::addVertexData");
95        }
96
97        mVertexDataList.push_back(vertexData);
98    }
99    //---------------------------------------------------------------------
100    void EdgeListBuilder::addIndexData(const IndexData* indexData, 
101        size_t vertexSet, RenderOperation::OperationType opType)
102    {
103        if (opType != RenderOperation::OT_TRIANGLE_LIST &&
104            opType != RenderOperation::OT_TRIANGLE_FAN &&
105            opType != RenderOperation::OT_TRIANGLE_STRIP)
106        {
107            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
108                "Only triangle list, fan and strip are supported to build edge list.",
109                "EdgeListBuilder::addIndexData");
110        }
111
112        Geometry geometry;
113        geometry.indexData = indexData;
114        geometry.vertexSet = vertexSet;
115        geometry.opType = opType;
116        geometry.indexSet = mGeometryList.size();
117        mGeometryList.push_back(geometry);
118    }
119    //---------------------------------------------------------------------
120    EdgeData* EdgeListBuilder::build(void)
121    {
122        /* Ok, here's the algorithm:
123        For each set of indices in turn
124          For each set of 3 indexes
125            Create a new Triangle entry in the list
126            For each vertex referenced by the tri indexes
127              Get the position of the vertex as a Vector3 from the correct vertex buffer
128              Attempt to locate this position in the existing common vertex set
129              If not found
130                Create a new common vertex entry in the list
131              End If
132              Populate the original vertex index and common vertex index
133            Next vertex
134            Connect to existing edge(v1, v0) or create a new edge(v0, v1)
135            Connect to existing edge(v2, v1) or create a new edge(v1, v2)
136            Connect to existing edge(v0, v2) or create a new edge(v2, v0)
137          Next set of 3 indexes
138        Next index set
139
140        Note that all edges 'belong' to the index set which originally caused them
141        to be created, which also means that the 2 vertices on the edge are both referencing the
142        vertex buffer which this index set uses.
143        */
144
145
146        /*
147        There is a major consideration: 'What is a common vertex'? This is a
148        crucial decision, since to form a completely close hull, you need to treat
149        vertices which are not physically the same as equivalent. This is because
150        there will be 'seams' in the model, where discrepancies in vertex components
151        other than position (such as normals or texture coordinates) will mean
152        that there are 2 vertices in the same place, and we MUST 'weld' them
153        into a single common vertex in order to have a closed hull. Just looking
154        at the unique vertex indices is not enough, since these seams would render
155        the hull invalid.
156
157        So, we look for positions which are the same across vertices, and treat
158        those as as single vertex for our edge calculation. However, this has
159        it's own problems. There are OTHER vertices which may have a common
160        position that should not be welded. Imagine 2 cubes touching along one
161        single edge. The common vertices on that edge, if welded, will cause
162        an ambiguous hull, since the edge will have 4 triangles attached to it,
163        whilst a manifold mesh should only have 2 triangles attached to each edge.
164        This is a problem.
165
166        We deal with this with allow welded multiple pairs of edges. Using this
167        techniques, we can build a individual hull even if the model which has a
168        potentially ambiguous hull. This is feasible, because in the case of
169        multiple hulls existing, each hull can cast same shadow in any situation.
170        Notice: For stencil shadow, we intent to build a valid shadow volume for
171        the mesh, not the valid hull for the mesh.
172        */
173
174        // Sort the geometries in the order of vertex set, so we can grouping
175        // triangles by vertex set easy.
176        std::sort(mGeometryList.begin(), mGeometryList.end(), geometryLess());
177        // Initialize edge data
178        mEdgeData = new EdgeData();
179        // resize the edge group list to equal the number of vertex sets
180        mEdgeData->edgeGroups.resize(mVertexDataList.size());
181        // Initialise edge group data
182        for (unsigned short vSet = 0; vSet < mVertexDataList.size(); ++vSet)
183        {
184            mEdgeData->edgeGroups[vSet].vertexSet = vSet;
185            mEdgeData->edgeGroups[vSet].vertexData = mVertexDataList[vSet];
186            mEdgeData->edgeGroups[vSet].triStart = 0;
187            mEdgeData->edgeGroups[vSet].triCount = 0;
188        }
189
190        // Build triangles and edge list
191        GeometryList::const_iterator i, iend;
192        iend = mGeometryList.end();
193        for (i = mGeometryList.begin(); i != iend; ++i)
194        {
195            buildTrianglesEdges(*i);
196        }
197
198        // Allocate memory for light facing calculate
199        mEdgeData->triangleLightFacings.resize(mEdgeData->triangles.size());
200
201        // Record closed, ie the mesh is manifold
202        mEdgeData->isClosed = mEdgeMap.empty();
203
204        return mEdgeData;
205    }
206    //---------------------------------------------------------------------
207    void EdgeListBuilder::buildTrianglesEdges(const Geometry &geometry)
208    {
209        size_t indexSet = geometry.indexSet;
210        size_t vertexSet = geometry.vertexSet;
211        const IndexData* indexData = geometry.indexData;
212        RenderOperation::OperationType opType = geometry.opType;
213
214        size_t iterations;
215       
216        switch (opType)
217        {
218        case RenderOperation::OT_TRIANGLE_LIST:
219            iterations = indexData->indexCount / 3;
220            break;
221        case RenderOperation::OT_TRIANGLE_FAN:
222        case RenderOperation::OT_TRIANGLE_STRIP:
223            iterations = indexData->indexCount - 2;
224            break;
225        default:
226            return; // Just in case
227        };
228
229        // The edge group now we are dealing with.
230        EdgeData::EdgeGroup& eg = mEdgeData->edgeGroups[vertexSet];
231
232                // locate position element & the buffer to go with it
233        const VertexData* vertexData = mVertexDataList[vertexSet];
234                const VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
235                HardwareVertexBufferSharedPtr vbuf = 
236                        vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
237                // lock the buffer for reading
238                unsigned char* pBaseVertex = static_cast<unsigned char*>(
239                        vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
240
241        // Get the indexes ready for reading
242                bool idx32bit = (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
243                size_t indexSize = idx32bit ? sizeof(uint32) : sizeof(uint16);
244#if defined(_MSC_VER) && _MSC_VER <= 1300
245        // NB: Can't use un-named union with VS.NET 2002 when /RTC1 compile flag enabled.
246        void* pIndex = indexData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
247                pIndex = static_cast<void*>(
248                        static_cast<char*>(pIndex) + indexData->indexStart * indexSize);
249        unsigned short* p16Idx = static_cast<unsigned short*>(pIndex);
250        unsigned int* p32Idx = static_cast<unsigned int*>(pIndex);
251#else
252        union {
253            void* pIndex;
254            unsigned short* p16Idx;
255            unsigned int* p32Idx;
256        };
257        pIndex = indexData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
258                pIndex = static_cast<void*>(
259                        static_cast<char*>(pIndex) + indexData->indexStart * indexSize);
260#endif
261
262        // Iterate over all the groups of 3 indexes
263        unsigned int index[3];
264        // Get the triangle start, if we have more than one index set then this
265        // will not be zero
266        size_t triangleIndex = mEdgeData->triangles.size();
267        // If it's first time dealing with the edge group, setup triStart for it.
268        // Note that we are assume geometries sorted by vertex set.
269        if (!eg.triCount)
270        {
271            eg.triStart = triangleIndex;
272        }
273        // Pre-reserve memory for less thrashing
274        mEdgeData->triangles.reserve(triangleIndex + iterations);
275        mEdgeData->triangleFaceNormals.reserve(triangleIndex + iterations);
276        for (size_t t = 0; t < iterations; ++t)
277        {
278            EdgeData::Triangle tri;
279            tri.indexSet = indexSet;
280            tri.vertexSet = vertexSet;
281
282            if (opType == RenderOperation::OT_TRIANGLE_LIST || t == 0)
283            {
284                // Standard 3-index read for tri list or first tri in strip / fan
285                if (idx32bit)
286                {
287                    index[0] = p32Idx[0];
288                    index[1] = p32Idx[1];
289                    index[2] = p32Idx[2];
290                    p32Idx += 3;
291                }
292                else
293                {
294                    index[0] = p16Idx[0];
295                    index[1] = p16Idx[1];
296                    index[2] = p16Idx[2];
297                    p16Idx += 3;
298                }
299            }
300            else
301            {
302                // Strips are formed from last 2 indexes plus the current one for
303                // triangles after the first.
304                // For fans, all the triangles share the first vertex, plus last
305                // one index and the current one for triangles after the first.
306                // We also make sure that all the triangles are process in the
307                // _anti_ clockwise orientation
308                index[(opType == RenderOperation::OT_TRIANGLE_STRIP) && (t & 1) ? 0 : 1] = index[2];
309                // Read for the last tri index
310                if (idx32bit)
311                    index[2] = *p32Idx++;
312                else
313                    index[2] = *p16Idx++;
314            }
315
316            Vector3 v[3];
317            for (size_t i = 0; i < 3; ++i)
318            {
319                // Populate tri original vertex index
320                tri.vertIndex[i] = index[i];
321
322                // Retrieve the vertex position
323                unsigned char* pVertex = pBaseVertex + (index[i] * vbuf->getVertexSize());
324                float* pFloat;
325                posElem->baseVertexPointerToElement(pVertex, &pFloat);
326                v[i].x = *pFloat++;
327                v[i].y = *pFloat++;
328                v[i].z = *pFloat++;
329                // find this vertex in the existing vertex map, or create it
330                tri.sharedVertIndex[i] = 
331                    findOrCreateCommonVertex(v[i], vertexSet, indexSet, index[i]);
332            }
333
334            // Ignore degenerate triangle
335            if (tri.sharedVertIndex[0] != tri.sharedVertIndex[1] &&
336                tri.sharedVertIndex[1] != tri.sharedVertIndex[2] &&
337                tri.sharedVertIndex[2] != tri.sharedVertIndex[0])
338            {
339                // Calculate triangle normal (NB will require recalculation for
340                // skeletally animated meshes)
341                mEdgeData->triangleFaceNormals.push_back(
342                    Math::calculateFaceNormalWithoutNormalize(v[0], v[1], v[2]));
343                // Add triangle to list
344                mEdgeData->triangles.push_back(tri);
345                // Connect or create edges from common list
346                connectOrCreateEdge(vertexSet, triangleIndex, 
347                    tri.vertIndex[0], tri.vertIndex[1], 
348                    tri.sharedVertIndex[0], tri.sharedVertIndex[1]);
349                connectOrCreateEdge(vertexSet, triangleIndex, 
350                    tri.vertIndex[1], tri.vertIndex[2], 
351                    tri.sharedVertIndex[1], tri.sharedVertIndex[2]);
352                connectOrCreateEdge(vertexSet, triangleIndex, 
353                    tri.vertIndex[2], tri.vertIndex[0], 
354                    tri.sharedVertIndex[2], tri.sharedVertIndex[0]);
355                ++triangleIndex;
356            }
357        }
358
359        // Update triCount for the edge group. Note that we are assume
360        // geometries sorted by vertex set.
361        eg.triCount = triangleIndex - eg.triStart;
362
363        indexData->indexBuffer->unlock();
364        vbuf->unlock();
365    }
366    //---------------------------------------------------------------------
367    void EdgeListBuilder::connectOrCreateEdge(size_t vertexSet, size_t triangleIndex, 
368        size_t vertIndex0, size_t vertIndex1, size_t sharedVertIndex0, 
369        size_t sharedVertIndex1)
370    {
371        // Find the existing edge (should be reversed order) on shared vertices
372        EdgeMap::iterator emi = mEdgeMap.find(std::pair<size_t, size_t>(sharedVertIndex1, sharedVertIndex0));
373        if (emi != mEdgeMap.end())
374        {
375            // The edge already exist, connect it
376            EdgeData::Edge& e = mEdgeData->edgeGroups[emi->second.first].edges[emi->second.second];
377            // update with second side
378            e.triIndex[1] = triangleIndex;
379            e.degenerate = false;
380
381            // Remove from the edge map, so we never supplied to connect edge again
382            mEdgeMap.erase(emi);
383        }
384        else
385        {
386            // Not found, create new edge
387            mEdgeMap.insert(EdgeMap::value_type(
388                std::pair<size_t, size_t>(sharedVertIndex0, sharedVertIndex1),
389                std::pair<size_t, size_t>(vertexSet, mEdgeData->edgeGroups[vertexSet].edges.size())));
390            EdgeData::Edge e;
391            e.degenerate = true; // initialise as degenerate
392
393            // Set only first tri, the other will be completed in connect existing edge
394            e.triIndex[0] = triangleIndex;
395            e.triIndex[1] = static_cast<size_t>(~0);
396            e.sharedVertIndex[0] = sharedVertIndex0;
397            e.sharedVertIndex[1] = sharedVertIndex1;
398            e.vertIndex[0] = vertIndex0;
399            e.vertIndex[1] = vertIndex1;
400            mEdgeData->edgeGroups[vertexSet].edges.push_back(e);
401        }
402    }
403    //---------------------------------------------------------------------
404    size_t EdgeListBuilder::findOrCreateCommonVertex(const Vector3& vec, 
405        size_t vertexSet, size_t indexSet, size_t originalIndex)
406    {
407        // Because the algorithm doesn't care about manifold or not, we just identifying
408        // the common vertex by EXACT same position.
409        // Hint: We can use quantize method for welding almost same position vertex fastest.
410        std::pair<CommonVertexMap::iterator, bool> inserted =
411            mCommonVertexMap.insert(CommonVertexMap::value_type(vec, mVertices.size()));
412        if (!inserted.second)
413        {
414            // Already existing, return old one
415            return inserted.first->second;
416        }
417        // Not found, insert
418        CommonVertex newCommon;
419        newCommon.index = mVertices.size();
420        newCommon.position = vec;
421        newCommon.vertexSet = vertexSet;
422        newCommon.indexSet = indexSet;
423        newCommon.originalIndex = originalIndex;
424        mVertices.push_back(newCommon);
425        return newCommon.index;
426    }
427    //---------------------------------------------------------------------
428    //---------------------------------------------------------------------
429    void EdgeData::updateTriangleLightFacing(const Vector4& lightPos)
430    {
431        // Triangle face normals should be 1:1 with light facing flags
432        assert(triangleFaceNormals.size() == triangleLightFacings.size());
433
434        // Use optimised util to determine if triangle's face normal are light facing
435        OptimisedUtil::getImplementation()->calculateLightFacing(
436            lightPos,
437            &triangleFaceNormals.front(),
438            &triangleLightFacings.front(),
439            triangleLightFacings.size());
440    }
441    //---------------------------------------------------------------------
442    void EdgeData::updateFaceNormals(size_t vertexSet, 
443        const HardwareVertexBufferSharedPtr& positionBuffer)
444    {
445        assert (positionBuffer->getVertexSize() == sizeof(float) * 3
446            && "Position buffer should contain only positions!");
447
448        // Triangle face normals should be 1:1 with triangles
449        assert(triangleFaceNormals.size() == triangles.size());
450
451        // Lock buffer for reading
452        float* pVert = static_cast<float*>(
453            positionBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
454
455        // Calculate triangles which are using this vertex set
456        const EdgeData::EdgeGroup& eg = edgeGroups[vertexSet];
457        OptimisedUtil::getImplementation()->calculateFaceNormals(
458            pVert,
459            &triangles[eg.triStart],
460            &triangleFaceNormals[eg.triStart],
461            eg.triCount);
462
463        // unlock the buffer
464        positionBuffer->unlock();
465    }
466    //---------------------------------------------------------------------
467    void EdgeListBuilder::log(Log* l)
468    {
469        l->logMessage("EdgeListBuilder Log");
470        l->logMessage("-------------------");
471        l->logMessage("Number of vertex sets: " + StringConverter::toString(mVertexDataList.size()));
472        l->logMessage("Number of index sets: " + StringConverter::toString(mGeometryList.size()));
473       
474        size_t i, j;
475        // Log original vertex data
476        for(i = 0; i < mVertexDataList.size(); ++i)
477        {
478            const VertexData* vData = mVertexDataList[i];
479            l->logMessage(".");
480            l->logMessage("Original vertex set " + 
481                StringConverter::toString(i) + " - vertex count " + 
482                StringConverter::toString(vData->vertexCount));
483            const VertexElement* posElem = vData->vertexDeclaration->findElementBySemantic(VES_POSITION);
484            HardwareVertexBufferSharedPtr vbuf = 
485                vData->vertexBufferBinding->getBuffer(posElem->getSource());
486            // lock the buffer for reading
487            unsigned char* pBaseVertex = static_cast<unsigned char*>(
488                vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
489            float* pFloat;
490            for (j = 0; j < vData->vertexCount; ++j)
491            {
492                posElem->baseVertexPointerToElement(pBaseVertex, &pFloat);
493                l->logMessage("Vertex " + StringConverter::toString(j) + 
494                    ": (" + StringConverter::toString(pFloat[0]) + 
495                    ", " + StringConverter::toString(pFloat[1]) + 
496                    ", " + StringConverter::toString(pFloat[2]) + ")");
497                pBaseVertex += vbuf->getVertexSize();
498            }
499            vbuf->unlock();
500        }
501
502        // Log original index data
503        for(i = 0; i < mGeometryList.size(); i++)
504        {
505            const IndexData* iData = mGeometryList[i].indexData;
506            l->logMessage(".");
507            l->logMessage("Original triangle set " + 
508                StringConverter::toString(mGeometryList[i].indexSet) + " - index count " + 
509                StringConverter::toString(iData->indexCount) + " - " + 
510            "vertex set " + StringConverter::toString(mGeometryList[i].vertexSet) + " - " + 
511            "operationType " + StringConverter::toString(mGeometryList[i].opType));
512            // Get the indexes ready for reading
513            unsigned short* p16Idx;
514            unsigned int* p32Idx;
515
516            if (iData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
517            {
518                p32Idx = static_cast<unsigned int*>(
519                    iData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
520            }
521            else
522            {
523                p16Idx = static_cast<unsigned short*>(
524                    iData->indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
525            }
526
527            for (j = 0; j < iData->indexCount;  )
528            {
529                if (iData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
530                {
531                    if (mGeometryList[i].opType == RenderOperation::OT_TRIANGLE_LIST
532                        || j == 0)
533                    {
534                        unsigned int n1 = *p32Idx++;
535                        unsigned int n2 = *p32Idx++;
536                        unsigned int n3 = *p32Idx++;
537                        l->logMessage("Triangle " + StringConverter::toString(j) + 
538                            ": (" + StringConverter::toString(n1) + 
539                            ", " + StringConverter::toString(n2) + 
540                            ", " + StringConverter::toString(n3) + ")");
541                        j += 3;
542                    }
543                    else
544                    {
545                        l->logMessage("Triangle " + StringConverter::toString(j) + 
546                            ": (" + StringConverter::toString(*p32Idx++) + ")");
547                        j++;
548                    }
549                }
550                else
551                {
552                    if (mGeometryList[i].opType == RenderOperation::OT_TRIANGLE_LIST
553                        || j == 0)
554                    {
555                        unsigned short n1 = *p16Idx++;
556                        unsigned short n2 = *p16Idx++;
557                        unsigned short n3 = *p16Idx++;
558                        l->logMessage("Index " + StringConverter::toString(j) + 
559                            ": (" + StringConverter::toString(n1) + 
560                            ", " + StringConverter::toString(n2) + 
561                            ", " + StringConverter::toString(n3) + ")");
562                        j += 3;
563                    }
564                    else
565                    {
566                        l->logMessage("Triangle " + StringConverter::toString(j) + 
567                            ": (" + StringConverter::toString(*p16Idx++) + ")");
568                        j++;
569                    }
570                }
571
572
573            }
574
575            iData->indexBuffer->unlock();
576
577
578            // Log common vertex list
579            l->logMessage(".");
580            l->logMessage("Common vertex list - vertex count " + 
581                StringConverter::toString(mVertices.size()));
582            for (i = 0; i < mVertices.size(); ++i)
583            {
584                CommonVertex& c = mVertices[i];
585                l->logMessage("Common vertex " + StringConverter::toString(i) + 
586                    ": (vertexSet=" + StringConverter::toString(c.vertexSet) + 
587                    ", originalIndex=" + StringConverter::toString(c.originalIndex) + 
588                    ", position=" + StringConverter::toString(c.position));
589            }
590        }
591
592    }
593
594
595
596}
597
Note: See TracBrowser for help on using the repository browser.