Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreManualObject.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

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