Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgrePanelOverlayElement.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 15.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  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
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
31#include "OgrePanelOverlayElement.h"
32#include "OgreMaterial.h"
33#include "OgreTechnique.h"
34#include "OgrePass.h"
35#include "OgreStringConverter.h"
36#include "OgreHardwareBufferManager.h"
37#include "OgreRoot.h"
38#include "OgreRenderSystem.h"
39
40namespace Ogre {
41    //---------------------------------------------------------------------
42    String PanelOverlayElement::msTypeName = "Panel";
43    PanelOverlayElement::CmdTiling PanelOverlayElement::msCmdTiling;
44    PanelOverlayElement::CmdTransparent PanelOverlayElement::msCmdTransparent;
45    PanelOverlayElement::CmdUVCoords PanelOverlayElement::msCmdUVCoords;
46    //---------------------------------------------------------------------
47    // vertex buffer bindings, set at compile time (we could look these up but no point)
48    #define POSITION_BINDING 0
49    #define TEXCOORD_BINDING 1
50
51    //---------------------------------------------------------------------
52    PanelOverlayElement::PanelOverlayElement(const String& name)
53        : OverlayContainer(name)
54        , mTransparent(false)
55        // Defer creation of texcoord buffer until we know how big it needs to be
56        , mNumTexCoordsInBuffer(0)
57        , mU1(0.0)
58        , mV1(0.0)
59        , mU2(1.0)
60        , mV2(1.0)
61
62    {
63        // Init tiling
64        for (ushort i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; ++i)
65        {
66            mTileX[i] = 1.0f;
67            mTileY[i] = 1.0f;
68        }
69
70        // No normals or colours
71        if (createParamDictionary("PanelOverlayElement"))
72        {
73            addBaseParameters();
74        }
75
76    }
77    //---------------------------------------------------------------------
78    PanelOverlayElement::~PanelOverlayElement()
79    {
80        delete mRenderOp.vertexData;
81    }
82    //---------------------------------------------------------------------
83    void PanelOverlayElement::initialise(void)
84    {
85                bool init = !mInitialised;
86
87                OverlayContainer::initialise();
88                if (init)
89                {
90                        // Setup render op in advance
91                        mRenderOp.vertexData = new VertexData();
92                        // Vertex declaration: 1 position, add texcoords later depending on #layers
93                        // Create as separate buffers so we can lock & discard separately
94                        VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
95                        decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION);
96
97                        // Basic vertex data
98                        mRenderOp.vertexData->vertexStart = 0;
99                        mRenderOp.vertexData->vertexCount = 4;
100
101                        // Vertex buffer #1
102                        HardwareVertexBufferSharedPtr vbuf =
103                                HardwareBufferManager::getSingleton().createVertexBuffer(
104                                decl->getVertexSize(POSITION_BINDING), mRenderOp.vertexData->vertexCount,
105                                HardwareBuffer::HBU_STATIC_WRITE_ONLY// mostly static except during resizing
106                                );
107                        // Bind buffer
108                        mRenderOp.vertexData->vertexBufferBinding->setBinding(POSITION_BINDING, vbuf);
109
110                        // No indexes & issue as a strip
111                        mRenderOp.useIndexes = false;
112                        mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP;
113
114                        mInitialised = true;
115                }
116    }
117    //---------------------------------------------------------------------
118    void PanelOverlayElement::setTiling(Real x, Real y, ushort layer)
119    {
120        assert (layer < OGRE_MAX_TEXTURE_COORD_SETS);
121        assert (x != 0 && y != 0);
122
123        mTileX[layer] = x;
124        mTileY[layer] = y;
125
126        mGeomUVsOutOfDate = true;
127
128    }
129    //---------------------------------------------------------------------
130    Real PanelOverlayElement::getTileX(ushort layer) const
131    {
132        return mTileX[layer];
133    }
134    //---------------------------------------------------------------------
135    Real PanelOverlayElement::getTileY(ushort layer) const
136    {
137        return mTileY[layer];
138    }
139    //---------------------------------------------------------------------
140    void PanelOverlayElement::setTransparent(bool isTransparent)
141    {
142        mTransparent = isTransparent;
143    }
144    //---------------------------------------------------------------------
145    bool PanelOverlayElement::isTransparent(void) const
146    {
147        return mTransparent;
148    }
149    //---------------------------------------------------------------------
150    void PanelOverlayElement::setUV(Real u1, Real v1, Real u2, Real v2)
151    {
152                mU1 = u1;
153                mU2 = u2;
154                mV1 = v1;
155                mV2 = v2;
156                mGeomUVsOutOfDate = true;
157    }
158    void PanelOverlayElement::getUV(Real& u1, Real& v1, Real& u2, Real& v2) const
159    {
160                u1 = mU1;
161                u2 = mU2;
162                v1 = mV1;
163                v2 = mV2;
164    }
165    //---------------------------------------------------------------------
166    const String& PanelOverlayElement::getTypeName(void) const
167    {
168        return msTypeName;
169    }
170    //---------------------------------------------------------------------
171    void PanelOverlayElement::getRenderOperation(RenderOperation& op)
172    {
173        op = mRenderOp;
174    }
175    //---------------------------------------------------------------------
176    void PanelOverlayElement::setMaterialName(const String& matName)
177    {
178        OverlayContainer::setMaterialName(matName);
179    }
180    //---------------------------------------------------------------------
181    void PanelOverlayElement::_updateRenderQueue(RenderQueue* queue)
182    {
183        if (mVisible)
184        {
185
186            if (!mTransparent && !mpMaterial.isNull())
187            {
188                OverlayElement::_updateRenderQueue(queue);
189            }
190
191            // Also add children
192            ChildIterator it = getChildIterator();
193            while (it.hasMoreElements())
194            {
195                // Give children ZOrder 1 higher than this
196                it.getNext()->_updateRenderQueue(queue);
197            }
198        }
199    }
200    //---------------------------------------------------------------------
201    void PanelOverlayElement::updatePositionGeometry(void)
202    {
203                /*
204                        0-----2
205                        |    /|
206                        |  /  |
207                        |/    |
208                        1-----3
209                */
210                Real left, right, top, bottom;
211
212                /* Convert positions into -1, 1 coordinate space (homogenous clip space).
213                        - Left / right is simple range conversion
214                        - Top / bottom also need inverting since y is upside down - this means
215                        that top will end up greater than bottom and when computing texture
216                        coordinates, we have to flip the v-axis (ie. subtract the value from
217                        1.0 to get the actual correct value).
218                */
219                left = _getDerivedLeft() * 2 - 1;
220                right = left + (mWidth * 2);
221                top = -((_getDerivedTop() * 2) - 1);
222                bottom =  top -  (mHeight * 2);
223
224                HardwareVertexBufferSharedPtr vbuf =
225                        mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);
226                float* pPos = static_cast<float*>(
227                        vbuf->lock(HardwareBuffer::HBL_DISCARD) );
228
229                // Use the furthest away depth value, since materials should have depth-check off
230                // This initialised the depth buffer for any 3D objects in front
231                Real zValue = Root::getSingleton().getRenderSystem()->getMaximumDepthInputValue();
232                *pPos++ = left;
233                *pPos++ = top;
234                *pPos++ = zValue;
235
236                *pPos++ = left;
237                *pPos++ = bottom;
238                *pPos++ = zValue;
239
240                *pPos++ = right;
241                *pPos++ = top;
242                *pPos++ = zValue;
243
244                *pPos++ = right;
245                *pPos++ = bottom;
246                *pPos++ = zValue;
247
248                vbuf->unlock();
249    }
250    //---------------------------------------------------------------------
251    void PanelOverlayElement::updateTextureGeometry(void)
252    {
253        // Generate for as many texture layers as there are in material
254        if (!mpMaterial.isNull() && mInitialised)
255        {
256            // Assume one technique and pass for the moment
257            size_t numLayers = mpMaterial->getTechnique(0)->getPass(0)->getNumTextureUnitStates();
258
259            VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
260            // Check the number of texcoords we have in our buffer now
261            if (mNumTexCoordsInBuffer > numLayers)
262            {
263                // remove extras
264                for (size_t i = mNumTexCoordsInBuffer; i > numLayers; --i)
265                {
266                    decl->removeElement(VES_TEXTURE_COORDINATES, 
267                                                static_cast<unsigned short>(i));
268                }
269            }
270            else if (mNumTexCoordsInBuffer < numLayers)
271            {
272                // Add extra texcoord elements
273                size_t offset = VertexElement::getTypeSize(VET_FLOAT2) * mNumTexCoordsInBuffer;
274                for (size_t i = mNumTexCoordsInBuffer; i < numLayers; ++i)
275                {
276                    decl->addElement(TEXCOORD_BINDING,
277                        offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 
278                                                static_cast<unsigned short>(i));
279                    offset += VertexElement::getTypeSize(VET_FLOAT2);
280
281                }
282            }
283
284            // if number of layers changed at all, we'll need to reallocate buffer
285            if (mNumTexCoordsInBuffer != numLayers)
286            {
287                // NB reference counting will take care of the old one if it exists
288                HardwareVertexBufferSharedPtr newbuf =
289                    HardwareBufferManager::getSingleton().createVertexBuffer(
290                    decl->getVertexSize(TEXCOORD_BINDING), mRenderOp.vertexData->vertexCount,
291                    HardwareBuffer::HBU_STATIC_WRITE_ONLY // mostly static except during resizing
292                    );
293                // Bind buffer, note this will unbind the old one and destroy the buffer it had
294                mRenderOp.vertexData->vertexBufferBinding->setBinding(TEXCOORD_BINDING, newbuf);
295                // Set num tex coords in use now
296                mNumTexCoordsInBuffer = numLayers;
297            }
298
299            // Get the tcoord buffer & lock
300                        if (mNumTexCoordsInBuffer)
301                        {
302                                HardwareVertexBufferSharedPtr vbuf =
303                                        mRenderOp.vertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING);
304                                float* pVBStart = static_cast<float*>(
305                                        vbuf->lock(HardwareBuffer::HBL_DISCARD) );
306
307                                size_t uvSize = VertexElement::getTypeSize(VET_FLOAT2) / sizeof(float);
308                                size_t vertexSize = decl->getVertexSize(TEXCOORD_BINDING) / sizeof(float);
309                                for (ushort i = 0; i < numLayers; ++i)
310                                {
311                                    // Calc upper tex coords
312                    Real upperX = mU2 * mTileX[i];
313                    Real upperY = mV2 * mTileY[i];
314
315
316                                    /*
317                                            0-----2
318                                            |    /|
319                                            |  /  |
320                                            |/    |
321                                            1-----3
322                                    */
323                                    // Find start offset for this set
324                                    float* pTex = pVBStart + (i * uvSize);
325
326                    pTex[0] = mU1;
327                    pTex[1] = mV1;
328
329                    pTex += vertexSize; // jump by 1 vertex stride
330                    pTex[0] = mU1;
331                    pTex[1] = upperY;
332
333                    pTex += vertexSize;
334                    pTex[0] = upperX;
335                    pTex[1] = mV1;
336
337                    pTex += vertexSize;
338                    pTex[0] = upperX;
339                    pTex[1] = upperY;
340                                }
341                                vbuf->unlock();
342                        }
343        }
344    }
345    //-----------------------------------------------------------------------
346    void PanelOverlayElement::addBaseParameters(void)
347    {
348        OverlayContainer::addBaseParameters();
349        ParamDictionary* dict = getParamDictionary();
350
351        dict->addParameter(ParameterDef("uv_coords",
352           "The texture coordinates for the texture. 1 set of uv values."
353           , PT_STRING),
354           &msCmdUVCoords);
355
356        dict->addParameter(ParameterDef("tiling",
357            "The number of times to repeat the background texture."
358            , PT_STRING),
359            &msCmdTiling);
360
361        dict->addParameter(ParameterDef("transparent",
362            "Sets whether the panel is transparent, i.e. invisible itself "
363            "but it's contents are still displayed."
364            , PT_BOOL),
365            &msCmdTransparent);
366    }
367    //-----------------------------------------------------------------------
368    // Command objects
369    //-----------------------------------------------------------------------
370    String PanelOverlayElement::CmdTiling::doGet(const void* target) const
371    {
372        // NB only returns 1st layer tiling
373        String ret = "0 " + StringConverter::toString(
374            static_cast<const PanelOverlayElement*>(target)->getTileX() );
375        ret += " " + StringConverter::toString(
376            static_cast<const PanelOverlayElement*>(target)->getTileY() );
377        return ret;
378    }
379    void PanelOverlayElement::CmdTiling::doSet(void* target, const String& val)
380    {
381        // 3 params: <layer> <x_tile> <y_tile>
382        // Param count is validated higher up
383        std::vector<String> vec = StringUtil::split(val);
384        ushort layer = (ushort)StringConverter::parseUnsignedInt(vec[0]);
385        Real x_tile = StringConverter::parseReal(vec[1]);
386        Real y_tile = StringConverter::parseReal(vec[2]);
387
388        static_cast<PanelOverlayElement*>(target)->setTiling(x_tile, y_tile, layer);
389    }
390    //-----------------------------------------------------------------------
391    String PanelOverlayElement::CmdTransparent::doGet(const void* target) const
392    {
393        return StringConverter::toString(
394            static_cast<const PanelOverlayElement*>(target)->isTransparent() );
395    }
396    void PanelOverlayElement::CmdTransparent::doSet(void* target, const String& val)
397    {
398        static_cast<PanelOverlayElement*>(target)->setTransparent(
399            StringConverter::parseBool(val));
400    }
401    //-----------------------------------------------------------------------
402    String PanelOverlayElement::CmdUVCoords::doGet(const void* target) const
403    {
404        Real u1, v1, u2, v2;
405
406        static_cast<const PanelOverlayElement*>(target)->getUV(u1, v1, u2, v2);
407        String ret = " " + StringConverter::toString(u1) + " "
408             + StringConverter::toString(v1) + " " + StringConverter::toString(u2) + " "
409             + StringConverter::toString(v2);
410
411        return ret;
412    }
413    void PanelOverlayElement::CmdUVCoords::doSet(void* target, const String& val)
414    {
415        std::vector<String> vec = StringUtil::split(val);
416
417        static_cast<PanelOverlayElement*>(target)->setUV(
418            StringConverter::parseReal(vec[0]),
419            StringConverter::parseReal(vec[1]),
420            StringConverter::parseReal(vec[2]),
421            StringConverter::parseReal(vec[3])
422            );
423    }
424
425}
426
427
428
Note: See TracBrowser for help on using the repository browser.