Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreSubEntity.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 15.9 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreSubEntity.h"
31
32#include "OgreEntity.h"
33#include "OgreSkeletonInstance.h"
34#include "OgreSceneManager.h"
35#include "OgreMaterialManager.h"
36#include "OgreSubMesh.h"
37#include "OgreTagPoint.h"
38#include "OgreLogManager.h"
39#include "OgreMesh.h"
40#include "OgreException.h"
41#include "OgreCamera.h"
42
43namespace Ogre {
44    //-----------------------------------------------------------------------
45    SubEntity::SubEntity (Entity* parent, SubMesh* subMeshBasis)
46        : Renderable(), mParentEntity(parent), mMaterialName("BaseWhite"),
47                mSubMesh(subMeshBasis), mCachedCamera(0)
48    {
49        mpMaterial = MaterialManager::getSingleton().getByName(mMaterialName);
50        mMaterialLodIndex = 0;
51        mVisible = true;
52        mSkelAnimVertexData = 0;
53                mSoftwareVertexAnimVertexData = 0;
54                mHardwareVertexAnimVertexData = 0;
55                mHardwarePoseCount = 0;
56
57
58
59    }
60    //-----------------------------------------------------------------------
61    SubEntity::~SubEntity()
62    {
63        if (mSkelAnimVertexData)
64            delete mSkelAnimVertexData;
65                if (mHardwareVertexAnimVertexData)
66                        delete mHardwareVertexAnimVertexData;
67                if (mSoftwareVertexAnimVertexData)
68                        delete mSoftwareVertexAnimVertexData;
69    }
70    //-----------------------------------------------------------------------
71    SubMesh* SubEntity::getSubMesh(void)
72    {
73        return mSubMesh;
74    }
75    //-----------------------------------------------------------------------
76    const String& SubEntity::getMaterialName(void) const
77    {
78        return mMaterialName;
79    }
80    //-----------------------------------------------------------------------
81    void SubEntity::setMaterialName( const String& name)
82    {
83
84        //String oldName = mMaterialName;
85        mMaterialName = name;
86        mpMaterial = MaterialManager::getSingleton().getByName(mMaterialName);
87
88        if (mpMaterial.isNull())
89        {
90            LogManager::getSingleton().logMessage("Can't assign material " + name + 
91                " to SubEntity of " + mParentEntity->getName() + " because this "
92                "Material does not exist. Have you forgotten to define it in a "
93                ".material script?");
94            mpMaterial = MaterialManager::getSingleton().getByName("BaseWhite");
95            if (mpMaterial.isNull())
96            {
97                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Can't assign default material "
98                    "to SubEntity of " + mParentEntity->getName() + ". Did "
99                    "you forget to call MaterialManager::initialise()?",
100                    "SubEntity.setMaterialName");
101            }
102        }
103        // Ensure new material loaded (will not load again if already loaded)
104        mpMaterial->load();
105
106        // tell parent to reconsider material vertex processing options
107        mParentEntity->reevaluateVertexProcessing();
108
109
110    }
111    //-----------------------------------------------------------------------
112    const MaterialPtr& SubEntity::getMaterial(void) const
113    {
114        return mpMaterial;
115    }
116    //-----------------------------------------------------------------------
117    Technique* SubEntity::getTechnique(void) const
118    {
119        return mpMaterial->getBestTechnique(mMaterialLodIndex);
120    }
121    //-----------------------------------------------------------------------
122    void SubEntity::getRenderOperation(RenderOperation& op)
123    {
124                // Use LOD
125        mSubMesh->_getRenderOperation(op, mParentEntity->mMeshLodIndex);
126                // Deal with any vertex data overrides
127                op.vertexData = getVertexDataForBinding();
128
129    }
130        //-----------------------------------------------------------------------
131        VertexData* SubEntity::getVertexDataForBinding(void)
132        {
133                if (mSubMesh->useSharedVertices)
134                {
135                        return mParentEntity->getVertexDataForBinding();
136                }
137                else
138                {
139                        Entity::VertexDataBindChoice c = 
140                                mParentEntity->chooseVertexDataForBinding(
141                                        mSubMesh->getVertexAnimationType() != VAT_NONE);
142                        switch(c)
143                        {
144                        case Entity::BIND_ORIGINAL:
145                                return mSubMesh->vertexData;
146                        case Entity::BIND_HARDWARE_MORPH:
147                                return mHardwareVertexAnimVertexData;
148                        case Entity::BIND_SOFTWARE_MORPH:
149                                return mSoftwareVertexAnimVertexData;
150                        case Entity::BIND_SOFTWARE_SKELETAL:
151                                return mSkelAnimVertexData;
152                        };
153                        // keep compiler happy
154                        return mSubMesh->vertexData;
155
156                }
157        }
158    //-----------------------------------------------------------------------
159    void SubEntity::getWorldTransforms(Matrix4* xform) const
160    {
161        if (!mParentEntity->mNumBoneMatrices ||
162            !mParentEntity->isHardwareAnimationEnabled())
163        {
164            // No skeletal animation, or software skinning
165            *xform = mParentEntity->_getParentNodeFullTransform();
166        }
167        else
168        {
169            // Hardware skinning, pass all actually used matrices
170            const Mesh::IndexMap& indexMap = mSubMesh->useSharedVertices ?
171                mSubMesh->parent->sharedBlendIndexToBoneIndexMap : mSubMesh->blendIndexToBoneIndexMap;
172            assert(indexMap.size() <= mParentEntity->mNumBoneMatrices);
173
174            if (mParentEntity->_isSkeletonAnimated())
175            {
176                // Bones, use cached matrices built when Entity::_updateRenderQueue was called
177                assert(mParentEntity->mBoneWorldMatrices);
178
179                Mesh::IndexMap::const_iterator it, itend;
180                itend = indexMap.end();
181                for (it = indexMap.begin(); it != itend; ++it, ++xform)
182                {
183                    *xform = mParentEntity->mBoneWorldMatrices[*it];
184                }
185            }
186            else
187            {
188                // All animations disabled, use parent entity world transform only
189                std::fill_n(xform, indexMap.size(), mParentEntity->_getParentNodeFullTransform());
190            }
191        }
192    }
193    //-----------------------------------------------------------------------
194    const Quaternion& SubEntity::getWorldOrientation(void) const
195    {
196        return mParentEntity->mParentNode->_getDerivedOrientation();
197    }
198    //-----------------------------------------------------------------------
199    const Vector3& SubEntity::getWorldPosition(void) const
200    {
201        return mParentEntity->mParentNode->_getDerivedPosition();
202    }
203
204    //-----------------------------------------------------------------------
205    unsigned short SubEntity::getNumWorldTransforms(void) const
206    {
207        if (!mParentEntity->mNumBoneMatrices ||
208            !mParentEntity->isHardwareAnimationEnabled())
209        {
210            // No skeletal animation, or software skinning
211            return 1;
212        }
213        else
214        {
215            // Hardware skinning, pass all actually used matrices
216            const Mesh::IndexMap& indexMap = mSubMesh->useSharedVertices ?
217                mSubMesh->parent->sharedBlendIndexToBoneIndexMap : mSubMesh->blendIndexToBoneIndexMap;
218            assert(indexMap.size() <= mParentEntity->mNumBoneMatrices);
219
220            return static_cast<unsigned short>(indexMap.size());
221        }
222    }
223    //-----------------------------------------------------------------------
224    Real SubEntity::getSquaredViewDepth(const Camera* cam) const
225    {
226        // First of all, check the cached value
227                // NB this is manually invalidated by parent each _notifyCurrentCamera call
228                // Done this here rather than there since we only need this for transparent objects
229        if (mCachedCamera == cam)
230            return mCachedCameraDist;
231
232        Node* n = mParentEntity->getParentNode();
233        assert(n);
234        Real dist;
235        if (!mSubMesh->extremityPoints.empty())
236        {
237            const Vector3 &cp = cam->getDerivedPosition();
238            const Matrix4 &l2w = mParentEntity->_getParentNodeFullTransform();
239                        dist = std::numeric_limits<Real>::infinity();
240            for (std::vector<Vector3>::const_iterator i = mSubMesh->extremityPoints.begin();
241                 i != mSubMesh->extremityPoints.end (); ++i)
242            {
243                Vector3 v = l2w * (*i);
244                Real d = (v - cp).squaredLength();
245               
246                                dist = std::min(d, dist);
247            }
248        }
249        else
250            dist = n->getSquaredViewDepth(cam);
251
252        mCachedCameraDist = dist;
253        mCachedCamera = cam;
254
255        return dist;
256    }
257    //-----------------------------------------------------------------------
258    bool SubEntity::getNormaliseNormals(void) const
259    {
260        return mParentEntity->mNormaliseNormals;
261    }
262    //-----------------------------------------------------------------------
263    const LightList& SubEntity::getLights(void) const
264    {
265        return mParentEntity->queryLights();
266    }
267    //-----------------------------------------------------------------------
268    void SubEntity::setVisible(bool visible)
269    {
270        mVisible = visible;
271    }
272    //-----------------------------------------------------------------------
273    bool SubEntity::isVisible(void) const
274    {
275        return mVisible;
276
277    }
278    //-----------------------------------------------------------------------
279    void SubEntity::prepareTempBlendBuffers(void)
280    {
281                if (mSubMesh->useSharedVertices)
282                        return;
283
284        if (mSkelAnimVertexData) 
285        {
286            delete mSkelAnimVertexData;
287            mSkelAnimVertexData = 0;
288        }
289                if (mSoftwareVertexAnimVertexData) 
290                {
291                        delete mSoftwareVertexAnimVertexData;
292                        mSoftwareVertexAnimVertexData = 0;
293                }
294                if (mHardwareVertexAnimVertexData) 
295                {
296                        delete mHardwareVertexAnimVertexData;
297                        mHardwareVertexAnimVertexData = 0;
298                }
299
300                if (!mSubMesh->useSharedVertices)
301                {
302                        if (mSubMesh->getVertexAnimationType() != VAT_NONE)
303                        {
304                                // Create temporary vertex blend info
305                                // Prepare temp vertex data if needed
306                                // Clone without copying data, don't remove any blending info
307                                // (since if we skeletally animate too, we need it)
308                                mSoftwareVertexAnimVertexData = mSubMesh->vertexData->clone(false);
309                                mParentEntity->extractTempBufferInfo(mSoftwareVertexAnimVertexData, &mTempVertexAnimInfo);
310
311                                // Also clone for hardware usage, don't remove blend info since we'll
312                                // need it if we also hardware skeletally animate
313                                mHardwareVertexAnimVertexData = mSubMesh->vertexData->clone(false);
314                        }
315
316                        if (mParentEntity->hasSkeleton())
317                        {
318                                // Create temporary vertex blend info
319                                // Prepare temp vertex data if needed
320                                // Clone without copying data, remove blending info
321                                // (since blend is performed in software)
322                                mSkelAnimVertexData = 
323                                        mParentEntity->cloneVertexDataRemoveBlendInfo(mSubMesh->vertexData);
324                                mParentEntity->extractTempBufferInfo(mSkelAnimVertexData, &mTempSkelAnimInfo);
325
326                        }
327                }
328    }
329    //-----------------------------------------------------------------------
330    bool SubEntity::getCastsShadows(void) const
331    {
332        return mParentEntity->getCastShadows();
333    }
334        //-----------------------------------------------------------------------
335        VertexData* SubEntity::_getSkelAnimVertexData(void) 
336        {
337                assert (mSkelAnimVertexData && "Not software skinned or has no dedicated geometry!");
338                return mSkelAnimVertexData;
339        }
340        //-----------------------------------------------------------------------
341        VertexData* SubEntity::_getSoftwareVertexAnimVertexData(void)
342        {
343                assert (mSoftwareVertexAnimVertexData && "Not vertex animated or has no dedicated geometry!");
344                return mSoftwareVertexAnimVertexData;
345        }
346        //-----------------------------------------------------------------------
347        VertexData* SubEntity::_getHardwareVertexAnimVertexData(void)
348        {
349                assert (mHardwareVertexAnimVertexData && "Not vertex animated or has no dedicated geometry!");
350                return mHardwareVertexAnimVertexData;
351        }
352        //-----------------------------------------------------------------------
353        TempBlendedBufferInfo* SubEntity::_getSkelAnimTempBufferInfo(void) 
354        {
355                return &mTempSkelAnimInfo;
356        }
357        //-----------------------------------------------------------------------
358        TempBlendedBufferInfo* SubEntity::_getVertexAnimTempBufferInfo(void) 
359        {
360                return &mTempVertexAnimInfo;
361        }
362        //-----------------------------------------------------------------------
363        void SubEntity::_updateCustomGpuParameter(
364                const GpuProgramParameters::AutoConstantEntry& constantEntry,
365                GpuProgramParameters* params) const
366        {
367                if (constantEntry.paramType == GpuProgramParameters::ACT_ANIMATION_PARAMETRIC)
368                {
369                        // Set up to 4 values, or up to limit of hardware animation entries
370                        // Pack into 4-element constants offset based on constant data index
371                        // If there are more than 4 entries, this will be called more than once
372                        Vector4 val(0.0f,0.0f,0.0f,0.0f);
373
374                        size_t animIndex = constantEntry.data * 4;
375                        for (size_t i = 0; i < 4 && 
376                                animIndex < mHardwareVertexAnimVertexData->hwAnimationDataList.size();
377                                ++i, ++animIndex)
378                        {
379                                val[i] = 
380                                        mHardwareVertexAnimVertexData->hwAnimationDataList[animIndex].parametric;
381                        }
382                        // set the parametric morph value
383                        params->_writeRawConstant(constantEntry.physicalIndex, val);
384                }
385                else
386                {
387                        // default
388                        return Renderable::_updateCustomGpuParameter(constantEntry, params);
389                }
390        }
391        //-----------------------------------------------------------------------------
392        void SubEntity::_markBuffersUnusedForAnimation(void)
393        {
394                mVertexAnimationAppliedThisFrame = false;
395        }
396        //-----------------------------------------------------------------------------
397        void SubEntity::_markBuffersUsedForAnimation(void)
398        {
399                mVertexAnimationAppliedThisFrame = true;
400        }
401        //-----------------------------------------------------------------------------
402        void SubEntity::_restoreBuffersForUnusedAnimation(bool hardwareAnimation)
403        {
404                // Rebind original positions if:
405                //  We didn't apply any animation and
406                //    We're morph animated (hardware binds keyframe, software is missing)
407                //    or we're pose animated and software (hardware is fine, still bound)
408                if (mSubMesh->getVertexAnimationType() != VAT_NONE && 
409                        !mSubMesh->useSharedVertices && 
410                        !mVertexAnimationAppliedThisFrame &&
411                        (!hardwareAnimation || mSubMesh->getVertexAnimationType() == VAT_MORPH))
412                {
413                        const VertexElement* srcPosElem = 
414                                mSubMesh->vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
415                        HardwareVertexBufferSharedPtr srcBuf = 
416                                mSubMesh->vertexData->vertexBufferBinding->getBuffer(
417                                srcPosElem->getSource());
418
419                        // Bind to software
420                        const VertexElement* destPosElem = 
421                                mSoftwareVertexAnimVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
422                        mSoftwareVertexAnimVertexData->vertexBufferBinding->setBinding(
423                                destPosElem->getSource(), srcBuf);
424
425                }
426
427                // rebind any missing hardware pose buffers
428                // Caused by not having any animations enabled, or keyframes which reference
429                // no poses
430                if (!mSubMesh->useSharedVertices && hardwareAnimation
431                        && mSubMesh->getVertexAnimationType() == VAT_POSE)
432                {
433                        mParentEntity->bindMissingHardwarePoseBuffers(
434                                mSubMesh->vertexData, mHardwareVertexAnimVertexData);
435                }
436
437        }
438
439
440}
Note: See TracBrowser for help on using the repository browser.