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

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