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-2006 Torus Knot Software Ltd |
---|
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 | #include "OgreManualObject.h" |
---|
31 | #include "OgreException.h" |
---|
32 | #include "OgreMaterialManager.h" |
---|
33 | #include "OgreSceneNode.h" |
---|
34 | #include "OgreRoot.h" |
---|
35 | #include "OgreRenderSystem.h" |
---|
36 | #include "OgreHardwareBufferManager.h" |
---|
37 | #include "OgreEdgeListBuilder.h" |
---|
38 | #include "OgreMeshManager.h" |
---|
39 | #include "OgreMesh.h" |
---|
40 | #include "OgreSubMesh.h" |
---|
41 | |
---|
42 | namespace Ogre { |
---|
43 | |
---|
44 | #define TEMP_INITIAL_SIZE 50 |
---|
45 | #define TEMP_VERTEXSIZE_GUESS sizeof(float) * 12 |
---|
46 | #define TEMP_INITIAL_VERTEX_SIZE TEMP_VERTEXSIZE_GUESS * TEMP_INITIAL_SIZE |
---|
47 | #define TEMP_INITIAL_INDEX_SIZE sizeof(uint16) * TEMP_INITIAL_SIZE |
---|
48 | //----------------------------------------------------------------------------- |
---|
49 | ManualObject::ManualObject(const String& name) |
---|
50 | : MovableObject(name), |
---|
51 | mDynamic(false), mCurrentSection(0), mFirstVertex(true), |
---|
52 | mTempVertexPending(false), |
---|
53 | mTempVertexBuffer(0), mTempVertexSize(TEMP_INITIAL_VERTEX_SIZE), |
---|
54 | mTempIndexBuffer(0), mTempIndexSize(TEMP_INITIAL_INDEX_SIZE), |
---|
55 | mDeclSize(0), mEstVertexCount(0), mEstIndexCount(0), mTexCoordIndex(0), |
---|
56 | mRadius(0), mAnyIndexed(false), mEdgeList(0), |
---|
57 | mUseIdentityProjection(false), mUseIdentityView(false) |
---|
58 | { |
---|
59 | } |
---|
60 | //----------------------------------------------------------------------------- |
---|
61 | ManualObject::~ManualObject() |
---|
62 | { |
---|
63 | clear(); |
---|
64 | } |
---|
65 | //----------------------------------------------------------------------------- |
---|
66 | void ManualObject::clear(void) |
---|
67 | { |
---|
68 | resetTempAreas(); |
---|
69 | for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) |
---|
70 | { |
---|
71 | delete *i; |
---|
72 | } |
---|
73 | mSectionList.clear(); |
---|
74 | mRadius = 0; |
---|
75 | mAABB.setNull(); |
---|
76 | delete mEdgeList; |
---|
77 | mEdgeList = 0; |
---|
78 | mAnyIndexed = false; |
---|
79 | for (ShadowRenderableList::iterator s = mShadowRenderables.begin(); |
---|
80 | s != mShadowRenderables.end(); ++s) |
---|
81 | { |
---|
82 | delete *s; |
---|
83 | } |
---|
84 | mShadowRenderables.clear(); |
---|
85 | |
---|
86 | |
---|
87 | } |
---|
88 | //----------------------------------------------------------------------------- |
---|
89 | void ManualObject::resetTempAreas(void) |
---|
90 | { |
---|
91 | delete [] mTempVertexBuffer; |
---|
92 | delete [] mTempIndexBuffer; |
---|
93 | mTempVertexBuffer = 0; |
---|
94 | mTempIndexBuffer = 0; |
---|
95 | mTempVertexSize = TEMP_INITIAL_VERTEX_SIZE; |
---|
96 | mTempIndexSize = TEMP_INITIAL_INDEX_SIZE; |
---|
97 | } |
---|
98 | //----------------------------------------------------------------------------- |
---|
99 | void ManualObject::resizeTempVertexBufferIfNeeded(size_t numVerts) |
---|
100 | { |
---|
101 | // Calculate byte size |
---|
102 | // Use decl if we know it by now, otherwise default size to pos/norm/texcoord*2 |
---|
103 | size_t newSize; |
---|
104 | if (!mFirstVertex) |
---|
105 | { |
---|
106 | newSize = mDeclSize * numVerts; |
---|
107 | } |
---|
108 | else |
---|
109 | { |
---|
110 | // estimate - size checks will deal for subsequent verts |
---|
111 | newSize = TEMP_VERTEXSIZE_GUESS * numVerts; |
---|
112 | } |
---|
113 | if (newSize > mTempVertexSize || !mTempVertexBuffer) |
---|
114 | { |
---|
115 | if (!mTempVertexBuffer) |
---|
116 | { |
---|
117 | // init |
---|
118 | newSize = mTempVertexSize; |
---|
119 | } |
---|
120 | else |
---|
121 | { |
---|
122 | // increase to at least double current |
---|
123 | newSize = std::max(newSize, mTempVertexSize*2); |
---|
124 | } |
---|
125 | // copy old data |
---|
126 | char* tmp = mTempVertexBuffer; |
---|
127 | mTempVertexBuffer = new char[newSize]; |
---|
128 | if (tmp) |
---|
129 | { |
---|
130 | memcpy(mTempVertexBuffer, tmp, mTempVertexSize); |
---|
131 | // delete old buffer |
---|
132 | delete [] tmp; |
---|
133 | } |
---|
134 | mTempVertexSize = newSize; |
---|
135 | } |
---|
136 | } |
---|
137 | //----------------------------------------------------------------------------- |
---|
138 | void ManualObject::resizeTempIndexBufferIfNeeded(size_t numInds) |
---|
139 | { |
---|
140 | size_t newSize = numInds * sizeof(uint16); |
---|
141 | if (newSize > mTempIndexSize || !mTempIndexBuffer) |
---|
142 | { |
---|
143 | if (!mTempIndexBuffer) |
---|
144 | { |
---|
145 | // init |
---|
146 | newSize = mTempIndexSize; |
---|
147 | } |
---|
148 | else |
---|
149 | { |
---|
150 | // increase to at least double current |
---|
151 | newSize = std::max(newSize, mTempIndexSize*2); |
---|
152 | } |
---|
153 | numInds = newSize / sizeof(uint16); |
---|
154 | uint16* tmp = mTempIndexBuffer; |
---|
155 | mTempIndexBuffer = new uint16[numInds]; |
---|
156 | if (tmp) |
---|
157 | { |
---|
158 | memcpy(mTempIndexBuffer, tmp, mTempIndexSize); |
---|
159 | delete [] tmp; |
---|
160 | } |
---|
161 | mTempIndexSize = newSize; |
---|
162 | } |
---|
163 | |
---|
164 | } |
---|
165 | //----------------------------------------------------------------------------- |
---|
166 | void ManualObject::estimateVertexCount(size_t vcount) |
---|
167 | { |
---|
168 | resizeTempVertexBufferIfNeeded(vcount); |
---|
169 | mEstVertexCount = vcount; |
---|
170 | } |
---|
171 | //----------------------------------------------------------------------------- |
---|
172 | void ManualObject::estimateIndexCount(size_t icount) |
---|
173 | { |
---|
174 | resizeTempIndexBufferIfNeeded(icount); |
---|
175 | mEstIndexCount = icount; |
---|
176 | } |
---|
177 | //----------------------------------------------------------------------------- |
---|
178 | void ManualObject::begin(const String& materialName, |
---|
179 | RenderOperation::OperationType opType) |
---|
180 | { |
---|
181 | if (mCurrentSection) |
---|
182 | { |
---|
183 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
184 | "You cannot call begin() again until after you call end()", |
---|
185 | "ManualObject::begin"); |
---|
186 | } |
---|
187 | mCurrentSection = new ManualObjectSection(this, materialName, opType); |
---|
188 | mCurrentUpdating = false; |
---|
189 | mCurrentSection->setUseIdentityProjection(mUseIdentityProjection); |
---|
190 | mCurrentSection->setUseIdentityView(mUseIdentityView); |
---|
191 | mSectionList.push_back(mCurrentSection); |
---|
192 | mFirstVertex = true; |
---|
193 | mDeclSize = 0; |
---|
194 | mTexCoordIndex = 0; |
---|
195 | } |
---|
196 | //----------------------------------------------------------------------------- |
---|
197 | void ManualObject::beginUpdate(size_t sectionIndex) |
---|
198 | { |
---|
199 | if (mCurrentSection) |
---|
200 | { |
---|
201 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
202 | "You cannot call begin() again until after you call end()", |
---|
203 | "ManualObject::beginUpdate"); |
---|
204 | } |
---|
205 | if (sectionIndex >= mSectionList.size()) |
---|
206 | { |
---|
207 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
208 | "Invalid section index - out of range.", |
---|
209 | "ManualObject::beginUpdate"); |
---|
210 | } |
---|
211 | mCurrentSection = mSectionList[sectionIndex]; |
---|
212 | mCurrentUpdating = true; |
---|
213 | mFirstVertex = true; |
---|
214 | mTexCoordIndex = 0; |
---|
215 | // reset vertex & index count |
---|
216 | RenderOperation* rop = mCurrentSection->getRenderOperation(); |
---|
217 | rop->vertexData->vertexCount = 0; |
---|
218 | if (rop->indexData) |
---|
219 | rop->indexData->indexCount = 0; |
---|
220 | rop->useIndexes = false; |
---|
221 | mDeclSize = rop->vertexData->vertexDeclaration->getVertexSize(0); |
---|
222 | } |
---|
223 | //----------------------------------------------------------------------------- |
---|
224 | void ManualObject::position(const Vector3& pos) |
---|
225 | { |
---|
226 | position(pos.x, pos.y, pos.z); |
---|
227 | } |
---|
228 | //----------------------------------------------------------------------------- |
---|
229 | void ManualObject::position(Real x, Real y, Real z) |
---|
230 | { |
---|
231 | if (!mCurrentSection) |
---|
232 | { |
---|
233 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
234 | "You must call begin() before this method", |
---|
235 | "ManualObject::position"); |
---|
236 | } |
---|
237 | if (mTempVertexPending) |
---|
238 | { |
---|
239 | // bake current vertex |
---|
240 | copyTempVertexToBuffer(); |
---|
241 | mFirstVertex = false; |
---|
242 | } |
---|
243 | |
---|
244 | if (mFirstVertex && !mCurrentUpdating) |
---|
245 | { |
---|
246 | // defining declaration |
---|
247 | mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration |
---|
248 | ->addElement(0, mDeclSize, VET_FLOAT3, VES_POSITION); |
---|
249 | mDeclSize += VertexElement::getTypeSize(VET_FLOAT3); |
---|
250 | } |
---|
251 | |
---|
252 | mTempVertex.position.x = x; |
---|
253 | mTempVertex.position.y = y; |
---|
254 | mTempVertex.position.z = z; |
---|
255 | |
---|
256 | // update bounds |
---|
257 | mAABB.merge(mTempVertex.position); |
---|
258 | mRadius = std::max(mRadius, mTempVertex.position.length()); |
---|
259 | |
---|
260 | // reset current texture coord |
---|
261 | mTexCoordIndex = 0; |
---|
262 | |
---|
263 | mTempVertexPending = true; |
---|
264 | } |
---|
265 | //----------------------------------------------------------------------------- |
---|
266 | void ManualObject::normal(const Vector3& norm) |
---|
267 | { |
---|
268 | normal(norm.x, norm.y, norm.z); |
---|
269 | } |
---|
270 | //----------------------------------------------------------------------------- |
---|
271 | void ManualObject::normal(Real x, Real y, Real z) |
---|
272 | { |
---|
273 | if (!mCurrentSection) |
---|
274 | { |
---|
275 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
276 | "You must call begin() before this method", |
---|
277 | "ManualObject::normal"); |
---|
278 | } |
---|
279 | if (mFirstVertex && !mCurrentUpdating) |
---|
280 | { |
---|
281 | // defining declaration |
---|
282 | mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration |
---|
283 | ->addElement(0, mDeclSize, VET_FLOAT3, VES_NORMAL); |
---|
284 | mDeclSize += VertexElement::getTypeSize(VET_FLOAT3); |
---|
285 | } |
---|
286 | mTempVertex.normal.x = x; |
---|
287 | mTempVertex.normal.y = y; |
---|
288 | mTempVertex.normal.z = z; |
---|
289 | } |
---|
290 | //----------------------------------------------------------------------------- |
---|
291 | void ManualObject::textureCoord(Real u) |
---|
292 | { |
---|
293 | if (!mCurrentSection) |
---|
294 | { |
---|
295 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
296 | "You must call begin() before this method", |
---|
297 | "ManualObject::textureCoord"); |
---|
298 | } |
---|
299 | if (mFirstVertex && !mCurrentUpdating) |
---|
300 | { |
---|
301 | // defining declaration |
---|
302 | mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration |
---|
303 | ->addElement(0, mDeclSize, VET_FLOAT1, VES_TEXTURE_COORDINATES, mTexCoordIndex); |
---|
304 | mDeclSize += VertexElement::getTypeSize(VET_FLOAT1); |
---|
305 | } |
---|
306 | mTempVertex.texCoordDims[mTexCoordIndex] = 1; |
---|
307 | mTempVertex.texCoord[mTexCoordIndex].x = u; |
---|
308 | |
---|
309 | ++mTexCoordIndex; |
---|
310 | |
---|
311 | } |
---|
312 | //----------------------------------------------------------------------------- |
---|
313 | void ManualObject::textureCoord(Real u, Real v) |
---|
314 | { |
---|
315 | if (!mCurrentSection) |
---|
316 | { |
---|
317 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
318 | "You must call begin() before this method", |
---|
319 | "ManualObject::textureCoord"); |
---|
320 | } |
---|
321 | if (mFirstVertex && !mCurrentUpdating) |
---|
322 | { |
---|
323 | // defining declaration |
---|
324 | mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration |
---|
325 | ->addElement(0, mDeclSize, VET_FLOAT2, VES_TEXTURE_COORDINATES, mTexCoordIndex); |
---|
326 | mDeclSize += VertexElement::getTypeSize(VET_FLOAT2); |
---|
327 | } |
---|
328 | mTempVertex.texCoordDims[mTexCoordIndex] = 2; |
---|
329 | mTempVertex.texCoord[mTexCoordIndex].x = u; |
---|
330 | mTempVertex.texCoord[mTexCoordIndex].y = v; |
---|
331 | |
---|
332 | ++mTexCoordIndex; |
---|
333 | } |
---|
334 | //----------------------------------------------------------------------------- |
---|
335 | void ManualObject::textureCoord(Real u, Real v, Real w) |
---|
336 | { |
---|
337 | if (!mCurrentSection) |
---|
338 | { |
---|
339 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
340 | "You must call begin() before this method", |
---|
341 | "ManualObject::textureCoord"); |
---|
342 | } |
---|
343 | if (mFirstVertex && !mCurrentUpdating) |
---|
344 | { |
---|
345 | // defining declaration |
---|
346 | mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration |
---|
347 | ->addElement(0, mDeclSize, VET_FLOAT3, VES_TEXTURE_COORDINATES, mTexCoordIndex); |
---|
348 | mDeclSize += VertexElement::getTypeSize(VET_FLOAT3); |
---|
349 | } |
---|
350 | mTempVertex.texCoordDims[mTexCoordIndex] = 3; |
---|
351 | mTempVertex.texCoord[mTexCoordIndex].x = u; |
---|
352 | mTempVertex.texCoord[mTexCoordIndex].y = v; |
---|
353 | mTempVertex.texCoord[mTexCoordIndex].z = w; |
---|
354 | |
---|
355 | ++mTexCoordIndex; |
---|
356 | } |
---|
357 | //----------------------------------------------------------------------------- |
---|
358 | void ManualObject::textureCoord(const Vector2& uv) |
---|
359 | { |
---|
360 | textureCoord(uv.x, uv.y); |
---|
361 | } |
---|
362 | //----------------------------------------------------------------------------- |
---|
363 | void ManualObject::textureCoord(const Vector3& uvw) |
---|
364 | { |
---|
365 | textureCoord(uvw.x, uvw.y, uvw.z); |
---|
366 | } |
---|
367 | //----------------------------------------------------------------------------- |
---|
368 | void ManualObject::colour(const ColourValue& col) |
---|
369 | { |
---|
370 | colour(col.r, col.g, col.b, col.a); |
---|
371 | } |
---|
372 | //----------------------------------------------------------------------------- |
---|
373 | void ManualObject::colour(Real r, Real g, Real b, Real a) |
---|
374 | { |
---|
375 | if (!mCurrentSection) |
---|
376 | { |
---|
377 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
378 | "You must call begin() before this method", |
---|
379 | "ManualObject::colour"); |
---|
380 | } |
---|
381 | if (mFirstVertex && !mCurrentUpdating) |
---|
382 | { |
---|
383 | // defining declaration |
---|
384 | mCurrentSection->getRenderOperation()->vertexData->vertexDeclaration |
---|
385 | ->addElement(0, mDeclSize, VET_COLOUR, VES_DIFFUSE); |
---|
386 | mDeclSize += VertexElement::getTypeSize(VET_COLOUR); |
---|
387 | } |
---|
388 | mTempVertex.colour.r = r; |
---|
389 | mTempVertex.colour.g = g; |
---|
390 | mTempVertex.colour.b = b; |
---|
391 | mTempVertex.colour.a = a; |
---|
392 | |
---|
393 | } |
---|
394 | //----------------------------------------------------------------------------- |
---|
395 | void ManualObject::index(uint16 idx) |
---|
396 | { |
---|
397 | if (!mCurrentSection) |
---|
398 | { |
---|
399 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
400 | "You must call begin() before this method", |
---|
401 | "ManualObject::index"); |
---|
402 | } |
---|
403 | mAnyIndexed = true; |
---|
404 | // make sure we have index data |
---|
405 | RenderOperation* rop = mCurrentSection->getRenderOperation(); |
---|
406 | if (!rop->indexData) |
---|
407 | { |
---|
408 | rop->indexData = new IndexData(); |
---|
409 | rop->indexData->indexCount = 0; |
---|
410 | } |
---|
411 | rop->useIndexes = true; |
---|
412 | resizeTempIndexBufferIfNeeded(++rop->indexData->indexCount); |
---|
413 | |
---|
414 | mTempIndexBuffer[rop->indexData->indexCount - 1] = idx; |
---|
415 | } |
---|
416 | //----------------------------------------------------------------------------- |
---|
417 | void ManualObject::triangle(uint16 i1, uint16 i2, uint16 i3) |
---|
418 | { |
---|
419 | if (!mCurrentSection) |
---|
420 | { |
---|
421 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
422 | "You must call begin() before this method", |
---|
423 | "ManualObject::index"); |
---|
424 | } |
---|
425 | if (mCurrentSection->getRenderOperation()->operationType != |
---|
426 | RenderOperation::OT_TRIANGLE_LIST) |
---|
427 | { |
---|
428 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
429 | "This method is only valid on triangle lists", |
---|
430 | "ManualObject::index"); |
---|
431 | } |
---|
432 | |
---|
433 | index(i1); |
---|
434 | index(i2); |
---|
435 | index(i3); |
---|
436 | } |
---|
437 | //----------------------------------------------------------------------------- |
---|
438 | void ManualObject::quad(uint16 i1, uint16 i2, uint16 i3, uint16 i4) |
---|
439 | { |
---|
440 | // first tri |
---|
441 | triangle(i1, i2, i3); |
---|
442 | // second tri |
---|
443 | triangle(i3, i4, i1); |
---|
444 | } |
---|
445 | //----------------------------------------------------------------------------- |
---|
446 | void ManualObject::copyTempVertexToBuffer(void) |
---|
447 | { |
---|
448 | mTempVertexPending = false; |
---|
449 | RenderOperation* rop = mCurrentSection->getRenderOperation(); |
---|
450 | if (rop->vertexData->vertexCount == 0 && !mCurrentUpdating) |
---|
451 | { |
---|
452 | // first vertex, autoorganise decl |
---|
453 | VertexDeclaration* oldDcl = rop->vertexData->vertexDeclaration; |
---|
454 | rop->vertexData->vertexDeclaration = |
---|
455 | oldDcl->getAutoOrganisedDeclaration(false, false); |
---|
456 | HardwareBufferManager::getSingleton().destroyVertexDeclaration(oldDcl); |
---|
457 | } |
---|
458 | resizeTempVertexBufferIfNeeded(++rop->vertexData->vertexCount); |
---|
459 | |
---|
460 | // get base pointer |
---|
461 | char* pBase = mTempVertexBuffer + (mDeclSize * (rop->vertexData->vertexCount-1)); |
---|
462 | const VertexDeclaration::VertexElementList& elemList = |
---|
463 | rop->vertexData->vertexDeclaration->getElements(); |
---|
464 | for (VertexDeclaration::VertexElementList::const_iterator i = elemList.begin(); |
---|
465 | i != elemList.end(); ++i) |
---|
466 | { |
---|
467 | float* pFloat = 0; |
---|
468 | RGBA* pRGBA = 0; |
---|
469 | const VertexElement& elem = *i; |
---|
470 | switch(elem.getType()) |
---|
471 | { |
---|
472 | case VET_FLOAT1: |
---|
473 | case VET_FLOAT2: |
---|
474 | case VET_FLOAT3: |
---|
475 | elem.baseVertexPointerToElement(pBase, &pFloat); |
---|
476 | break; |
---|
477 | case VET_COLOUR: |
---|
478 | case VET_COLOUR_ABGR: |
---|
479 | case VET_COLOUR_ARGB: |
---|
480 | elem.baseVertexPointerToElement(pBase, &pRGBA); |
---|
481 | break; |
---|
482 | default: |
---|
483 | // nop ? |
---|
484 | break; |
---|
485 | }; |
---|
486 | |
---|
487 | |
---|
488 | RenderSystem* rs; |
---|
489 | unsigned short dims; |
---|
490 | switch(elem.getSemantic()) |
---|
491 | { |
---|
492 | case VES_POSITION: |
---|
493 | *pFloat++ = mTempVertex.position.x; |
---|
494 | *pFloat++ = mTempVertex.position.y; |
---|
495 | *pFloat++ = mTempVertex.position.z; |
---|
496 | break; |
---|
497 | case VES_NORMAL: |
---|
498 | *pFloat++ = mTempVertex.normal.x; |
---|
499 | *pFloat++ = mTempVertex.normal.y; |
---|
500 | *pFloat++ = mTempVertex.normal.z; |
---|
501 | break; |
---|
502 | case VES_TEXTURE_COORDINATES: |
---|
503 | dims = VertexElement::getTypeCount(elem.getType()); |
---|
504 | for (ushort t = 0; t < dims; ++t) |
---|
505 | *pFloat++ = mTempVertex.texCoord[elem.getIndex()][t]; |
---|
506 | break; |
---|
507 | case VES_DIFFUSE: |
---|
508 | rs = Root::getSingleton().getRenderSystem(); |
---|
509 | if (rs) |
---|
510 | rs->convertColourValue(mTempVertex.colour, pRGBA++); |
---|
511 | else |
---|
512 | *pRGBA++ = mTempVertex.colour.getAsRGBA(); // pick one! |
---|
513 | break; |
---|
514 | default: |
---|
515 | // nop ? |
---|
516 | break; |
---|
517 | }; |
---|
518 | |
---|
519 | } |
---|
520 | |
---|
521 | } |
---|
522 | //----------------------------------------------------------------------------- |
---|
523 | ManualObject::ManualObjectSection* ManualObject::end(void) |
---|
524 | { |
---|
525 | if (!mCurrentSection) |
---|
526 | { |
---|
527 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
528 | "You cannot call end() until after you call begin()", |
---|
529 | "ManualObject::end"); |
---|
530 | } |
---|
531 | if (mTempVertexPending) |
---|
532 | { |
---|
533 | // bake current vertex |
---|
534 | copyTempVertexToBuffer(); |
---|
535 | } |
---|
536 | |
---|
537 | // pointer that will be returned |
---|
538 | ManualObjectSection* result = NULL; |
---|
539 | |
---|
540 | RenderOperation* rop = mCurrentSection->getRenderOperation(); |
---|
541 | // Check for empty content |
---|
542 | if (rop->vertexData->vertexCount == 0 || |
---|
543 | (rop->useIndexes && rop->indexData->indexCount == 0)) |
---|
544 | { |
---|
545 | // You're wasting my time sonny |
---|
546 | if (mCurrentUpdating) |
---|
547 | { |
---|
548 | // Can't just undo / remove since may be in the middle |
---|
549 | // Just allow counts to be 0, will not be issued to renderer |
---|
550 | |
---|
551 | // return the finished section (though it has zero vertices) |
---|
552 | result = mCurrentSection; |
---|
553 | } |
---|
554 | else |
---|
555 | { |
---|
556 | // First creation, can really undo |
---|
557 | // Has already been added to section list end, so remove |
---|
558 | mSectionList.pop_back(); |
---|
559 | delete mCurrentSection; |
---|
560 | |
---|
561 | } |
---|
562 | } |
---|
563 | else // not an empty section |
---|
564 | { |
---|
565 | |
---|
566 | // Bake the real buffers |
---|
567 | HardwareVertexBufferSharedPtr vbuf; |
---|
568 | // Check buffer sizes |
---|
569 | bool vbufNeedsCreating = true; |
---|
570 | bool ibufNeedsCreating = rop->useIndexes; |
---|
571 | if (mCurrentUpdating) |
---|
572 | { |
---|
573 | // May be able to reuse buffers, check sizes |
---|
574 | vbuf = rop->vertexData->vertexBufferBinding->getBuffer(0); |
---|
575 | if (vbuf->getNumVertices() >= rop->vertexData->vertexCount) |
---|
576 | vbufNeedsCreating = false; |
---|
577 | |
---|
578 | if (rop->useIndexes) |
---|
579 | { |
---|
580 | if (rop->indexData->indexBuffer->getNumIndexes() >= |
---|
581 | rop->indexData->indexCount) |
---|
582 | ibufNeedsCreating = false; |
---|
583 | } |
---|
584 | |
---|
585 | } |
---|
586 | if (vbufNeedsCreating) |
---|
587 | { |
---|
588 | // Make the vertex buffer larger if estimated vertex count higher |
---|
589 | // to allow for user-configured growth area |
---|
590 | size_t vertexCount = std::max(rop->vertexData->vertexCount, |
---|
591 | mEstVertexCount); |
---|
592 | vbuf = |
---|
593 | HardwareBufferManager::getSingleton().createVertexBuffer( |
---|
594 | mDeclSize, |
---|
595 | vertexCount, |
---|
596 | mDynamic? HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY : |
---|
597 | HardwareBuffer::HBU_STATIC_WRITE_ONLY); |
---|
598 | rop->vertexData->vertexBufferBinding->setBinding(0, vbuf); |
---|
599 | } |
---|
600 | if (ibufNeedsCreating) |
---|
601 | { |
---|
602 | // Make the index buffer larger if estimated index count higher |
---|
603 | // to allow for user-configured growth area |
---|
604 | size_t indexCount = std::max(rop->indexData->indexCount, |
---|
605 | mEstIndexCount); |
---|
606 | rop->indexData->indexBuffer = |
---|
607 | HardwareBufferManager::getSingleton().createIndexBuffer( |
---|
608 | HardwareIndexBuffer::IT_16BIT, |
---|
609 | indexCount, |
---|
610 | mDynamic? HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY : |
---|
611 | HardwareBuffer::HBU_STATIC_WRITE_ONLY); |
---|
612 | } |
---|
613 | // Write vertex data |
---|
614 | vbuf->writeData( |
---|
615 | 0, rop->vertexData->vertexCount * vbuf->getVertexSize(), |
---|
616 | mTempVertexBuffer, true); |
---|
617 | // Write index data |
---|
618 | if(rop->useIndexes) |
---|
619 | { |
---|
620 | rop->indexData->indexBuffer->writeData( |
---|
621 | 0, |
---|
622 | rop->indexData->indexCount |
---|
623 | * rop->indexData->indexBuffer->getIndexSize(), |
---|
624 | mTempIndexBuffer, true); |
---|
625 | } |
---|
626 | |
---|
627 | // return the finished section |
---|
628 | result = mCurrentSection; |
---|
629 | |
---|
630 | } // empty section check |
---|
631 | |
---|
632 | mCurrentSection = 0; |
---|
633 | resetTempAreas(); |
---|
634 | |
---|
635 | // Tell parent if present |
---|
636 | if (mParentNode) |
---|
637 | { |
---|
638 | mParentNode->needUpdate(); |
---|
639 | } |
---|
640 | |
---|
641 | // will return the finished section or NULL if |
---|
642 | // the section was empty (i.e. zero vertices/indices) |
---|
643 | return result; |
---|
644 | } |
---|
645 | //----------------------------------------------------------------------------- |
---|
646 | void ManualObject::setMaterialName(size_t idx, const String& name) |
---|
647 | { |
---|
648 | if (idx >= mSectionList.size()) |
---|
649 | { |
---|
650 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
651 | "Index out of bounds!", |
---|
652 | "ManualObject::setMaterialName"); |
---|
653 | } |
---|
654 | |
---|
655 | mSectionList[idx]->setMaterialName(name); |
---|
656 | |
---|
657 | } |
---|
658 | //----------------------------------------------------------------------------- |
---|
659 | MeshPtr ManualObject::convertToMesh(const String& meshName, const String& groupName) |
---|
660 | { |
---|
661 | if (mCurrentSection) |
---|
662 | { |
---|
663 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
664 | "You cannot call convertToMesh() whilst you are in the middle of " |
---|
665 | "defining the object; call end() first.", |
---|
666 | "ManualObject::convertToMesh"); |
---|
667 | } |
---|
668 | if (mSectionList.empty()) |
---|
669 | { |
---|
670 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
671 | "No data defined to convert to a mesh.", |
---|
672 | "ManualObject::convertToMesh"); |
---|
673 | } |
---|
674 | for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) |
---|
675 | { |
---|
676 | ManualObjectSection* sec = *i; |
---|
677 | if (!sec->getRenderOperation()->useIndexes) |
---|
678 | { |
---|
679 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
680 | "Only indexed geometry may be converted to a mesh.", |
---|
681 | "ManualObject::convertToMesh"); |
---|
682 | } |
---|
683 | } |
---|
684 | MeshPtr m = MeshManager::getSingleton().createManual(meshName, groupName); |
---|
685 | |
---|
686 | for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) |
---|
687 | { |
---|
688 | ManualObjectSection* sec = *i; |
---|
689 | RenderOperation* rop = sec->getRenderOperation(); |
---|
690 | SubMesh* sm = m->createSubMesh(); |
---|
691 | sm->useSharedVertices = false; |
---|
692 | sm->operationType = rop->operationType; |
---|
693 | sm->setMaterialName(sec->getMaterialName()); |
---|
694 | // Copy vertex data; replicate buffers too |
---|
695 | sm->vertexData = rop->vertexData->clone(true); |
---|
696 | // Copy index data; replicate buffers too; delete the default, old one to avoid memory leaks |
---|
697 | delete sm->indexData; |
---|
698 | sm->indexData = rop->indexData->clone(true); |
---|
699 | } |
---|
700 | // update bounds |
---|
701 | m->_setBounds(mAABB); |
---|
702 | m->_setBoundingSphereRadius(mRadius); |
---|
703 | |
---|
704 | m->load(); |
---|
705 | |
---|
706 | return m; |
---|
707 | |
---|
708 | |
---|
709 | } |
---|
710 | //----------------------------------------------------------------------------- |
---|
711 | void ManualObject::setUseIdentityProjection(bool useIdentityProjection) |
---|
712 | { |
---|
713 | // Set existing |
---|
714 | for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) |
---|
715 | { |
---|
716 | (*i)->setUseIdentityProjection(useIdentityProjection); |
---|
717 | } |
---|
718 | |
---|
719 | // Save setting for future sections |
---|
720 | mUseIdentityProjection = useIdentityProjection; |
---|
721 | } |
---|
722 | //----------------------------------------------------------------------------- |
---|
723 | void ManualObject::setUseIdentityView(bool useIdentityView) |
---|
724 | { |
---|
725 | // Set existing |
---|
726 | for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) |
---|
727 | { |
---|
728 | (*i)->setUseIdentityView(useIdentityView); |
---|
729 | } |
---|
730 | |
---|
731 | // Save setting for future sections |
---|
732 | mUseIdentityView = useIdentityView; |
---|
733 | } |
---|
734 | //----------------------------------------------------------------------- |
---|
735 | ManualObject::ManualObjectSection* ManualObject::getSection(unsigned int index) const |
---|
736 | { |
---|
737 | if (index >= mSectionList.size()) |
---|
738 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
739 | "Index out of bounds.", |
---|
740 | "ManualObject::getSection"); |
---|
741 | return mSectionList[index]; |
---|
742 | } |
---|
743 | //----------------------------------------------------------------------- |
---|
744 | unsigned int ManualObject::getNumSections(void) const |
---|
745 | { |
---|
746 | return static_cast< unsigned int >( mSectionList.size() ); |
---|
747 | } |
---|
748 | //----------------------------------------------------------------------------- |
---|
749 | const String& ManualObject::getMovableType(void) const |
---|
750 | { |
---|
751 | return ManualObjectFactory::FACTORY_TYPE_NAME; |
---|
752 | } |
---|
753 | //----------------------------------------------------------------------------- |
---|
754 | const AxisAlignedBox& ManualObject::getBoundingBox(void) const |
---|
755 | { |
---|
756 | return mAABB; |
---|
757 | } |
---|
758 | //----------------------------------------------------------------------------- |
---|
759 | Real ManualObject::getBoundingRadius(void) const |
---|
760 | { |
---|
761 | return mRadius; |
---|
762 | } |
---|
763 | //----------------------------------------------------------------------------- |
---|
764 | void ManualObject::_updateRenderQueue(RenderQueue* queue) |
---|
765 | { |
---|
766 | for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) |
---|
767 | { |
---|
768 | // Skip empty sections (only happens if non-empty first, then updated) |
---|
769 | RenderOperation* rop = (*i)->getRenderOperation(); |
---|
770 | if (rop->vertexData->vertexCount == 0 || |
---|
771 | (rop->useIndexes && rop->indexData->indexCount == 0)) |
---|
772 | continue; |
---|
773 | |
---|
774 | if (mRenderQueueIDSet) |
---|
775 | queue->addRenderable(*i, mRenderQueueID); |
---|
776 | else |
---|
777 | queue->addRenderable(*i); |
---|
778 | } |
---|
779 | } |
---|
780 | //----------------------------------------------------------------------------- |
---|
781 | EdgeData* ManualObject::getEdgeList(void) |
---|
782 | { |
---|
783 | // Build on demand |
---|
784 | if (!mEdgeList && mAnyIndexed) |
---|
785 | { |
---|
786 | EdgeListBuilder eb; |
---|
787 | size_t vertexSet = 0; |
---|
788 | bool anyBuilt = false; |
---|
789 | for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) |
---|
790 | { |
---|
791 | RenderOperation* rop = (*i)->getRenderOperation(); |
---|
792 | // Only indexed triangle geometry supported for stencil shadows |
---|
793 | if (rop->useIndexes && rop->indexData->indexCount != 0 && |
---|
794 | (rop->operationType == RenderOperation::OT_TRIANGLE_FAN || |
---|
795 | rop->operationType == RenderOperation::OT_TRIANGLE_LIST || |
---|
796 | rop->operationType == RenderOperation::OT_TRIANGLE_STRIP)) |
---|
797 | { |
---|
798 | eb.addVertexData(rop->vertexData); |
---|
799 | eb.addIndexData(rop->indexData, vertexSet++); |
---|
800 | anyBuilt = true; |
---|
801 | } |
---|
802 | } |
---|
803 | |
---|
804 | if (anyBuilt) |
---|
805 | mEdgeList = eb.build(); |
---|
806 | |
---|
807 | } |
---|
808 | return mEdgeList; |
---|
809 | } |
---|
810 | //--------------------------------------------------------------------- |
---|
811 | bool ManualObject::hasEdgeList() |
---|
812 | { |
---|
813 | return getEdgeList() != 0; |
---|
814 | } |
---|
815 | //----------------------------------------------------------------------------- |
---|
816 | ShadowCaster::ShadowRenderableListIterator |
---|
817 | ManualObject::getShadowVolumeRenderableIterator( |
---|
818 | ShadowTechnique shadowTechnique, const Light* light, |
---|
819 | HardwareIndexBufferSharedPtr* indexBuffer, |
---|
820 | bool extrude, Real extrusionDistance, unsigned long flags) |
---|
821 | { |
---|
822 | assert(indexBuffer && "Only external index buffers are supported right now"); |
---|
823 | assert((*indexBuffer)->getType() == HardwareIndexBuffer::IT_16BIT && |
---|
824 | "Only 16-bit indexes supported for now"); |
---|
825 | |
---|
826 | EdgeData* edgeList = getEdgeList(); |
---|
827 | if (!edgeList) |
---|
828 | { |
---|
829 | return ShadowRenderableListIterator( |
---|
830 | mShadowRenderables.begin(), mShadowRenderables.end()); |
---|
831 | } |
---|
832 | |
---|
833 | // Calculate the object space light details |
---|
834 | Vector4 lightPos = light->getAs4DVector(); |
---|
835 | Matrix4 world2Obj = mParentNode->_getFullTransform().inverseAffine(); |
---|
836 | lightPos = world2Obj.transformAffine(lightPos); |
---|
837 | |
---|
838 | |
---|
839 | // Init shadow renderable list if required (only allow indexed) |
---|
840 | bool init = mShadowRenderables.empty() && mAnyIndexed; |
---|
841 | |
---|
842 | EdgeData::EdgeGroupList::iterator egi; |
---|
843 | ShadowRenderableList::iterator si, siend; |
---|
844 | ManualObjectSectionShadowRenderable* esr = 0; |
---|
845 | SectionList::iterator seci; |
---|
846 | if (init) |
---|
847 | mShadowRenderables.resize(edgeList->edgeGroups.size()); |
---|
848 | |
---|
849 | siend = mShadowRenderables.end(); |
---|
850 | egi = edgeList->edgeGroups.begin(); |
---|
851 | seci = mSectionList.begin(); |
---|
852 | for (si = mShadowRenderables.begin(); si != siend; ++seci) |
---|
853 | { |
---|
854 | // Skip non-indexed geometry |
---|
855 | if (!(*seci)->getRenderOperation()->useIndexes) |
---|
856 | { |
---|
857 | continue; |
---|
858 | } |
---|
859 | |
---|
860 | if (init) |
---|
861 | { |
---|
862 | // Create a new renderable, create a separate light cap if |
---|
863 | // we're using a vertex program (either for this model, or |
---|
864 | // for extruding the shadow volume) since otherwise we can |
---|
865 | // get depth-fighting on the light cap |
---|
866 | MaterialPtr mat = (*seci)->getMaterial(); |
---|
867 | mat->load(); |
---|
868 | bool vertexProgram = false; |
---|
869 | Technique* t = mat->getBestTechnique(); |
---|
870 | for (int p = 0; p < t->getNumPasses(); ++p) |
---|
871 | { |
---|
872 | Pass* pass = t->getPass(p); |
---|
873 | if (pass->hasVertexProgram()) |
---|
874 | { |
---|
875 | vertexProgram = true; |
---|
876 | break; |
---|
877 | } |
---|
878 | } |
---|
879 | *si = new ManualObjectSectionShadowRenderable(this, indexBuffer, |
---|
880 | egi->vertexData, vertexProgram || !extrude); |
---|
881 | } |
---|
882 | // Get shadow renderable |
---|
883 | esr = static_cast<ManualObjectSectionShadowRenderable*>(*si); |
---|
884 | HardwareVertexBufferSharedPtr esrPositionBuffer = esr->getPositionBuffer(); |
---|
885 | // Extrude vertices in software if required |
---|
886 | if (extrude) |
---|
887 | { |
---|
888 | extrudeVertices(esrPositionBuffer, |
---|
889 | egi->vertexData->vertexCount, |
---|
890 | lightPos, extrusionDistance); |
---|
891 | |
---|
892 | } |
---|
893 | |
---|
894 | ++si; |
---|
895 | ++egi; |
---|
896 | } |
---|
897 | // Calc triangle light facing |
---|
898 | updateEdgeListLightFacing(edgeList, lightPos); |
---|
899 | |
---|
900 | // Generate indexes and update renderables |
---|
901 | generateShadowVolume(edgeList, *indexBuffer, light, |
---|
902 | mShadowRenderables, flags); |
---|
903 | |
---|
904 | |
---|
905 | return ShadowRenderableListIterator( |
---|
906 | mShadowRenderables.begin(), mShadowRenderables.end()); |
---|
907 | |
---|
908 | |
---|
909 | } |
---|
910 | //----------------------------------------------------------------------------- |
---|
911 | //----------------------------------------------------------------------------- |
---|
912 | //----------------------------------------------------------------------------- |
---|
913 | ManualObject::ManualObjectSection::ManualObjectSection(ManualObject* parent, |
---|
914 | const String& materialName, RenderOperation::OperationType opType) |
---|
915 | : mParent(parent), mMaterialName(materialName) |
---|
916 | { |
---|
917 | mRenderOperation.operationType = opType; |
---|
918 | // default to no indexes unless we're told |
---|
919 | mRenderOperation.useIndexes = false; |
---|
920 | mRenderOperation.vertexData = new VertexData(); |
---|
921 | mRenderOperation.vertexData->vertexCount = 0; |
---|
922 | |
---|
923 | } |
---|
924 | //----------------------------------------------------------------------------- |
---|
925 | ManualObject::ManualObjectSection::~ManualObjectSection() |
---|
926 | { |
---|
927 | delete mRenderOperation.vertexData; |
---|
928 | delete mRenderOperation.indexData; // ok to delete 0 |
---|
929 | } |
---|
930 | //----------------------------------------------------------------------------- |
---|
931 | RenderOperation* ManualObject::ManualObjectSection::getRenderOperation(void) |
---|
932 | { |
---|
933 | return &mRenderOperation; |
---|
934 | } |
---|
935 | //----------------------------------------------------------------------------- |
---|
936 | const MaterialPtr& ManualObject::ManualObjectSection::getMaterial(void) const |
---|
937 | { |
---|
938 | if (mMaterial.isNull()) |
---|
939 | { |
---|
940 | // Load from default group. If user wants to use alternate groups, |
---|
941 | // they can define it and preload |
---|
942 | mMaterial = MaterialManager::getSingleton().load(mMaterialName, |
---|
943 | ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); |
---|
944 | } |
---|
945 | return mMaterial; |
---|
946 | } |
---|
947 | //----------------------------------------------------------------------------- |
---|
948 | void ManualObject::ManualObjectSection::setMaterialName(const String& name) |
---|
949 | { |
---|
950 | if (mMaterialName != name) |
---|
951 | { |
---|
952 | mMaterialName = name; |
---|
953 | mMaterial.setNull(); |
---|
954 | } |
---|
955 | } |
---|
956 | //----------------------------------------------------------------------------- |
---|
957 | void ManualObject::ManualObjectSection::getRenderOperation(RenderOperation& op) |
---|
958 | { |
---|
959 | // direct copy |
---|
960 | op = mRenderOperation; |
---|
961 | } |
---|
962 | //----------------------------------------------------------------------------- |
---|
963 | void ManualObject::ManualObjectSection::getWorldTransforms(Matrix4* xform) const |
---|
964 | { |
---|
965 | xform[0] = mParent->_getParentNodeFullTransform(); |
---|
966 | } |
---|
967 | //----------------------------------------------------------------------------- |
---|
968 | const Quaternion& ManualObject::ManualObjectSection::getWorldOrientation(void) const |
---|
969 | { |
---|
970 | return mParent->getParentNode()->_getDerivedOrientation(); |
---|
971 | } |
---|
972 | //----------------------------------------------------------------------------- |
---|
973 | const Vector3& ManualObject::ManualObjectSection::getWorldPosition(void) const |
---|
974 | { |
---|
975 | return mParent->getParentNode()->_getDerivedPosition(); |
---|
976 | } |
---|
977 | //----------------------------------------------------------------------------- |
---|
978 | Real ManualObject::ManualObjectSection::getSquaredViewDepth(const Ogre::Camera *cam) const |
---|
979 | { |
---|
980 | Node* n = mParent->getParentNode(); |
---|
981 | assert(n); |
---|
982 | return n->getSquaredViewDepth(cam); |
---|
983 | } |
---|
984 | //----------------------------------------------------------------------------- |
---|
985 | const LightList& ManualObject::ManualObjectSection::getLights(void) const |
---|
986 | { |
---|
987 | return mParent->queryLights(); |
---|
988 | } |
---|
989 | //----------------------------------------------------------------------------- |
---|
990 | //-------------------------------------------------------------------------- |
---|
991 | ManualObject::ManualObjectSectionShadowRenderable::ManualObjectSectionShadowRenderable( |
---|
992 | ManualObject* parent, HardwareIndexBufferSharedPtr* indexBuffer, |
---|
993 | const VertexData* vertexData, bool createSeparateLightCap, |
---|
994 | bool isLightCap) |
---|
995 | : mParent(parent) |
---|
996 | { |
---|
997 | // Initialise render op |
---|
998 | mRenderOp.indexData = new IndexData(); |
---|
999 | mRenderOp.indexData->indexBuffer = *indexBuffer; |
---|
1000 | mRenderOp.indexData->indexStart = 0; |
---|
1001 | // index start and count are sorted out later |
---|
1002 | |
---|
1003 | // Create vertex data which just references position component (and 2 component) |
---|
1004 | mRenderOp.vertexData = new VertexData(); |
---|
1005 | // Map in position data |
---|
1006 | mRenderOp.vertexData->vertexDeclaration->addElement(0,0,VET_FLOAT3, VES_POSITION); |
---|
1007 | ushort origPosBind = |
---|
1008 | vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource(); |
---|
1009 | mPositionBuffer = vertexData->vertexBufferBinding->getBuffer(origPosBind); |
---|
1010 | mRenderOp.vertexData->vertexBufferBinding->setBinding(0, mPositionBuffer); |
---|
1011 | // Map in w-coord buffer (if present) |
---|
1012 | if(!vertexData->hardwareShadowVolWBuffer.isNull()) |
---|
1013 | { |
---|
1014 | mRenderOp.vertexData->vertexDeclaration->addElement(1,0,VET_FLOAT1, VES_TEXTURE_COORDINATES, 0); |
---|
1015 | mWBuffer = vertexData->hardwareShadowVolWBuffer; |
---|
1016 | mRenderOp.vertexData->vertexBufferBinding->setBinding(1, mWBuffer); |
---|
1017 | } |
---|
1018 | // Use same vertex start as input |
---|
1019 | mRenderOp.vertexData->vertexStart = vertexData->vertexStart; |
---|
1020 | |
---|
1021 | if (isLightCap) |
---|
1022 | { |
---|
1023 | // Use original vertex count, no extrusion |
---|
1024 | mRenderOp.vertexData->vertexCount = vertexData->vertexCount; |
---|
1025 | } |
---|
1026 | else |
---|
1027 | { |
---|
1028 | // Vertex count must take into account the doubling of the buffer, |
---|
1029 | // because second half of the buffer is the extruded copy |
---|
1030 | mRenderOp.vertexData->vertexCount = |
---|
1031 | vertexData->vertexCount * 2; |
---|
1032 | if (createSeparateLightCap) |
---|
1033 | { |
---|
1034 | // Create child light cap |
---|
1035 | mLightCap = new ManualObjectSectionShadowRenderable(parent, |
---|
1036 | indexBuffer, vertexData, false, true); |
---|
1037 | } |
---|
1038 | } |
---|
1039 | } |
---|
1040 | //-------------------------------------------------------------------------- |
---|
1041 | ManualObject::ManualObjectSectionShadowRenderable::~ManualObjectSectionShadowRenderable() |
---|
1042 | { |
---|
1043 | delete mRenderOp.indexData; |
---|
1044 | delete mRenderOp.vertexData; |
---|
1045 | } |
---|
1046 | //-------------------------------------------------------------------------- |
---|
1047 | void ManualObject::ManualObjectSectionShadowRenderable::getWorldTransforms( |
---|
1048 | Matrix4* xform) const |
---|
1049 | { |
---|
1050 | // pretransformed |
---|
1051 | *xform = mParent->_getParentNodeFullTransform(); |
---|
1052 | } |
---|
1053 | //-------------------------------------------------------------------------- |
---|
1054 | const Quaternion& |
---|
1055 | ManualObject::ManualObjectSectionShadowRenderable::getWorldOrientation(void) const |
---|
1056 | { |
---|
1057 | return mParent->getParentNode()->_getDerivedOrientation(); |
---|
1058 | } |
---|
1059 | //-------------------------------------------------------------------------- |
---|
1060 | const Vector3& |
---|
1061 | ManualObject::ManualObjectSectionShadowRenderable::getWorldPosition(void) const |
---|
1062 | { |
---|
1063 | return mParent->getParentNode()->_getDerivedPosition(); |
---|
1064 | } |
---|
1065 | //----------------------------------------------------------------------------- |
---|
1066 | //----------------------------------------------------------------------------- |
---|
1067 | String ManualObjectFactory::FACTORY_TYPE_NAME = "ManualObject"; |
---|
1068 | //----------------------------------------------------------------------------- |
---|
1069 | const String& ManualObjectFactory::getType(void) const |
---|
1070 | { |
---|
1071 | return FACTORY_TYPE_NAME; |
---|
1072 | } |
---|
1073 | //----------------------------------------------------------------------------- |
---|
1074 | MovableObject* ManualObjectFactory::createInstanceImpl( |
---|
1075 | const String& name, const NameValuePairList* params) |
---|
1076 | { |
---|
1077 | return new ManualObject(name); |
---|
1078 | } |
---|
1079 | //----------------------------------------------------------------------------- |
---|
1080 | void ManualObjectFactory::destroyInstance( MovableObject* obj) |
---|
1081 | { |
---|
1082 | delete obj; |
---|
1083 | } |
---|
1084 | |
---|
1085 | |
---|
1086 | |
---|
1087 | } |
---|