| 1 | /* | 
|---|
| 2 | ----------------------------------------------------------------------------- | 
|---|
| 3 | This source file is part of OGRE | 
|---|
| 4 |     (Object-oriented Graphics Rendering Engine) | 
|---|
| 5 | For the latest info, see http://www.ogre3d.org/ | 
|---|
| 6 |  | 
|---|
| 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd | 
|---|
| 8 | Also see acknowledgements in Readme.html | 
|---|
| 9 |  | 
|---|
| 10 | This program is free software; you can redistribute it and/or modify it under | 
|---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software | 
|---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later | 
|---|
| 13 | version. | 
|---|
| 14 |  | 
|---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT | 
|---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
|---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | 
|---|
| 18 |  | 
|---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with | 
|---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple | 
|---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to | 
|---|
| 22 | http://www.gnu.org/copyleft/lesser.txt. | 
|---|
| 23 |  | 
|---|
| 24 | You may alternatively use this source under the terms of a specific version of | 
|---|
| 25 | the OGRE Unrestricted License provided you have obtained such a license from | 
|---|
| 26 | Torus Knot Software Ltd. | 
|---|
| 27 | ----------------------------------------------------------------------------- | 
|---|
| 28 | */ | 
|---|
| 29 | #include "OgreStableHeaders.h" | 
|---|
| 30 |  | 
|---|
| 31 | #include "OgreMeshManager.h" | 
|---|
| 32 |  | 
|---|
| 33 | #include "OgreMesh.h" | 
|---|
| 34 | #include "OgreSubMesh.h" | 
|---|
| 35 | #include "OgreMatrix4.h" | 
|---|
| 36 | #include "OgreMatrix3.h" | 
|---|
| 37 | #include "OgreVector3.h" | 
|---|
| 38 | #include "OgrePlane.h" | 
|---|
| 39 | #include "OgreHardwareBufferManager.h" | 
|---|
| 40 | #include "OgrePatchSurface.h" | 
|---|
| 41 | #include "OgreException.h" | 
|---|
| 42 |  | 
|---|
| 43 | #include "OgrePrefabFactory.h" | 
|---|
| 44 |  | 
|---|
| 45 | namespace Ogre | 
|---|
| 46 | { | 
|---|
| 47 |         #define PI 3.1415926535897932384626433832795 | 
|---|
| 48 |  | 
|---|
| 49 |     //----------------------------------------------------------------------- | 
|---|
| 50 |     template<> MeshManager* Singleton<MeshManager>::ms_Singleton = 0; | 
|---|
| 51 |     MeshManager* MeshManager::getSingletonPtr(void) | 
|---|
| 52 |     { | 
|---|
| 53 |         return ms_Singleton; | 
|---|
| 54 |     } | 
|---|
| 55 |     MeshManager& MeshManager::getSingleton(void) | 
|---|
| 56 |     {   | 
|---|
| 57 |         assert( ms_Singleton );  return ( *ms_Singleton );   | 
|---|
| 58 |     } | 
|---|
| 59 |     //----------------------------------------------------------------------- | 
|---|
| 60 |     MeshManager::MeshManager(): | 
|---|
| 61 |     mBoundsPaddingFactor(0.01) | 
|---|
| 62 |     { | 
|---|
| 63 |         mPrepAllMeshesForShadowVolumes = false; | 
|---|
| 64 |  | 
|---|
| 65 |         mLoadOrder = 350.0f; | 
|---|
| 66 |         mResourceType = "Mesh"; | 
|---|
| 67 |  | 
|---|
| 68 |         ResourceGroupManager::getSingleton()._registerResourceManager(mResourceType, this); | 
|---|
| 69 |  | 
|---|
| 70 |     } | 
|---|
| 71 |     //----------------------------------------------------------------------- | 
|---|
| 72 |     MeshManager::~MeshManager() | 
|---|
| 73 |     { | 
|---|
| 74 |         ResourceGroupManager::getSingleton()._unregisterResourceManager(mResourceType); | 
|---|
| 75 |     } | 
|---|
| 76 |     //----------------------------------------------------------------------- | 
|---|
| 77 |     void MeshManager::_initialise(void) | 
|---|
| 78 |     { | 
|---|
| 79 |         // Create prefab objects | 
|---|
| 80 |         createPrefabPlane(); | 
|---|
| 81 |                 createPrefabCube(); | 
|---|
| 82 |                 createPrefabSphere(); | 
|---|
| 83 |     } | 
|---|
| 84 |     //----------------------------------------------------------------------- | 
|---|
| 85 |     MeshPtr MeshManager::load( const String& filename, const String& groupName,  | 
|---|
| 86 |                 HardwareBuffer::Usage vertexBufferUsage,  | 
|---|
| 87 |                 HardwareBuffer::Usage indexBufferUsage,  | 
|---|
| 88 |                 bool vertexBufferShadowed, bool indexBufferShadowed) | 
|---|
| 89 |     { | 
|---|
| 90 |         ResourceCreateOrRetrieveResult res = createOrRetrieve(filename, groupName); | 
|---|
| 91 |                 MeshPtr pMesh = res.first; | 
|---|
| 92 |                 // Was it created? | 
|---|
| 93 |         if (res.second) | 
|---|
| 94 |         { | 
|---|
| 95 |                         pMesh->setVertexBufferPolicy(vertexBufferUsage, vertexBufferShadowed); | 
|---|
| 96 |                         pMesh->setIndexBufferPolicy(indexBufferUsage, indexBufferShadowed); | 
|---|
| 97 |         } | 
|---|
| 98 |                 pMesh->load(); | 
|---|
| 99 |         return pMesh; | 
|---|
| 100 |  | 
|---|
| 101 |     } | 
|---|
| 102 |     //----------------------------------------------------------------------- | 
|---|
| 103 |     MeshPtr MeshManager::createManual( const String& name, const String& groupName,  | 
|---|
| 104 |         ManualResourceLoader* loader) | 
|---|
| 105 |     { | 
|---|
| 106 |                 // Don't try to get existing, create should fail if already exists | 
|---|
| 107 |         return create(name, groupName, true, loader); | 
|---|
| 108 |     } | 
|---|
| 109 |     //----------------------------------------------------------------------- | 
|---|
| 110 |     MeshPtr MeshManager::createPlane( const String& name, const String& groupName, | 
|---|
| 111 |         const Plane& plane, Real width, Real height, int xsegments, int ysegments, | 
|---|
| 112 |         bool normals, int numTexCoordSets, Real xTile, Real yTile, const Vector3& upVector, | 
|---|
| 113 |                 HardwareBuffer::Usage vertexBufferUsage, HardwareBuffer::Usage indexBufferUsage, | 
|---|
| 114 |                 bool vertexShadowBuffer, bool indexShadowBuffer) | 
|---|
| 115 |     { | 
|---|
| 116 |         // Create manual mesh which calls back self to load | 
|---|
| 117 |         MeshPtr pMesh = createManual(name, groupName, this); | 
|---|
| 118 |                 // Planes can never be manifold | 
|---|
| 119 |                 pMesh->setAutoBuildEdgeLists(false); | 
|---|
| 120 |         // store parameters | 
|---|
| 121 |         MeshBuildParams params; | 
|---|
| 122 |         params.type = MBT_PLANE; | 
|---|
| 123 |         params.plane = plane; | 
|---|
| 124 |         params.width = width; | 
|---|
| 125 |         params.height = height; | 
|---|
| 126 |         params.xsegments = xsegments; | 
|---|
| 127 |         params.ysegments = ysegments; | 
|---|
| 128 |         params.normals = normals; | 
|---|
| 129 |         params.numTexCoordSets = numTexCoordSets; | 
|---|
| 130 |         params.xTile = xTile; | 
|---|
| 131 |         params.yTile = yTile; | 
|---|
| 132 |         params.upVector = upVector; | 
|---|
| 133 |         params.vertexBufferUsage = vertexBufferUsage; | 
|---|
| 134 |         params.indexBufferUsage = indexBufferUsage; | 
|---|
| 135 |         params.vertexShadowBuffer = vertexShadowBuffer; | 
|---|
| 136 |         params.indexShadowBuffer = indexShadowBuffer; | 
|---|
| 137 |         mMeshBuildParams[pMesh.getPointer()] = params; | 
|---|
| 138 |  | 
|---|
| 139 |         // to preserve previous behaviour, load immediately | 
|---|
| 140 |         pMesh->load(); | 
|---|
| 141 |  | 
|---|
| 142 |         return pMesh; | 
|---|
| 143 |     } | 
|---|
| 144 |          | 
|---|
| 145 |         //----------------------------------------------------------------------- | 
|---|
| 146 |         MeshPtr MeshManager::createCurvedPlane( const String& name, const String& groupName,  | 
|---|
| 147 |         const Plane& plane, Real width, Real height, Real bow, int xsegments, int ysegments, | 
|---|
| 148 |         bool normals, int numTexCoordSets, Real xTile, Real yTile, const Vector3& upVector, | 
|---|
| 149 |                         HardwareBuffer::Usage vertexBufferUsage, HardwareBuffer::Usage indexBufferUsage, | 
|---|
| 150 |                         bool vertexShadowBuffer, bool indexShadowBuffer) | 
|---|
| 151 |     { | 
|---|
| 152 |         // Create manual mesh which calls back self to load | 
|---|
| 153 |         MeshPtr pMesh = createManual(name, groupName, this); | 
|---|
| 154 |                 // Planes can never be manifold | 
|---|
| 155 |                 pMesh->setAutoBuildEdgeLists(false); | 
|---|
| 156 |         // store parameters | 
|---|
| 157 |         MeshBuildParams params; | 
|---|
| 158 |         params.type = MBT_CURVED_PLANE; | 
|---|
| 159 |         params.plane = plane; | 
|---|
| 160 |         params.width = width; | 
|---|
| 161 |         params.height = height; | 
|---|
| 162 |         params.curvature = bow; | 
|---|
| 163 |         params.xsegments = xsegments; | 
|---|
| 164 |         params.ysegments = ysegments; | 
|---|
| 165 |         params.normals = normals; | 
|---|
| 166 |         params.numTexCoordSets = numTexCoordSets; | 
|---|
| 167 |         params.xTile = xTile; | 
|---|
| 168 |         params.yTile = yTile; | 
|---|
| 169 |         params.upVector = upVector; | 
|---|
| 170 |         params.vertexBufferUsage = vertexBufferUsage; | 
|---|
| 171 |         params.indexBufferUsage = indexBufferUsage; | 
|---|
| 172 |         params.vertexShadowBuffer = vertexShadowBuffer; | 
|---|
| 173 |         params.indexShadowBuffer = indexShadowBuffer; | 
|---|
| 174 |         mMeshBuildParams[pMesh.getPointer()] = params; | 
|---|
| 175 |  | 
|---|
| 176 |         // to preserve previous behaviour, load immediately | 
|---|
| 177 |         pMesh->load(); | 
|---|
| 178 |  | 
|---|
| 179 |         return pMesh; | 
|---|
| 180 |  | 
|---|
| 181 |     } | 
|---|
| 182 |     //----------------------------------------------------------------------- | 
|---|
| 183 |         MeshPtr MeshManager::createCurvedIllusionPlane( | 
|---|
| 184 |         const String& name, const String& groupName, const Plane& plane, | 
|---|
| 185 |         Real width, Real height, Real curvature, | 
|---|
| 186 |         int xsegments, int ysegments, | 
|---|
| 187 |         bool normals, int numTexCoordSets, | 
|---|
| 188 |         Real uTile, Real vTile, const Vector3& upVector, | 
|---|
| 189 |                 const Quaternion& orientation,  | 
|---|
| 190 |         HardwareBuffer::Usage vertexBufferUsage,  | 
|---|
| 191 |                 HardwareBuffer::Usage indexBufferUsage, | 
|---|
| 192 |                 bool vertexShadowBuffer, bool indexShadowBuffer, | 
|---|
| 193 |         int ySegmentsToKeep) | 
|---|
| 194 |         { | 
|---|
| 195 |         // Create manual mesh which calls back self to load | 
|---|
| 196 |         MeshPtr pMesh = createManual(name, groupName, this); | 
|---|
| 197 |                 // Planes can never be manifold | 
|---|
| 198 |                 pMesh->setAutoBuildEdgeLists(false); | 
|---|
| 199 |         // store parameters | 
|---|
| 200 |         MeshBuildParams params; | 
|---|
| 201 |         params.type = MBT_CURVED_ILLUSION_PLANE; | 
|---|
| 202 |         params.plane = plane; | 
|---|
| 203 |         params.width = width; | 
|---|
| 204 |         params.height = height; | 
|---|
| 205 |         params.curvature = curvature; | 
|---|
| 206 |         params.xsegments = xsegments; | 
|---|
| 207 |         params.ysegments = ysegments; | 
|---|
| 208 |         params.normals = normals; | 
|---|
| 209 |         params.numTexCoordSets = numTexCoordSets; | 
|---|
| 210 |         params.xTile = uTile; | 
|---|
| 211 |         params.yTile = vTile; | 
|---|
| 212 |         params.upVector = upVector; | 
|---|
| 213 |         params.orientation = orientation; | 
|---|
| 214 |         params.vertexBufferUsage = vertexBufferUsage; | 
|---|
| 215 |         params.indexBufferUsage = indexBufferUsage; | 
|---|
| 216 |         params.vertexShadowBuffer = vertexShadowBuffer; | 
|---|
| 217 |         params.indexShadowBuffer = indexShadowBuffer; | 
|---|
| 218 |         params.ySegmentsToKeep = ySegmentsToKeep; | 
|---|
| 219 |         mMeshBuildParams[pMesh.getPointer()] = params; | 
|---|
| 220 |  | 
|---|
| 221 |         // to preserve previous behaviour, load immediately | 
|---|
| 222 |         pMesh->load(); | 
|---|
| 223 |  | 
|---|
| 224 |         return pMesh; | 
|---|
| 225 |         } | 
|---|
| 226 |  | 
|---|
| 227 |     //----------------------------------------------------------------------- | 
|---|
| 228 |     void MeshManager::tesselate2DMesh(SubMesh* sm, int meshWidth, int meshHeight,  | 
|---|
| 229 |                 bool doubleSided, HardwareBuffer::Usage indexBufferUsage, bool indexShadowBuffer) | 
|---|
| 230 |     { | 
|---|
| 231 |         // The mesh is built, just make a list of indexes to spit out the triangles | 
|---|
| 232 |         int vInc, uInc, v, u, iterations; | 
|---|
| 233 |         int vCount, uCount; | 
|---|
| 234 |  | 
|---|
| 235 |         if (doubleSided) | 
|---|
| 236 |         { | 
|---|
| 237 |             iterations = 2; | 
|---|
| 238 |             vInc = 1; | 
|---|
| 239 |             v = 0; // Start with front | 
|---|
| 240 |         } | 
|---|
| 241 |         else | 
|---|
| 242 |         { | 
|---|
| 243 |             iterations = 1; | 
|---|
| 244 |             vInc = 1; | 
|---|
| 245 |             v = 0; | 
|---|
| 246 |         } | 
|---|
| 247 |  | 
|---|
| 248 |         // Allocate memory for faces | 
|---|
| 249 |         // Num faces, width*height*2 (2 tris per square), index count is * 3 on top | 
|---|
| 250 |         sm->indexData->indexCount = (meshWidth-1) * (meshHeight-1) * 2 * iterations * 3; | 
|---|
| 251 |                 sm->indexData->indexBuffer = HardwareBufferManager::getSingleton(). | 
|---|
| 252 |                         createIndexBuffer(HardwareIndexBuffer::IT_16BIT, | 
|---|
| 253 |                         sm->indexData->indexCount, indexBufferUsage, indexShadowBuffer); | 
|---|
| 254 |  | 
|---|
| 255 |         int v1, v2, v3; | 
|---|
| 256 |         //bool firstTri = true; | 
|---|
| 257 |                 HardwareIndexBufferSharedPtr ibuf = sm->indexData->indexBuffer; | 
|---|
| 258 |                 // Lock the whole buffer | 
|---|
| 259 |                 unsigned short* pIndexes = static_cast<unsigned short*>( | 
|---|
| 260 |                         ibuf->lock(HardwareBuffer::HBL_DISCARD) ); | 
|---|
| 261 |  | 
|---|
| 262 |         while (iterations--) | 
|---|
| 263 |         { | 
|---|
| 264 |             // Make tris in a zigzag pattern (compatible with strips) | 
|---|
| 265 |             u = 0; | 
|---|
| 266 |             uInc = 1; // Start with moving +u | 
|---|
| 267 |  | 
|---|
| 268 |             vCount = meshHeight - 1; | 
|---|
| 269 |             while (vCount--) | 
|---|
| 270 |             { | 
|---|
| 271 |                 uCount = meshWidth - 1; | 
|---|
| 272 |                 while (uCount--) | 
|---|
| 273 |                 { | 
|---|
| 274 |                     // First Tri in cell | 
|---|
| 275 |                     // ----------------- | 
|---|
| 276 |                     v1 = ((v + vInc) * meshWidth) + u; | 
|---|
| 277 |                     v2 = (v * meshWidth) + u; | 
|---|
| 278 |                     v3 = ((v + vInc) * meshWidth) + (u + uInc); | 
|---|
| 279 |                     // Output indexes | 
|---|
| 280 |                     *pIndexes++ = v1; | 
|---|
| 281 |                     *pIndexes++ = v2; | 
|---|
| 282 |                     *pIndexes++ = v3; | 
|---|
| 283 |                     // Second Tri in cell | 
|---|
| 284 |                     // ------------------ | 
|---|
| 285 |                     v1 = ((v + vInc) * meshWidth) + (u + uInc); | 
|---|
| 286 |                     v2 = (v * meshWidth) + u; | 
|---|
| 287 |                     v3 = (v * meshWidth) + (u + uInc); | 
|---|
| 288 |                     // Output indexes | 
|---|
| 289 |                     *pIndexes++ = v1; | 
|---|
| 290 |                     *pIndexes++ = v2; | 
|---|
| 291 |                     *pIndexes++ = v3; | 
|---|
| 292 |  | 
|---|
| 293 |                     // Next column | 
|---|
| 294 |                     u += uInc; | 
|---|
| 295 |                 } | 
|---|
| 296 |                 // Next row | 
|---|
| 297 |                 v += vInc; | 
|---|
| 298 |                 u = 0; | 
|---|
| 299 |  | 
|---|
| 300 |  | 
|---|
| 301 |             } | 
|---|
| 302 |  | 
|---|
| 303 |             // Reverse vInc for double sided | 
|---|
| 304 |             v = meshHeight - 1; | 
|---|
| 305 |             vInc = -vInc; | 
|---|
| 306 |  | 
|---|
| 307 |         } | 
|---|
| 308 |                 // Unlock | 
|---|
| 309 |                 ibuf->unlock(); | 
|---|
| 310 |  | 
|---|
| 311 |     } | 
|---|
| 312 |  | 
|---|
| 313 |     //----------------------------------------------------------------------- | 
|---|
| 314 |     void MeshManager::createPrefabPlane(void) | 
|---|
| 315 |     { | 
|---|
| 316 |         MeshPtr msh = create( | 
|---|
| 317 |             "Prefab_Plane",  | 
|---|
| 318 |             ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,  | 
|---|
| 319 |             true, // manually loaded | 
|---|
| 320 |             this); | 
|---|
| 321 |                 // Planes can never be manifold | 
|---|
| 322 |                 msh->setAutoBuildEdgeLists(false); | 
|---|
| 323 |         // to preserve previous behaviour, load immediately | 
|---|
| 324 |         msh->load(); | 
|---|
| 325 |     } | 
|---|
| 326 |         //----------------------------------------------------------------------- | 
|---|
| 327 |         void MeshManager::createPrefabCube(void) | 
|---|
| 328 |         { | 
|---|
| 329 |                 MeshPtr msh = create( | 
|---|
| 330 |                         "Prefab_Cube",  | 
|---|
| 331 |                         ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,  | 
|---|
| 332 |                         true, // manually loaded | 
|---|
| 333 |                         this); | 
|---|
| 334 |  | 
|---|
| 335 |                 // to preserve previous behaviour, load immediately | 
|---|
| 336 |                 msh->load(); | 
|---|
| 337 |         } | 
|---|
| 338 |  | 
|---|
| 339 |         void MeshManager::createPrefabSphere(void) | 
|---|
| 340 |         { | 
|---|
| 341 |                 MeshPtr msh = create( | 
|---|
| 342 |                         "Prefab_Sphere",  | 
|---|
| 343 |                         ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,  | 
|---|
| 344 |                         true, // manually loaded | 
|---|
| 345 |                         this); | 
|---|
| 346 |  | 
|---|
| 347 |                 // to preserve previous behaviour, load immediately | 
|---|
| 348 |                 msh->load(); | 
|---|
| 349 |         } | 
|---|
| 350 |  | 
|---|
| 351 |     //----------------------------------------------------------------------- | 
|---|
| 352 |         void MeshManager::loadResource(Resource* res) | 
|---|
| 353 |         { | 
|---|
| 354 |                 Mesh* msh = static_cast<Mesh*>(res); | 
|---|
| 355 |  | 
|---|
| 356 |                 // attempt to create a prefab mesh | 
|---|
| 357 |                 bool createdPrefab = PrefabFactory::createPrefab(msh); | 
|---|
| 358 |  | 
|---|
| 359 |                 // the mesh was not a prefab.. | 
|---|
| 360 |                 if(!createdPrefab) | 
|---|
| 361 |                 { | 
|---|
| 362 |                         // Find build parameters | 
|---|
| 363 |                         MeshBuildParamsMap::iterator ibld = mMeshBuildParams.find(res); | 
|---|
| 364 |                         if (ibld == mMeshBuildParams.end()) | 
|---|
| 365 |                         { | 
|---|
| 366 |                                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 367 |                                         "Cannot find build parameters for " + res->getName(), | 
|---|
| 368 |                                         "MeshManager::loadResource"); | 
|---|
| 369 |                         } | 
|---|
| 370 |                         MeshBuildParams& params = ibld->second; | 
|---|
| 371 |  | 
|---|
| 372 |                         switch(params.type) | 
|---|
| 373 |                         { | 
|---|
| 374 |                         case MBT_PLANE: | 
|---|
| 375 |                                 loadManualPlane(msh, params); | 
|---|
| 376 |                                 break; | 
|---|
| 377 |                         case MBT_CURVED_ILLUSION_PLANE: | 
|---|
| 378 |                                 loadManualCurvedIllusionPlane(msh, params); | 
|---|
| 379 |                                 break; | 
|---|
| 380 |                         case MBT_CURVED_PLANE: | 
|---|
| 381 |                                 loadManualCurvedPlane(msh, params); | 
|---|
| 382 |                                 break; | 
|---|
| 383 |                         default: | 
|---|
| 384 |                                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 385 |                                         "Unknown build parameters for " + res->getName(), | 
|---|
| 386 |                                         "MeshManager::loadResource"); | 
|---|
| 387 |                         } | 
|---|
| 388 |                 } | 
|---|
| 389 |         } | 
|---|
| 390 |  | 
|---|
| 391 |     //----------------------------------------------------------------------- | 
|---|
| 392 |     void MeshManager::loadManualPlane(Mesh* pMesh, MeshBuildParams& params) | 
|---|
| 393 |     { | 
|---|
| 394 |         int i; | 
|---|
| 395 |  | 
|---|
| 396 |         SubMesh *pSub = pMesh->createSubMesh(); | 
|---|
| 397 |  | 
|---|
| 398 |         // Set up vertex data | 
|---|
| 399 |         // Use a single shared buffer | 
|---|
| 400 |         pMesh->sharedVertexData = new VertexData(); | 
|---|
| 401 |         VertexData* vertexData = pMesh->sharedVertexData; | 
|---|
| 402 |         // Set up Vertex Declaration | 
|---|
| 403 |         VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; | 
|---|
| 404 |         size_t currOffset = 0; | 
|---|
| 405 |         // We always need positions | 
|---|
| 406 |         vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); | 
|---|
| 407 |         currOffset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 408 |         // Optional normals | 
|---|
| 409 |         if(params.normals) | 
|---|
| 410 |         { | 
|---|
| 411 |             vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); | 
|---|
| 412 |             currOffset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 413 |         } | 
|---|
| 414 |  | 
|---|
| 415 |         for (i = 0; i < params.numTexCoordSets; ++i) | 
|---|
| 416 |         { | 
|---|
| 417 |             // Assumes 2D texture coords | 
|---|
| 418 |             vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i); | 
|---|
| 419 |             currOffset += VertexElement::getTypeSize(VET_FLOAT2); | 
|---|
| 420 |         } | 
|---|
| 421 |  | 
|---|
| 422 |         vertexData->vertexCount = (params.xsegments + 1) * (params.ysegments + 1); | 
|---|
| 423 |  | 
|---|
| 424 |         // Allocate vertex buffer | 
|---|
| 425 |         HardwareVertexBufferSharedPtr vbuf =  | 
|---|
| 426 |             HardwareBufferManager::getSingleton(). | 
|---|
| 427 |             createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, | 
|---|
| 428 |             params.vertexBufferUsage, params.vertexShadowBuffer); | 
|---|
| 429 |  | 
|---|
| 430 |         // Set up the binding (one source only) | 
|---|
| 431 |         VertexBufferBinding* binding = vertexData->vertexBufferBinding; | 
|---|
| 432 |         binding->setBinding(0, vbuf); | 
|---|
| 433 |  | 
|---|
| 434 |         // Work out the transform required | 
|---|
| 435 |         // Default orientation of plane is normal along +z, distance 0 | 
|---|
| 436 |         Matrix4 xlate, xform, rot; | 
|---|
| 437 |         Matrix3 rot3; | 
|---|
| 438 |         xlate = rot = Matrix4::IDENTITY; | 
|---|
| 439 |         // Determine axes | 
|---|
| 440 |         Vector3 zAxis, yAxis, xAxis; | 
|---|
| 441 |         zAxis = params.plane.normal; | 
|---|
| 442 |         zAxis.normalise(); | 
|---|
| 443 |         yAxis = params.upVector; | 
|---|
| 444 |         yAxis.normalise(); | 
|---|
| 445 |         xAxis = yAxis.crossProduct(zAxis); | 
|---|
| 446 |         if (xAxis.length() == 0) | 
|---|
| 447 |         { | 
|---|
| 448 |             //upVector must be wrong | 
|---|
| 449 |             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.", | 
|---|
| 450 |                 "MeshManager::createPlane"); | 
|---|
| 451 |         } | 
|---|
| 452 |  | 
|---|
| 453 |         rot3.FromAxes(xAxis, yAxis, zAxis); | 
|---|
| 454 |         rot = rot3; | 
|---|
| 455 |  | 
|---|
| 456 |         // Set up standard xform from origin | 
|---|
| 457 |         xlate.setTrans(params.plane.normal * -params.plane.d); | 
|---|
| 458 |  | 
|---|
| 459 |         // concatenate | 
|---|
| 460 |         xform = xlate * rot; | 
|---|
| 461 |  | 
|---|
| 462 |         // Generate vertex data | 
|---|
| 463 |         // Lock the whole buffer | 
|---|
| 464 |         float* pReal = static_cast<float*>( | 
|---|
| 465 |             vbuf->lock(HardwareBuffer::HBL_DISCARD) ); | 
|---|
| 466 |         Real xSpace = params.width / params.xsegments; | 
|---|
| 467 |         Real ySpace = params.height / params.ysegments; | 
|---|
| 468 |         Real halfWidth = params.width / 2; | 
|---|
| 469 |         Real halfHeight = params.height / 2; | 
|---|
| 470 |         Real xTex = (1.0f * params.xTile) / params.xsegments; | 
|---|
| 471 |         Real yTex = (1.0f * params.yTile) / params.ysegments; | 
|---|
| 472 |         Vector3 vec; | 
|---|
| 473 |         Vector3 min, max; | 
|---|
| 474 |         Real maxSquaredLength = 0; | 
|---|
| 475 |         bool firstTime = true; | 
|---|
| 476 |  | 
|---|
| 477 |         for (int y = 0; y < params.ysegments + 1; ++y) | 
|---|
| 478 |         { | 
|---|
| 479 |             for (int x = 0; x < params.xsegments + 1; ++x) | 
|---|
| 480 |             { | 
|---|
| 481 |                 // Work out centered on origin | 
|---|
| 482 |                 vec.x = (x * xSpace) - halfWidth; | 
|---|
| 483 |                 vec.y = (y * ySpace) - halfHeight; | 
|---|
| 484 |                 vec.z = 0.0f; | 
|---|
| 485 |                 // Transform by orientation and distance | 
|---|
| 486 |                 vec = xform.transformAffine(vec); | 
|---|
| 487 |                 // Assign to geometry | 
|---|
| 488 |                 *pReal++ = vec.x; | 
|---|
| 489 |                 *pReal++ = vec.y; | 
|---|
| 490 |                 *pReal++ = vec.z; | 
|---|
| 491 |  | 
|---|
| 492 |                 // Build bounds as we go | 
|---|
| 493 |                 if (firstTime) | 
|---|
| 494 |                 { | 
|---|
| 495 |                     min = vec; | 
|---|
| 496 |                     max = vec; | 
|---|
| 497 |                     maxSquaredLength = vec.squaredLength(); | 
|---|
| 498 |                     firstTime = false; | 
|---|
| 499 |                 } | 
|---|
| 500 |                 else | 
|---|
| 501 |                 { | 
|---|
| 502 |                     min.makeFloor(vec); | 
|---|
| 503 |                     max.makeCeil(vec); | 
|---|
| 504 |                     maxSquaredLength = std::max(maxSquaredLength, vec.squaredLength()); | 
|---|
| 505 |                 } | 
|---|
| 506 |  | 
|---|
| 507 |                 if (params.normals) | 
|---|
| 508 |                 { | 
|---|
| 509 |                     // Default normal is along unit Z | 
|---|
| 510 |                     vec = Vector3::UNIT_Z; | 
|---|
| 511 |                     // Rotate | 
|---|
| 512 |                     vec = rot.transformAffine(vec); | 
|---|
| 513 |  | 
|---|
| 514 |                     *pReal++ = vec.x; | 
|---|
| 515 |                     *pReal++ = vec.y; | 
|---|
| 516 |                     *pReal++ = vec.z; | 
|---|
| 517 |                 } | 
|---|
| 518 |  | 
|---|
| 519 |                 for (i = 0; i < params.numTexCoordSets; ++i) | 
|---|
| 520 |                 { | 
|---|
| 521 |                     *pReal++ = x * xTex; | 
|---|
| 522 |                     *pReal++ = 1 - (y * yTex); | 
|---|
| 523 |                 } | 
|---|
| 524 |  | 
|---|
| 525 |  | 
|---|
| 526 |             } // x | 
|---|
| 527 |         } // y | 
|---|
| 528 |  | 
|---|
| 529 |         // Unlock | 
|---|
| 530 |         vbuf->unlock(); | 
|---|
| 531 |         // Generate face list | 
|---|
| 532 |         pSub->useSharedVertices = true; | 
|---|
| 533 |         tesselate2DMesh(pSub, params.xsegments + 1, params.ysegments + 1, false,  | 
|---|
| 534 |             params.indexBufferUsage, params.indexShadowBuffer); | 
|---|
| 535 |  | 
|---|
| 536 |         pMesh->_setBounds(AxisAlignedBox(min, max), true); | 
|---|
| 537 |         pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredLength)); | 
|---|
| 538 |     } | 
|---|
| 539 |     //----------------------------------------------------------------------- | 
|---|
| 540 |     void MeshManager::loadManualCurvedPlane(Mesh* pMesh, MeshBuildParams& params) | 
|---|
| 541 |     { | 
|---|
| 542 |         int i; | 
|---|
| 543 |         SubMesh *pSub = pMesh->createSubMesh(); | 
|---|
| 544 |  | 
|---|
| 545 |         // Set options | 
|---|
| 546 |         pMesh->sharedVertexData = new VertexData(); | 
|---|
| 547 |         pMesh->sharedVertexData->vertexStart = 0; | 
|---|
| 548 |         VertexBufferBinding* bind = pMesh->sharedVertexData->vertexBufferBinding; | 
|---|
| 549 |         VertexDeclaration* decl = pMesh->sharedVertexData->vertexDeclaration; | 
|---|
| 550 |  | 
|---|
| 551 |         pMesh->sharedVertexData->vertexCount = (params.xsegments + 1) * (params.ysegments + 1); | 
|---|
| 552 |  | 
|---|
| 553 |         size_t offset = 0; | 
|---|
| 554 |         decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); | 
|---|
| 555 |         offset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 556 |         if (params.normals) | 
|---|
| 557 |         { | 
|---|
| 558 |             decl->addElement(0, 0, VET_FLOAT3, VES_NORMAL); | 
|---|
| 559 |             offset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 560 |         } | 
|---|
| 561 |  | 
|---|
| 562 |         for (i = 0; i < params.numTexCoordSets; ++i) | 
|---|
| 563 |         { | 
|---|
| 564 |             decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i); | 
|---|
| 565 |             offset += VertexElement::getTypeSize(VET_FLOAT2); | 
|---|
| 566 |         } | 
|---|
| 567 |  | 
|---|
| 568 |  | 
|---|
| 569 |         // Allocate memory | 
|---|
| 570 |         HardwareVertexBufferSharedPtr vbuf =  | 
|---|
| 571 |             HardwareBufferManager::getSingleton().createVertexBuffer( | 
|---|
| 572 |             offset,  | 
|---|
| 573 |             pMesh->sharedVertexData->vertexCount,  | 
|---|
| 574 |             params.vertexBufferUsage,  | 
|---|
| 575 |             params.vertexShadowBuffer); | 
|---|
| 576 |         bind->setBinding(0, vbuf); | 
|---|
| 577 |  | 
|---|
| 578 |         // Work out the transform required | 
|---|
| 579 |         // Default orientation of plane is normal along +z, distance 0 | 
|---|
| 580 |         Matrix4 xlate, xform, rot; | 
|---|
| 581 |         Matrix3 rot3; | 
|---|
| 582 |         xlate = rot = Matrix4::IDENTITY; | 
|---|
| 583 |         // Determine axes | 
|---|
| 584 |         Vector3 zAxis, yAxis, xAxis; | 
|---|
| 585 |         zAxis = params.plane.normal; | 
|---|
| 586 |         zAxis.normalise(); | 
|---|
| 587 |         yAxis = params.upVector; | 
|---|
| 588 |         yAxis.normalise(); | 
|---|
| 589 |         xAxis = yAxis.crossProduct(zAxis); | 
|---|
| 590 |         if (xAxis.length() == 0) | 
|---|
| 591 |         { | 
|---|
| 592 |             //upVector must be wrong | 
|---|
| 593 |             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.", | 
|---|
| 594 |                 "MeshManager::createPlane"); | 
|---|
| 595 |         } | 
|---|
| 596 |  | 
|---|
| 597 |         rot3.FromAxes(xAxis, yAxis, zAxis); | 
|---|
| 598 |         rot = rot3; | 
|---|
| 599 |  | 
|---|
| 600 |         // Set up standard xform from origin | 
|---|
| 601 |         xlate.setTrans(params.plane.normal * -params.plane.d); | 
|---|
| 602 |  | 
|---|
| 603 |         // concatenate | 
|---|
| 604 |         xform = xlate * rot; | 
|---|
| 605 |  | 
|---|
| 606 |         // Generate vertex data | 
|---|
| 607 |         float* pFloat = static_cast<float*>( | 
|---|
| 608 |             vbuf->lock(HardwareBuffer::HBL_DISCARD));  | 
|---|
| 609 |         Real xSpace = params.width / params.xsegments; | 
|---|
| 610 |         Real ySpace = params.height / params.ysegments; | 
|---|
| 611 |         Real halfWidth = params.width / 2; | 
|---|
| 612 |         Real halfHeight = params.height / 2; | 
|---|
| 613 |         Real xTex = (1.0f * params.xTile) / params.xsegments; | 
|---|
| 614 |         Real yTex = (1.0f * params.yTile) / params.ysegments; | 
|---|
| 615 |         Vector3 vec; | 
|---|
| 616 |  | 
|---|
| 617 |         Vector3 min, max; | 
|---|
| 618 |         Real maxSqLen = 0; | 
|---|
| 619 |         bool first = true; | 
|---|
| 620 |  | 
|---|
| 621 |         Real diff_x, diff_y, dist; | 
|---|
| 622 |  | 
|---|
| 623 |         for (int y = 0; y < params.ysegments + 1; ++y) | 
|---|
| 624 |         { | 
|---|
| 625 |             for (int x = 0; x < params.xsegments + 1; ++x) | 
|---|
| 626 |             { | 
|---|
| 627 |                 // Work out centered on origin | 
|---|
| 628 |                 vec.x = (x * xSpace) - halfWidth; | 
|---|
| 629 |                 vec.y = (y * ySpace) - halfHeight; | 
|---|
| 630 |  | 
|---|
| 631 |                 // Here's where curved plane is different from standard plane.  Amazing, I know. | 
|---|
| 632 |                 diff_x = (x - ((params.xsegments) / 2)) / static_cast<Real>((params.xsegments)); | 
|---|
| 633 |                 diff_y = (y - ((params.ysegments) / 2)) / static_cast<Real>((params.ysegments)); | 
|---|
| 634 |                 dist = sqrt(diff_x*diff_x + diff_y * diff_y ); | 
|---|
| 635 |                 vec.z = (-sin((1-dist) * (PI/2)) * params.curvature) + params.curvature; | 
|---|
| 636 |  | 
|---|
| 637 |                 // Transform by orientation and distance | 
|---|
| 638 |                 Vector3 pos = xform.transformAffine(vec); | 
|---|
| 639 |                 // Assign to geometry | 
|---|
| 640 |                 *pFloat++ = pos.x; | 
|---|
| 641 |                 *pFloat++ = pos.y; | 
|---|
| 642 |                 *pFloat++ = pos.z; | 
|---|
| 643 |  | 
|---|
| 644 |                 // Record bounds | 
|---|
| 645 |                 if (first) | 
|---|
| 646 |                 { | 
|---|
| 647 |                     min = max = vec; | 
|---|
| 648 |                     maxSqLen = vec.squaredLength(); | 
|---|
| 649 |                     first = false; | 
|---|
| 650 |                 } | 
|---|
| 651 |                 else | 
|---|
| 652 |                 { | 
|---|
| 653 |                     min.makeFloor(vec); | 
|---|
| 654 |                     max.makeCeil(vec); | 
|---|
| 655 |                     maxSqLen = std::max(maxSqLen, vec.squaredLength()); | 
|---|
| 656 |                 } | 
|---|
| 657 |  | 
|---|
| 658 |                 if (params.normals) | 
|---|
| 659 |                 { | 
|---|
| 660 |                     // This part is kinda 'wrong' for curved planes... but curved planes are | 
|---|
| 661 |                     //   very valuable outside sky planes, which don't typically need normals | 
|---|
| 662 |                     //   so I'm not going to mess with it for now.  | 
|---|
| 663 |  | 
|---|
| 664 |                     // Default normal is along unit Z | 
|---|
| 665 |                     //vec = Vector3::UNIT_Z; | 
|---|
| 666 |                     // Rotate | 
|---|
| 667 |                     vec = rot.transformAffine(vec); | 
|---|
| 668 |                                         vec.normalise(); | 
|---|
| 669 |  | 
|---|
| 670 |                     *pFloat++ = vec.x; | 
|---|
| 671 |                     *pFloat++ = vec.y; | 
|---|
| 672 |                     *pFloat++ = vec.z; | 
|---|
| 673 |                 } | 
|---|
| 674 |  | 
|---|
| 675 |                 for (i = 0; i < params.numTexCoordSets; ++i) | 
|---|
| 676 |                 { | 
|---|
| 677 |                     *pFloat++ = x * xTex; | 
|---|
| 678 |                     *pFloat++ = 1 - (y * yTex); | 
|---|
| 679 |                 } | 
|---|
| 680 |  | 
|---|
| 681 |             } // x | 
|---|
| 682 |         } // y | 
|---|
| 683 |         vbuf->unlock(); | 
|---|
| 684 |  | 
|---|
| 685 |         // Generate face list | 
|---|
| 686 |         tesselate2DMesh(pSub, params.xsegments + 1, params.ysegments + 1,  | 
|---|
| 687 |             false, params.indexBufferUsage, params.indexShadowBuffer); | 
|---|
| 688 |  | 
|---|
| 689 |         pMesh->_setBounds(AxisAlignedBox(min, max), true); | 
|---|
| 690 |         pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSqLen)); | 
|---|
| 691 |  | 
|---|
| 692 |     } | 
|---|
| 693 |     //----------------------------------------------------------------------- | 
|---|
| 694 |     void MeshManager::loadManualCurvedIllusionPlane(Mesh* pMesh, MeshBuildParams& params) | 
|---|
| 695 |     { | 
|---|
| 696 |         int i; | 
|---|
| 697 |         SubMesh *pSub = pMesh->createSubMesh(); | 
|---|
| 698 |  | 
|---|
| 699 |         if (params.ySegmentsToKeep == -1) params.ySegmentsToKeep = params.ysegments; | 
|---|
| 700 |  | 
|---|
| 701 |         // Set up vertex data | 
|---|
| 702 |         // Use a single shared buffer | 
|---|
| 703 |         pMesh->sharedVertexData = new VertexData(); | 
|---|
| 704 |         VertexData* vertexData = pMesh->sharedVertexData; | 
|---|
| 705 |         // Set up Vertex Declaration | 
|---|
| 706 |         VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; | 
|---|
| 707 |         size_t currOffset = 0; | 
|---|
| 708 |         // We always need positions | 
|---|
| 709 |         vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); | 
|---|
| 710 |         currOffset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 711 |         // Optional normals | 
|---|
| 712 |         if(params.normals) | 
|---|
| 713 |         { | 
|---|
| 714 |             vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); | 
|---|
| 715 |             currOffset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 716 |         } | 
|---|
| 717 |  | 
|---|
| 718 |         for (i = 0; i < params.numTexCoordSets; ++i) | 
|---|
| 719 |         { | 
|---|
| 720 |             // Assumes 2D texture coords | 
|---|
| 721 |             vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i); | 
|---|
| 722 |             currOffset += VertexElement::getTypeSize(VET_FLOAT2); | 
|---|
| 723 |         } | 
|---|
| 724 |  | 
|---|
| 725 |         vertexData->vertexCount = (params.xsegments + 1) * (params.ySegmentsToKeep + 1); | 
|---|
| 726 |  | 
|---|
| 727 |         // Allocate vertex buffer | 
|---|
| 728 |         HardwareVertexBufferSharedPtr vbuf =  | 
|---|
| 729 |             HardwareBufferManager::getSingleton(). | 
|---|
| 730 |             createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, | 
|---|
| 731 |             params.vertexBufferUsage, params.vertexShadowBuffer); | 
|---|
| 732 |  | 
|---|
| 733 |         // Set up the binding (one source only) | 
|---|
| 734 |         VertexBufferBinding* binding = vertexData->vertexBufferBinding; | 
|---|
| 735 |         binding->setBinding(0, vbuf); | 
|---|
| 736 |  | 
|---|
| 737 |         // Work out the transform required | 
|---|
| 738 |         // Default orientation of plane is normal along +z, distance 0 | 
|---|
| 739 |         Matrix4 xlate, xform, rot; | 
|---|
| 740 |         Matrix3 rot3; | 
|---|
| 741 |         xlate = rot = Matrix4::IDENTITY; | 
|---|
| 742 |         // Determine axes | 
|---|
| 743 |         Vector3 zAxis, yAxis, xAxis; | 
|---|
| 744 |         zAxis = params.plane.normal; | 
|---|
| 745 |         zAxis.normalise(); | 
|---|
| 746 |         yAxis = params.upVector; | 
|---|
| 747 |         yAxis.normalise(); | 
|---|
| 748 |         xAxis = yAxis.crossProduct(zAxis); | 
|---|
| 749 |         if (xAxis.length() == 0) | 
|---|
| 750 |         { | 
|---|
| 751 |             //upVector must be wrong | 
|---|
| 752 |             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.", | 
|---|
| 753 |                 "MeshManager::createPlane"); | 
|---|
| 754 |         } | 
|---|
| 755 |  | 
|---|
| 756 |         rot3.FromAxes(xAxis, yAxis, zAxis); | 
|---|
| 757 |         rot = rot3; | 
|---|
| 758 |  | 
|---|
| 759 |         // Set up standard xform from origin | 
|---|
| 760 |         xlate.setTrans(params.plane.normal * -params.plane.d); | 
|---|
| 761 |  | 
|---|
| 762 |         // concatenate | 
|---|
| 763 |         xform = xlate * rot; | 
|---|
| 764 |  | 
|---|
| 765 |         // Generate vertex data | 
|---|
| 766 |         // Imagine a large sphere with the camera located near the top | 
|---|
| 767 |         // The lower the curvature, the larger the sphere | 
|---|
| 768 |         // Use the angle from viewer to the points on the plane | 
|---|
| 769 |         // Credit to Aftershock for the general approach | 
|---|
| 770 |         Real camPos;      // Camera position relative to sphere center | 
|---|
| 771 |  | 
|---|
| 772 |         // Derive sphere radius | 
|---|
| 773 |         Vector3 vertPos;  // position relative to camera | 
|---|
| 774 |         Real sphDist;      // Distance from camera to sphere along box vertex vector | 
|---|
| 775 |         // Vector3 camToSph; // camera position to sphere | 
|---|
| 776 |         Real sphereRadius;// Sphere radius | 
|---|
| 777 |         // Actual values irrelevant, it's the relation between sphere radius and camera position that's important | 
|---|
| 778 |         const Real SPHERE_RAD = 100.0; | 
|---|
| 779 |         const Real CAM_DIST = 5.0; | 
|---|
| 780 |  | 
|---|
| 781 |         sphereRadius = SPHERE_RAD - params.curvature; | 
|---|
| 782 |         camPos = sphereRadius - CAM_DIST; | 
|---|
| 783 |  | 
|---|
| 784 |         // Lock the whole buffer | 
|---|
| 785 |         float* pFloat = static_cast<float*>( | 
|---|
| 786 |             vbuf->lock(HardwareBuffer::HBL_DISCARD) ); | 
|---|
| 787 |         Real xSpace = params.width / params.xsegments; | 
|---|
| 788 |         Real ySpace = params.height / params.ysegments; | 
|---|
| 789 |         Real halfWidth = params.width / 2; | 
|---|
| 790 |         Real halfHeight = params.height / 2; | 
|---|
| 791 |         Vector3 vec, norm; | 
|---|
| 792 |         Vector3 min, max; | 
|---|
| 793 |         Real maxSquaredLength = 0; | 
|---|
| 794 |         bool firstTime = true; | 
|---|
| 795 |  | 
|---|
| 796 |         for (int y = params.ysegments - params.ySegmentsToKeep; y < params.ysegments + 1; ++y) | 
|---|
| 797 |         { | 
|---|
| 798 |             for (int x = 0; x < params.xsegments + 1; ++x) | 
|---|
| 799 |             { | 
|---|
| 800 |                 // Work out centered on origin | 
|---|
| 801 |                 vec.x = (x * xSpace) - halfWidth; | 
|---|
| 802 |                 vec.y = (y * ySpace) - halfHeight; | 
|---|
| 803 |                 vec.z = 0.0f; | 
|---|
| 804 |                 // Transform by orientation and distance | 
|---|
| 805 |                 vec = xform.transformAffine(vec); | 
|---|
| 806 |                 // Assign to geometry | 
|---|
| 807 |                 *pFloat++ = vec.x; | 
|---|
| 808 |                 *pFloat++ = vec.y; | 
|---|
| 809 |                 *pFloat++ = vec.z; | 
|---|
| 810 |  | 
|---|
| 811 |                 // Build bounds as we go | 
|---|
| 812 |                 if (firstTime) | 
|---|
| 813 |                 { | 
|---|
| 814 |                     min = vec; | 
|---|
| 815 |                     max = vec; | 
|---|
| 816 |                     maxSquaredLength = vec.squaredLength(); | 
|---|
| 817 |                     firstTime = false; | 
|---|
| 818 |                 } | 
|---|
| 819 |                 else | 
|---|
| 820 |                 { | 
|---|
| 821 |                     min.makeFloor(vec); | 
|---|
| 822 |                     max.makeCeil(vec); | 
|---|
| 823 |                     maxSquaredLength = std::max(maxSquaredLength, vec.squaredLength()); | 
|---|
| 824 |                 } | 
|---|
| 825 |  | 
|---|
| 826 |                 if (params.normals) | 
|---|
| 827 |                 { | 
|---|
| 828 |                     // Default normal is along unit Z | 
|---|
| 829 |                     norm = Vector3::UNIT_Z; | 
|---|
| 830 |                     // Rotate | 
|---|
| 831 |                     norm = params.orientation * norm; | 
|---|
| 832 |  | 
|---|
| 833 |                     *pFloat++ = norm.x; | 
|---|
| 834 |                     *pFloat++ = norm.y; | 
|---|
| 835 |                     *pFloat++ = norm.z; | 
|---|
| 836 |                 } | 
|---|
| 837 |  | 
|---|
| 838 |                 // Generate texture coords | 
|---|
| 839 |                 // Normalise position | 
|---|
| 840 |                 // modify by orientation to return +y up | 
|---|
| 841 |                 vec = params.orientation.Inverse() * vec; | 
|---|
| 842 |                 vec.normalise(); | 
|---|
| 843 |                 // Find distance to sphere | 
|---|
| 844 |                 sphDist = Math::Sqrt(camPos*camPos * (vec.y*vec.y-1.0) + sphereRadius*sphereRadius) - camPos*vec.y; | 
|---|
| 845 |  | 
|---|
| 846 |                 vec.x *= sphDist; | 
|---|
| 847 |                 vec.z *= sphDist; | 
|---|
| 848 |  | 
|---|
| 849 |                 // Use x and y on sphere as texture coordinates, tiled | 
|---|
| 850 |                 Real s = vec.x * (0.01 * params.xTile); | 
|---|
| 851 |                 Real t = 1 - (vec.z * (0.01 * params.yTile)); | 
|---|
| 852 |                 for (i = 0; i < params.numTexCoordSets; ++i) | 
|---|
| 853 |                 { | 
|---|
| 854 |                     *pFloat++ = s; | 
|---|
| 855 |                     *pFloat++ = t; | 
|---|
| 856 |                 } | 
|---|
| 857 |  | 
|---|
| 858 |  | 
|---|
| 859 |             } // x | 
|---|
| 860 |         } // y | 
|---|
| 861 |  | 
|---|
| 862 |         // Unlock | 
|---|
| 863 |         vbuf->unlock(); | 
|---|
| 864 |         // Generate face list | 
|---|
| 865 |         pSub->useSharedVertices = true; | 
|---|
| 866 |         tesselate2DMesh(pSub, params.xsegments + 1, params.ySegmentsToKeep + 1, false,  | 
|---|
| 867 |             params.indexBufferUsage, params.indexShadowBuffer); | 
|---|
| 868 |  | 
|---|
| 869 |         pMesh->_setBounds(AxisAlignedBox(min, max), true); | 
|---|
| 870 |         pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredLength)); | 
|---|
| 871 |     } | 
|---|
| 872 |     //----------------------------------------------------------------------- | 
|---|
| 873 |     PatchMeshPtr MeshManager::createBezierPatch(const String& name, const String& groupName,  | 
|---|
| 874 |             void* controlPointBuffer, VertexDeclaration *declaration,  | 
|---|
| 875 |             size_t width, size_t height, | 
|---|
| 876 |             size_t uMaxSubdivisionLevel, size_t vMaxSubdivisionLevel, | 
|---|
| 877 |             PatchSurface::VisibleSide visibleSide,  | 
|---|
| 878 |             HardwareBuffer::Usage vbUsage, HardwareBuffer::Usage ibUsage, | 
|---|
| 879 |             bool vbUseShadow, bool ibUseShadow) | 
|---|
| 880 |     { | 
|---|
| 881 |         if (width < 3 || height < 3) | 
|---|
| 882 |         { | 
|---|
| 883 |             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, | 
|---|
| 884 |                 "Bezier patch require at least 3x3 control points", | 
|---|
| 885 |                 "MeshManager::createBezierPatch"); | 
|---|
| 886 |         } | 
|---|
| 887 |  | 
|---|
| 888 |         MeshPtr pMesh = getByName(name); | 
|---|
| 889 |         if (!pMesh.isNull()) | 
|---|
| 890 |         { | 
|---|
| 891 |             OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, "A mesh called " + name +  | 
|---|
| 892 |                 " already exists!", "MeshManager::createBezierPatch"); | 
|---|
| 893 |         } | 
|---|
| 894 |         PatchMesh* pm = new PatchMesh(this, name, getNextHandle(), groupName); | 
|---|
| 895 |         pm->define(controlPointBuffer, declaration, width, height, | 
|---|
| 896 |             uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide, vbUsage, ibUsage, | 
|---|
| 897 |             vbUseShadow, ibUseShadow); | 
|---|
| 898 |         pm->load(); | 
|---|
| 899 |         ResourcePtr res(pm); | 
|---|
| 900 |         addImpl(res); | 
|---|
| 901 |  | 
|---|
| 902 |         return res; | 
|---|
| 903 |     } | 
|---|
| 904 |     //----------------------------------------------------------------------- | 
|---|
| 905 |     void MeshManager::setPrepareAllMeshesForShadowVolumes(bool enable) | 
|---|
| 906 |     { | 
|---|
| 907 |         mPrepAllMeshesForShadowVolumes = enable; | 
|---|
| 908 |     } | 
|---|
| 909 |     //----------------------------------------------------------------------- | 
|---|
| 910 |     bool MeshManager::getPrepareAllMeshesForShadowVolumes(void) | 
|---|
| 911 |     { | 
|---|
| 912 |         return mPrepAllMeshesForShadowVolumes; | 
|---|
| 913 |     } | 
|---|
| 914 |     //----------------------------------------------------------------------- | 
|---|
| 915 |     Real MeshManager::getBoundsPaddingFactor(void) | 
|---|
| 916 |     { | 
|---|
| 917 |         return mBoundsPaddingFactor; | 
|---|
| 918 |     } | 
|---|
| 919 |     //----------------------------------------------------------------------- | 
|---|
| 920 |     void MeshManager::setBoundsPaddingFactor(Real paddingFactor) | 
|---|
| 921 |     { | 
|---|
| 922 |         mBoundsPaddingFactor = paddingFactor; | 
|---|
| 923 |     } | 
|---|
| 924 |     //----------------------------------------------------------------------- | 
|---|
| 925 |     Resource* MeshManager::createImpl(const String& name, ResourceHandle handle,  | 
|---|
| 926 |         const String& group, bool isManual, ManualResourceLoader* loader,  | 
|---|
| 927 |         const NameValuePairList* createParams) | 
|---|
| 928 |     { | 
|---|
| 929 |         // no use for createParams here | 
|---|
| 930 |         return new Mesh(this, name, handle, group, isManual, loader); | 
|---|
| 931 |     } | 
|---|
| 932 |     //----------------------------------------------------------------------- | 
|---|
| 933 |  | 
|---|
| 934 | } | 
|---|