Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgrePatchSurface.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 26.8 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
31#include "OgrePatchSurface.h"
32
33#include "OgreMeshManager.h"
34#include "OgreMesh.h"
35#include "OgreSubMesh.h"
36#include "OgreException.h"
37#include "OgreHardwareBufferManager.h"
38#include "OgreHardwareVertexBuffer.h"
39#include "OgreHardwareIndexBuffer.h"
40
41#define LEVEL_WIDTH(lvl) ((1 << (lvl+1)) + 1)
42
43namespace Ogre {
44
45    // TODO: make this deal with specular colours and more than 2 texture coords
46
47    //-----------------------------------------------------------------------
48    PatchSurface::PatchSurface()
49    {
50        mType = PST_BEZIER;
51    }
52    //-----------------------------------------------------------------------
53    PatchSurface::~PatchSurface()
54    {
55    }
56    //-----------------------------------------------------------------------
57    void PatchSurface::defineSurface(void* controlPointBuffer, 
58            VertexDeclaration *declaration, size_t width, size_t height,
59            PatchSurfaceType pType, size_t uMaxSubdivisionLevel, 
60            size_t vMaxSubdivisionLevel, VisibleSide visibleSide)
61    {
62        if (height == 0 || width == 0)
63            return; // Do nothing - garbage
64
65        mType = pType;
66        mCtlWidth = width;
67        mCtlHeight = height;
68        mCtlCount = width * height;
69        mControlPointBuffer = controlPointBuffer;
70        mDeclaration = declaration;
71
72        // Copy positions into Vector3 vector
73        mVecCtlPoints.clear();
74        const VertexElement* elem = declaration->findElementBySemantic(VES_POSITION);
75        size_t vertSize = declaration->getVertexSize(0);
76        const unsigned char *pVert = static_cast<const unsigned char*>(controlPointBuffer);
77        float* pFloat;
78        for (size_t i = 0; i < mCtlCount; ++i)
79        {
80            elem->baseVertexPointerToElement((void*)pVert, &pFloat);
81            mVecCtlPoints.push_back(Vector3(pFloat[0], pFloat[1], pFloat[2]));
82            pVert += vertSize;
83        }
84
85        mVSide = visibleSide;
86
87        // Determine max level
88        // Initialise to 100% detail
89        mSubdivisionFactor = 1.0f;
90        if (uMaxSubdivisionLevel == AUTO_LEVEL)
91        {
92            mULevel = mMaxULevel = getAutoULevel();
93        }
94        else
95        {
96            mULevel = mMaxULevel = uMaxSubdivisionLevel;
97        }
98
99        if (vMaxSubdivisionLevel == AUTO_LEVEL)
100        {
101            mVLevel = mMaxVLevel = getAutoVLevel();
102        }
103        else
104        {
105            mVLevel = mMaxVLevel = vMaxSubdivisionLevel;
106        }
107
108
109
110        // Derive mesh width / height
111        mMeshWidth  = (LEVEL_WIDTH(mMaxULevel)-1) * ((mCtlWidth-1)/2) + 1;
112        mMeshHeight = (LEVEL_WIDTH(mMaxVLevel)-1) * ((mCtlHeight-1)/2) + 1;
113
114
115        // Calculate number of required vertices / indexes at max resolution
116        mRequiredVertexCount = mMeshWidth * mMeshHeight;
117        int iterations = (mVSide == VS_BOTH)? 2 : 1;
118        mRequiredIndexCount = (mMeshWidth-1) * (mMeshHeight-1) * 2 * iterations * 3;
119
120        // Calculate bounds based on control points
121        std::vector<Vector3>::const_iterator ctli;
122        Vector3 min, max;
123        Real maxSqRadius;
124        bool first = true;
125        for (ctli = mVecCtlPoints.begin(); ctli != mVecCtlPoints.end(); ++ctli)
126        {
127            if (first)
128            {
129                min = max = *ctli;
130                maxSqRadius = ctli->squaredLength();
131                first = false;
132            }
133            else
134            {
135                min.makeFloor(*ctli);
136                max.makeCeil(*ctli);
137                maxSqRadius = std::max(ctli->squaredLength(), maxSqRadius);
138
139            }
140        }
141        mAABB.setExtents(min, max);
142        mBoundingSphere = Math::Sqrt(maxSqRadius);
143
144    }
145    //-----------------------------------------------------------------------
146    const AxisAlignedBox& PatchSurface::getBounds(void) const
147    {
148        return mAABB;
149    }
150    //-----------------------------------------------------------------------
151    Real PatchSurface::getBoundingSphereRadius(void) const
152    {
153        return mBoundingSphere;
154    }
155    //-----------------------------------------------------------------------
156    size_t PatchSurface::getRequiredVertexCount(void) const
157    {
158        return mRequiredVertexCount;
159    }
160    //-----------------------------------------------------------------------
161    size_t PatchSurface::getRequiredIndexCount(void) const
162    {
163        return mRequiredIndexCount;
164    }
165    //-----------------------------------------------------------------------
166    void PatchSurface::build(HardwareVertexBufferSharedPtr destVertexBuffer, 
167        size_t vertexStart, HardwareIndexBufferSharedPtr destIndexBuffer, size_t indexStart)
168    {
169
170        if (mVecCtlPoints.empty())
171            return;
172
173        mVertexBuffer = destVertexBuffer;
174        mVertexOffset = vertexStart;
175        mIndexBuffer = destIndexBuffer;
176        mIndexOffset = indexStart;
177
178        // Lock just the region we are interested in
179        void* lockedBuffer = mVertexBuffer->lock(
180            mVertexOffset * mDeclaration->getVertexSize(0), 
181            mRequiredVertexCount * mDeclaration->getVertexSize(0),
182            HardwareBuffer::HBL_NO_OVERWRITE);
183
184        distributeControlPoints(lockedBuffer);
185
186        // Subdivide the curve to the MAX :)
187        // Do u direction first, so need to step over v levels not done yet
188        size_t vStep = 1 << mMaxVLevel;
189        size_t uStep = 1 << mMaxULevel;
190
191        size_t v, u;
192        for (v = 0; v < mMeshHeight; v += vStep)
193        {
194            // subdivide this row in u
195            subdivideCurve(lockedBuffer, v*mMeshWidth, uStep, mMeshWidth / uStep, mULevel);
196        }
197
198        // Now subdivide in v direction, this time all the u direction points are there so no step
199        for (u = 0; u < mMeshWidth; ++u)
200        {
201            subdivideCurve(lockedBuffer, u, vStep*mMeshWidth, mMeshHeight / vStep, mVLevel);
202        }
203       
204
205        mVertexBuffer->unlock();
206
207        // Make triangles from mesh at this current level of detail
208        makeTriangles();
209
210    }
211    //-----------------------------------------------------------------------
212    size_t PatchSurface::getAutoULevel(bool forMax)
213    {
214        // determine levels
215        // Derived from work by Bart Sekura in Rogl
216        Vector3 a,b,c;
217        size_t u,v;
218        bool found=false;
219        // Find u level
220        for(v = 0; v < mCtlHeight; v++) {
221            for(u = 0; u < mCtlWidth-1; u += 2) {
222                a = mVecCtlPoints[v * mCtlWidth + u];
223                b = mVecCtlPoints[v * mCtlWidth + u+1];
224                c = mVecCtlPoints[v * mCtlWidth + u+2];
225                if(a!=c) {
226                    found=true;
227                    break;
228                }
229            }
230            if(found) break;
231        }
232        if(!found) {
233            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Can't find suitable control points for determining U subdivision level",
234                "PatchSurface::getAutoULevel");
235        }
236
237        return findLevel(a,b,c);
238
239    }
240    //-----------------------------------------------------------------------
241    size_t PatchSurface::getAutoVLevel(bool forMax)
242    {
243        Vector3 a,b,c;
244        size_t u,v;
245        bool found=false;
246        for(u = 0; u < mCtlWidth; u++) {
247            for(v = 0; v < mCtlHeight-1; v += 2) {
248                a = mVecCtlPoints[v * mCtlWidth + u];
249                b = mVecCtlPoints[(v+1) * mCtlWidth + u];
250                c = mVecCtlPoints[(v+2) * mCtlWidth + u];
251                if(a!=c) {
252                    found=true;
253                    break;
254                }
255            }
256            if(found) break;
257        }
258        if(!found) {
259            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Can't find suitable control points for determining V subdivision level",
260                "PatchSurface::getAutoVLevel");
261        }
262
263        return findLevel(a,b,c);
264
265    }
266    //-----------------------------------------------------------------------
267    void PatchSurface::setSubdivisionFactor(Real factor)
268    {
269        assert(factor >= 0.0f && factor <= 1.0f);
270
271        mSubdivisionFactor = factor;
272        mULevel = static_cast<size_t>(factor * mMaxULevel);
273        mVLevel = static_cast<size_t>(factor * mMaxVLevel);
274
275        makeTriangles();
276
277
278    }
279    //-----------------------------------------------------------------------
280    Real PatchSurface::getSubdivisionFactor(void) const
281    {
282        return mSubdivisionFactor;
283    }
284    //-----------------------------------------------------------------------
285    size_t PatchSurface::getCurrentIndexCount(void) const
286    {
287        return mCurrIndexCount;
288    }
289    //-----------------------------------------------------------------------
290    size_t PatchSurface::findLevel(Vector3& a, Vector3& b, Vector3& c)
291    {
292        // Derived from work by Bart Sekura in rogl
293        // Apart from I think I fixed a bug - see below
294        // I also commented the code, the only thing wrong with rogl is almost no comments!!
295
296        const size_t max_levels = 5;
297        const float subdiv = 10;
298        size_t level;
299
300        float test=subdiv*subdiv;
301        Vector3 s,t,d;
302        for(level=0; level<max_levels-1; level++)
303        {
304            // Subdivide the 2 lines
305            s = a.midPoint(b);
306            t = b.midPoint(c);
307            // Find the midpoint between the 2 midpoints
308            c = s.midPoint(t);
309            // Get the vector between this subdivided midpoint and the middle point of the original line
310            d = c - b;
311            // Find the squared length, and break when small enough
312            if(d.dotProduct(d) < test) {
313                break;
314            }
315            b=a; 
316        }
317
318        return level;
319
320    }
321
322    /*
323    //-----------------------------------------------------------------------
324    void PatchSurface::allocateMemory(void)
325    {
326        if (mMemoryAllocated)
327            deallocateMemory();
328
329        // Allocate to the size of max level
330
331        // Create mesh
332        mMesh = MeshManager::getSingleton().createManual(mMeshName);
333        mMesh->sharedVertexData = new VertexData();
334        // Copy all vertex parameters
335        mMesh->sharedVertexData->vertexStart = 0;
336        // Vertex count will be set on build() because it depends on current level
337        // NB clone the declaration because Mesh's VertexData will destroy it
338        mMesh->sharedVertexData->vertexDeclaration = mDeclaration->clone();
339        // Create buffer (only a single buffer)
340        // Allocate enough buffer memory for maximum subdivision, not current subdivision
341        HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().
342            createVertexBuffer(
343                mDeclaration->getVertexSize(0),
344                mMaxMeshHeight * mMaxMeshWidth, // maximum size
345                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // dynamic for changing level
346
347        // Set binding
348        mMesh->sharedVertexData->vertexBufferBinding->setBinding(0, vbuf);
349
350        SubMesh* sm = mMesh->createSubMesh();
351        // Allocate enough index data for max subdivision
352        sm->indexData->indexStart = 0;
353        // Index count will be set on build()
354        unsigned short iterations = (mVSide == VS_BOTH ? 2 : 1);
355        sm->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(
356            HardwareIndexBuffer::IT_16BIT,
357            (mMaxMeshWidth-1) * (mMaxMeshHeight-1) * 2 * iterations * 3, 
358            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
359
360        mMesh->load();
361
362        // Derive bounds from control points, cannot stray outside that
363        Vector3 min, max;
364        Real maxSquaredRadius;
365        bool first = true;
366        std::vector<Vector3>::iterator i, iend;
367        iend = mVecCtlPoints.end();
368        for (i = mVecCtlPoints.begin(); i != iend; ++i)
369        {
370            if (first)
371            {
372                min = max = *i;
373                maxSquaredRadius = i->squaredLength();
374            }
375            else
376            {
377                min.makeFloor(*i);
378                max.makeCeil(*i);
379                maxSquaredRadius = std::max(maxSquaredRadius, i->squaredLength());
380            }
381
382        }
383        mMesh->_setBounds(AxisAlignedBox(min, max));
384        mMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
385
386
387
388    }
389    */
390    //-----------------------------------------------------------------------
391    void PatchSurface::distributeControlPoints(void* lockedBuffer)
392    {
393        // Insert original control points into expanded mesh
394        size_t uStep = 1 << mULevel;
395        size_t vStep = 1 << mVLevel;
396
397
398        void* pSrc = mControlPointBuffer;
399        size_t vertexSize = mDeclaration->getVertexSize(0);
400        float *pSrcReal, *pDestReal;
401        RGBA *pSrcRGBA, *pDestRGBA;
402        void* pDest;
403        const VertexElement* elemPos = mDeclaration->findElementBySemantic(VES_POSITION);
404        const VertexElement* elemNorm = mDeclaration->findElementBySemantic(VES_NORMAL);
405        const VertexElement* elemTex0 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
406        const VertexElement* elemTex1 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);
407        const VertexElement* elemDiffuse = mDeclaration->findElementBySemantic(VES_DIFFUSE);
408        for (size_t v = 0; v < mMeshHeight; v += vStep)
409        {
410            // set dest by v from base
411            pDest = static_cast<void*>(
412                static_cast<unsigned char*>(lockedBuffer) + (vertexSize * mMeshWidth * v));
413            for (size_t u = 0; u < mMeshWidth; u += uStep)
414            {
415
416                // Copy Position
417                elemPos->baseVertexPointerToElement(pSrc, &pSrcReal);
418                elemPos->baseVertexPointerToElement(pDest, &pDestReal);
419                *pDestReal++ = *pSrcReal++;
420                *pDestReal++ = *pSrcReal++;
421                *pDestReal++ = *pSrcReal++;
422
423                // Copy Normals
424                if (elemNorm)
425                {
426                    elemNorm->baseVertexPointerToElement(pSrc, &pSrcReal);
427                    elemNorm->baseVertexPointerToElement(pDest, &pDestReal);
428                    *pDestReal++ = *pSrcReal++;
429                    *pDestReal++ = *pSrcReal++;
430                    *pDestReal++ = *pSrcReal++;
431                }
432
433                // Copy Diffuse
434                if (elemDiffuse)
435                {
436                    elemDiffuse->baseVertexPointerToElement(pSrc, &pSrcRGBA);
437                    elemDiffuse->baseVertexPointerToElement(pDest, &pDestRGBA);
438                    *pDestRGBA++ = *pSrcRGBA++;
439                }
440
441                // Copy texture coords
442                if (elemTex0)
443                {
444                    elemTex0->baseVertexPointerToElement(pSrc, &pSrcReal);
445                    elemTex0->baseVertexPointerToElement(pDest, &pDestReal);
446                    for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex0->getType()); ++dim)
447                        *pDestReal++ = *pSrcReal++;
448                }
449                if (elemTex1)
450                {
451                    elemTex1->baseVertexPointerToElement(pSrc, &pSrcReal);
452                    elemTex1->baseVertexPointerToElement(pDest, &pDestReal);
453                    for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex1->getType()); ++dim)
454                        *pDestReal++ = *pSrcReal++;
455                }
456
457                // Increment source by one vertex
458                pSrc = static_cast<void*>(
459                    static_cast<unsigned char*>(pSrc) + vertexSize);
460                // Increment dest by 1 vertex * uStep
461                pDest = static_cast<void*>(
462                    static_cast<unsigned char*>(pDest) + (vertexSize * uStep));
463            } // u
464        } // v
465
466       
467    }
468    //-----------------------------------------------------------------------
469    void PatchSurface::subdivideCurve(void* lockedBuffer, size_t startIdx, size_t stepSize, size_t numSteps, size_t iterations)
470    {
471        // Subdivides a curve within a sparsely populated buffer (gaps are already there to be interpolated into)
472        size_t leftIdx, rightIdx, destIdx, halfStep, maxIdx;
473        bool firstSegment;
474
475        maxIdx = startIdx + (numSteps * stepSize);
476        size_t step = stepSize;
477
478        while(iterations--)
479        {
480            halfStep = step / 2;
481            leftIdx = startIdx;
482            destIdx = leftIdx + halfStep;
483            rightIdx = leftIdx + step;
484            firstSegment = true;
485            while (leftIdx < maxIdx)
486            {
487                // Interpolate
488                interpolateVertexData(lockedBuffer, leftIdx, rightIdx, destIdx);
489
490                // If 2nd or more segment, interpolate current left between current and last mid points
491                if (!firstSegment)
492                {
493                    interpolateVertexData(lockedBuffer, leftIdx - halfStep, leftIdx + halfStep, leftIdx);
494                }
495                // Next segment
496                leftIdx = rightIdx;
497                destIdx = leftIdx + halfStep;
498                rightIdx = leftIdx + step;
499                firstSegment = false;
500            }
501
502            step = halfStep;
503        }
504    }
505    //-----------------------------------------------------------------------
506    void PatchSurface::makeTriangles(void)
507    {
508        // Our vertex buffer is subdivided to the highest level, we need to generate tris
509        // which step over the vertices we don't need for this level of detail.
510
511        // Calculate steps
512        int vStep = 1 << (mMaxVLevel - mVLevel);
513        int uStep = 1 << (mMaxULevel - mULevel);
514        size_t currWidth = (LEVEL_WIDTH(mULevel)-1) * ((mCtlWidth-1)/2) + 1;
515        size_t currHeight = (LEVEL_WIDTH(mVLevel)-1) * ((mCtlHeight-1)/2) + 1;
516
517        bool use32bitindexes = (mIndexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
518
519        // The mesh is built, just make a list of indexes to spit out the triangles
520        int vInc, uInc;
521       
522        size_t vCount, uCount, v, u, iterations;
523
524        if (mVSide == VS_BOTH)
525        {
526            iterations = 2;
527            vInc = vStep;
528            v = 0; // Start with front
529        }
530        else
531        {
532            iterations = 1;
533            if (mVSide == VS_FRONT)
534            {
535                vInc = vStep;
536                v = 0;
537            }
538            else
539            {
540                vInc = -vStep;
541                v = mMeshHeight - 1;
542            }
543        }
544
545        // Calc num indexes
546        mCurrIndexCount = (currWidth - 1) * (currHeight - 1) * 6 * iterations;
547
548        size_t v1, v2, v3;
549        // Lock just the section of the buffer we need
550        unsigned short* p16;
551        unsigned int* p32;
552        if (use32bitindexes)
553        {
554            p32 = static_cast<unsigned int*>(
555                mIndexBuffer->lock(
556                    mIndexOffset * sizeof(unsigned int), 
557                    mRequiredIndexCount * sizeof(unsigned int), 
558                    HardwareBuffer::HBL_NO_OVERWRITE));
559        }
560        else
561        {
562            p16 = static_cast<unsigned short*>(
563                mIndexBuffer->lock(
564                    mIndexOffset * sizeof(unsigned short), 
565                    mRequiredIndexCount * sizeof(unsigned short), 
566                    HardwareBuffer::HBL_NO_OVERWRITE));
567        }
568
569        while (iterations--)
570        {
571            // Make tris in a zigzag pattern (compatible with strips)
572            u = 0;
573            uInc = uStep; // Start with moving +u
574
575            vCount = currHeight - 1;
576            while (vCount--)
577            {
578                uCount = currWidth - 1;
579                while (uCount--)
580                {
581                    // First Tri in cell
582                    // -----------------
583                    v1 = ((v + vInc) * mMeshWidth) + u;
584                    v2 = (v * mMeshWidth) + u;
585                    v3 = ((v + vInc) * mMeshWidth) + (u + uInc);
586                    // Output indexes
587                    if (use32bitindexes)
588                    {
589                        *p32++ = static_cast<unsigned int>(v1);
590                        *p32++ = static_cast<unsigned int>(v2);
591                        *p32++ = static_cast<unsigned int>(v3);
592                    }
593                    else
594                    {
595                        *p16++ = static_cast<unsigned short>(v1);
596                        *p16++ = static_cast<unsigned short>(v2);
597                        *p16++ = static_cast<unsigned short>(v3);
598                    }
599                    // Second Tri in cell
600                    // ------------------
601                    v1 = ((v + vInc) * mMeshWidth) + (u + uInc);
602                    v2 = (v * mMeshWidth) + u;
603                    v3 = (v * mMeshWidth) + (u + uInc);
604                    // Output indexes
605                    if (use32bitindexes)
606                    {
607                        *p32++ = static_cast<unsigned int>(v1);
608                        *p32++ = static_cast<unsigned int>(v2);
609                        *p32++ = static_cast<unsigned int>(v3);
610                    }
611                    else
612                    {
613                        *p16++ = static_cast<unsigned short>(v1);
614                        *p16++ = static_cast<unsigned short>(v2);
615                        *p16++ = static_cast<unsigned short>(v3);
616                    }
617
618                    // Next column
619                    u += uInc;
620                }
621                // Next row
622                v += vInc;
623                u = 0;
624
625
626            }
627
628            // Reverse vInc for double sided
629            v = mMeshHeight - 1;
630            vInc = -vInc;
631
632        }
633
634        mIndexBuffer->unlock();
635
636
637    }
638    //-----------------------------------------------------------------------
639    void PatchSurface::interpolateVertexData(void* lockedBuffer, size_t leftIdx, size_t rightIdx, size_t destIdx)
640    {
641        size_t vertexSize = mDeclaration->getVertexSize(0);
642        const VertexElement* elemPos = mDeclaration->findElementBySemantic(VES_POSITION);
643        const VertexElement* elemNorm = mDeclaration->findElementBySemantic(VES_NORMAL);
644        const VertexElement* elemDiffuse = mDeclaration->findElementBySemantic(VES_DIFFUSE);
645        const VertexElement* elemTex0 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
646        const VertexElement* elemTex1 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);
647
648        float *pDestReal, *pLeftReal, *pRightReal;
649        unsigned char *pDestChar, *pLeftChar, *pRightChar;
650        unsigned char *pDest, *pLeft, *pRight;
651
652        // Set up pointers & interpolate
653        pDest = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * destIdx);
654        pLeft = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * leftIdx);
655        pRight = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * rightIdx);
656
657        // Position
658        elemPos->baseVertexPointerToElement(pDest, &pDestReal);
659        elemPos->baseVertexPointerToElement(pLeft, &pLeftReal);
660        elemPos->baseVertexPointerToElement(pRight, &pRightReal);
661
662        *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5;
663        *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5;
664        *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5;
665
666        if (elemNorm)
667        {
668            elemNorm->baseVertexPointerToElement(pDest, &pDestReal);
669            elemNorm->baseVertexPointerToElement(pLeft, &pLeftReal);
670            elemNorm->baseVertexPointerToElement(pRight, &pRightReal);
671            Vector3 norm;
672            norm.x = (*pLeftReal++ + *pRightReal++) * 0.5;
673            norm.y = (*pLeftReal++ + *pRightReal++) * 0.5;
674            norm.z = (*pLeftReal++ + *pRightReal++) * 0.5;
675            norm.normalise();
676
677            *pDestReal++ = norm.x;
678            *pDestReal++ = norm.y;
679            *pDestReal++ = norm.z;
680        }
681        if (elemDiffuse)
682        {
683            // Blend each byte individually
684            elemDiffuse->baseVertexPointerToElement(pDest, &pDestChar);
685            elemDiffuse->baseVertexPointerToElement(pLeft, &pLeftChar);
686            elemDiffuse->baseVertexPointerToElement(pRight, &pRightChar);
687            // 4 bytes to RGBA
688            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
689            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
690            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
691            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
692        }
693        if (elemTex0)
694        {
695            elemTex0->baseVertexPointerToElement(pDest, &pDestReal);
696            elemTex0->baseVertexPointerToElement(pLeft, &pLeftReal);
697            elemTex0->baseVertexPointerToElement(pRight, &pRightReal);
698
699            for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex0->getType()); ++dim)
700                *pDestReal++ = ((*pLeftReal++) + (*pRightReal++)) * 0.5;
701        }
702        if (elemTex1)
703        {
704            elemTex1->baseVertexPointerToElement(pDest, &pDestReal);
705            elemTex1->baseVertexPointerToElement(pLeft, &pLeftReal);
706            elemTex1->baseVertexPointerToElement(pRight, &pRightReal);
707
708            for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex1->getType()); ++dim)
709                *pDestReal++ = ((*pLeftReal++) + (*pRightReal++)) * 0.5;
710        }
711    }
712
713}
714
Note: See TracBrowser for help on using the repository browser.