source: GTP/trunk/Lib/Geom/OgreStuff/include/OgreHardwareVertexBuffer.h @ 1809

Revision 1809, 22.6 KB checked in by gumbau, 18 years ago (diff)
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#ifndef __HardwareVertexBuffer__
26#define __HardwareVertexBuffer__
27
28// Precompiler options
29#include "OgrePrerequisites.h"
30#include "OgreHardwareBuffer.h"
31#include "OgreSharedPtr.h"
32#include "OgreColourValue.h"
33
34namespace Ogre {
35    /** Specialisation of HardwareBuffer for a vertex buffer. */
36    class _OgreExport HardwareVertexBuffer : public HardwareBuffer
37    {
38            protected:
39
40                    size_t mNumVertices;
41            size_t mVertexSize;
42
43            public:
44                    /// Should be called by HardwareBufferManager
45                    HardwareVertexBuffer(size_t vertexSize, size_t numVertices,
46                HardwareBuffer::Usage usage, bool useSystemMemory, bool useShadowBuffer);
47            ~HardwareVertexBuffer();
48            /// Gets the size in bytes of a single vertex in this buffer
49            size_t getVertexSize(void) const { return mVertexSize; }
50            /// Get the number of vertices in this buffer
51            size_t getNumVertices(void) const { return mNumVertices; }
52
53
54
55                    // NB subclasses should override lock, unlock, readData, writeData
56
57    };
58
59    /** Shared pointer implementation used to share index buffers. */
60    class _OgreExport HardwareVertexBufferSharedPtr : public SharedPtr<HardwareVertexBuffer>
61    {
62    public:
63        HardwareVertexBufferSharedPtr() : SharedPtr<HardwareVertexBuffer>() {}
64        explicit HardwareVertexBufferSharedPtr(HardwareVertexBuffer* buf);
65
66
67    };
68
69    /// Vertex element semantics, used to identify the meaning of vertex buffer contents
70        enum VertexElementSemantic {
71                /// Position, 3 reals per vertex
72                VES_POSITION = 1,
73                /// Blending weights
74                VES_BLEND_WEIGHTS = 2,
75        /// Blending indices
76        VES_BLEND_INDICES = 3,
77                /// Normal, 3 reals per vertex
78                VES_NORMAL = 4,
79                /// Diffuse colours
80                VES_DIFFUSE = 5,
81                /// Specular colours
82                VES_SPECULAR = 6,
83                /// Texture coordinates
84                VES_TEXTURE_COORDINATES = 7,
85        /// Binormal (Y axis if normal is Z)
86        VES_BINORMAL = 8,
87        /// Tangent (X axis if normal is Z)
88        VES_TANGENT = 9
89
90        };
91
92    /// Vertex element type, used to identify the base types of the vertex contents
93    enum VertexElementType
94    {
95        VET_FLOAT1 = 0,
96        VET_FLOAT2 = 1,
97        VET_FLOAT3 = 2,
98        VET_FLOAT4 = 3,
99        /// alias to more specific colour type - use the current rendersystem's colour packing
100                VET_COLOUR = 4,
101                VET_SHORT1 = 5,
102                VET_SHORT2 = 6,
103                VET_SHORT3 = 7,
104                VET_SHORT4 = 8,
105        VET_UBYTE4 = 9,
106        /// D3D style compact colour
107        VET_COLOUR_ARGB = 10,
108        /// GL style compact colour
109        VET_COLOUR_ABGR = 11
110    };
111
112    /** This class declares the usage of a single vertex buffer as a component
113        of a complete VertexDeclaration.
114        @remarks
115        Several vertex buffers can be used to supply the input geometry for a
116        rendering operation, and in each case a vertex buffer can be used in
117        different ways for different operations; the buffer itself does not
118        define the semantics (position, normal etc), the VertexElement
119        class does.
120    */
121    class _OgreExport VertexElement
122    {
123    protected:
124        /// The source vertex buffer, as bound to an index using VertexBufferBinding
125        unsigned short mSource;
126        /// The offset in the buffer that this element starts at
127        size_t mOffset;
128        /// The type of element
129        VertexElementType mType;
130        /// The meaning of the element
131        VertexElementSemantic mSemantic;
132        /// Index of the item, only applicable for some elements like texture coords
133        unsigned short mIndex;
134    public:
135        /// Constructor, should not be called directly, call VertexDeclaration::addElement
136        VertexElement(unsigned short source, size_t offset, VertexElementType theType,
137            VertexElementSemantic semantic, unsigned short index = 0);
138        /// Gets the vertex buffer index from where this element draws it's values
139        unsigned short getSource(void) const { return mSource; }
140        /// Gets the offset into the buffer where this element starts
141        size_t getOffset(void) const { return mOffset; }
142        /// Gets the data format of this element
143        VertexElementType getType(void) const { return mType; }
144        /// Gets the meaning of this element
145        VertexElementSemantic getSemantic(void) const { return mSemantic; }
146        /// Gets the index of this element, only applicable for repeating elements
147        unsigned short getIndex(void) const { return mIndex; }
148                /// Gets the size of this element in bytes
149                size_t getSize(void) const;
150                /// Utility method for helping to calculate offsets
151                static size_t getTypeSize(VertexElementType etype);
152                /// Utility method which returns the count of values in a given type
153                static unsigned short getTypeCount(VertexElementType etype);
154                /** Simple converter function which will turn a single-value type into a
155                        multi-value type based on a parameter.
156                */
157                static VertexElementType multiplyTypeCount(VertexElementType baseType, unsigned short count);
158                /** Simple converter function which will a type into it's single-value
159                        equivalent - makes switches on type easier.
160                */
161                static VertexElementType getBaseType(VertexElementType multiType);
162
163                /** Utility method for converting colour from
164                        one packed 32-bit colour type to another.
165                @param srcType The source type
166                @param dstType The destination type
167                @param ptr Read / write value to change
168                */
169                static void convertColourValue(VertexElementType srcType,
170                        VertexElementType dstType, uint32* ptr);
171
172                /** Utility method for converting colour to
173                        a packed 32-bit colour type.
174                @param src source colour
175                @param dst The destination type
176                */
177                static uint32 convertColourValue(const ColourValue& src,
178                        VertexElementType dst);
179
180                /** Utility method to get the most appropriate packed colour vertex element format. */
181                static VertexElementType getBestColourVertexElementType(void);
182
183        inline bool operator== (const VertexElement& rhs) const
184        {
185            if (mType != rhs.mType ||
186                mIndex != rhs.mIndex ||
187                mOffset != rhs.mOffset ||
188                mSemantic != rhs.mSemantic ||
189                mSource != rhs.mSource)
190                return false;
191            else
192                return true;
193
194        }
195        /** Adjusts a pointer to the base of a vertex to point at this element.
196        @remarks
197            This variant is for void pointers, passed as a parameter because we can't
198            rely on covariant return types.
199        @param pBase Pointer to the start of a vertex in this buffer.
200        @param pElem Pointer to a pointer which will be set to the start of this element.
201        */
202        inline void baseVertexPointerToElement(void* pBase, void** pElem) const
203        {
204            // The only way we can do this is to cast to char* in order to use byte offset
205            // then cast back to void*.
206            *pElem = static_cast<void*>(
207                static_cast<unsigned char*>(pBase) + mOffset);
208        }
209        /** Adjusts a pointer to the base of a vertex to point at this element.
210        @remarks
211            This variant is for float pointers, passed as a parameter because we can't
212            rely on covariant return types.
213        @param pBase Pointer to the start of a vertex in this buffer.
214        @param pElem Pointer to a pointer which will be set to the start of this element.
215        */
216        inline void baseVertexPointerToElement(void* pBase, float** pElem) const
217        {
218            // The only way we can do this is to cast to char* in order to use byte offset
219            // then cast back to float*. However we have to go via void* because casting
220            // directly is not allowed
221            *pElem = static_cast<float*>(
222                static_cast<void*>(
223                    static_cast<unsigned char*>(pBase) + mOffset));
224        }
225
226        /** Adjusts a pointer to the base of a vertex to point at this element.
227        @remarks
228            This variant is for RGBA pointers, passed as a parameter because we can't
229            rely on covariant return types.
230        @param pBase Pointer to the start of a vertex in this buffer.
231        @param pElem Pointer to a pointer which will be set to the start of this element.
232        */
233        inline void baseVertexPointerToElement(void* pBase, RGBA** pElem) const
234        {
235            *pElem = static_cast<RGBA*>(
236                static_cast<void*>(
237                    static_cast<unsigned char*>(pBase) + mOffset));
238        }
239        /** Adjusts a pointer to the base of a vertex to point at this element.
240        @remarks
241            This variant is for char pointers, passed as a parameter because we can't
242            rely on covariant return types.
243        @param pBase Pointer to the start of a vertex in this buffer.
244        @param pElem Pointer to a pointer which will be set to the start of this element.
245        */
246        inline void baseVertexPointerToElement(void* pBase, unsigned char** pElem) const
247        {
248            *pElem = static_cast<unsigned char*>(pBase) + mOffset;
249        }
250
251        /** Adjusts a pointer to the base of a vertex to point at this element.
252        @remarks
253        This variant is for ushort pointers, passed as a parameter because we can't
254        rely on covariant return types.
255        @param pBase Pointer to the start of a vertex in this buffer.
256        @param pElem Pointer to a pointer which will be set to the start of this element.
257        */
258        inline void baseVertexPointerToElement(void* pBase, unsigned short** pElem) const
259        {
260            *pElem = static_cast<unsigned short*>(pBase) + mOffset;
261        }
262
263
264    };
265    /** This class declares the format of a set of vertex inputs, which
266        can be issued to the rendering API through a RenderOperation.
267        @remarks
268        You should be aware that the ordering and structure of the
269        VertexDeclaration can be very important on DirectX with older
270        cards,so if you want to maintain maximum compatibility with
271        all render systems and all cards you should be careful to follow these
272        rules:<ol>
273        <li>VertexElements should be added in the following order, and the order of the
274        elements within a shared buffer should be as follows:
275        position, blending weights, normals, diffuse colours, specular colours,
276            texture coordinates (in order, with no gaps)</li>
277        <li>You must not have unused gaps in your buffers which are not referenced
278        by any VertexElement</li>
279        <li>You must not cause the buffer & offset settings of 2 VertexElements to overlap</li>
280        </ol>
281        Whilst GL and more modern graphics cards in D3D will allow you to defy these rules,
282        sticking to them will ensure that your buffers have the maximum compatibility.
283        @par
284        Like the other classes in this functional area, these declarations should be created and
285        destroyed using the HardwareBufferManager.
286    */
287    class _OgreExport VertexDeclaration
288    {
289    public:
290                /// Defines the list of vertex elements that makes up this declaration
291        typedef std::list<VertexElement> VertexElementList;
292        /// Sort routine for vertex elements
293        static bool vertexElementLess(const VertexElement& e1, const VertexElement& e2);
294    protected:
295        VertexElementList mElementList;
296    public:
297        /// Standard constructor, not you should use HardwareBufferManager::createVertexDeclaration
298        VertexDeclaration();
299        virtual ~VertexDeclaration();
300
301        /** Get the number of elements in the declaration. */
302        size_t getElementCount(void) { return mElementList.size(); }
303        /** Gets read-only access to the list of vertex elements. */
304        const VertexElementList& getElements(void) const;
305        /** Get a single element. */
306        const VertexElement* getElement(unsigned short index);
307
308        /** Sorts the elements in this list to be compatible with the maximum
309            number of rendering APIs / graphics cards.
310        @remarks
311            Older graphics cards require vertex data to be presented in a more
312            rigid way, as defined in the main documentation for this class. As well
313            as the ordering being important, where shared source buffers are used, the
314            declaration must list all the elements for each source in turn.
315        */
316        void sort(void);
317
318        /** Remove any gaps in the source buffer list used by this declaration.
319        @remarks
320            This is useful if you've modified a declaration and want to remove
321            any gaps in the list of buffers being used. Note, however, that if this
322            declaration is already being used with a VertexBufferBinding, you will
323            need to alter that too. This method is mainly useful when reorganising
324            buffers based on an altered declaration.
325        @note
326            This will cause the vertex declaration to be re-sorted.
327        */
328        void closeGapsInSource(void);
329
330        /** Generates a new VertexDeclaration for optimal usage based on the current
331            vertex declaration, which can be used with VertexData::reorganiseBuffers later
332            if you wish, or simply used as a template.
333                @remarks
334                        Different buffer organisations and buffer usages will be returned
335            depending on the parameters passed to this method.
336        @param skeletalAnimation Whether this vertex data is going to be
337                        skeletally animated
338                @param vertexAnimation Whether this vertex data is going to be vertex animated
339        */
340        VertexDeclaration* getAutoOrganisedDeclaration(bool skeletalAnimation,
341                        bool vertexAnimation);
342
343        /** Gets the indeex of the highest source value referenced by this declaration. */
344        unsigned short getMaxSource(void) const;
345
346
347
348        /** Adds a new VertexElement to this declaration.
349        @remarks
350            This method adds a single element (positions, normals etc) to the end of the
351            vertex declaration. <b>Please read the information in VertexDeclaration about
352            the importance of ordering and structure for compatibility with older D3D drivers</b>.
353            @param source The binding index of HardwareVertexBuffer which will provide the source for this element.
354                        See VertexBufferBindingState for full information.
355        @param offset The offset in bytes where this element is located in the buffer
356        @param theType The data format of the element (3 floats, a colour etc)
357        @param semantic The meaning of the data (position, normal, diffuse colour etc)
358        @param index Optional index for multi-input elements like texture coordinates
359                @returns A reference to the VertexElement added.
360        */
361        virtual const VertexElement& addElement(unsigned short source, size_t offset, VertexElementType theType,
362            VertexElementSemantic semantic, unsigned short index = 0);
363        /** Inserts a new VertexElement at a given position in this declaration.
364        @remarks
365        This method adds a single element (positions, normals etc) at a given position in this
366        vertex declaration. <b>Please read the information in VertexDeclaration about
367        the importance of ordering and structure for compatibility with older D3D drivers</b>.
368        @param source The binding index of HardwareVertexBuffer which will provide the source for this element.
369        See VertexBufferBindingState for full information.
370        @param offset The offset in bytes where this element is located in the buffer
371        @param theType The data format of the element (3 floats, a colour etc)
372        @param semantic The meaning of the data (position, normal, diffuse colour etc)
373        @param index Optional index for multi-input elements like texture coordinates
374        @returns A reference to the VertexElement added.
375        */
376        virtual const VertexElement& insertElement(unsigned short atPosition,
377            unsigned short source, size_t offset, VertexElementType theType,
378            VertexElementSemantic semantic, unsigned short index = 0);
379
380        /** Remove the element at the given index from this declaration. */
381        virtual void removeElement(unsigned short elem_index);
382
383        /** Remove the element with the given semantic and usage index.
384        @remarks
385            In this case 'index' means the usage index for repeating elements such
386            as texture coordinates. For other elements this will always be 0 and does
387            not refer to the index in the vector.
388        */
389        virtual void removeElement(VertexElementSemantic semantic, unsigned short index = 0);
390
391                /** Remove all elements. */
392                virtual void removeAllElements(void);
393
394        /** Modify an element in-place, params as addElement.
395           @remarks
396           <b>Please read the information in VertexDeclaration about
397            the importance of ordering and structure for compatibility with older D3D drivers</b>.
398         */
399        virtual void modifyElement(unsigned short elem_index, unsigned short source, size_t offset, VertexElementType theType,
400            VertexElementSemantic semantic, unsigned short index = 0);
401
402                /** Finds a VertexElement with the given semantic, and index if there is more than
403                        one element with the same semantic.
404        @remarks
405            If the element is not found, this method returns null.
406                */
407                virtual const VertexElement* findElementBySemantic(VertexElementSemantic sem, unsigned short index = 0);
408                /** Based on the current elements, gets the size of the vertex for a given buffer source.
409                @param source The buffer binding index for which to get the vertex size.
410                */
411
412                /** Gets a list of elements which use a given source.
413                @remarks
414                        Note that the list of elements is returned by value therefore is separate from
415                        the declaration as soon as this method returns.
416                */
417                virtual VertexElementList findElementsBySource(unsigned short source);
418
419                /** Gets the vertex size defined by this declaration for a given source. */
420        virtual size_t getVertexSize(unsigned short source);
421
422        /** Clones this declaration. */
423        virtual VertexDeclaration* clone(void);
424
425        inline bool operator== (const VertexDeclaration& rhs) const
426        {
427            if (mElementList.size() != rhs.mElementList.size())
428                return false;
429
430            VertexElementList::const_iterator i, iend, rhsi, rhsiend;
431            iend = mElementList.end();
432            rhsiend = rhs.mElementList.end();
433            rhsi = rhs.mElementList.begin();
434            for (i = mElementList.begin(); i != iend && rhsi != rhsiend; ++i, ++rhsi)
435            {
436                if ( !(*i == *rhsi) )
437                    return false;
438            }
439
440            return true;
441        }
442        inline bool operator!= (const VertexDeclaration& rhs) const
443        {
444            return !(*this == rhs);
445        }
446
447    };
448
449        /** Records the state of all the vertex buffer bindings required to provide a vertex declaration
450                with the input data it needs for the vertex elements.
451        @remarks
452                Why do we have this binding list rather than just have VertexElement referring to the
453                vertex buffers direct? Well, in the underlying APIs, binding the vertex buffers to an
454                index (or 'stream') is the way that vertex data is linked, so this structure better
455                reflects the realities of that. In addition, by separating the vertex declaration from
456                the list of vertex buffer bindings, it becomes possible to reuse bindings between declarations
457                and vice versa, giving opportunities to reduce the state changes required to perform rendering.
458        @par
459                Like the other classes in this functional area, these binding maps should be created and
460                destroyed using the HardwareBufferManager.
461        */
462        class _OgreExport VertexBufferBinding
463        {
464        public:
465                /// Defines the vertex buffer bindings used as source for vertex declarations
466                typedef std::map<unsigned short, HardwareVertexBufferSharedPtr> VertexBufferBindingMap;
467        protected:
468                VertexBufferBindingMap mBindingMap;
469                mutable unsigned short mHighIndex;
470        public:
471                /// Constructor, should not be called direct, use HardwareBufferManager::createVertexBufferBinding
472                VertexBufferBinding();
473                virtual ~VertexBufferBinding();
474                /** Set a binding, associating a vertex buffer with a given index.
475                @remarks
476                        If the index is already associated with a vertex buffer,
477            the association will be replaced. This may cause the old buffer
478            to be destroyed if nothing else is referring to it.
479                        You should assign bindings from 0 and not leave gaps, although you can
480                        bind them in any order.
481                */
482                virtual void setBinding(unsigned short index, HardwareVertexBufferSharedPtr buffer);
483                /** Removes an existing binding. */
484                virtual void unsetBinding(unsigned short index);
485
486        /** Removes all the bindings. */
487        virtual void unsetAllBindings(void);
488
489                /// Gets a read-only version of the buffer bindings
490                virtual const VertexBufferBindingMap& getBindings(void) const;
491
492                /// Gets the buffer bound to the given source index
493                virtual HardwareVertexBufferSharedPtr getBuffer(unsigned short index);
494                /// Gets whether a buffer is bound to the given source index
495                virtual bool isBufferBound(unsigned short index);
496
497        virtual size_t getBufferCount(void) const { return mBindingMap.size(); }
498
499                /** Gets the highest index which has already been set, plus 1.
500                @remarks
501                        This is to assist in binding the vertex buffers such that there are
502                        not gaps in the list.
503                */
504                virtual unsigned short getNextIndex(void) const { return mHighIndex++; }
505
506
507
508
509        };
510
511
512
513}
514#endif
515
Note: See TracBrowser for help on using the repository browser.