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

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:26 2004