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