source: OGRE/trunk/ogrenew/OgreMain/src/OgrePatchSurface.cpp @ 692

Revision 692, 26.5 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

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