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