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 2000-2005 The OGRE Team |
---|
8 | Also see acknowledgements in Readme.html |
---|
9 | |
---|
10 | This program is free software; you can redistribute it and/or modify it under |
---|
11 | the terms of the GNU Lesser General Public License as published by the Free Software |
---|
12 | Foundation; either version 2 of the License, or (at your option) any later |
---|
13 | version. |
---|
14 | |
---|
15 | This program is distributed in the hope that it will be useful, but WITHOUT |
---|
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
---|
18 | |
---|
19 | You should have received a copy of the GNU Lesser General Public License along with |
---|
20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
---|
22 | http://www.gnu.org/copyleft/lesser.txt. |
---|
23 | |
---|
24 | You may alternatively use this source under the terms of a specific version of |
---|
25 | the OGRE Unrestricted License provided you have obtained such a license from |
---|
26 | Torus 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 | |
---|
40 | namespace 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 | |
---|