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