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