Coverage Report

Created: 2026-05-30 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/include/OgreManualObject.h
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
(Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
29
#ifndef __OgreManualObject_H__
30
#define __OgreManualObject_H__
31
32
#include "OgrePrerequisites.h"
33
#include "OgreMovableObject.h"
34
#include "OgreRenderable.h"
35
#include "OgreResourceGroupManager.h"
36
#include "OgreHeaderPrefix.h"
37
38
namespace Ogre
39
{
40
    /** \addtogroup Core
41
    *  @{
42
    */
43
    /** \addtogroup Scene
44
    *  @{
45
    */
46
    /** Class providing a much simplified interface to generating manual
47
        objects with custom geometry.
48
49
        Building one-off geometry objects manually usually requires getting
50
        down and dirty with the vertex buffer and vertex declaration API, 
51
        which some people find a steep learning curve. This class gives you 
52
        a simpler interface specifically for the purpose of building a 
53
        3D object simply and quickly. Note that if you intend to instance your
54
        object you will still need to become familiar with the Mesh class. 
55
56
        This class draws heavily on the interface for OpenGL 
57
        immediate-mode (@c glBegin, @c glVertex, @c glNormal etc), since this
58
        is generally well-liked by people. There are a couple of differences
59
        in the results though - internally this class still builds hardware 
60
        buffers which can be re-used, so you can render the resulting object
61
        multiple times without re-issuing all the same commands again. 
62
        Secondly, the rendering is not immediate, it is still queued just like
63
        all OGRE objects. This makes this object more efficient than the 
64
        equivalent GL immediate-mode commands, so it's feasible to use it for
65
        large objects if you really want to.
66
67
        To construct some geometry with this object:
68
          -# If you know roughly how many vertices (and indices, if you use them)
69
             you're going to submit, call estimateVertexCount() and estimateIndexCount().
70
             This is not essential but will make the process more efficient by saving
71
             memory reallocations.
72
          -# Call begin() to begin entering data
73
          -# For each vertex, call position(), normal(), textureCoord(), colour()
74
             to define your vertex data. Note that each time you call position()
75
             you start a new vertex. Note that the first vertex defines the 
76
             components of the vertex - you can't add more after that. For example
77
             if you didn't call normal() in the first vertex, you cannot call it
78
             in any others. You ought to call the same combination of methods per
79
             vertex.
80
          -# If you want to define triangles (or lines/points) by indexing into the vertex list, 
81
             you can call index() as many times as you need to define them.
82
             If you don't do this, the class will assume you want triangles drawn
83
             directly as defined by the vertex list, i.e. non-indexed geometry. Note
84
             that stencil shadows are only supported on indexed geometry, and that
85
             indexed geometry is a little faster; so you should try to use it.
86
          -# Call end() to finish entering data.
87
          -# Optionally repeat the begin-end cycle if you want more geometry 
88
            using different rendering operation types, or different materials
89
        After calling end(), the class will organise the data for that section
90
        internally and make it ready to render with. Like any other 
91
        MovableObject you should attach the object to a SceneNode to make it 
92
        visible. Other aspects like the relative render order can be controlled
93
        using standard MovableObject methods like setRenderQueueGroup.
94
95
        You can also use beginUpdate() to alter the geometry later on if you wish.
96
        If you do this, you should call setDynamic(true) before your first call 
97
        to begin(), and also consider using estimateVertexCount() / estimateIndexCount()
98
        if your geometry is going to be growing, to avoid buffer recreation during
99
        growth.
100
101
        @note like all OGRE geometry, triangles should be specified in 
102
        anti-clockwise winding order (whether you're doing it with just
103
        vertices, or using indexes too). That is to say that the front of the
104
        face is the one where the vertices are listed in anti-clockwise order.
105
    */
106
    class _OgreExport ManualObject : public MovableObject
107
    {
108
    public:
109
        ManualObject(const String& name);
110
        virtual ~ManualObject();
111
112
        /** @copydoc MovableObject::_releaseManualHardwareResources */
113
0
        void _releaseManualHardwareResources() override { clear(); }
114
115
        //pre-declare ManualObjectSection
116
        class ManualObjectSection;
117
118
        /** Completely clear the contents of the object.
119
120
            Clearing the contents of this object and rebuilding from scratch
121
            is not the optimal way to manage dynamic vertex data, since the 
122
            buffers are recreated. If you want to keep the same structure but
123
            update the content within that structure, use beginUpdate() instead 
124
            of clear() begin(). However if you do want to modify the structure 
125
            from time to time you can do so by clearing and re-specifying the data.
126
        */
127
        void clear(void);
128
        
129
        /** Estimate the number of vertices ahead of time.
130
131
            Calling this helps to avoid memory reallocation when you define
132
            vertices. Also very handy when using beginUpdate() to manage dynamic
133
            data - you can make the vertex buffers a little larger than their
134
            initial needs to allow for growth later with this method.
135
        */
136
        virtual void estimateVertexCount(uint32 vcount);
137
138
        /** Estimate the number of indices ahead of time.
139
140
            Calling this helps to avoid memory reallocation when you define
141
            indices. Also very handy when using beginUpdate() to manage dynamic
142
            data - you can make the index buffer a little larger than the
143
            initial need to allow for growth later with this method.
144
        */
145
        virtual void estimateIndexCount(uint32 icount);
146
147
        /** Start defining a part of the object.
148
149
            Each time you call this method, you start a new section of the
150
            object with its own material and potentially its own type of
151
            rendering operation (triangles, points or lines for example).
152
        @param materialName The name of the material to render this part of the
153
            object with.
154
        @param opType The type of operation to use to render.
155
        @param groupName The resource group of the material to render this part
156
            of the object with.
157
        */
158
        virtual void begin(const String& materialName,
159
            RenderOperation::OperationType opType = RenderOperation::OT_TRIANGLE_LIST,
160
            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
161
162
        /** @overload
163
        @param mat The material to render this part of the object with.
164
        @param opType The type of operation to use to render.
165
        */
166
        virtual void begin(const MaterialPtr& mat,
167
            RenderOperation::OperationType opType = RenderOperation::OT_TRIANGLE_LIST);
168
169
        /** Use before defining geometry to indicate how you intend to update the
170
            geometry.
171
        */
172
0
        void setBufferUsage(HardwareBuffer::Usage usage) { mBufferUsage = (HardwareBufferUsage)usage; }
173
174
        /// @overload
175
0
        void setDynamic(bool dyn) { mBufferUsage = dyn ? HBU_CPU_TO_GPU : HBU_GPU_ONLY; }
176
177
        /** Gets whether this object is marked as dynamic */
178
0
        bool getDynamic() const { return mBufferUsage & HBU_CPU_ONLY; }
179
180
        /** Start the definition of an update to a part of the object.
181
182
            Using this method, you can update an existing section of the object
183
            efficiently. You do not have the option of changing the operation type
184
            obviously, since it must match the one that was used before. 
185
        @note If your sections are changing size, particularly growing, use
186
            estimateVertexCount and estimateIndexCount to pre-size the buffers a little
187
            larger than the initial needs to avoid buffer reconstruction.
188
        @param sectionIndex The index of the section you want to update. The first
189
            call to begin() would have created section 0, the second section 1, etc.
190
        */
191
        virtual void beginUpdate(size_t sectionIndex);
192
        /** Add a vertex position, starting a new vertex at the same time. 
193
        @remarks A vertex position is slightly special among the other vertex data
194
            methods like normal() and textureCoord(), since calling it indicates
195
            the start of a new vertex. All other vertex data methods you call 
196
            after this are assumed to be adding more information (like normals or
197
            texture coordinates) to the last vertex started with position().
198
        */
199
        void position(const Vector3& pos)
200
0
        {
201
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
202
0
            if (mTempVertexPending)
203
0
            {
204
0
                // bake current vertex
205
0
                copyTempVertexToBuffer();
206
0
                mFirstVertex = false;
207
0
            }
208
0
209
0
            if (mFirstVertex && !mCurrentUpdating)
210
0
            {
211
0
                declareElement(VET_FLOAT3, VES_POSITION);
212
0
            }
213
0
214
0
            mTempVertex.position = Vector3f(pos);
215
0
216
0
            // update bounds
217
0
            mAABB.merge(pos);
218
0
            mRadius = std::max(mRadius, mTempVertex.position.length());
219
0
220
0
            // reset current texture coord
221
0
            mTexCoordIndex = 0;
222
0
223
0
            mTempVertexPending = true;
224
0
        }
225
        /// @overload
226
0
        void position(float x, float y, float z) { position({x, y, z}); }
227
228
        /** Add a vertex normal to the current vertex.
229
230
            Vertex normals are most often used for dynamic lighting, and 
231
            their components should be normalised.
232
        */
233
        void normal(const Vector3& norm)
234
0
        {
235
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
236
0
            if (mFirstVertex && !mCurrentUpdating)
237
0
            {
238
0
                declareElement(VET_FLOAT3, VES_NORMAL);
239
0
            }
240
0
            mTempVertex.normal = Vector3f(norm);
241
0
        }
242
        /// @overload
243
0
        void normal(float x, float y, float z)  { normal({x, y, z}); }
244
245
        /** Add a vertex tangent to the current vertex.
246
247
            Vertex tangents are most often used for dynamic lighting, and 
248
            their components should be normalised. 
249
            Also, using tangent() you enable VES_TANGENT vertex semantic, which is not
250
            supported on old non-SM2 cards.
251
        */
252
        void tangent(const Vector3& tan)
253
0
        {
254
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
255
0
            if (mFirstVertex && !mCurrentUpdating)
256
0
            {
257
0
                declareElement(VET_FLOAT3, VES_TANGENT);
258
0
            }
259
0
            mTempVertex.tangent = Vector3f(tan);
260
0
        }
261
262
        /// @overload
263
0
        void tangent(float x, float y, float z)  { tangent({x, y, z}); }
264
265
        /** Add a texture coordinate to the current vertex.
266
267
            You can call this method multiple times between position() calls
268
            to add multiple texture coordinates to a vertex. Each one can have
269
            between 1 and 3 dimensions, depending on your needs, although 2 is
270
            most common. There are several versions of this method for the 
271
            variations in number of dimensions.
272
        */
273
        void textureCoord(float u)
274
0
        {
275
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
276
0
            if (mFirstVertex && !mCurrentUpdating)
277
0
            {
278
0
                declareElement(VET_FLOAT1, VES_TEXTURE_COORDINATES);
279
0
            }
280
0
            mTempVertex.texCoord[mTexCoordIndex][0] = u;
281
0
282
0
            ++mTexCoordIndex;
283
0
        }
284
        /// @overload
285
        void textureCoord(float u, float v)
286
0
        {
287
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
288
0
            if (mFirstVertex && !mCurrentUpdating)
289
0
            {
290
0
                declareElement(VET_FLOAT2, VES_TEXTURE_COORDINATES);
291
0
            }
292
0
            mTempVertex.texCoord[mTexCoordIndex][0] = u;
293
0
            mTempVertex.texCoord[mTexCoordIndex][1] = v;
294
0
295
0
            ++mTexCoordIndex;
296
0
        }
297
        /// @overload
298
        void textureCoord(float u, float v, float w)
299
0
        {
300
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
301
0
            if (mFirstVertex && !mCurrentUpdating)
302
0
            {
303
0
                declareElement(VET_FLOAT3, VES_TEXTURE_COORDINATES);
304
0
            }
305
0
            mTempVertex.texCoord[mTexCoordIndex][0] = u;
306
0
            mTempVertex.texCoord[mTexCoordIndex][1] = v;
307
0
            mTempVertex.texCoord[mTexCoordIndex][2] = w;
308
0
309
0
            ++mTexCoordIndex;
310
0
        }
311
        /// @overload
312
0
        void textureCoord(float x, float y, float z, float w) { textureCoord(Vector4(x, y, z, w)); }
313
        /// @overload
314
0
        void textureCoord(const Vector2& uv) { textureCoord(uv.x, uv.y); }
315
        /// @overload
316
0
        void textureCoord(const Vector3& uvw) { textureCoord(uvw.x, uvw.y, uvw.z); }
317
        /// @@overload
318
        void textureCoord(const Vector4& xyzw)
319
0
        {
320
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
321
0
            if (mFirstVertex && !mCurrentUpdating)
322
0
            {
323
0
                declareElement(VET_FLOAT4, VES_TEXTURE_COORDINATES);
324
0
            }
325
0
            mTempVertex.texCoord[mTexCoordIndex] = Vector4f(xyzw);
326
0
327
0
            ++mTexCoordIndex;
328
0
        }
329
330
        /** Add a vertex colour to a vertex.
331
        */
332
        void colour(const ColourValue& col)
333
0
        {
334
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
335
0
            if (mFirstVertex && !mCurrentUpdating)
336
0
            {
337
0
                declareElement(VET_COLOUR, VES_DIFFUSE);
338
0
            }
339
0
            mTempVertex.colour = col;
340
0
        }
341
        /// @overload
342
0
        void colour(float r, float g, float b, float a = 1.0f) { colour(ColourValue(r, g, b, a)); };
343
344
        /** Add a vertex index to construct faces / lines / points via indexing
345
            rather than just by a simple list of vertices. 
346
347
            You will have to call this 3 times for each face for a triangle list, 
348
            or use the alternative 3-parameter version. Other operation types
349
            require different numbers of indexes, @see RenderOperation::OperationType.
350
        @note
351
            32-bit indexes are not supported on all cards and will only be used
352
            when required, if an index is > 65535.
353
        @param idx A vertex index from 0 to 4294967295. 
354
        */
355
        void index(uint32 idx)
356
0
        {
357
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
358
0
            mAnyIndexed = true;
359
0
            if (idx >= 65536)
360
0
                mCurrentSection->set32BitIndices(true);
361
0
362
0
            // make sure we have index data
363
0
            RenderOperation* rop = mCurrentSection->getRenderOperation();
364
0
            if (!rop->indexData)
365
0
            {
366
0
                rop->indexData = OGRE_NEW IndexData();
367
0
                rop->indexData->indexCount = 0;
368
0
            }
369
0
            rop->useIndexes = true;
370
0
            resizeTempIndexBufferIfNeeded(++rop->indexData->indexCount);
371
0
372
0
            mTempIndexBuffer[rop->indexData->indexCount - 1] = idx;
373
0
        }
374
        /** Add a set of 3 vertex indices to construct a triangle; this is a
375
            shortcut to calling index() 3 times. It is only valid for triangle 
376
            lists.
377
        @note
378
            32-bit indexes are not supported on all cards and will only be used
379
            when required, if an index is > 65535.
380
        @param i1, i2, i3 3 vertex indices from 0 to 4294967295 defining a face.
381
        */
382
        void triangle(uint32 i1, uint32 i2, uint32 i3)
383
0
        {
384
0
            OgreAssert(mCurrentSection, "You must call begin() before this method");
385
0
            OgreAssert(mCurrentSection->getRenderOperation()->operationType ==
386
0
                           RenderOperation::OT_TRIANGLE_LIST,
387
0
                       "This method is only valid on triangle lists");
388
0
            index(i1);
389
0
            index(i2);
390
0
            index(i3);
391
0
        }
392
        /** Add a set of 4 vertex indices to construct a quad (out of 2 
393
            triangles); this is a shortcut to calling index() 6 times, 
394
            or triangle() twice. It's only valid for triangle list operations.
395
        @note
396
            32-bit indexes are not supported on all cards and will only be used
397
            when required, if an index is > 65535.
398
        @param i1, i2, i3, i4 4 vertex indices from 0 to 4294967295 defining a quad. 
399
        */
400
        void quad(uint32 i1, uint32 i2, uint32 i3, uint32 i4)
401
0
        {
402
0
            // first tri
403
0
            triangle(i1, i2, i3);
404
0
            // second tri
405
0
            triangle(i3, i4, i1);
406
0
        }
407
408
        /// Get the number of vertices in the section currently being defined (returns 0 if no section is in progress).
409
        virtual size_t getCurrentVertexCount() const;
410
411
        /// Get the number of indices in the section currently being defined (returns 0 if no section is in progress).
412
        virtual size_t getCurrentIndexCount() const;
413
        
414
        /** Finish defining the object and compile the final renderable version. 
415
        @note
416
            Will return a pointer to the finished section or NULL if the section was discarded (i.e. has zero vertices/indices).
417
        */
418
        virtual ManualObjectSection* end(void);
419
420
        /** Alter the material for a subsection of this object after it has been
421
            specified.
422
423
            You specify the material to use on a section of this object during the
424
            call to begin(), however if you want to change the material afterwards
425
            you can do so by calling this method.
426
        @param subIndex The index of the subsection to alter
427
        @param name The name of the new material to use
428
        @param group The resource group of the new material to use
429
        */
430
        void setMaterialName(size_t subIndex, const String& name,
431
            const String & group = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)
432
0
        {
433
0
            mSectionList.at(subIndex)->setMaterialName(name, group);
434
0
        }
435
436
        /** @overload
437
        @param subIndex The index of the subsection to alter
438
        @param mat The new material to use
439
        */
440
        void setMaterial(size_t subIndex, const MaterialPtr& mat)
441
0
        {
442
0
            mSectionList.at(subIndex)->setMaterial(mat);
443
0
        }
444
445
        /** Convert this object to a Mesh. 
446
447
            After you've finished building this object, you may convert it to 
448
            a Mesh if you want in order to be able to create many instances of
449
            it in the world (via Entity). This is optional, since this instance
450
            can be directly attached to a SceneNode itself, but of course only
451
            one instance of it can exist that way. 
452
        @note Only objects which use indexed geometry may be converted to a mesh.
453
        @param meshName The name to give the mesh
454
        @param groupName The resource group to create the mesh in
455
        */
456
        virtual MeshPtr convertToMesh(const String& meshName, 
457
            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
458
459
        /** Sets whether or not to use an 'identity' projection.
460
461
            Usually ManualObjects will use a projection matrix as determined
462
            by the active camera. However, if they want they can cancel this out
463
            and use an identity projection, which effectively projects in 2D using
464
            a {-1, 1} view space. Useful for overlay rendering. Normally you don't
465
            need to change this. The default is false.
466
        @see ManualObject::getUseIdentityProjection
467
        */
468
        void setUseIdentityProjection(bool useIdentityProjection);
469
470
        /** Returns whether or not to use an 'identity' projection.
471
472
            Usually ManualObjects will use a projection matrix as determined
473
            by the active camera. However, if they want they can cancel this out
474
            and use an identity projection, which effectively projects in 2D using
475
            a {-1, 1} view space. Useful for overlay rendering. Normally you don't
476
            need to change this.
477
        @see ManualObject::setUseIdentityProjection
478
        */
479
0
        bool getUseIdentityProjection(void) const { return mUseIdentityProjection; }
480
481
        /** Sets whether or not to use an 'identity' view.
482
483
            Usually ManualObjects will use a view matrix as determined
484
            by the active camera. However, if they want they can cancel this out
485
            and use an identity matrix, which means all geometry is assumed
486
            to be relative to camera space already. Useful for overlay rendering. 
487
            Normally you don't need to change this. The default is false.
488
        @see ManualObject::getUseIdentityView
489
        */
490
        void setUseIdentityView(bool useIdentityView);
491
492
        /** Returns whether or not to use an 'identity' view.
493
494
            Usually ManualObjects will use a view matrix as determined
495
            by the active camera. However, if they want they can cancel this out
496
            and use an identity matrix, which means all geometry is assumed
497
            to be relative to camera space already. Useful for overlay rendering. 
498
            Normally you don't need to change this.
499
        @see ManualObject::setUseIdentityView
500
        */
501
0
        bool getUseIdentityView(void) const { return mUseIdentityView; }
502
503
        /** Sets the bounding box.
504
            @remarks Call this after having finished creating sections to modify the
505
                bounding box. E.g. if you're using ManualObject to create 2D overlays
506
                you can call things function to set an infinite bounding box so that
507
                the object always stays visible when attached.
508
            @see ManualObject::setUseIdentityProjection, ManualObject::setUseIdentityView,
509
                AxisAlignedBox::setInfinite */
510
0
        void setBoundingBox(const AxisAlignedBox& box) { mAABB = box; }
511
512
        /** Gets the list of ManualObjectSection, i.e. a part of a ManualObject.
513
        */
514
0
        const std::vector<ManualObjectSection*>& getSections() const { return mSectionList; }
515
516
0
        ManualObjectSection* getSection(size_t index) const { return mSectionList.at(index); }
517
518
0
        size_t getNumSections(void) const { return mSectionList.size(); }
519
520
521
        /** Sets whether or not to keep the original declaration order when 
522
            queuing the renderables.
523
524
            This overrides the default behavior of the rendering queue, 
525
            specifically stating the desired order of rendering. Might result in a 
526
            performance loss, but lets the user to have more direct control when 
527
            creating geometry through this class.
528
        @param keepOrder Whether to keep the declaration order or not.
529
        */
530
0
        void setKeepDeclarationOrder(bool keepOrder) { mKeepDeclarationOrder = keepOrder; }
531
532
        /** Gets whether or not the declaration order is to be kept or not.
533
        @return A flag indication if the declaration order will be kept when 
534
            queuing the renderables.
535
        */
536
0
        bool getKeepDeclarationOrder() const { return mKeepDeclarationOrder; }
537
        // MovableObject overrides
538
539
        /** @copydoc MovableObject::getMovableType */
540
        const String& getMovableType(void) const override;
541
        /** @copydoc MovableObject::getBoundingBox */
542
0
        const AxisAlignedBox& getBoundingBox(void) const override { return mAABB; }
543
        /** @copydoc MovableObject::getBoundingRadius */
544
0
        Real getBoundingRadius(void) const override { return mRadius; }
545
        /** @copydoc MovableObject::_updateRenderQueue */
546
        void _updateRenderQueue(RenderQueue* queue) override;
547
        /** Implement this method to enable stencil shadows */
548
        EdgeData* getEdgeList(void) override;
549
        /** Implement this method to enable stencil shadows. */
550
        const ShadowRenderableList& getShadowVolumeRenderableList(
551
            const Light* light, const HardwareIndexBufferPtr& indexBuffer,
552
            size_t& indexBufferUsedSize, float extrusionDist, int flags = 0) override;
553
554
        /// Built, renderable section of geometry
555
        class _OgreExport ManualObjectSection : public Renderable, public MovableAlloc
556
        {
557
        protected:
558
            ManualObject* mParent;
559
            mutable MaterialPtr mMaterial;
560
            RenderOperation mRenderOperation;
561
            bool m32BitIndices;
562
563
564
        public:
565
            ManualObjectSection(ManualObject* parent, const String& materialName,
566
                RenderOperation::OperationType opType,
567
                const String & groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
568
            /// @remark mat should not be null.
569
            ManualObjectSection(ManualObject* parent, const MaterialPtr& mat,
570
                RenderOperation::OperationType opType);
571
            virtual ~ManualObjectSection();
572
573
            /// Retrieve render operation for manipulation
574
            RenderOperation* getRenderOperation(void);
575
            /// Retrieve the material name in use
576
0
            const String& getMaterialName(void) const { return mMaterial ? mMaterial->getName() : BLANKSTRING; }
577
            /// Retrieve the material group in use
578
0
            const String& getMaterialGroup(void) const { return mMaterial ? mMaterial->getGroup() : BLANKSTRING; }
579
            /// update the material name in use
580
            void setMaterialName(const String& name,
581
                const String& groupName = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
582
            /// Update the material in use
583
            /// @remark mat should not be null.
584
            void setMaterial(const MaterialPtr& mat);
585
586
            /// Set whether we need 32-bit indices
587
0
            void set32BitIndices(bool n32) { m32BitIndices = n32; }
588
            /// Get whether we need 32-bit indices
589
0
            bool get32BitIndices() const { return m32BitIndices; }
590
            
591
            // Renderable overrides
592
            /** @copydoc Renderable::getMaterial */
593
            const MaterialPtr& getMaterial(void) const override;
594
            /** @copydoc Renderable::getRenderOperation */
595
            void getRenderOperation(RenderOperation& op) override;
596
            /** @copydoc Renderable::getWorldTransforms */
597
            void getWorldTransforms(Matrix4* xform) const override;
598
            /** @copydoc Renderable::getSquaredViewDepth */
599
            Real getSquaredViewDepth(const Ogre::Camera *) const override;
600
            /** @copydoc Renderable::getLights */
601
            const LightList &getLights(void) const override;
602
603
            /// convert this section to a SubMesh
604
            void convertToSubMesh(SubMesh* sm) const;
605
                    
606
        };
607
608
        typedef std::vector<ManualObjectSection*> SectionList;
609
610
        /// @copydoc MovableObject::visitRenderables
611
        void visitRenderables(Renderable::Visitor* visitor, 
612
            bool debugRenderables = false) override;
613
        
614
        
615
    private:
616
        /// Dynamic?
617
        HardwareBufferUsage mBufferUsage;
618
        /// List of subsections
619
        SectionList mSectionList;
620
        /// Current section
621
        ManualObjectSection* mCurrentSection;
622
        /// Are we updating?
623
        bool mCurrentUpdating;
624
        /// Temporary vertex structure
625
        struct TempVertex
626
        {
627
            Vector3f position;
628
            Vector3f normal;
629
            Vector3f tangent;
630
            Vector4f texCoord[OGRE_MAX_TEXTURE_COORD_SETS];
631
            ColourValue colour;
632
        };
633
        /// Temp storage
634
        TempVertex mTempVertex;
635
        /// First vertex indicator
636
        bool mFirstVertex;
637
        /// Temp vertex data to copy?
638
        bool mTempVertexPending;
639
        /// System-memory buffer whilst we establish the size required
640
        char* mTempVertexBuffer;
641
        /// System memory allocation size, in bytes
642
        size_t mTempVertexSize;
643
        /// System-memory buffer whilst we establish the size required
644
        uint32* mTempIndexBuffer;
645
        /// System memory allocation size, in bytes
646
        size_t mTempIndexSize;
647
        /// Current declaration vertex size
648
        size_t mDeclSize;
649
        /// Estimated vertex count
650
        uint32 mEstVertexCount;
651
        /// Estimated index count
652
        uint32 mEstIndexCount;
653
        /// Current texture coordinate
654
        ushort mTexCoordIndex;
655
        /// Bounding box
656
        AxisAlignedBox mAABB;
657
        /// Bounding sphere
658
        Real mRadius;
659
        /// Any indexed geometry on any sections?
660
        bool mAnyIndexed;
661
        /// Edge list, used if stencil shadow casting is enabled 
662
        EdgeData* mEdgeList;
663
        /// List of shadow renderables
664
        ShadowRenderableList mShadowRenderables;
665
        /// Whether to use identity projection for sections
666
        bool mUseIdentityProjection;
667
        /// Whether to use identity view for sections
668
        bool mUseIdentityView;
669
        /// Keep declaration order or let the queue optimize it
670
        bool mKeepDeclarationOrder;
671
672
673
        /// Delete temp buffers and reset init counts
674
        void resetTempAreas(void);
675
        /// Resize the temp vertex buffer?
676
        void resizeTempVertexBufferIfNeeded(size_t numVerts);
677
        /// Resize the temp index buffer?
678
        void resizeTempIndexBufferIfNeeded(size_t numInds);
679
680
        /// Copy current temp vertex into buffer
681
        void copyTempVertexToBuffer(void);
682
683
    private:
684
        void declareElement(VertexElementType t, VertexElementSemantic s);
685
    };
686
    /** @} */
687
    /** @} */
688
}
689
690
#include "OgreHeaderSuffix.h"
691
692
#endif
693
694