Skeleton Debugger

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
NickLH
Gnoblar
Posts: 13
Joined: Thu Jul 26, 2012 2:00 am
x 2

Skeleton Debugger

Post by NickLH »

I'm fairly new to Ogre (only downloaded it two days ago after playing with JMonkeyEngine for the last 4 months). The first thing I noticed is the complete lack of skeleton debugging tools. So my first endevour is to remedy this.

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):
Image

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
SkeletonDebug.cpp

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);
    }
}
If you guys find any errors or want to make any requests, please do so. I hope that one day this makes it into Ogre.
mdias
Gnoblar
Posts: 19
Joined: Mon Jan 30, 2012 4:25 pm
x 2

Re: Skeleton Debugger

Post by mdias »

I'm not sure what you mean by displaying the arrows "above" the model, but if you mean translating the origin somewhere else, I think it will defeat the purpose of the debugging.
If you mean displaying the arrows even if they're inside the mesh, you'll have to have Z always pass (see http://www.ogre3d.org/docs/manual/manual_16.html#SEC51).

For extra eye candy you could make the material have 2 passes, one like the current one you have, and other with inverted depth_func and some transparency, this way arrows inside the mesh (behind polygons) would show with some transparency, and other arrows would show fully opaque.

P.S. it would be nice to have a full featured skeleton debugger in Ogre. Keep up the good work!
NickLH
Gnoblar
Posts: 13
Joined: Thu Jul 26, 2012 2:00 am
x 2

Re: Skeleton Debugger

Post by NickLH »

The idea about the dual pass rendering is great and was quite easy to implement (looks great too). I also added bone names. Donno what to do about the bones names being cluttered when multiple bones are close...

Image

I'll release the next set of code once I get through adding octahedral bones like in blender and have cleaned up the source a bit to allow for turning on and off the different debug options.
User avatar
Zonder
Ogre Magi
Posts: 1172
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 76

Re: Skeleton Debugger

Post by Zonder »

Might be worth changing the alpha on the text as well for ones behind others maybe use there depth to determine an opacity.

Organising the names would be better though I can't think what the algorithm would be called, but try putting a code request in general the chances someone has done somthing like that already and may donate the code.
There are 10 types of people in the world: Those who understand binary, and those who don't...
NickLH
Gnoblar
Posts: 13
Joined: Thu Jul 26, 2012 2:00 am
x 2

Re: Skeleton Debugger

Post by NickLH »

What do you mean by "organizing the names"?
mdias
Gnoblar
Posts: 19
Joined: Mon Jan 30, 2012 4:25 pm
x 2

Re: Skeleton Debugger

Post by mdias »

I believe an outline (much like a black outward "glow/blur") would help a lot the readability since it'd be hiding away characters that are very close to the one being rendered. I'm not sure about this though, and I also wouldn't know how to implement it myself...
NickLH
Gnoblar
Posts: 13
Joined: Thu Jul 26, 2012 2:00 am
x 2

Re: Skeleton Debugger

Post by NickLH »

mdias wrote:I believe an outline (much like a black outward "glow/blur") would help a lot the readability since it'd be hiding away characters that are very close to the one being rendered. I'm not sure about this though, and I also wouldn't know how to implement it myself...
One option might be to render the characters twice with different colors and a small scale factor, but there would be offset problems. The easier way would be via a custom font that has the borders added in already. Since my skeleton debugger is not tied to a particular font type, it should be easy to add your own font into it.

I got the octahedral bones working now, so the last issue is once again the text. I want to get the text to render the same size independently of how far I am from the mesh. Once I solve that, the skeleton debugger will be complete (well at least to my satisfaction), and I'll post updated screenshots and code.
User avatar
Zonder
Ogre Magi
Posts: 1172
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 76

Re: Skeleton Debugger

Post by Zonder »

I mean so they don't overlap and would have a line to the node they are for. Like you would get in a pie chart for is

Forgot to say great work :D
There are 10 types of people in the world: Those who understand binary, and those who don't...
NickLH
Gnoblar
Posts: 13
Joined: Thu Jul 26, 2012 2:00 am
x 2

Re: Skeleton Debugger

Post by NickLH »

That seems like it would be a lot of work lol. Not sure I'm willing to put that much time into it. But if you know of any snippets that do something similar I might be able to integrate it.

I am currently using the MovableText snippet for rendering my text (http://www.ogre3d.org/tikiwiki/tiki-ind ... e=Cookbook), but it should be pretty simple to replace it with something else since all I am doing is attaching the text entity to the bone node. As long as it is a MovableObject and a Renderable, you can basically plug anything into it.
User avatar
areay
Bugbear
Posts: 819
Joined: Wed May 05, 2010 4:59 am
Location: Auckland, NZ
x 69

Re: Skeleton Debugger

Post by areay »

Good work NickLH, you should definitely put this in the wiki.
NickLH
Gnoblar
Posts: 13
Joined: Thu Jul 26, 2012 2:00 am
x 2

Re: Skeleton Debugger

Post by NickLH »

Wiki page has been added with full source code : http://www.ogre3d.org/tikiwiki/tiki-ind ... e=Cookbook
I switched to using a modified version of http://www.ogre3d.org/tikiwiki/ObjectTextDisplay for the text rendering (code also included in wiki page).

Bones that have no children (i.e. end bones) are rendered with a length of 1 so that they can be visualized. This makes finger bones look larger than they should (see bottom right pic), but imitates (to a degree) what can be seen in blender. It would be nice to have the bones store length information when exported from blender so that we can remove this limitation (hint hint.... request?).

Everything is working well now :
Image

Top left: no resource name clashes (different skeleton debuggers can run on different models at the same time).
Top right: Bone display only on Sinbad. The Robot skeleton is wonky, probably because the bones are all separate and have no parent-child relations?
Bottom left: Showing off the octahedral bone style from blender, and the dual pass rendering of the axis arrows (semi-transparent when inside object, solid outside).
Bottom right: Works really nicely with wireframe (anyone up for making a modeler? :P ).

I think this will be my last update about this project (unless there is some request for a feature that I would find useful for my own projects). You are welcome to use the code in any way you see fit as long as you don't claim it's your own.
mdias
Gnoblar
Posts: 19
Joined: Mon Jan 30, 2012 4:25 pm
x 2

Re: Skeleton Debugger

Post by mdias »

Great work!

There's just one weird thing, the base of the octahedrons' faces all seem to have the normals wrong compared to the rest of the shapes giving a checker-like effect.
Is this a bug on made on purpose? [edit2] nvm, I just read the source :)

[edit] Also, end bones length of 1 is probably too big or too small depending on the scale of things. Since making that a class property would only solve part of the problem, I believe the most correct thing to do would be having a different shape mayeb colored in a different way or something. But I guess that'll be left to end users to do since you're done with it!

Thanks a lot for this :)
NickLH
Gnoblar
Posts: 13
Joined: Thu Jul 26, 2012 2:00 am
x 2

Re: Skeleton Debugger

Post by NickLH »

I know that the end bones being too big/small is a problem, but since no bone length information is stored I don't really know how to handle it automatically.

And yeah, the checker pattern was on purpose so that the bone orientations would be easily distinguishable.
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80

Re: Skeleton Debugger

Post by duststorm »

Thanks, this is very useful.
There is a model viewer called OgreMeshy that also has a skeleton visualisation.
Developer @ MakeHuman.org
FlorianGeorge
Halfling
Posts: 86
Joined: Tue Sep 01, 2009 7:15 pm
Location: Cologne, Germany
x 4

Re: Skeleton Debugger

Post by FlorianGeorge »

Looks great, I like that you try to make it look similar to Blender.

Wouldn't it make sense to integrate this into Ogre so you could toggle it e.g. with Entity::setDebugDisplayEnabled?
uzik
Goblin
Posts: 202
Joined: Sun Feb 25, 2007 1:45 am
Location: USA
x 6

Re: Skeleton Debugger

Post by uzik »

Hey Nick,

To use the code I assume you just instantiate a SkeletonDebug object and call the update method when you want it to render?
What should the value of boneSize be? Is it scaled to a reasonable size for the environment?

Thanks for releasing your code :)

p.s. Where did you get the font file you're using?
---A dream doesn't become reality through magic; it takes sweat, determination and hard work.
uzik
Goblin
Posts: 202
Joined: Sun Feb 25, 2007 1:45 am
Location: USA
x 6

Re: Skeleton Debugger

Post by uzik »

Suggestion:

Allow the user to pass a parameter to scale the axes as well.
In my case they were so large it made it hard to see the model.
---A dream doesn't become reality through magic; it takes sweat, determination and hard work.
daarkron
Gnoblar
Posts: 16
Joined: Fri Nov 01, 2013 12:00 pm
Location: Switzerland

Re: Skeleton Debugger

Post by daarkron »

I added an extra parameter to the call of attachObjectToBone in order to fix bones orientation (perhaps that could fix the "Top right : Robot" issue of NickLH's post)

Code: Select all

ent = mSceneMan->createEntity("SkeletonDebug/BoneMesh");
tp = mEntity->attachObjectToBone(pBone->getName(), (Ogre::MovableObject*)ent, Vector3::UNIT_Y.getRotationTo(v));