source: OGRE/trunk/ogrenew/OgreMain/src/OgreManualObject.cpp @ 692

Revision 692, 28.7 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

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#include "OgreManualObject.h"
27#include "OgreException.h"
28#include "OgreMaterialManager.h"
29#include "OgreSceneNode.h"
30#include "OgreRoot.h"
31#include "OgreRenderSystem.h"
32#include "OgreHardwareBufferManager.h"
33#include "OgreEdgeListBuilder.h"
34#include "OgreMeshManager.h"
35#include "OgreMesh.h"
36#include "OgreSubMesh.h"
37
38namespace Ogre {
39
40#define TEMP_INITIAL_SIZE 50
41#define TEMP_VERTEXSIZE_GUESS sizeof(float) * 12
42#define TEMP_INITIAL_VERTEX_SIZE TEMP_VERTEXSIZE_GUESS * TEMP_INITIAL_SIZE
43#define TEMP_INITIAL_INDEX_SIZE sizeof(uint16) * TEMP_INITIAL_SIZE
44        //-----------------------------------------------------------------------------
45        ManualObject::ManualObject(const String& name)
46                : MovableObject(name),
47                  mCurrentSection(0), mFirstVertex(true),
48                  mTempVertexPending(false),
49                  mTempVertexBuffer(0), mTempVertexSize(TEMP_INITIAL_VERTEX_SIZE),
50                  mTempIndexBuffer(0), mTempIndexSize(TEMP_INITIAL_INDEX_SIZE),
51                  mDeclSize(0), mTexCoordIndex(0), mRadius(0), mAnyIndexed(false),
52                  mEdgeList(0)
53        {
54        }
55        //-----------------------------------------------------------------------------
56        ManualObject::~ManualObject()
57        {
58                clear();
59        }
60        //-----------------------------------------------------------------------------
61        void ManualObject::clear(void)
62        {
63                resetTempAreas();
64                for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i)
65                {
66                        delete *i;
67                }
68                mSectionList.clear();
69                mRadius = 0;
70                mAABB.setNull();
71                delete mEdgeList;
72                mEdgeList = 0;
73                mAnyIndexed = false;
74                for (ShadowRenderableList::iterator s = mShadowRenderables.begin();
75                        s != mShadowRenderables.end(); ++s)
76                {
77                        delete *s;
78                }
79                mShadowRenderables.clear();
80
81
82        }
83        //-----------------------------------------------------------------------------
84        void ManualObject::resetTempAreas(void)
85        {
86                delete [] mTempVertexBuffer;
87                delete [] mTempIndexBuffer;
88                mTempVertexBuffer = 0;
89                mTempIndexBuffer = 0;
90                mTempVertexSize = TEMP_INITIAL_VERTEX_SIZE;
91                mTempIndexSize = TEMP_INITIAL_INDEX_SIZE;
92        }
93        //-----------------------------------------------------------------------------
94        void ManualObject::resizeTempVertexBufferIfNeeded(size_t numVerts)
95        {
96                // Calculate byte size
97                // Use decl if we know it by now, otherwise default size to pos/norm/texcoord*2
98                size_t newSize;
99                if (!mFirstVertex)
100                {
101                        newSize = mDeclSize * numVerts;
102                }
103                else
104                {
105                        // estimate - size checks will deal for subsequent verts
106                        newSize = TEMP_VERTEXSIZE_GUESS * numVerts;
107                }
108                if (newSize > mTempVertexSize || !mTempVertexBuffer)
109                {
110                        if (!mTempVertexBuffer)
111                        {
112                                // init
113                                newSize = mTempVertexSize;
114                        }
115                        else
116                        {
117                                // increase to at least double current
118                                newSize = std::max(newSize, mTempVertexSize*2);
119                        }
120                        // copy old data
121                        char* tmp = mTempVertexBuffer;
122                        mTempVertexBuffer = new char[newSize];
123                        if (tmp)
124                        {
125                                memcpy(mTempVertexBuffer, tmp, mTempVertexSize);
126                                // delete old buffer
127                                delete [] tmp;
128                        }
129                        mTempVertexSize = newSize;
130                }
131        }
132        //-----------------------------------------------------------------------------
133        void ManualObject::resizeTempIndexBufferIfNeeded(size_t numInds)
134        {
135                size_t newSize = numInds * sizeof(uint16);
136                if (newSize > mTempIndexSize || !mTempIndexBuffer)
137                {
138                        if (!mTempIndexBuffer)
139                        {
140                                // init
141                                newSize = mTempIndexSize;
142                        }
143                        else
144                        {
145                                // increase to at least double current
146                                newSize = std::max(newSize, mTempIndexSize*2);
147                        }
148                        numInds = newSize / sizeof(uint16);
149                        uint16* tmp = mTempIndexBuffer;
150                        mTempIndexBuffer = new uint16[numInds];
151                        if (tmp)
152                        {
153                                memcpy(mTempIndexBuffer, tmp, mTempIndexSize);
154                                delete [] tmp;
155                        }
156                        mTempIndexSize = newSize;
157                }
158
159        }
160        //-----------------------------------------------------------------------------
161        void ManualObject::estimateVertexCount(size_t vcount)
162        {
163                resizeTempVertexBufferIfNeeded(vcount);
164        }
165        //-----------------------------------------------------------------------------
166        void ManualObject::estimateIndexCount(size_t icount)
167        {
168                resizeTempIndexBufferIfNeeded(icount);
169        }
170        //-----------------------------------------------------------------------------
171        void ManualObject::begin(const String& materialName,
172                RenderOperation::OperationType opType)
173        {
174                if (mCurrentSection)
175                {
176                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
177                                "You cannot call begin() again until after you call end()",
178                                "ManualObject::begin");
179                }
180                mCurrentSection = new ManualObjectSection(this, materialName, opType);
181                mSectionList.push_back(mCurrentSection);
182                mFirstVertex = true;
183                mDeclSize = 0;
184                mTexCoordIndex = 0;
185        }
186        //-----------------------------------------------------------------------------
187        void ManualObject::position(const Vector3& pos)
188        {
189                position(pos.x, pos.y, pos.z);
190        }
191        //-----------------------------------------------------------------------------
192        void ManualObject::position(Real x, Real y, Real z)
193        {
194                if (!mCurrentSection)
195                {
196                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
197                                "You must call begin() before this method",
198                                "ManualObject::position");
199                }
200                if (mTempVertexPending)
201                {
202                        // bake current vertex
203                        copyTempVertexToBuffer();
204                        mFirstVertex = false;
205                }
206
207                if (mFirstVertex)
208                {
209                        // defining declaration
210                        mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration
211                                ->addElement(0, mDeclSize, VET_FLOAT3, VES_POSITION);
212                        mDeclSize += VertexElement::getTypeSize(VET_FLOAT3);
213                }
214
215                mTempVertex.position.x = x;
216                mTempVertex.position.y = y;
217                mTempVertex.position.z = z;
218
219                // update bounds
220                mAABB.merge(mTempVertex.position);
221                mRadius = std::max(mRadius, mTempVertex.position.length());
222
223                // reset current texture coord
224                mTexCoordIndex = 0;
225
226                mTempVertexPending = true;
227        }
228        //-----------------------------------------------------------------------------
229        void ManualObject::normal(const Vector3& norm)
230        {
231                normal(norm.x, norm.y, norm.z);
232        }
233        //-----------------------------------------------------------------------------
234        void ManualObject::normal(Real x, Real y, Real z)
235        {
236                if (!mCurrentSection)
237                {
238                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
239                                "You must call begin() before this method",
240                                "ManualObject::normal");
241                }
242                if (mFirstVertex)
243                {
244                        // defining declaration
245                        mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration
246                                ->addElement(0, mDeclSize, VET_FLOAT3, VES_NORMAL);
247                        mDeclSize += VertexElement::getTypeSize(VET_FLOAT3);
248                }
249                mTempVertex.normal.x = x;
250                mTempVertex.normal.y = y;
251                mTempVertex.normal.z = z;
252        }
253        //-----------------------------------------------------------------------------
254        void ManualObject::textureCoord(Real u)
255        {
256                if (!mCurrentSection)
257                {
258                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
259                                "You must call begin() before this method",
260                                "ManualObject::textureCoord");
261                }
262                if (mFirstVertex)
263                {
264                        // defining declaration
265                        mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration
266                                ->addElement(0, mDeclSize, VET_FLOAT1, VES_TEXTURE_COORDINATES, mTexCoordIndex);
267                        mDeclSize += VertexElement::getTypeSize(VET_FLOAT1);
268                }
269                mTempVertex.texCoordDims[mTexCoordIndex] = 1;
270                mTempVertex.texCoord[mTexCoordIndex].x = u;
271
272                ++mTexCoordIndex;
273
274        }
275        //-----------------------------------------------------------------------------
276        void ManualObject::textureCoord(Real u, Real v)
277        {
278                if (!mCurrentSection)
279                {
280                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
281                                "You must call begin() before this method",
282                                "ManualObject::textureCoord");
283                }
284                if (mFirstVertex)
285                {
286                        // defining declaration
287                        mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration
288                                ->addElement(0, mDeclSize, VET_FLOAT2, VES_TEXTURE_COORDINATES, mTexCoordIndex);
289                        mDeclSize += VertexElement::getTypeSize(VET_FLOAT2);
290                }
291                mTempVertex.texCoordDims[mTexCoordIndex] = 2;
292                mTempVertex.texCoord[mTexCoordIndex].x = u;
293                mTempVertex.texCoord[mTexCoordIndex].y = v;
294
295                ++mTexCoordIndex;
296        }
297        //-----------------------------------------------------------------------------
298        void ManualObject::textureCoord(Real u, Real v, Real w)
299        {
300                if (!mCurrentSection)
301                {
302                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
303                                "You must call begin() before this method",
304                                "ManualObject::textureCoord");
305                }
306                if (mFirstVertex)
307                {
308                        // defining declaration
309                        mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration
310                                ->addElement(0, mDeclSize, VET_FLOAT3, VES_TEXTURE_COORDINATES, mTexCoordIndex);
311                        mDeclSize += VertexElement::getTypeSize(VET_FLOAT3);
312                }
313                mTempVertex.texCoordDims[mTexCoordIndex] = 3;
314                mTempVertex.texCoord[mTexCoordIndex].x = u;
315                mTempVertex.texCoord[mTexCoordIndex].y = v;
316                mTempVertex.texCoord[mTexCoordIndex].z = w;
317
318                ++mTexCoordIndex;
319        }
320        //-----------------------------------------------------------------------------
321        void ManualObject::textureCoord(const Vector2& uv)
322        {
323                textureCoord(uv.x, uv.y);
324        }
325        //-----------------------------------------------------------------------------
326        void ManualObject::textureCoord(const Vector3& uvw)
327        {
328                textureCoord(uvw.x, uvw.y, uvw.z);
329        }
330        //-----------------------------------------------------------------------------
331        void ManualObject::colour(const ColourValue& col)
332        {
333                colour(col.r, col.g, col.b, col.a);
334        }
335        //-----------------------------------------------------------------------------
336        void ManualObject::colour(Real r, Real g, Real b, Real a)
337        {
338                if (!mCurrentSection)
339                {
340                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
341                                "You must call begin() before this method",
342                                "ManualObject::colour");
343                }
344                if (mFirstVertex)
345                {
346                        // defining declaration
347                        mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration
348                                ->addElement(0, mDeclSize, VET_COLOUR, VES_DIFFUSE);
349                        mDeclSize += VertexElement::getTypeSize(VET_COLOUR);
350                }
351                mTempVertex.colour.r = r;
352                mTempVertex.colour.g = g;
353                mTempVertex.colour.b = b;
354                mTempVertex.colour.a = a;
355
356        }
357        //-----------------------------------------------------------------------------
358        void ManualObject::index(uint16 idx)
359        {
360                if (!mCurrentSection)
361                {
362                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
363                                "You must call begin() before this method",
364                                "ManualObject::index");
365                }
366                mAnyIndexed = true;
367                // make sure we have index data
368                RenderOperation* rop = mCurrentSection->getRenderOperation();
369                if (!rop->indexData)
370                {
371                        rop->indexData = new IndexData();
372                        rop->indexData->indexCount = 0;
373                        rop->useIndexes = true;
374                }
375                resizeTempIndexBufferIfNeeded(++rop->indexData->indexCount);
376
377                mTempIndexBuffer[rop->indexData->indexCount - 1] = idx;
378        }
379        //-----------------------------------------------------------------------------
380        void ManualObject::triangle(uint16 i1, uint16 i2, uint16 i3)
381        {
382                if (!mCurrentSection)
383                {
384                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
385                                "You must call begin() before this method",
386                                "ManualObject::index");
387                }
388                if (mCurrentSection->getRenderOperation()->operationType !=
389                        RenderOperation::OT_TRIANGLE_LIST)
390                {
391                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
392                                "This method is only valid on triangle lists",
393                                "ManualObject::index");
394                }
395
396                index(i1);
397                index(i2);
398                index(i3);
399        }
400        //-----------------------------------------------------------------------------
401        void ManualObject::quad(uint16 i1, uint16 i2, uint16 i3, uint16 i4)
402        {
403                // first tri
404                triangle(i1, i2, i3);
405                // second tri
406                triangle(i3, i4, i1);
407        }
408        //-----------------------------------------------------------------------------
409        void ManualObject::copyTempVertexToBuffer(void)
410        {
411                mTempVertexPending = false;
412                RenderOperation* rop = mCurrentSection->getRenderOperation();
413                if (rop->vertexData->vertexCount == 0)
414                {
415                        // first vertex, autoorganise decl
416                        VertexDeclaration* oldDcl = rop->vertexData->vertexDeclaration;
417                        rop->vertexData->vertexDeclaration =
418                                oldDcl->getAutoOrganisedDeclaration(false, false);
419                        HardwareBufferManager::getSingleton().destroyVertexDeclaration(oldDcl);
420                }
421                resizeTempVertexBufferIfNeeded(++rop->vertexData->vertexCount);
422
423                // get base pointer
424                char* pBase = mTempVertexBuffer + (mDeclSize * (rop->vertexData->vertexCount-1));
425                const VertexDeclaration::VertexElementList& elemList =
426                        rop->vertexData->vertexDeclaration->getElements();
427                for (VertexDeclaration::VertexElementList::const_iterator i = elemList.begin();
428                        i != elemList.end(); ++i)
429                {
430                        float* pFloat;
431                        RGBA* pRGBA;
432                        const VertexElement& elem = *i;
433                        switch(elem.getType())
434                        {
435                        case VET_FLOAT1:
436                        case VET_FLOAT2:
437                        case VET_FLOAT3:
438                                elem.baseVertexPointerToElement(pBase, &pFloat);
439                                break;
440                        case VET_COLOUR:
441                        case VET_COLOUR_ABGR:
442                        case VET_COLOUR_ARGB:
443                                elem.baseVertexPointerToElement(pBase, &pRGBA);
444                                break;
445                        };
446
447
448                        RenderSystem* rs;
449                        unsigned short dims;
450                        switch(elem.getSemantic())
451                        {
452                        case VES_POSITION:
453                                *pFloat++ = mTempVertex.position.x;
454                                *pFloat++ = mTempVertex.position.y;
455                                *pFloat++ = mTempVertex.position.z;
456                                break;
457                        case VES_NORMAL:
458                                *pFloat++ = mTempVertex.normal.x;
459                                *pFloat++ = mTempVertex.normal.y;
460                                *pFloat++ = mTempVertex.normal.z;
461                                break;
462                        case VES_TEXTURE_COORDINATES:
463                                dims = VertexElement::getTypeCount(elem.getType());
464                                for (ushort t = 0; t < dims; ++t)
465                                        *pFloat++ = mTempVertex.texCoord[elem.getIndex()].val[t];
466                                break;
467                        case VES_DIFFUSE:
468                                rs = Root::getSingleton().getRenderSystem();
469                                if (rs)
470                                        rs->convertColourValue(mTempVertex.colour, pRGBA++);
471                                else
472                                        *pRGBA++ = mTempVertex.colour.getAsRGBA(); // pick one!
473                                break;
474                        };
475
476                }
477
478        }
479        //-----------------------------------------------------------------------------
480        void ManualObject::end(void)
481        {
482                if (!mCurrentSection)
483                {
484                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
485                                "You cannot call end() until after you call begin()",
486                                "ManualObject::end");
487                }
488                if (mTempVertexPending)
489                {
490                        // bake current vertex
491                        copyTempVertexToBuffer();
492                }
493
494                // Bake the real buffers
495                RenderOperation* rop = mCurrentSection->getRenderOperation();
496                HardwareVertexBufferSharedPtr vbuf =
497                        HardwareBufferManager::getSingleton().createVertexBuffer(
498                                mDeclSize,
499                                rop->vertexData->vertexCount,
500                                HardwareBuffer::HBU_STATIC_WRITE_ONLY);
501                rop->vertexData->vertexBufferBinding->setBinding(0, vbuf);
502                vbuf->writeData(0, vbuf->getSizeInBytes(), mTempVertexBuffer, true);
503
504                if(rop->useIndexes)
505                {
506                        rop->indexData->indexBuffer =
507                                HardwareBufferManager::getSingleton().createIndexBuffer(
508                                        HardwareIndexBuffer::IT_16BIT,
509                                        rop->indexData->indexCount,
510                                        HardwareBuffer::HBU_STATIC_WRITE_ONLY);
511                        rop->indexData->indexBuffer->writeData(
512                                0, rop->indexData->indexBuffer->getSizeInBytes(),
513                                mTempIndexBuffer, true);
514                }
515
516                mCurrentSection = 0;
517                resetTempAreas();
518
519        }
520        //-----------------------------------------------------------------------------
521        MeshPtr ManualObject::convertToMesh(const String& meshName, const String& groupName)
522        {
523                if (mCurrentSection)
524                {
525                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
526                                "You cannot call convertToMesh() whilst you are in the middle of "
527                                "defining the object; call end() first.",
528                                "ManualObject::convertToMesh");
529                }
530                if (mSectionList.empty())
531                {
532                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
533                                "No data defined to convert to a mesh.",
534                                "ManualObject::convertToMesh");
535                }
536                for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i)
537                {
538                        ManualObjectSection* sec = *i;
539                        if (!sec->getRenderOperation()->useIndexes)
540                        {
541                                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
542                                        "Only indexed geometry may be converted to a mesh.",
543                                        "ManualObject::convertToMesh");
544                        }
545                }
546                MeshPtr m = MeshManager::getSingleton().createManual(meshName, groupName);
547
548                for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i)
549                {
550                        ManualObjectSection* sec = *i;
551                        RenderOperation* rop = sec->getRenderOperation();
552                        SubMesh* sm = m->createSubMesh();
553                        sm->useSharedVertices = false;
554                        sm->operationType = rop->operationType;
555                        sm->setMaterialName(sec->getMaterialName());
556                        // Copy vertex data; replicate buffers too
557                        sm->vertexData = rop->vertexData->clone(true);
558                        // Copy index data; replicate buffers too
559                        sm->indexData = rop->indexData->clone(true);
560                }
561        // update bounds
562                m->_setBounds(mAABB);
563                m->_setBoundingSphereRadius(mRadius);
564
565                m->load();
566
567                return m;
568
569
570        }
571        //-----------------------------------------------------------------------------
572        const String& ManualObject::getMovableType(void) const
573        {
574                return ManualObjectFactory::FACTORY_TYPE_NAME;
575        }
576        //-----------------------------------------------------------------------------
577        const AxisAlignedBox& ManualObject::getBoundingBox(void) const
578        {
579                return mAABB;
580        }
581        //-----------------------------------------------------------------------------
582        Real ManualObject::getBoundingRadius(void) const
583        {
584                return mRadius;
585        }
586        //-----------------------------------------------------------------------------
587        void ManualObject::_updateRenderQueue(RenderQueue* queue)
588        {
589                for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i)
590                {
591                        if (mRenderQueueIDSet)
592                                queue->addRenderable(*i, mRenderQueueID);
593                        else
594                                queue->addRenderable(*i);
595                }
596        }
597        //-----------------------------------------------------------------------------
598        EdgeData* ManualObject::getEdgeList(void)
599        {
600                // Build on demand
601                if (!mEdgeList && mAnyIndexed)
602                {
603                        EdgeListBuilder eb;
604                        size_t vertexSet = 0;
605                        for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i)
606                        {
607                                RenderOperation* rop = (*i)->getRenderOperation();
608                                // Only indexed geometry supported for stencil shadows
609                                if (rop->useIndexes)
610                                {
611                                        eb.addVertexData(rop->vertexData);
612                                        eb.addIndexData(rop->indexData, vertexSet++);
613                                }
614                        }
615
616                        mEdgeList = eb.build();
617
618                }
619                return mEdgeList;
620        }
621        //-----------------------------------------------------------------------------
622        ShadowCaster::ShadowRenderableListIterator
623        ManualObject::getShadowVolumeRenderableIterator(
624                ShadowTechnique shadowTechnique, const Light* light,
625                HardwareIndexBufferSharedPtr* indexBuffer,
626                bool extrude, Real extrusionDistance, unsigned long flags)
627        {
628                assert(indexBuffer && "Only external index buffers are supported right now");
629                assert((*indexBuffer)->getType() == HardwareIndexBuffer::IT_16BIT &&
630                        "Only 16-bit indexes supported for now");
631
632                // Calculate the object space light details
633                Vector4 lightPos = light->getAs4DVector();
634                Matrix4 world2Obj = mParentNode->_getFullTransform().inverse();
635                lightPos =  world2Obj * lightPos;
636
637
638                // Init shadow renderable list if required (only allow indexed)
639                bool init = mShadowRenderables.empty() && mAnyIndexed;
640
641                EdgeData::EdgeGroupList::iterator egi;
642                ShadowRenderableList::iterator si, siend;
643                ManualObjectSectionShadowRenderable* esr = 0;
644                SectionList::iterator seci;
645                if (init)
646                        mShadowRenderables.resize(mEdgeList->edgeGroups.size());
647
648                siend = mShadowRenderables.end();
649                egi = mEdgeList->edgeGroups.begin();
650                seci = mSectionList.begin();
651                for (si = mShadowRenderables.begin(); si != siend; ++si, ++egi, ++seci)
652                {
653                        if (init)
654                        {
655                                // Create a new renderable, create a separate light cap if
656                                // we're using a vertex program (either for this model, or
657                                // for extruding the shadow volume) since otherwise we can
658                                // get depth-fighting on the light cap
659                                MaterialPtr mat = (*seci)->getMaterial();
660                                mat->load();
661                                bool vertexProgram = false;
662                                Technique* t = mat->getBestTechnique();
663                                for (int p = 0; p < t->getNumPasses(); ++p)
664                                {
665                                        Pass* pass = t->getPass(p);
666                                        if (pass->hasVertexProgram())
667                                        {
668                                                vertexProgram = true;
669                                                break;
670                                        }
671                                }
672                                *si = new ManualObjectSectionShadowRenderable(this, indexBuffer,
673                                        egi->vertexData, vertexProgram || !extrude);
674                        }
675                        // Get shadow renderable
676                        esr = static_cast<ManualObjectSectionShadowRenderable*>(*si);
677                        HardwareVertexBufferSharedPtr esrPositionBuffer = esr->getPositionBuffer();
678                        // Extrude vertices in software if required
679                        if (extrude)
680                        {
681                                extrudeVertices(esrPositionBuffer,
682                                        egi->vertexData->vertexCount,
683                                        lightPos, extrusionDistance);
684
685                        }
686
687                }
688                // Calc triangle light facing
689                updateEdgeListLightFacing(mEdgeList, lightPos);
690
691                // Generate indexes and update renderables
692                generateShadowVolume(mEdgeList, *indexBuffer, light,
693                        mShadowRenderables, flags);
694
695
696                return ShadowRenderableListIterator(
697                        mShadowRenderables.begin(), mShadowRenderables.end());
698
699
700        }
701        //-----------------------------------------------------------------------------
702        //-----------------------------------------------------------------------------
703        //-----------------------------------------------------------------------------
704        ManualObject::ManualObjectSection::ManualObjectSection(ManualObject* parent,
705                const String& materialName,     RenderOperation::OperationType opType)
706                : mParent(parent), mMaterialName(materialName)
707        {
708                mRenderOperation.operationType = opType;
709                // default to no indexes unless we're told
710                mRenderOperation.useIndexes = false;
711                mRenderOperation.vertexData = new VertexData();
712                mRenderOperation.vertexData->vertexCount = 0;
713
714        }
715        //-----------------------------------------------------------------------------
716        ManualObject::ManualObjectSection::~ManualObjectSection()
717        {
718                delete mRenderOperation.vertexData;
719                delete mRenderOperation.indexData; // ok to delete 0
720        }
721        //-----------------------------------------------------------------------------
722        RenderOperation* ManualObject::ManualObjectSection::getRenderOperation(void)
723        {
724                return &mRenderOperation;
725        }
726        //-----------------------------------------------------------------------------
727        const MaterialPtr& ManualObject::ManualObjectSection::getMaterial(void) const
728        {
729                if (mMaterial.isNull())
730                {
731                        // Load from default group. If user wants to use alternate groups,
732                        // they can define it and preload
733                        mMaterial = MaterialManager::getSingleton().load(mMaterialName,
734                                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
735                }
736                return mMaterial;
737        }
738        //-----------------------------------------------------------------------------
739        void ManualObject::ManualObjectSection::getRenderOperation(RenderOperation& op)
740        {
741                // direct copy
742                op = mRenderOperation;
743        }
744        //-----------------------------------------------------------------------------
745        void ManualObject::ManualObjectSection::getWorldTransforms(Matrix4* xform) const
746        {
747                xform[0] = mParent->_getParentNodeFullTransform();
748        }
749        //-----------------------------------------------------------------------------
750        const Quaternion& ManualObject::ManualObjectSection::getWorldOrientation(void) const
751        {
752                return mParent->getParentNode()->_getDerivedOrientation();
753        }
754        //-----------------------------------------------------------------------------
755        const Vector3& ManualObject::ManualObjectSection::getWorldPosition(void) const
756        {
757                return mParent->getParentNode()->_getDerivedPosition();
758        }
759        //-----------------------------------------------------------------------------
760        Real ManualObject::ManualObjectSection::getSquaredViewDepth(const Ogre::Camera *cam) const
761        {
762                Node* n = mParent->getParentNode();
763                assert(n);
764                return n->getSquaredViewDepth(cam);
765        }
766        //-----------------------------------------------------------------------------
767        const LightList& ManualObject::ManualObjectSection::getLights(void) const
768        {
769                SceneNode* n = mParent->getParentSceneNode();
770                assert(n);
771                return n->findLights(mParent->getBoundingRadius());
772        }
773        //-----------------------------------------------------------------------------
774        //--------------------------------------------------------------------------
775        ManualObject::ManualObjectSectionShadowRenderable::ManualObjectSectionShadowRenderable(
776                ManualObject* parent, HardwareIndexBufferSharedPtr* indexBuffer,
777                const VertexData* vertexData, bool createSeparateLightCap,
778                bool isLightCap)
779                : mParent(parent)
780        {
781                // Initialise render op
782                mRenderOp.indexData = new IndexData();
783                mRenderOp.indexData->indexBuffer = *indexBuffer;
784                mRenderOp.indexData->indexStart = 0;
785                // index start and count are sorted out later
786
787                // Create vertex data which just references position component (and 2 component)
788                mRenderOp.vertexData = new VertexData();
789                mRenderOp.vertexData->vertexDeclaration =
790                        HardwareBufferManager::getSingleton().createVertexDeclaration();
791                mRenderOp.vertexData->vertexBufferBinding =
792                        HardwareBufferManager::getSingleton().createVertexBufferBinding();
793                // Map in position data
794                mRenderOp.vertexData->vertexDeclaration->addElement(0,0,VET_FLOAT3, VES_POSITION);
795                ushort origPosBind =
796                        vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
797                mPositionBuffer = vertexData->vertexBufferBinding->getBuffer(origPosBind);
798                mRenderOp.vertexData->vertexBufferBinding->setBinding(0, mPositionBuffer);
799                // Map in w-coord buffer (if present)
800                if(!vertexData->hardwareShadowVolWBuffer.isNull())
801                {
802                        mRenderOp.vertexData->vertexDeclaration->addElement(1,0,VET_FLOAT1, VES_TEXTURE_COORDINATES, 0);
803                        mWBuffer = vertexData->hardwareShadowVolWBuffer;
804                        mRenderOp.vertexData->vertexBufferBinding->setBinding(1, mWBuffer);
805                }
806                // Use same vertex start as input
807                mRenderOp.vertexData->vertexStart = vertexData->vertexStart;
808
809                if (isLightCap)
810                {
811                        // Use original vertex count, no extrusion
812                        mRenderOp.vertexData->vertexCount = vertexData->vertexCount;
813                }
814                else
815                {
816                        // Vertex count must take into account the doubling of the buffer,
817                        // because second half of the buffer is the extruded copy
818                        mRenderOp.vertexData->vertexCount =
819                                vertexData->vertexCount * 2;
820                        if (createSeparateLightCap)
821                        {
822                                // Create child light cap
823                                mLightCap = new ManualObjectSectionShadowRenderable(parent,
824                                        indexBuffer, vertexData, false, true);
825                        }
826                }
827        }
828        //--------------------------------------------------------------------------
829        ManualObject::ManualObjectSectionShadowRenderable::~ManualObjectSectionShadowRenderable()
830        {
831                delete mRenderOp.indexData;
832                delete mRenderOp.vertexData;
833        }
834        //--------------------------------------------------------------------------
835        void ManualObject::ManualObjectSectionShadowRenderable::getWorldTransforms(
836                Matrix4* xform) const
837        {
838                // pretransformed
839                *xform = mParent->_getParentNodeFullTransform();
840        }
841        //--------------------------------------------------------------------------
842        const Quaternion&
843                ManualObject::ManualObjectSectionShadowRenderable::getWorldOrientation(void) const
844        {
845                return mParent->getParentNode()->_getDerivedOrientation();
846        }
847        //--------------------------------------------------------------------------
848        const Vector3&
849                ManualObject::ManualObjectSectionShadowRenderable::getWorldPosition(void) const
850        {
851                return mParent->getParentNode()->_getDerivedPosition();
852        }
853        //-----------------------------------------------------------------------------
854        //-----------------------------------------------------------------------------
855        String ManualObjectFactory::FACTORY_TYPE_NAME = "ManualObject";
856        //-----------------------------------------------------------------------------
857        const String& ManualObjectFactory::getType(void) const
858        {
859                return FACTORY_TYPE_NAME;
860        }
861        //-----------------------------------------------------------------------------
862        MovableObject* ManualObjectFactory::createInstanceImpl(
863                const String& name, const NameValuePairList* params)
864        {
865                return new ManualObject(name);
866        }
867        //-----------------------------------------------------------------------------
868        void ManualObjectFactory::destroyInstance( MovableObject* obj)
869        {
870                delete obj;
871        }
872
873
874
875}
Note: See TracBrowser for help on using the repository browser.