[5] | 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 | } |
---|