I shamelessly stole a bit of code from Node::DebugRenderable and hacked this together in a couple of hours (don't mind the low framerate, i'm on my slow laptop):
The main advantage is that the debug arrows actually translate with the character, something that is absent when using Ogre::Entity->setDisplaySkeleton(true)
I'll be adding more updates soon, with rendered bones like in blender, names, and making the arrows appear above the model instead of inside it (any ideas on how to do this?)
SkeletonDebug.h
Code: Select all
#ifndef SKELETONDEBUG_H_INCLUDED
#define SKELETONDEBUG_H_INCLUDED
#include <Ogre.h>
class SkeletonDebug
{
public:
SkeletonDebug(Ogre::Entity *entity, Ogre::SceneManager *man);
~SkeletonDebug();
// For future use
void setUniformScale(bool enable){mEnableUniformScaling = enable;}
bool isUniformScale(){return mEnableUniformScaling;}
private:
Ogre::Entity *mEntity;
Ogre::MaterialPtr mMat;
Ogre::MeshPtr mMeshPtr;
Ogre::SceneManager *mSceneMan;
bool mEnableUniformScaling;
float mScale;
void createMaterial();
void createMesh();
};
#endif
Code: Select all
#include "SkeletonDebug.h"
SkeletonDebug::SkeletonDebug(Ogre::Entity* entity, Ogre::SceneManager *man)
{
mEntity = entity;
mSceneMan = man;
createMaterial();
createMesh();
int numBones = mEntity->getSkeleton()->getNumBones();
for(unsigned short int iBone = 0; iBone < numBones; ++iBone)
{
Ogre::Bone* pBone = mEntity->getSkeleton()->getBone(iBone);
if ( !pBone )
{
assert(false);
continue;
}
Ogre::Entity *ent = mSceneMan->createEntity("SkeletonDebug/AxesMesh");
mEntity->attachObjectToBone(pBone->getName(), (Ogre::MovableObject*)ent);
}
}
SkeletonDebug::~SkeletonDebug()
{
}
void SkeletonDebug::createMaterial()
{
Ogre::String matName = "SkeletonDebug/AxesMat";
mMat = MaterialManager::getSingletonPtr()->getByName(matName);
mMat = MaterialManager::getSingleton().getByName(matName);
if (mMat.isNull())
{
mMat = MaterialManager::getSingleton().create(matName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
Pass* p = mMat->getTechnique(0)->getPass(0);
p->setLightingEnabled(false);
p->setPolygonModeOverrideable(false);
p->setVertexColourTracking(TVC_AMBIENT);
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
p->setCullingMode(CULL_NONE);
p->setDepthWriteEnabled(false);
}
}
void SkeletonDebug::createMesh()
{
String meshName = "SkeletonDebug/AxesMesh";
mMeshPtr = MeshManager::getSingleton().getByName(meshName);
if (mMeshPtr.isNull())
{
ManualObject mo("tmp");
mo.begin(mMat->getName());
/* 3 axes, each made up of 2 of these (base plane = XY)
* .------------|\
* '------------|/
*/
mo.estimateVertexCount(7 * 2 * 3);
mo.estimateIndexCount(3 * 2 * 3);
Quaternion quat[6];
ColourValue col[3];
// x-axis
quat[0] = Quaternion::IDENTITY;
quat[1].FromAxes(Vector3::UNIT_X, Vector3::NEGATIVE_UNIT_Z, Vector3::UNIT_Y);
col[0] = ColourValue::Red;
col[0].a = 0.8;
// y-axis
quat[2].FromAxes(Vector3::UNIT_Y, Vector3::NEGATIVE_UNIT_X, Vector3::UNIT_Z);
quat[3].FromAxes(Vector3::UNIT_Y, Vector3::UNIT_Z, Vector3::UNIT_X);
col[1] = ColourValue::Green;
col[1].a = 0.8;
// z-axis
quat[4].FromAxes(Vector3::UNIT_Z, Vector3::UNIT_Y, Vector3::NEGATIVE_UNIT_X);
quat[5].FromAxes(Vector3::UNIT_Z, Vector3::UNIT_X, Vector3::UNIT_Y);
col[2] = ColourValue::Blue;
col[2].a = 0.8;
Vector3 basepos[7] =
{
// stalk
Vector3(0, 0.05, 0),
Vector3(0, -0.05, 0),
Vector3(0.7, -0.05, 0),
Vector3(0.7, 0.05, 0),
// head
Vector3(0.7, -0.15, 0),
Vector3(1, 0, 0),
Vector3(0.7, 0.15, 0)
};
// vertices
// 6 arrows
for (size_t i = 0; i < 6; ++i)
{
// 7 points
for (size_t p = 0; p < 7; ++p)
{
Vector3 pos = quat[i] * basepos[p];
mo.position(pos);
mo.colour(col[i / 2]);
}
}
// indices
// 6 arrows
for (size_t i = 0; i < 6; ++i)
{
size_t base = i * 7;
mo.triangle(base + 0, base + 1, base + 2);
mo.triangle(base + 0, base + 2, base + 3);
mo.triangle(base + 4, base + 5, base + 6);
}
mo.end();
mMeshPtr = mo.convertToMesh(meshName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
}
}