Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreMeshManager.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 34.2 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus 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
45namespace 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}
Note: See TracBrowser for help on using the repository browser.