/usr/include/OGRE/OgreInstancedEntity.h is in libogre-1.8-dev 1.8.0+dfsg1-7+b1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | /*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2012 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#ifndef __InstancedEntity_H__
#define __InstancedEntity_H__
#include "OgreMovableObject.h"
#include "OgreNode.h"
namespace Ogre
{
/** \addtogroup Core
* @{
*/
/** \addtogroup Scene
* @{
*/
/** @see InstanceBatch to understand how instancing works.
Instanced entities work in a very similar way as how an Entity works, as this interface
tries to mimic it as most as possible to make the transition between Entity and InstancedEntity
as straightforward and simple as possible.
There are a couple inherent limitations, for example setRenderQueueGroup only works on
the InstanceBatch level, not the individual instance. This limits Z sorting for alpha blending
quite significantly
An InstancedEntity won't appear in scene until a SceneNode is attached to them. Once the
InstancedEntity is no longer needed, call InstanceBatch::removeInstancedEntity to put them
back into a queue so the batch can return it back again when a new instance is requested.
@par
Internally, instanced entities that are not visible (i.e. by setting setVisible(false) or
when they don't have a SceneNode attached to them) a Zero world matrix is sent to the vertex shader
which in turn causes a zero area triangle.
This obviously means no Vertex shader benefit, but saves a bit of pixel shader processing power.
Also this means this object won't be considered when sizing the InstanceBatch's bounding box.
@par
Each instance has an instance ID unique within the batch, which matches the ID sent to the vertex
shader by some techniques (like InstanceBatchShader).
@par
Differences between Entity and InstancedEntity:
* Setting RenderQueueGroup and other Renderable stuff works at InstanceBatch level, not
InstancedEntity. This is obviously a limitation from instancing in general, not this particular
implementation
@remarks
Design discussion webpage
@author
Matias N. Goldberg ("dark_sylinc")
@version
1.0
*/
class _OgreExport InstancedEntity : public Ogre::MovableObject
{
friend class InstanceBatch;
friend class InstanceBatchShader;
friend class InstanceBatchHW;
friend class InstanceBatchHW_VTF;
friend class BaseInstanceBatchVTF;
protected:
uint16 mInstanceId; //Note it may change after defragmenting!
bool mInUse;
InstanceBatch *mBatchOwner;
AnimationStateSet *mAnimationState;
SkeletonInstance *mSkeletonInstance;
Matrix4 *mBoneMatrices; //Local space
Matrix4 *mBoneWorldMatrices; //World space
unsigned long mFrameAnimationLastUpdated;
InstancedEntity* mSharedTransformEntity; //When not null, another InstancedEntity controls the skeleton
/** Used in conjunction with bone matrix lookup. Tells the number of the transform for
as arranged in the vertex texture */
uint16 mTransformLookupNumber;
/// Stores the master when we're the slave, store our slaves when we're the master
typedef vector<InstancedEntity*>::type InstancedEntityVec;
InstancedEntityVec mSharingPartners;
//////////////////////////////////////////////////////////////////////////
// Parameters used for local transformation offset information
// The
//////////////////////////////////////////////////////////////////////////
/// Object position
Vector3 mPosition;
Vector3 mDerivedLocalPosition;
/// Object orientation
Quaternion mOrientation;
/// Object scale
Vector3 mScale;
/// The maximum absolute scale for all dimension
Real mMaxScaleLocal;
/// Full world transform
Matrix4 mFullLocalTransform;
/// Tells if mFullTransform needs an updated
bool mNeedTransformUpdate;
/// Tells if the animation world transform needs an update
bool mNeedAnimTransformUpdate;
/// Tells whether to use the local transform parameters
bool mUseLocalTransform;
/// Returns number of matrices written to transform, assumes transform has enough space
size_t getTransforms( Matrix4 *xform ) const;
/// Returns number of 32-bit values written
size_t getTransforms3x4( float *xform ) const;
/// Returns true if this InstancedObject is visible to the current camera
bool findVisible( Camera *camera ) const;
/// Creates/destroys our own skeleton, also tells slaves to unlink if we're destroying
void createSkeletonInstance();
void destroySkeletonInstance();
/// Just unlinks, and tells our master we're no longer sharing
void unlinkTransform();
/// Called when a slave has unlinked from us
void notifyUnlink( const InstancedEntity *slave );
/// Mark the transformation matrixes as dirty
inline void markTransformDirty();
/// Incremented count for next name extension
static NameGenerator msNameGenerator;
public:
InstancedEntity( InstanceBatch *batchOwner, uint32 instanceID, InstancedEntity* sharedTransformEntity = NULL);
virtual ~InstancedEntity();
/** Shares the entire transformation with another InstancedEntity. This is useful when a mesh
has more than one submeshes, therefore creating multiple InstanceManagers (one for each
submesh). With this function, sharing makes the skeleton to be shared (less memory) and
updated once (performance optimization).
Note that one InstancedEntity (i.e. submesh 0) must be chosen as "master" which will share
with the other instanced entities (i.e. submeshes 1-N) which are called "slaves"
@par
Requirements to share trasnformations:
* Both InstancedEntities must have use the same skeleton
* An InstancedEntity can't be both "master" and "slave" at the same time
@remarks
Sharing does nothing if the original mesh doesn't have a skeleton
When an InstancedEntity is removed (@see InstanceBatch::removeInstancedEntity), it stops
sharing the transform. If the instanced entity was the master one, all it's slaves stop
sharing and start having their own transform too.
@param slave The InstancedEntity that should share with us and become our slave
@return true if successfully shared (may fail if they aren't skeletally animated)
*/
bool shareTransformWith( InstancedEntity *slave );
/** @see shareTransformWith
Stops sharing the transform if this is a slave, and notifies the master we're no longer
a slave.
If this is a master, tells all it's slave to stop sharing
@remarks
This function is automatically called in InstanceBatch::removeInstancedEntity
*/
void stopSharingTransform();
InstanceBatch* _getOwner() const { return mBatchOwner; }
const String& getMovableType(void) const;
const AxisAlignedBox& getBoundingBox(void) const;
Real getBoundingRadius(void) const;
/** This is used by our batch owner to get the closest entity's depth, returns infinity
when not attached to a scene node */
Real getSquaredViewDepth( const Camera* cam ) const;
/// Overriden so we can tell the InstanceBatch it needs to update it's bounds
void _notifyMoved(void);
void _notifyAttached( Node* parent, bool isTagPoint = false );
/// Do nothing, InstanceBatch takes care of this.
void _updateRenderQueue( RenderQueue* queue ) {}
void visitRenderables( Renderable::Visitor* visitor, bool debugRenderables = false ) {}
/** @see Entity::hasSkeleton */
bool hasSkeleton(void) const { return mSkeletonInstance != 0; }
/** @see Entity::getSkeleton */
SkeletonInstance* getSkeleton(void) const { return mSkeletonInstance; }
/** @see Entity::getAnimationState */
AnimationState* getAnimationState(const String& name) const;
/** @see Entity::getAllAnimationStates */
AnimationStateSet* getAllAnimationStates(void) const;
/** Called by InstanceBatch in <i>his</i> _updateRenderQueue to tell us we need
to calculate our bone matrices.
@remarks Assumes it has a skeleton (mSkeletonInstance != 0)
@return true if something was actually updated
*/
virtual bool _updateAnimation(void);
/** Sets the transformation look up number */
void setTransformLookupNumber(uint16 num) { mTransformLookupNumber = num;}
/** Retrieve the position */
const Vector3& getPosition() const { return mPosition; }
/** Set the position or the offset from the parent node if a parent node exists */
void setPosition(const Vector3& position, bool doUpdate = true);
/** Retrieve the orientation */
const Quaternion& getOrientation() const { return mOrientation; }
/** Set the orientation or the offset from the parent node if a parent node exists */
void setOrientation(const Quaternion& orientation, bool doUpdate = true);
/** Retrieve the local scale */
const Vector3& getScale() const { return mScale; }
/** Set the scale or the offset from the parent node if a parent node exists */
void setScale(const Vector3& scale, bool doUpdate = true);
/** Returns the maximum derived scale coefficient among the xyz values */
Real getMaxScaleCoef() const;
/** Update the world transform and derived values */
void updateTransforms();
/** Tells if the entity is in use. */
bool isInUse() const { return mInUse; }
/** Sets whether the entity is in use. */
void setInUse(bool used);
/** Returns the world transform of the instanced entity including local transform */
virtual const Matrix4& _getParentNodeFullTransform(void) const {
assert((!mNeedTransformUpdate || !mUseLocalTransform) && "Transform data should be updated at this point");
return mUseLocalTransform ? mFullLocalTransform :
mParentNode ? mParentNode->_getFullTransform() : Matrix4::IDENTITY;
}
/** Returns the derived position of the instanced entity including local transform */
const Vector3& _getDerivedPosition() const {
assert((!mNeedTransformUpdate || !mUseLocalTransform) && "Transform data should be updated at this point");
return mUseLocalTransform ? mDerivedLocalPosition :
mParentNode ? mParentNode->_getDerivedPosition() : Vector3::ZERO;
}
/** @copydoc MovableObject::isInScene. */
virtual bool isInScene(void) const
{
//We assume that the instanced entity is in the scene if it is in use
//It is in the scene whether it has a parent node or not
return mInUse;
}
};
}
#endif
|