/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 | | |