source: OGRE/trunk/ogrenew/OgreMain/src/OgreMeshManager.cpp @ 657

Revision 657, 35.5 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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