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

# OgrePatchSurface.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-2002 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
    00027 #include "OgrePatchSurface.h"
    00028
    00029 #include "OgreMeshManager.h"
    00030 #include "OgreMesh.h"
    00031 #include "OgreSubMesh.h"
    00032 #include "OgreException.h"
    00033 #include "OgreHardwareBufferManager.h"
    00034 #include "OgreHardwareVertexBuffer.h"
    00035 #include "OgreHardwareIndexBuffer.h"
    00036
    00037 #define LEVEL_WIDTH(lvl) ((1 << (lvl+1)) + 1)
    00038
    00039 namespace Ogre {
    00040
    00041     // TODO: make this deal with specular colours and more than 2 texture coords
    00042
    00043     //-----------------------------------------------------------------------
    00044     PatchSurface::PatchSurface()
    00045     {
    00046         mType = PST_BEZIER;
    00047     }
    00048     //-----------------------------------------------------------------------
    00049     PatchSurface::~PatchSurface()
    00050     {
    00051     }
    00052     //-----------------------------------------------------------------------
    00053     void PatchSurface::defineSurface(void* controlPointBuffer,
    00054             VertexDeclaration *declaration, size_t width, size_t height,
    00055             PatchSurfaceType pType, size_t uMaxSubdivisionLevel,
    00056             size_t vMaxSubdivisionLevel, VisibleSide visibleSide)
    00057     {
    00058         if (height == 0 || width == 0)
    00059             return; // Do nothing - garbage
    00060
    00061         mType = pType;
    00062         mCtlWidth = width;
    00063         mCtlHeight = height;
    00064         mCtlCount = width * height;
    00065         mControlPointBuffer = controlPointBuffer;
    00066         mDeclaration = declaration;
    00067
    00068         // Copy positions into Vector3 vector
    00069         mVecCtlPoints.clear();
    00070         const VertexElement* elem = declaration->findElementBySemantic(VES_POSITION);
    00071         size_t vertSize = declaration->getVertexSize(0);
    00072         const unsigned char *pVert = static_cast<const unsigned char*>(controlPointBuffer);
    00073         Real* pReal;
    00074         for (size_t i = 0; i < mCtlCount; ++i)
    00075         {
    00076             elem->baseVertexPointerToElement((void*)pVert, &pReal);
    00077             mVecCtlPoints.push_back(Vector3(pReal));
    00078             pVert += vertSize;
    00079         }
    00080
    00081         mVSide = visibleSide;
    00082
    00083         // Determine max level
    00084         // Initialise to 100% detail
    00085         mSubdivisionFactor = 1.0f;
    00086         if (uMaxSubdivisionLevel == AUTO_LEVEL)
    00087         {
    00088             mULevel = mMaxULevel = getAutoULevel();
    00089         }
    00090         else
    00091         {
    00092             mULevel = mMaxULevel = uMaxSubdivisionLevel;
    00093         }
    00094
    00095         if (vMaxSubdivisionLevel == AUTO_LEVEL)
    00096         {
    00097             mVLevel = mMaxVLevel = getAutoVLevel();
    00098         }
    00099         else
    00100         {
    00101             mVLevel = mMaxVLevel = vMaxSubdivisionLevel;
    00102         }
    00103
    00104
    00105
    00106         // Derive mesh width / height
    00107         mMeshWidth  = (LEVEL_WIDTH(mMaxULevel)-1) * ((mCtlWidth-1)/2) + 1;
    00108         mMeshHeight = (LEVEL_WIDTH(mMaxVLevel)-1) * ((mCtlHeight-1)/2) + 1;
    00109
    00110
    00111         // Calculate number of required vertices / indexes at max resolution
    00112         mRequiredVertexCount = mMeshWidth * mMeshHeight;
    00113         int iterations = (mVSide == VS_BOTH)? 2 : 1;
    00114         mRequiredIndexCount = (mMeshWidth-1) * (mMeshHeight-1) * 2 * iterations * 3;
    00115
    00116         // Calculate bounds based on control points
    00117         std::vector<Vector3>::const_iterator ctli;
    00118         Vector3 min, max;
    00119         Real maxSqRadius;
    00120         bool first = true;
    00121         for (ctli = mVecCtlPoints.begin(); ctli != mVecCtlPoints.end(); ++ctli)
    00122         {
    00123             if (first)
    00124             {
    00125                 min = max = *ctli;
    00126                 maxSqRadius = ctli->squaredLength();
    00127                 first = false;
    00128             }
    00129             else
    00130             {
    00131                 min.makeFloor(*ctli);
    00132                 max.makeCeil(*ctli);
    00133                 maxSqRadius = std::max(ctli->squaredLength(), maxSqRadius);
    00134
    00135             }
    00136         }
    00137         mAABB.setExtents(min, max);
    00138         mBoundingSphere = Math::Sqrt(maxSqRadius);
    00139
    00140     }
    00141     //-----------------------------------------------------------------------
    00142     const AxisAlignedBox& PatchSurface::getBounds(void) const
    00143     {
    00144         return mAABB;
    00145     }
    00146     //-----------------------------------------------------------------------
    00147     Real PatchSurface::getBoundingSphereRadius(void) const
    00148     {
    00149         return mBoundingSphere;
    00150     }
    00151     //-----------------------------------------------------------------------
    00152     size_t PatchSurface::getRequiredVertexCount(void) const
    00153     {
    00154         return mRequiredVertexCount;
    00155     }
    00156     //-----------------------------------------------------------------------
    00157     size_t PatchSurface::getRequiredIndexCount(void) const
    00158     {
    00159         return mRequiredIndexCount;
    00160     }
    00161     //-----------------------------------------------------------------------
    00162     void PatchSurface::build(HardwareVertexBufferSharedPtr destVertexBuffer,
    00163         size_t vertexStart, HardwareIndexBufferSharedPtr destIndexBuffer, size_t indexStart)
    00164     {
    00165
    00166         if (mVecCtlPoints.empty())
    00167             return;
    00168
    00169         mVertexBuffer = destVertexBuffer;
    00170         mVertexOffset = vertexStart;
    00171         mIndexBuffer = destIndexBuffer;
    00172         mIndexOffset = indexStart;
    00173
    00174         // Lock just the region we are interested in
    00175         void* lockedBuffer = mVertexBuffer->lock(
    00176             mVertexOffset * mDeclaration->getVertexSize(0),
    00177             mRequiredVertexCount * mDeclaration->getVertexSize(0),
    00178             HardwareBuffer::HBL_NO_OVERWRITE);
    00179
    00180         distributeControlPoints(lockedBuffer);
    00181
    00182         // Subdivide the curve to the MAX :)
    00183         // Do u direction first, so need to step over v levels not done yet
    00184         size_t vStep = 1 << mMaxVLevel;
    00185         size_t uStep = 1 << mMaxULevel;
    00186
    00187         size_t v, u;
    00188         for (v = 0; v < mMeshHeight; v += vStep)
    00189         {
    00190             // subdivide this row in u
    00191             subdivideCurve(lockedBuffer, v*mMeshWidth, uStep, mMeshWidth / uStep, mULevel);
    00192         }
    00193
    00194         // Now subdivide in v direction, this time all the u direction points are there so no step
    00195         for (u = 0; u < mMeshWidth; ++u)
    00196         {
    00197             subdivideCurve(lockedBuffer, u, vStep*mMeshWidth, mMeshHeight / vStep, mVLevel);
    00198         }
    00199
    00200
    00201         mVertexBuffer->unlock();
    00202
    00203         // Make triangles from mesh at this current level of detail
    00204         makeTriangles();
    00205
    00206     }
    00207     //-----------------------------------------------------------------------
    00208     size_t PatchSurface::getAutoULevel(bool forMax)
    00209     {
    00210         // determine levels
    00211         // Derived from work by Bart Sekura in Rogl
    00212         Vector3 a,b,c;
    00213         size_t u,v;
    00214         bool found=false;
    00215         // Find u level
    00216         for(v = 0; v < mCtlHeight; v++) {
    00217             for(u = 0; u < mCtlWidth-1; u += 2) {
    00218                 a = mVecCtlPoints[v * mCtlWidth + u];
    00219                 b = mVecCtlPoints[v * mCtlWidth + u+1];
    00220                 c = mVecCtlPoints[v * mCtlWidth + u+2];
    00221                 if(a!=c) {
    00222                     found=true;
    00223                     break;
    00224                 }
    00225             }
    00226             if(found) break;
    00227         }
    00228         if(!found) {
    00229             Except(Exception::ERR_INTERNAL_ERROR, "Can't find suitable control points for determining U subdivision level",
    00230                 "PatchSurface::getAutoULevel");
    00231         }
    00232
    00233         return findLevel(a,b,c);
    00234
    00235     }
    00236     //-----------------------------------------------------------------------
    00237     size_t PatchSurface::getAutoVLevel(bool forMax)
    00238     {
    00239         Vector3 a,b,c;
    00240         size_t u,v;
    00241         bool found=false;
    00242         for(u = 0; u < mCtlWidth; u++) {
    00243             for(v = 0; v < mCtlHeight-1; v += 2) {
    00244                 a = mVecCtlPoints[v * mCtlWidth + u];
    00245                 b = mVecCtlPoints[(v+1) * mCtlWidth + u];
    00246                 c = mVecCtlPoints[(v+2) * mCtlWidth + u];
    00247                 if(a!=c) {
    00248                     found=true;
    00249                     break;
    00250                 }
    00251             }
    00252             if(found) break;
    00253         }
    00254         if(!found) {
    00255             Except(Exception::ERR_INTERNAL_ERROR, "Can't find suitable control points for determining V subdivision level",
    00256                 "PatchSurface::getAutoVLevel");
    00257         }
    00258
    00259         return findLevel(a,b,c);
    00260
    00261     }
    00262     //-----------------------------------------------------------------------
    00263     void PatchSurface::setSubdivisionFactor(Real factor)
    00264     {
    00265         assert(factor >= 0.0f && factor <= 1.0f);
    00266
    00267         mSubdivisionFactor = factor;
    00268         mULevel = factor * mMaxULevel;
    00269         mVLevel = factor * mMaxVLevel;
    00270
    00271         makeTriangles();
    00272
    00273
    00274     }
    00275     //-----------------------------------------------------------------------
    00276     Real PatchSurface::getSubdivisionFactor(void) const
    00277     {
    00278         return mSubdivisionFactor;
    00279     }
    00280     //-----------------------------------------------------------------------
    00281     size_t PatchSurface::getCurrentIndexCount(void) const
    00282     {
    00283         return mCurrIndexCount;
    00284     }
    00285     //-----------------------------------------------------------------------
    00286     size_t PatchSurface::findLevel(Vector3& a, Vector3& b, Vector3& c)
    00287     {
    00288         // Derived from work by Bart Sekura in rogl
    00289         // Apart from I think I fixed a bug - see below
    00290         // I also commented the code, the only thing wrong with rogl is almost no comments!!
    00291
    00292         const size_t max_levels = 5;
    00293         const float subdiv = 10;
    00294         size_t level;
    00295
    00296         float test=subdiv*subdiv;
    00297         Vector3 s,t,d;
    00298         for(level=0; level<max_levels-1; level++)
    00299         {
    00300             // Subdivide the 2 lines
    00301             s = a.midPoint(b);
    00302             t = b.midPoint(c);
    00303             // Find the midpoint between the 2 midpoints
    00304             c = s.midPoint(t);
    00305             // Get the vector between this subdivided midpoint and the middle point of the original line
    00306             d = c - b;
    00307             // Find the squared length, and break when small enough
    00308             if(d.dotProduct(d) < test) {
    00309                 break;
    00310             }
    00311             b=a;
    00312         }
    00313
    00314         return level;
    00315
    00316     }
    00317
    00318     /*
    00319     //-----------------------------------------------------------------------
    00320     void PatchSurface::allocateMemory(void)
    00321     {
    00322         if (mMemoryAllocated)
    00323             deallocateMemory();
    00324
    00325         // Allocate to the size of max level
    00326
    00327         // Create mesh
    00328         mMesh = MeshManager::getSingleton().createManual(mMeshName);
    00329         mMesh->sharedVertexData = new VertexData();
    00330         // Copy all vertex parameters
    00331         mMesh->sharedVertexData->vertexStart = 0;
    00332         // Vertex count will be set on build() because it depends on current level
    00333         // NB clone the declaration because Mesh's VertexData will destroy it
    00334         mMesh->sharedVertexData->vertexDeclaration = mDeclaration->clone();
    00335         // Create buffer (only a single buffer)
    00336         // Allocate enough buffer memory for maximum subdivision, not current subdivision
    00337         HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().
    00338             createVertexBuffer(
    00339                 mDeclaration->getVertexSize(0),
    00340                 mMaxMeshHeight * mMaxMeshWidth, // maximum size
    00341                 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // dynamic for changing level
    00342
    00343         // Set binding
    00344         mMesh->sharedVertexData->vertexBufferBinding->setBinding(0, vbuf);
    00345
    00346         SubMesh* sm = mMesh->createSubMesh();
    00347         // Allocate enough index data for max subdivision
    00348         sm->indexData->indexStart = 0;
    00349         // Index count will be set on build()
    00350         unsigned short iterations = (mVSide == VS_BOTH ? 2 : 1);
    00351         sm->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(
    00352             HardwareIndexBuffer::IT_16BIT,
    00353             (mMaxMeshWidth-1) * (mMaxMeshHeight-1) * 2 * iterations * 3,
    00354             HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
    00355
    00356         mMesh->load();
    00357
    00358         // Derive bounds from control points, cannot stray outside that
    00359         Vector3 min, max;
    00360         Real maxSquaredRadius;
    00361         bool first = true;
    00362         std::vector<Vector3>::iterator i, iend;
    00363         iend = mVecCtlPoints.end();
    00364         for (i = mVecCtlPoints.begin(); i != iend; ++i)
    00365         {
    00366             if (first)
    00367             {
    00368                 min = max = *i;
    00369                 maxSquaredRadius = i->squaredLength();
    00370             }
    00371             else
    00372             {
    00373                 min.makeFloor(*i);
    00374                 max.makeCeil(*i);
    00375                 maxSquaredRadius = std::max(maxSquaredRadius, i->squaredLength());
    00376             }
    00377
    00378         }
    00379         mMesh->_setBounds(AxisAlignedBox(min, max));
    00380         mMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
    00381
    00382
    00383
    00384     }
    00385     */
    00386     //-----------------------------------------------------------------------
    00387     void PatchSurface::distributeControlPoints(void* lockedBuffer)
    00388     {
    00389         // Insert original control points into expanded mesh
    00390         size_t uStep = 1 << mULevel;
    00391         size_t vStep = 1 << mVLevel;
    00392
    00393
    00394         void* pSrc = mControlPointBuffer;
    00395         size_t vertexSize = mDeclaration->getVertexSize(0);
    00396         Real *pSrcReal, *pDestReal;
    00397         RGBA *pSrcRGBA, *pDestRGBA;
    00398         void* pDest;
    00399         const VertexElement* elemPos = mDeclaration->findElementBySemantic(VES_POSITION);
    00400         const VertexElement* elemNorm = mDeclaration->findElementBySemantic(VES_NORMAL);
    00401         const VertexElement* elemTex0 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
    00402         const VertexElement* elemTex1 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);
    00403         const VertexElement* elemDiffuse = mDeclaration->findElementBySemantic(VES_DIFFUSE);
    00404         for (size_t v = 0; v < mMeshHeight; v += vStep)
    00405         {
    00406             // set dest by v from base
    00407             pDest = static_cast<void*>(
    00408                 static_cast<unsigned char*>(lockedBuffer) + (vertexSize * mMeshWidth * v));
    00409             for (size_t u = 0; u < mMeshWidth; u += uStep)
    00410             {
    00411
    00412                 // Copy Position
    00413                 elemPos->baseVertexPointerToElement(pSrc, &pSrcReal);
    00414                 elemPos->baseVertexPointerToElement(pDest, &pDestReal);
    00415                 *pDestReal++ = *pSrcReal++;
    00416                 *pDestReal++ = *pSrcReal++;
    00417                 *pDestReal++ = *pSrcReal++;
    00418
    00419                 // Copy Normals
    00420                 if (elemNorm)
    00421                 {
    00422                     elemNorm->baseVertexPointerToElement(pSrc, &pSrcReal);
    00423                     elemNorm->baseVertexPointerToElement(pDest, &pDestReal);
    00424                     *pDestReal++ = *pSrcReal++;
    00425                     *pDestReal++ = *pSrcReal++;
    00426                     *pDestReal++ = *pSrcReal++;
    00427                 }
    00428
    00429                 // Copy Diffuse
    00430                 if (elemDiffuse)
    00431                 {
    00432                     elemDiffuse->baseVertexPointerToElement(pSrc, &pSrcRGBA);
    00433                     elemDiffuse->baseVertexPointerToElement(pDest, &pDestRGBA);
    00434                     *pDestRGBA++ = *pSrcRGBA++;
    00435                 }
    00436
    00437                 // Copy texture coords
    00438                 if (elemTex0)
    00439                 {
    00440                     elemTex0->baseVertexPointerToElement(pSrc, &pSrcReal);
    00441                     elemTex0->baseVertexPointerToElement(pDest, &pDestReal);
    00442                     for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex0->getType()); ++dim)
    00443                         *pDestReal++ = *pSrcReal++;
    00444                 }
    00445                 if (elemTex1)
    00446                 {
    00447                     elemTex1->baseVertexPointerToElement(pSrc, &pSrcReal);
    00448                     elemTex1->baseVertexPointerToElement(pDest, &pDestReal);
    00449                     for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex1->getType()); ++dim)
    00450                         *pDestReal++ = *pSrcReal++;
    00451                 }
    00452
    00453                 // Increment source by one vertex
    00454                 pSrc = static_cast<void*>(
    00455                     static_cast<unsigned char*>(pSrc) + vertexSize);
    00456                 // Increment dest by 1 vertex * uStep
    00457                 pDest = static_cast<void*>(
    00458                     static_cast<unsigned char*>(pDest) + (vertexSize * uStep));
    00459             } // u
    00460         } // v
    00461
    00462
    00463     }
    00464     //-----------------------------------------------------------------------
    00465     void PatchSurface::subdivideCurve(void* lockedBuffer, size_t startIdx, size_t stepSize, size_t numSteps, size_t iterations)
    00466     {
    00467         // Subdivides a curve within a sparsely populated buffer (gaps are already there to be interpolated into)
    00468         size_t leftIdx, rightIdx, destIdx, halfStep, maxIdx;
    00469         bool firstSegment;
    00470
    00471         maxIdx = startIdx + (numSteps * stepSize);
    00472         size_t step = stepSize;
    00473
    00474         while(iterations--)
    00475         {
    00476             halfStep = step / 2;
    00477             leftIdx = startIdx;
    00478             destIdx = leftIdx + halfStep;
    00479             rightIdx = leftIdx + step;
    00480             firstSegment = true;
    00481             while (leftIdx < maxIdx)
    00482             {
    00483                 // Interpolate
    00484                 interpolateVertexData(lockedBuffer, leftIdx, rightIdx, destIdx);
    00485
    00486                 // If 2nd or more segment, interpolate current left between current and last mid points
    00487                 if (!firstSegment)
    00488                 {
    00489                     interpolateVertexData(lockedBuffer, leftIdx - halfStep, leftIdx + halfStep, leftIdx);
    00490                 }
    00491                 // Next segment
    00492                 leftIdx = rightIdx;
    00493                 destIdx = leftIdx + halfStep;
    00494                 rightIdx = leftIdx + step;
    00495                 firstSegment = false;
    00496             }
    00497
    00498             step = halfStep;
    00499         }
    00500     }
    00501     //-----------------------------------------------------------------------
    00502     void PatchSurface::makeTriangles(void)
    00503     {
    00504         // Our vertex buffer is subdivided to the highest level, we need to generate tris
    00505         // which step over the vertices we don't need for this level of detail.
    00506
    00507         // Calculate steps
    00508         int vStep = 1 << (mMaxVLevel - mVLevel);
    00509         int uStep = 1 << (mMaxULevel - mULevel);
    00510         size_t currWidth = (LEVEL_WIDTH(mULevel)-1) * ((mCtlWidth-1)/2) + 1;
    00511         size_t currHeight = (LEVEL_WIDTH(mVLevel)-1) * ((mCtlHeight-1)/2) + 1;
    00512
    00513         bool use32bitindexes = (mIndexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
    00514
    00515         // The mesh is built, just make a list of indexes to spit out the triangles
    00516         int vInc, uInc;
    00517
    00518         size_t vCount, uCount, v, u, iterations;
    00519
    00520         if (mVSide == VS_BOTH)
    00521         {
    00522             iterations = 2;
    00523             vInc = vStep;
    00524             v = 0; // Start with front
    00525         }
    00526         else
    00527         {
    00528             iterations = 1;
    00529             if (mVSide == VS_FRONT)
    00530             {
    00531                 vInc = vStep;
    00532                 v = 0;
    00533             }
    00534             else
    00535             {
    00536                 vInc = -vStep;
    00537                 v = mMeshHeight - 1;
    00538             }
    00539         }
    00540
    00541         // Calc num indexes
    00542         mCurrIndexCount = (currWidth - 1) * (currHeight - 1) * 6 * iterations;
    00543
    00544         size_t v1, v2, v3;
    00545         // Lock just the section of the buffer we need
    00546         unsigned short* p16;
    00547         unsigned int* p32;
    00548         if (use32bitindexes)
    00549         {
    00550             p32 = static_cast<unsigned int*>(
    00551                 mIndexBuffer->lock(
    00552                     mIndexOffset * sizeof(unsigned int),
    00553                     mRequiredIndexCount * sizeof(unsigned int),
    00554                     HardwareBuffer::HBL_NO_OVERWRITE));
    00555         }
    00556         else
    00557         {
    00558             p16 = static_cast<unsigned short*>(
    00559                 mIndexBuffer->lock(
    00560                     mIndexOffset * sizeof(unsigned short),
    00561                     mRequiredIndexCount * sizeof(unsigned short),
    00562                     HardwareBuffer::HBL_NO_OVERWRITE));
    00563         }
    00564
    00565         while (iterations--)
    00566         {
    00567             // Make tris in a zigzag pattern (compatible with strips)
    00568             u = 0;
    00569             uInc = uStep; // Start with moving +u
    00570
    00571             vCount = currHeight - 1;
    00572             while (vCount--)
    00573             {
    00574                 uCount = currWidth - 1;
    00575                 while (uCount--)
    00576                 {
    00577                     // First Tri in cell
    00578                     // -----------------
    00579                     v1 = ((v + vInc) * mMeshWidth) + u;
    00580                     v2 = (v * mMeshWidth) + u;
    00581                     v3 = ((v + vInc) * mMeshWidth) + (u + uInc);
    00582                     // Output indexes
    00583                     if (use32bitindexes)
    00584                     {
    00585                         *p32++ = static_cast<unsigned int>(v1);
    00586                         *p32++ = static_cast<unsigned int>(v2);
    00587                         *p32++ = static_cast<unsigned int>(v3);
    00588                     }
    00589                     else
    00590                     {
    00591                         *p16++ = static_cast<unsigned short>(v1);
    00592                         *p16++ = static_cast<unsigned short>(v2);
    00593                         *p16++ = static_cast<unsigned short>(v3);
    00594                     }
    00595                     // Second Tri in cell
    00596                     // ------------------
    00597                     v1 = ((v + vInc) * mMeshWidth) + (u + uInc);
    00598                     v2 = (v * mMeshWidth) + u;
    00599                     v3 = (v * mMeshWidth) + (u + uInc);
    00600                     // Output indexes
    00601                     if (use32bitindexes)
    00602                     {
    00603                         *p32++ = static_cast<unsigned int>(v1);
    00604                         *p32++ = static_cast<unsigned int>(v2);
    00605                         *p32++ = static_cast<unsigned int>(v3);
    00606                     }
    00607                     else
    00608                     {
    00609                         *p16++ = static_cast<unsigned short>(v1);
    00610                         *p16++ = static_cast<unsigned short>(v2);
    00611                         *p16++ = static_cast<unsigned short>(v3);
    00612                     }
    00613
    00614                     // Next column
    00615                     u += uInc;
    00616                 }
    00617                 // Next row
    00618                 v += vInc;
    00619                 u = 0;
    00620
    00621
    00622             }
    00623
    00624             // Reverse vInc for double sided
    00625             v = mMeshHeight - 1;
    00626             vInc = -vInc;
    00627
    00628         }
    00629
    00630         mIndexBuffer->unlock();
    00631
    00632
    00633     }
    00634     //-----------------------------------------------------------------------
    00635     void PatchSurface::interpolateVertexData(void* lockedBuffer, size_t leftIdx, size_t rightIdx, size_t destIdx)
    00636     {
    00637         size_t vertexSize = mDeclaration->getVertexSize(0);
    00638         const VertexElement* elemPos = mDeclaration->findElementBySemantic(VES_POSITION);
    00639         const VertexElement* elemNorm = mDeclaration->findElementBySemantic(VES_NORMAL);
    00640         const VertexElement* elemDiffuse = mDeclaration->findElementBySemantic(VES_DIFFUSE);
    00641         const VertexElement* elemTex0 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
    00642         const VertexElement* elemTex1 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);
    00643
    00644         Real *pDestReal, *pLeftReal, *pRightReal;
    00645         unsigned char *pDestChar, *pLeftChar, *pRightChar;
    00646         unsigned char *pDest, *pLeft, *pRight;
    00647
    00648         // Set up pointers & interpolate
    00649         pDest = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * destIdx);
    00650         pLeft = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * leftIdx);
    00651         pRight = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * rightIdx);
    00652
    00653         // Position
    00654         elemPos->baseVertexPointerToElement(pDest, &pDestReal);
    00655         elemPos->baseVertexPointerToElement(pLeft, &pLeftReal);
    00656         elemPos->baseVertexPointerToElement(pRight, &pRightReal);
    00657
    00658         *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5;
    00659         *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5;
    00660         *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5;
    00661
    00662         if (elemNorm)
    00663         {
    00664             elemNorm->baseVertexPointerToElement(pDest, &pDestReal);
    00665             elemNorm->baseVertexPointerToElement(pLeft, &pLeftReal);
    00666             elemNorm->baseVertexPointerToElement(pRight, &pRightReal);
    00667             Vector3 norm;
    00668             norm.x = (*pLeftReal++ + *pRightReal++) * 0.5;
    00669             norm.y = (*pLeftReal++ + *pRightReal++) * 0.5;
    00670             norm.z = (*pLeftReal++ + *pRightReal++) * 0.5;
    00671             norm.normalise();
    00672
    00673             *pDestReal++ = norm.x;
    00674             *pDestReal++ = norm.y;
    00675             *pDestReal++ = norm.z;
    00676         }
    00677         if (elemDiffuse)
    00678         {
    00679             // Blend each byte individually
    00680             elemDiffuse->baseVertexPointerToElement(pDest, &pDestChar);
    00681             elemDiffuse->baseVertexPointerToElement(pLeft, &pLeftChar);
    00682             elemDiffuse->baseVertexPointerToElement(pRight, &pRightChar);
    00683             // 4 bytes to RGBA
    00684             *pDestChar++ = ((*pLeftChar++) + (*pRightChar++)) * 0.5;
    00685             *pDestChar++ = ((*pLeftChar++) + (*pRightChar++)) * 0.5;
    00686             *pDestChar++ = ((*pLeftChar++) + (*pRightChar++)) * 0.5;
    00687             *pDestChar++ = ((*pLeftChar++) + (*pRightChar++)) * 0.5;
    00688         }
    00689         if (elemTex0)
    00690         {
    00691             elemTex0->baseVertexPointerToElement(pDest, &pDestReal);
    00692             elemTex0->baseVertexPointerToElement(pLeft, &pLeftReal);
    00693             elemTex0->baseVertexPointerToElement(pRight, &pRightReal);
    00694
    00695             for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex0->getType()); ++dim)
    00696                 *pDestReal++ = ((*pLeftReal++) + (*pRightReal++)) * 0.5;
    00697         }
    00698         if (elemTex1)
    00699         {
    00700             elemTex1->baseVertexPointerToElement(pDest, &pDestReal);
    00701             elemTex1->baseVertexPointerToElement(pLeft, &pLeftReal);
    00702             elemTex1->baseVertexPointerToElement(pRight, &pRightReal);
    00703
    00704             for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex1->getType()); ++dim)
    00705                 *pDestReal++ = ((*pLeftReal++) + (*pRightReal++)) * 0.5;
    00706         }
    00707     }
    00708
    00709 }
    00710

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