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