/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2005 The OGRE Team Also see acknowledgements in Readme.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. ----------------------------------------------------------------------------- */ #include "OgreStableHeaders.h" #include "OgreSubEntity.h" #include "OgreEntity.h" #include "OgreSceneManager.h" #include "OgreMaterialManager.h" #include "OgreSubMesh.h" #include "OgreTagPoint.h" #include "OgreLogManager.h" #include "OgreMesh.h" #include "OgreException.h" namespace Ogre { //----------------------------------------------------------------------- SubEntity::SubEntity (Entity* parent, SubMesh* subMeshBasis) : Renderable(), mParentEntity(parent), mMaterialName("BaseWhite"), mSubMesh(subMeshBasis) { mpMaterial = MaterialManager::getSingleton().getByName(mMaterialName); mMaterialLodIndex = 0; mRenderDetail = SDL_SOLID; mVisible = true; mBlendedVertexData = 0; mBlendedVertexData = NULL; } //----------------------------------------------------------------------- SubEntity::~SubEntity() { if (mBlendedVertexData) delete mBlendedVertexData; } //----------------------------------------------------------------------- SubMesh* SubEntity::getSubMesh(void) { return mSubMesh; } //----------------------------------------------------------------------- const String& SubEntity::getMaterialName(void) const { return mMaterialName; } //----------------------------------------------------------------------- void SubEntity::setMaterialName( const String& name) { //String oldName = mMaterialName; mMaterialName = name; // Update SceneManager re material change //mParentEntity->mCreatorSceneManager->_notifyMaterialUsage(oldName, mMaterialName, this); mpMaterial = MaterialManager::getSingleton().getByName(mMaterialName); if (mpMaterial.isNull()) { LogManager::getSingleton().logMessage("Can't assign material " + name + " to SubEntity of " + mParentEntity->getName() + " because this " "Material does not exist. Have you forgotten to define it in a " ".material script?"); mpMaterial = MaterialManager::getSingleton().getByName("BaseWhite"); if (mpMaterial.isNull()) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Can't assign default material " "to SubEntity of " + mParentEntity->getName() + ". Did " "you forget to call MaterialManager::initialise()?", "SubEntity.setMaterialName"); } } // Ensure new material loaded (will not load again if already loaded) mpMaterial->load(); // tell parent to reconsider material vertex processing options mParentEntity->reevaluateVertexProcessing(); } //----------------------------------------------------------------------- const MaterialPtr& SubEntity::getMaterial(void) const { return mpMaterial; } //----------------------------------------------------------------------- Technique* SubEntity::getTechnique(void) const { return mpMaterial->getBestTechnique(mMaterialLodIndex); } //----------------------------------------------------------------------- void SubEntity::getRenderOperation(RenderOperation& op) { // Use LOD mSubMesh->_getRenderOperation(op, mParentEntity->mMeshLodIndex); // Do we need to use software skinned vertex data? if (mParentEntity->hasSkeleton() && !mParentEntity->mHardwareSkinning) { op.vertexData = mSubMesh->useSharedVertices ? mParentEntity->mSharedBlendedVertexData : mBlendedVertexData; } } //----------------------------------------------------------------------- void SubEntity::getWorldTransforms(Matrix4* xform) const { if (!mParentEntity->mNumBoneMatrices) { *xform = mParentEntity->_getParentNodeFullTransform(); } else { if (!mParentEntity->isHardwareSkinningEnabled()) { // Software skinning involves pretransforming // No transform required *xform = Matrix4::IDENTITY; } else { // Bones, use cached matrices built when Entity::_updateRenderQueue was called int i; for (i = 0; i < mParentEntity->mNumBoneMatrices; ++i) { *xform = mParentEntity->mBoneMatrices[i]; ++xform; } } } } //----------------------------------------------------------------------- const Quaternion& SubEntity::getWorldOrientation(void) const { return mParentEntity->mParentNode->_getDerivedOrientation(); } //----------------------------------------------------------------------- const Vector3& SubEntity::getWorldPosition(void) const { return mParentEntity->mParentNode->_getDerivedPosition(); } //----------------------------------------------------------------------- unsigned short SubEntity::getNumWorldTransforms(void) const { if (!mParentEntity->mNumBoneMatrices || !mParentEntity->isHardwareSkinningEnabled()) { // No skeletal animation, or software skinning (pretransformed) return 1; } else { // Hardware skinning, pass all matrices return mParentEntity->mNumBoneMatrices; } } //----------------------------------------------------------------------- Real SubEntity::getSquaredViewDepth(const Camera* cam) const { Node* n = mParentEntity->getParentNode(); assert(n); return n->getSquaredViewDepth(cam); } //----------------------------------------------------------------------- bool SubEntity::getNormaliseNormals(void) const { return mParentEntity->mNormaliseNormals; } //----------------------------------------------------------------------- const LightList& SubEntity::getLights(void) const { SceneNode* n = mParentEntity->getParentSceneNode(); assert(n); return n->findLights(mParentEntity->getBoundingRadius()); } //----------------------------------------------------------------------- void SubEntity::setVisible(bool visible) { mVisible = visible; } //----------------------------------------------------------------------- bool SubEntity::isVisible(void) const { return mVisible; } //----------------------------------------------------------------------- void SubEntity::prepareTempBlendBuffers(void) { if (mBlendedVertexData) { delete mBlendedVertexData; mBlendedVertexData = 0; } if (!mSubMesh->useSharedVertices) { // Clone without copying data mBlendedVertexData = mParentEntity->cloneVertexDataRemoveBlendInfo( mSubMesh->vertexData); mParentEntity->extractTempBufferInfo( mBlendedVertexData, &mTempBlendedBuffer); } } //----------------------------------------------------------------------- bool SubEntity::getCastsShadows(void) const { return mParentEntity->getCastShadows(); } //----------------------------------------------------------------------- const VertexData* SubEntity::_getBlendedVertexData(void) const { assert (mBlendedVertexData && "Not software skinned!"); return mBlendedVertexData; } }