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

OgreMeshManager.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 "OgreMeshManager.h"
00028 
00029 #include "OgreMesh.h"
00030 #include "OgreSubMesh.h"
00031 #include "OgreMatrix4.h"
00032 #include "OgreMatrix3.h"
00033 #include "OgreVector3.h"
00034 #include "OgrePlane.h"
00035 #include "OgreHardwareBufferManager.h"
00036 #include "OgrePatchSurface.h"
00037 #include "OgreException.h"
00038 
00039 namespace Ogre
00040 {
00041     #define PI 3.1415926535897932384626433832795
00042 
00043     //-----------------------------------------------------------------------
00044     template<> MeshManager* Singleton<MeshManager>::ms_Singleton = 0;
00045     //-----------------------------------------------------------------------
00046     MeshManager::MeshManager()
00047     {
00048 
00049 
00050     }
00051     //-----------------------------------------------------------------------
00052     void MeshManager::_initialise(void)
00053     {
00054         // Create prefab objects
00055         createPrefabPlane();
00056 
00057 
00058     }
00059     //-----------------------------------------------------------------------
00060     Resource* MeshManager::create( const String& name)
00061     {
00062         return new Mesh(name);
00063     }
00064     //-----------------------------------------------------------------------
00065     Mesh* MeshManager::load( const String& filename, 
00066         HardwareBuffer::Usage vertexBufferUsage, 
00067         HardwareBuffer::Usage indexBufferUsage, 
00068         bool vertexBufferSysMem, bool indexBufferSysMem,
00069         int priority)
00070     {
00071         Mesh* pMesh = (Mesh*)(getByName(filename));
00072         if (!pMesh)
00073         {
00074             pMesh = (Mesh*)create(filename);
00075             pMesh->setVertexBufferPolicy(vertexBufferUsage, vertexBufferSysMem);
00076             pMesh->setIndexBufferPolicy(indexBufferUsage, indexBufferSysMem);
00077             ResourceManager::load(pMesh, priority);
00078             //pMesh->_registerMaterials();
00079         }
00080         return pMesh;
00081 
00082     }
00083     //-----------------------------------------------------------------------
00084     Mesh* MeshManager::createManual( const String& name)
00085     {
00086         Mesh* pMesh = (Mesh*)(getByName(name));
00087         if (!pMesh)
00088         {
00089             pMesh = (Mesh*)create(name);
00090             pMesh->setManuallyDefined(true);
00091             ResourceManager::load(pMesh,0);
00092         }
00093 
00094         return pMesh;
00095     }
00096     //-----------------------------------------------------------------------
00097     Mesh* MeshManager::createPlane( const String& name, const Plane& plane, Real width, Real height, int xsegments, int ysegments,
00098         bool normals, int numTexCoordSets, Real xTile, Real yTile, const Vector3& upVector,
00099         HardwareBuffer::Usage vertexBufferUsage, HardwareBuffer::Usage indexBufferUsage,
00100         bool vertexShadowBuffer, bool indexShadowBuffer)
00101     {
00102         int i;
00103         Mesh* pMesh = createManual(name);
00104         SubMesh *pSub = pMesh->createSubMesh();
00105 
00106         // Set up vertex data
00107         // Use a single shared buffer
00108         pMesh->sharedVertexData = new VertexData();
00109         VertexData* vertexData = pMesh->sharedVertexData;
00110         // Set up Vertex Declaration
00111         VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
00112         size_t currOffset = 0;
00113         // We always need positions
00114         vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
00115         currOffset += VertexElement::getTypeSize(VET_FLOAT3);
00116         // Optional normals
00117         if(normals)
00118         {
00119             vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
00120             currOffset += VertexElement::getTypeSize(VET_FLOAT3);
00121         }
00122 
00123         for (i = 0; i < numTexCoordSets; ++i)
00124         {
00125             // Assumes 2D texture coords
00126             vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i);
00127             currOffset += VertexElement::getTypeSize(VET_FLOAT2);
00128         }
00129 
00130         vertexData->vertexCount = (xsegments + 1) * (ysegments + 1);
00131 
00132         // Allocate vertex buffer
00133         HardwareVertexBufferSharedPtr vbuf = 
00134             HardwareBufferManager::getSingleton().
00135             createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount,
00136             vertexBufferUsage, vertexShadowBuffer);
00137 
00138         // Set up the binding (one source only)
00139         VertexBufferBinding* binding = vertexData->vertexBufferBinding;
00140         binding->setBinding(0, vbuf);
00141 
00142         // Work out the transform required
00143         // Default orientation of plane is normal along +z, distance 0
00144         Matrix4 xlate, xform, rot;
00145         Matrix3 rot3;
00146         xlate = rot = Matrix4::IDENTITY;
00147         // Determine axes
00148         Vector3 zAxis, yAxis, xAxis;
00149         zAxis = plane.normal;
00150         zAxis.normalise();
00151         yAxis = upVector;
00152         yAxis.normalise();
00153         xAxis = yAxis.crossProduct(zAxis);
00154         if (xAxis.length() == 0)
00155         {
00156             //upVector must be wrong
00157             Except(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.",
00158                 "MeshManager::createPlane");
00159         }
00160 
00161         rot3.FromAxes(xAxis, yAxis, zAxis);
00162         rot = rot3;
00163 
00164         // Set up standard xform from origin
00165         xlate.setTrans(plane.normal * -plane.d);
00166 
00167         // concatenate
00168         xform = xlate * rot;
00169 
00170         // Generate vertex data
00171         // Lock the whole buffer
00172         Real* pReal = static_cast<Real*>(
00173             vbuf->lock(HardwareBuffer::HBL_DISCARD) );
00174         Real xSpace = width / xsegments;
00175         Real ySpace = height / ysegments;
00176         Real halfWidth = width / 2;
00177         Real halfHeight = height / 2;
00178         Real xTex = (1.0f * xTile) / xsegments;
00179         Real yTex = (1.0f * yTile) / ysegments;
00180         Vector3 vec;
00181         Vector3 min, max;
00182         Real maxSquaredLength;
00183         bool firstTime = true;
00184 
00185         for (int y = 0; y < ysegments + 1; ++y)
00186         {
00187             for (int x = 0; x < xsegments + 1; ++x)
00188             {
00189                 // Work out centered on origin
00190                 vec.x = (x * xSpace) - halfWidth;
00191                 vec.y = (y * ySpace) - halfHeight;
00192                 vec.z = 0.0f;
00193                 // Transform by orientation and distance
00194                 vec = xform * vec;
00195                 // Assign to geometry
00196                 *pReal++ = vec.x;
00197                 *pReal++ = vec.y;
00198                 *pReal++ = vec.z;
00199 
00200                 // Build bounds as we go
00201                 if (firstTime)
00202                 {
00203                     min = vec;
00204                     max = vec;
00205                     maxSquaredLength = vec.squaredLength();
00206                     firstTime = false;
00207                 }
00208                 else
00209                 {
00210                     min.makeFloor(vec);
00211                     max.makeCeil(vec);
00212                     maxSquaredLength = std::max(maxSquaredLength, vec.squaredLength());
00213                 }
00214 
00215                 if (normals)
00216                 {
00217                     // Default normal is along unit Z
00218                     vec = Vector3::UNIT_Z;
00219                     // Rotate
00220                     vec = rot * vec;
00221 
00222                     *pReal++ = vec.x;
00223                     *pReal++ = vec.y;
00224                     *pReal++ = vec.z;
00225                 }
00226 
00227                 for (i = 0; i < numTexCoordSets; ++i)
00228                 {
00229                     *pReal++ = x * xTex;
00230                     *pReal++ = 1 - (y * yTex);
00231                 }
00232 
00233 
00234             } // x
00235         } // y
00236 
00237         // Unlock
00238         vbuf->unlock();
00239         // Generate face list
00240         pSub->useSharedVertices = true;
00241         tesselate2DMesh(pSub, xsegments + 1, ysegments + 1, false, indexBufferUsage, indexShadowBuffer);
00242 
00243         //pMesh->_updateBounds();
00244         pMesh->_setBounds(AxisAlignedBox(min, max));
00245         pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredLength));
00246         return pMesh;
00247     }
00248     
00249     //-----------------------------------------------------------------------
00250     Mesh* MeshManager::createCurvedPlane( const String& name, const Plane& plane, Real width, Real height, Real bow, int xsegments, int ysegments,
00251         bool normals, int numTexCoordSets, Real xTile, Real yTile, const Vector3& upVector,
00252             HardwareBuffer::Usage vertexBufferUsage, HardwareBuffer::Usage indexBufferUsage,
00253             bool vertexShadowBuffer, bool indexShadowBuffer)
00254     {
00255         int i;
00256         Mesh* pMesh = createManual(name);
00257         SubMesh *pSub = pMesh->createSubMesh();
00258 
00259         // Set options
00260         pMesh->sharedVertexData = new VertexData();
00261         pMesh->sharedVertexData->vertexStart = 0;
00262         VertexBufferBinding* bind = pMesh->sharedVertexData->vertexBufferBinding;
00263         VertexDeclaration* decl = pMesh->sharedVertexData->vertexDeclaration;
00264 
00265         pMesh->sharedVertexData->vertexCount = (xsegments + 1) * (ysegments + 1);
00266 
00267         size_t offset = 0;
00268         decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
00269         offset += VertexElement::getTypeSize(VET_FLOAT3);
00270         if (normals)
00271         {
00272             decl->addElement(0, 0, VET_FLOAT3, VES_NORMAL);
00273             offset += VertexElement::getTypeSize(VET_FLOAT3);
00274         }
00275 
00276         for (i = 0; i < numTexCoordSets; ++i)
00277         {
00278             decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i);
00279             offset += VertexElement::getTypeSize(VET_FLOAT2);
00280         }
00281 
00282 
00283         // Allocate memory
00284         HardwareVertexBufferSharedPtr vbuf = 
00285             HardwareBufferManager::getSingleton().createVertexBuffer(
00286                 offset, 
00287                 pMesh->sharedVertexData->vertexCount, 
00288                 vertexBufferUsage, 
00289                 vertexShadowBuffer);
00290         bind->setBinding(0, vbuf);
00291 
00292         // Work out the transform required
00293         // Default orientation of plane is normal along +z, distance 0
00294         Matrix4 xlate, xform, rot;
00295         Matrix3 rot3;
00296         xlate = rot = Matrix4::IDENTITY;
00297         // Determine axes
00298         Vector3 zAxis, yAxis, xAxis;
00299         zAxis = plane.normal;
00300         zAxis.normalise();
00301         yAxis = upVector;
00302         yAxis.normalise();
00303         xAxis = yAxis.crossProduct(zAxis);
00304         if (xAxis.length() == 0)
00305         {
00306             //upVector must be wrong
00307             Except(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.",
00308                 "MeshManager::createPlane");
00309         }
00310 
00311         rot3.FromAxes(xAxis, yAxis, zAxis);
00312         rot = rot3;
00313 
00314         // Set up standard xform from origin
00315         xlate.setTrans(plane.normal * -plane.d);
00316 
00317         // concatenate
00318         xform = xlate * rot;
00319 
00320         // Generate vertex data
00321         Real* pReal = static_cast<Real*>(
00322             vbuf->lock(HardwareBuffer::HBL_DISCARD)); 
00323         Real xSpace = width / xsegments;
00324         Real ySpace = height / ysegments;
00325         Real halfWidth = width / 2;
00326         Real halfHeight = height / 2;
00327         Real xTex = (1.0f * xTile) / xsegments;
00328         Real yTex = (1.0f * yTile) / ysegments;
00329         Vector3 vec;
00330 
00331         Vector3 min, max;
00332         Real maxSqLen;
00333         bool first = true;
00334 
00335         Real diff_x, diff_y, dist;
00336 
00337         for (int y = 0; y < ysegments + 1; ++y)
00338         {
00339             for (int x = 0; x < xsegments + 1; ++x)
00340             {
00341                 // Work out centered on origin
00342                 vec.x = (x * xSpace) - halfWidth;
00343                 vec.y = (y * ySpace) - halfHeight;
00344 
00345                 // Here's where curved plane is different from standard plane.  Amazing, I know.
00346                 diff_x = (x - ((xsegments) / 2)) / static_cast<Real>((xsegments));
00347                 diff_y = (y - ((ysegments) / 2)) / static_cast<Real>((ysegments));
00348                 dist = sqrt(diff_x*diff_x + diff_y * diff_y );
00349                 vec.z = (-sin((1-dist) * (PI/2)) * bow) + bow;
00350 
00351                 // Transform by orientation and distance
00352                 vec = xform * vec;
00353                 // Assign to geometry
00354                 *pReal++ = vec.x;
00355                 *pReal++ = vec.y;
00356                 *pReal++ = vec.z;
00357 
00358                 // Record bounds
00359                 if (first)
00360                 {
00361                     min = max = vec;
00362                     maxSqLen = vec.squaredLength();
00363                     first = false;
00364                 }
00365                 else
00366                 {
00367                     min.makeFloor(vec);
00368                     max.makeCeil(vec);
00369                     maxSqLen = std::max(maxSqLen, vec.squaredLength());
00370                 }
00371                 
00372                 if (normals)
00373                 {
00374                     // This part is kinda 'wrong' for curved planes... but curved planes are
00375                     //   very valuable outside sky planes, which don't typically need normals
00376                     //   so I'm not going to mess with it for now. 
00377 
00378                     // Default normal is along unit Z
00379                     vec = Vector3::UNIT_Z;
00380                     // Rotate
00381                     vec = rot * vec;
00382 
00383                     *pReal++ = vec.x;
00384                     *pReal++ = vec.y;
00385                     *pReal++ = vec.z;
00386                 }
00387 
00388                 for (i = 0; i < numTexCoordSets; ++i)
00389                 {
00390                     *pReal++ = x * xTex;
00391                     *pReal++ = 1 - (y * yTex);
00392                 }
00393 
00394             } // x
00395         } // y
00396         vbuf->unlock();
00397 
00398         // Generate face list
00399         tesselate2DMesh(pSub, xsegments + 1, ysegments + 1, 
00400             false, indexBufferUsage, indexShadowBuffer);
00401 
00402         pMesh->_setBounds(AxisAlignedBox(min, max));
00403         pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSqLen));
00404 
00405         return pMesh;
00406     }
00407     //-----------------------------------------------------------------------
00408     Mesh* MeshManager::createCurvedIllusionPlane(
00409         const String& name, const Plane& plane,
00410         Real width, Real height, Real curvature,
00411         int xsegments, int ysegments,
00412         bool normals, int numTexCoordSets,
00413         Real uTile, Real vTile, const Vector3& upVector,
00414         const Quaternion& orientation, 
00415         HardwareBuffer::Usage vertexBufferUsage, 
00416         HardwareBuffer::Usage indexBufferUsage,
00417         bool vertexShadowBuffer, bool indexShadowBuffer)
00418     {
00419         int i;
00420         Mesh* pMesh = createManual(name);
00421         SubMesh *pSub = pMesh->createSubMesh();
00422 
00423         // Set up vertex data
00424         // Use a single shared buffer
00425         pMesh->sharedVertexData = new VertexData();
00426         VertexData* vertexData = pMesh->sharedVertexData;
00427         // Set up Vertex Declaration
00428         VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
00429         size_t currOffset = 0;
00430         // We always need positions
00431         vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
00432         currOffset += VertexElement::getTypeSize(VET_FLOAT3);
00433         // Optional normals
00434         if(normals)
00435         {
00436             vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
00437             currOffset += VertexElement::getTypeSize(VET_FLOAT3);
00438         }
00439 
00440         for (i = 0; i < numTexCoordSets; ++i)
00441         {
00442             // Assumes 2D texture coords
00443             vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i);
00444             currOffset += VertexElement::getTypeSize(VET_FLOAT2);
00445         }
00446 
00447         vertexData->vertexCount = (xsegments + 1) * (ysegments + 1);
00448 
00449         // Allocate vertex buffer
00450         HardwareVertexBufferSharedPtr vbuf = 
00451             HardwareBufferManager::getSingleton().
00452             createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount,
00453             vertexBufferUsage, vertexShadowBuffer);
00454 
00455         // Set up the binding (one source only)
00456         VertexBufferBinding* binding = vertexData->vertexBufferBinding;
00457         binding->setBinding(0, vbuf);
00458 
00459         // Work out the transform required
00460         // Default orientation of plane is normal along +z, distance 0
00461         Matrix4 xlate, xform, rot;
00462         Matrix3 rot3;
00463         xlate = rot = Matrix4::IDENTITY;
00464         // Determine axes
00465         Vector3 zAxis, yAxis, xAxis;
00466         zAxis = plane.normal;
00467         zAxis.normalise();
00468         yAxis = upVector;
00469         yAxis.normalise();
00470         xAxis = yAxis.crossProduct(zAxis);
00471         if (xAxis.length() == 0)
00472         {
00473             //upVector must be wrong
00474             Except(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.",
00475                 "MeshManager::createPlane");
00476         }
00477 
00478         rot3.FromAxes(xAxis, yAxis, zAxis);
00479         rot = rot3;
00480 
00481         // Set up standard xform from origin
00482         xlate.setTrans(plane.normal * -plane.d);
00483 
00484         // concatenate
00485         xform = xlate * rot;
00486 
00487         // Generate vertex data
00488         // Imagine a large sphere with the camera located near the top
00489         // The lower the curvature, the larger the sphere
00490         // Use the angle from viewer to the points on the plane
00491         // Credit to Aftershock for the general approach
00492         Real camPos;      // Camera position relative to sphere center
00493 
00494         // Derive sphere radius
00495         Vector3 vertPos;  // position relative to camera
00496         Real sphDist;      // Distance from camera to sphere along box vertex vector
00497         // Vector3 camToSph; // camera position to sphere
00498         Real sphereRadius;// Sphere radius
00499         // Actual values irrelevant, it's the relation between sphere radius and camera position that's important
00500         const Real SPHERE_RAD = 100.0;
00501         const Real CAM_DIST = 5.0;
00502 
00503         sphereRadius = SPHERE_RAD - curvature;
00504         camPos = sphereRadius - CAM_DIST;
00505 
00506         // Lock the whole buffer
00507         Real* pReal = static_cast<Real*>(
00508             vbuf->lock(HardwareBuffer::HBL_DISCARD) );
00509         Real xSpace = width / xsegments;
00510         Real ySpace = height / ysegments;
00511         Real halfWidth = width / 2;
00512         Real halfHeight = height / 2;
00513         Vector3 vec, norm;
00514         Vector3 min, max;
00515         Real maxSquaredLength;
00516         bool firstTime = true;
00517 
00518         for (int y = 0; y < ysegments + 1; ++y)
00519         {
00520             for (int x = 0; x < xsegments + 1; ++x)
00521             {
00522                 // Work out centered on origin
00523                 vec.x = (x * xSpace) - halfWidth;
00524                 vec.y = (y * ySpace) - halfHeight;
00525                 vec.z = 0.0f;
00526                 // Transform by orientation and distance
00527                 vec = xform * vec;
00528                 // Assign to geometry
00529                 *pReal++ = vec.x;
00530                 *pReal++ = vec.y;
00531                 *pReal++ = vec.z;
00532 
00533                 // Build bounds as we go
00534                 if (firstTime)
00535                 {
00536                     min = vec;
00537                     max = vec;
00538                     maxSquaredLength = vec.squaredLength();
00539                     firstTime = false;
00540                 }
00541                 else
00542                 {
00543                     min.makeFloor(vec);
00544                     max.makeCeil(vec);
00545                     maxSquaredLength = std::max(maxSquaredLength, vec.squaredLength());
00546                 }
00547 
00548                 if (normals)
00549                 {
00550                     // Default normal is along unit Z
00551                     norm = Vector3::UNIT_Z;
00552                     // Rotate
00553                     norm = orientation * norm;
00554 
00555                     *pReal++ = norm.x;
00556                     *pReal++ = norm.y;
00557                     *pReal++ = norm.z;
00558                 }
00559 
00560                 // Generate texture coords
00561                 // Normalise position
00562                 // modify by orientation to return +y up
00563                 vec = orientation.Inverse() * vec;
00564                 vec.normalise();
00565                 // Find distance to sphere
00566                 sphDist = Math::Sqrt(camPos*camPos * (vec.y*vec.y-1.0) + sphereRadius*sphereRadius) - camPos*vec.y;
00567 
00568                 vec.x *= sphDist;
00569                 vec.z *= sphDist;
00570 
00571                 // Use x and y on sphere as texture coordinates, tiled
00572                 Real s = vec.x * (0.01 * uTile);
00573                 Real t = 1 - (vec.z * (0.01 * vTile));
00574                 for (i = 0; i < numTexCoordSets; ++i)
00575                 {
00576                     *pReal++ = s;
00577                     *pReal++ = t;
00578                 }
00579 
00580 
00581             } // x
00582         } // y
00583 
00584         // Unlock
00585         vbuf->unlock();
00586         // Generate face list
00587         pSub->useSharedVertices = true;
00588         tesselate2DMesh(pSub, xsegments + 1, ysegments + 1, false, indexBufferUsage, indexShadowBuffer);
00589 
00590         //pMesh->_updateBounds();
00591         pMesh->_setBounds(AxisAlignedBox(min, max));
00592         pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredLength));
00593         return pMesh;
00594     }
00595 
00596     //-----------------------------------------------------------------------
00597     void MeshManager::tesselate2DMesh(SubMesh* sm, int meshWidth, int meshHeight, 
00598         bool doubleSided, HardwareBuffer::Usage indexBufferUsage, bool indexShadowBuffer)
00599     {
00600         // The mesh is built, just make a list of indexes to spit out the triangles
00601         int vInc, uInc, v, u, iterations;
00602         int vCount, uCount;
00603 
00604         if (doubleSided)
00605         {
00606             iterations = 2;
00607             vInc = 1;
00608             v = 0; // Start with front
00609         }
00610         else
00611         {
00612             iterations = 1;
00613             vInc = 1;
00614             v = 0;
00615         }
00616 
00617         // Allocate memory for faces
00618         // Num faces, width*height*2 (2 tris per square), index count is * 3 on top
00619         sm->indexData->indexCount = (meshWidth-1) * (meshHeight-1) * 2 * iterations * 3;
00620         sm->indexData->indexBuffer = HardwareBufferManager::getSingleton().
00621             createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
00622             sm->indexData->indexCount, indexBufferUsage, indexShadowBuffer);
00623 
00624         int v1, v2, v3;
00625         //bool firstTri = true;
00626         HardwareIndexBufferSharedPtr ibuf = sm->indexData->indexBuffer;
00627         // Lock the whole buffer
00628         unsigned short* pIndexes = static_cast<unsigned short*>(
00629             ibuf->lock(HardwareBuffer::HBL_DISCARD) );
00630 
00631         while (iterations--)
00632         {
00633             // Make tris in a zigzag pattern (compatible with strips)
00634             u = 0;
00635             uInc = 1; // Start with moving +u
00636 
00637             vCount = meshHeight - 1;
00638             while (vCount--)
00639             {
00640                 uCount = meshWidth - 1;
00641                 while (uCount--)
00642                 {
00643                     // First Tri in cell
00644                     // -----------------
00645                     v1 = ((v + vInc) * meshWidth) + u;
00646                     v2 = (v * meshWidth) + u;
00647                     v3 = ((v + vInc) * meshWidth) + (u + uInc);
00648                     // Output indexes
00649                     *pIndexes++ = v1;
00650                     *pIndexes++ = v2;
00651                     *pIndexes++ = v3;
00652                     // Second Tri in cell
00653                     // ------------------
00654                     v1 = ((v + vInc) * meshWidth) + (u + uInc);
00655                     v2 = (v * meshWidth) + u;
00656                     v3 = (v * meshWidth) + (u + uInc);
00657                     // Output indexes
00658                     *pIndexes++ = v1;
00659                     *pIndexes++ = v2;
00660                     *pIndexes++ = v3;
00661 
00662                     // Next column
00663                     u += uInc;
00664                 }
00665                 // Next row
00666                 v += vInc;
00667                 u = 0;
00668 
00669 
00670             }
00671 
00672             // Reverse vInc for double sided
00673             v = meshHeight - 1;
00674             vInc = -vInc;
00675 
00676         }
00677         // Unlock
00678         ibuf->unlock();
00679 
00680     }
00681 
00682     //-----------------------------------------------------------------------
00683     void MeshManager::createPrefabPlane(void)
00684     {
00685         Mesh* msh = (Mesh*)create("Prefab_Plane");
00686         SubMesh* sub = msh->createSubMesh();
00687         Real vertices[32] = {
00688             -100, -100, 0,  // pos
00689             0,0,1,          // normal
00690             0,1,            // texcoord
00691             100, -100, 0,
00692             0,0,1,
00693             1,1,
00694             100,  100, 0,
00695             0,0,1,
00696             1,0,
00697             -100,  100, 0 ,
00698             0,0,1,
00699             0,0 
00700         };
00701         msh->sharedVertexData = new VertexData();
00702         msh->sharedVertexData->vertexCount = 4;
00703         VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration;
00704         VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
00705 
00706         size_t offset = 0;
00707         decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
00708         offset += VertexElement::getTypeSize(VET_FLOAT3);
00709         decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
00710         offset += VertexElement::getTypeSize(VET_FLOAT3);
00711         decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
00712         offset += VertexElement::getTypeSize(VET_FLOAT2);
00713 
00714         HardwareVertexBufferSharedPtr vbuf = 
00715             HardwareBufferManager::getSingleton().createVertexBuffer(
00716                 offset, 4, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
00717         bind->setBinding(0, vbuf);
00718 
00719         vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
00720 
00721         sub->useSharedVertices = true;
00722         HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
00723             createIndexBuffer(
00724                 HardwareIndexBuffer::IT_16BIT, 
00725                 6, 
00726                 HardwareBuffer::HBU_STATIC_WRITE_ONLY);
00727 
00728         unsigned short faces[6] = {0,1,2,
00729                                    0,2,3 };
00730         sub->indexData->indexBuffer = ibuf;
00731         sub->indexData->indexCount = 6;
00732         sub->indexData->indexStart =0;
00733         ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
00734 
00735         msh->_setBounds(AxisAlignedBox(-100,-100,0,100,100,0));
00736         msh->_setBoundingSphereRadius(Math::Sqrt(100*100+100*100));
00737 
00738         mResources[msh->getName()] = msh;
00739     }
00740     //-----------------------------------------------------------------------
00741     MeshManager& MeshManager::getSingleton(void)
00742     {
00743         return Singleton<MeshManager>::getSingleton();
00744     }
00745     //-----------------------------------------------------------------------
00746     PatchMesh* MeshManager::createBezierPatch(const String& name, 
00747             void* controlPointBuffer, VertexDeclaration *declaration, 
00748             size_t width, size_t height,
00749             size_t uMaxSubdivisionLevel, size_t vMaxSubdivisionLevel,
00750             PatchSurface::VisibleSide visibleSide, 
00751             HardwareBuffer::Usage vbUsage, HardwareBuffer::Usage ibUsage,
00752             bool vbUseShadow, bool ibUseShadow)
00753     {
00754 
00755         PatchMesh* pMesh = (PatchMesh*)(getByName(name));
00756         if (pMesh)
00757         {
00758             Except(Exception::ERR_DUPLICATE_ITEM, "A mesh called " + name + 
00759                 " already exists!", "MeshManager::createBezierPatch");
00760         }
00761         pMesh = new PatchMesh(name, controlPointBuffer, declaration, width, height,
00762             uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide, vbUsage, ibUsage,
00763             vbUseShadow, ibUseShadow);
00764         pMesh->setManuallyDefined(true);
00765         ResourceManager::load(pMesh,0);
00766 
00767         return pMesh;
00768     }
00769     //-----------------------------------------------------------------------
00770 
00771 
00772 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:18 2004