Manually moving bones of manually created skelton?

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
sjcomp
Gnome
Posts: 315
Joined: Sat Apr 23, 2005 2:35 pm
Location: Dover, NH
Contact:

Manually moving bones of manually created skelton?

Post by sjcomp » Mon Oct 17, 2005 12:06 am

I found a couple of threads which address the issue of moving a bone manually. I was following the instructions in these forums, but still can not make my bone to move. I create a mesh (triangle). After that I create a skeleton:

Code: Select all

// create skeleton and bones
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().create("skeleton",Ogre::ResourceGroupManager::getSingleton().getWorldResourceGroupName());
mesh->_notifySkeleton(skel);
Ogre::Bone* pRootBone = skel->createBone(0);
pRootBone->resetOrientation();
pRootBone->setPosition(0,0,0);
Ogre::Bone* pBone1=pRootBone->createChild(1,Vector3(-100.0, -100.0, 0.0));
Ogre::Bone* pBone2=pRootBone->createChild(2,Vector3(100.0, -100.0, 0.0));
Ogre::Bone* pBone3=pRootBone->createChild(3,Vector3(0.0, 100.0, 0.0));
// set manual control over the bones
pBone1->setManuallyControlled(true);pBone2->setManuallyControlled(true);pBone3->setManuallyControlled(true);
// assign vertices
Ogre::VertexBoneAssignment vba;
vba.weight = 1.0;
// first bone
vba.boneIndex = 1; vba.vertexIndex = 0;
sub->addBoneAssignment(vba);
// second bone
vba.boneIndex = 2; vba.vertexIndex = 1;
sub->addBoneAssignment(vba);
// third bone
vba.boneIndex = 3; vba.vertexIndex = 2;
sub->addBoneAssignment(vba);
skel->setBindingPose();
Now I move one bone to a new position:

Code: Select all

entity->getSkeleton()->getBone(1)->setPosition(Vector3(10,10,10));
Nothing happens. I am not using any animation tracks and can it be the problem? Some time ago it was an issue. I had to have an animation enabled for a mesh to be properly displayed. Should I use needUpdate() on the bone (I tried did not help) or getSkeleton()->_updateTransforms() (did not help either)?
Thanks a lot.
0 x
Regards, Alexander. http://sjcomp.com

genva
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 1603
Joined: Wed Oct 20, 2004 7:54 am
Location: Beijing, China

Post by genva » Mon Oct 17, 2005 6:23 am

You should set manually controlled to skeleton instance (which create by entity), not the skeleton resource (which create by SkeletonManager). For example:

Code: Select all

entity->getSkeleton()->getBone(1)->setManuallyControlled(true);
entity->getSkeleton()->getBone(2)->setManuallyControlled(true);
entity->getSkeleton()->getBone(3)->setManuallyControlled(true);
Kinda off-topic: I don't think is a bug that missing cloning the manually controlled state, because we don't store it into skeleton file.
0 x

User avatar
sjcomp
Gnome
Posts: 315
Joined: Sat Apr 23, 2005 2:35 pm
Location: Dover, NH
Contact:

Post by sjcomp » Mon Oct 17, 2005 4:38 pm

genva wrote:You should set manually controlled to skeleton instance (which create by entity)
Thanks that helped to move the bone. But it moves only once. I am using the following quick test:

Code: Select all

// global varialbes
Real r=0; Real inc=0.1;
// class AdvancedFrameListener: public ExampleFrameListener
bool AdvancedFrameListener::frameStarted(const FrameEvent& evt)
{
	if(r>100 || r<-100)inc=-inc; // pick direction
	r+=inc;  // increment or decrement r
	ent->getSkeleton()->getBone(1)->setPosition(Vector3(r,0,100));
	return ExampleFrameListener::frameStarted(evt);
}
I see that r is changing, but the bone stays in the position 0,0,100. What am I missing there? Should I call some kind of update function?
genva wrote:Kinda off-topic: I don't think is a bug that missing cloning the manually controlled state, because we don't store it into skeleton file.
I agree that it is not a bug. Now I understand that it makes sense to work with an instance of the skeleton as opposed to the resource.
Thank you very much for your help.
0 x
Regards, Alexander. http://sjcomp.com

genva
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 1603
Joined: Wed Oct 20, 2004 7:54 am
Location: Beijing, China

Post by genva » Mon Oct 17, 2005 5:28 pm

sjcomp wrote:I see that r is changing, but the bone stays in the position 0,0,100.
Strange, what's behavior that you are notice the bone stays in the position 0,0,100? Or, where are you see the bone position is 0,0,100?
sjcomp wrote:What am I missing there?
I don't know too (because no more detail information here).
sjcomp wrote:Should I call some kind of update function?
No, there aren't need call any update function directly here.
0 x

User avatar
sjcomp
Gnome
Posts: 315
Joined: Sat Apr 23, 2005 2:35 pm
Location: Dover, NH
Contact:

Post by sjcomp » Mon Oct 17, 2005 7:06 pm

genva wrote:Strange, what's behavior that you are notice the bone stays in the position 0,0,100? Or, where are you see the bone position is 0,0,100?
Actually, I used ent->getSkeleton()->getBone(1)->getPosition() to retrieve the bone position and it is correct. But vertex on the screen is at 0,0,100.
I am posting the complete code here. Bone supposed to be moved in frameStarted() function.

Code: Select all

#include "ExampleApplication.h"

SceneManager* sceneManager=NULL;
Entity *ent=NULL;
Real r=0;
Real inc=0.1;

// Handles camera motion via camNodes
class AdvancedFrameListener: public ExampleFrameListener
{
protected:
	SceneNode*	mCamNode;
	SceneNode*	mPitchNode;
	SceneNode*	mCamCtrlNode;
	SceneNode*	mCamCtrlNodeRotY;
	Radian		mTotalRotX;
	Radian		mTotalRotY;
public:
	// Constructor takes a RenderWindow because it uses that to determine input context
	AdvancedFrameListener(RenderWindow* win, Camera* cam, bool useBufferedInputKeys = false, bool useBufferedInputMouse = false)
		:ExampleFrameListener(win,cam,useBufferedInputKeys,useBufferedInputMouse)
	{
		mPitchNode=cam->getParentSceneNode();
		mCamNode=mPitchNode->getParentSceneNode();
		mCamCtrlNodeRotY=mCamNode->getParentSceneNode();
		mCamCtrlNode=mCamCtrlNodeRotY->getParentSceneNode();
	}
	virtual void moveCamera()
	{
		mTotalRotX+=mRotX;
		mTotalRotY+=mRotY;
		static const Radian c_NinetyDegreesInRadians=Degree(90);//1.5707964;
		static const Radian c_NegativeNinetyDegreesInRadians=Degree(-90);//1.5707964;
		// limit rotation
		if(mTotalRotY>c_NinetyDegreesInRadians)
			mRotY=0;
		else if(mTotalRotY<c_NegativeNinetyDegreesInRadians)
			mRotY=0;
		mCamCtrlNode->rotate(Ogre::Vector3::UNIT_Y,-mRotX);
		mCamCtrlNodeRotY->rotate(Ogre::Vector3::UNIT_Z,-mRotY);
	}
	virtual bool frameStarted(const FrameEvent& evt)
	{
		Vector3 pos=ent->getSkeleton()->getBone(1)->getPosition();
		// switch direction
		if(r>100 || r<-100)inc=-inc;
		r+=inc;
		ent->getSkeleton()->getBone(1)->setPosition(Vector3(r,0,100));
		bool ret=ExampleFrameListener::frameStarted(evt); mWindow->setDebugText(StringConverter::toString(r));
		return ret;
	}
};

MeshPtr GenerateMesh()
{
	Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual("Mesh",Ogre::ResourceGroupManager::getSingleton().getWorldResourceGroupName());
	Ogre::SubMesh * sub = mesh->createSubMesh();
	sub->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
	sub->useSharedVertices = false;

	const unsigned int num_verts = 3;
	const unsigned int size_vert = 6;
	const unsigned int uv_size_vert = 2;
	const unsigned int total_verts_size = num_verts * size_vert;
	const unsigned int uv_total_verts_size = num_verts * uv_size_vert;

	Ogre::Real verts[total_verts_size] =
	{
		-100.0, -100.0, 0.0,  0.0, 0.0, 1.0,
		100.0, -100.0, 0.0,  0.0, 0.0, 1.0,
		0.0, 100.0, 0.0,  0.0, 0.0, 1.0,
	};
	Ogre::Real uv_verts[uv_total_verts_size] =
	{
		0.0, 0.0,
		1.0, 0.0,
		0.0, 1.0
	};
	bool vertexShadowBuffer = true;
	Ogre::HardwareVertexBufferSharedPtr vbuf;
	vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer
		(size_vert*sizeof(Ogre::Real),
		num_verts,
		Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,vertexShadowBuffer);

	Ogre::HardwareVertexBufferSharedPtr uv_vbuf =
		Ogre::HardwareBufferManager::getSingleton().createVertexBuffer
		(uv_size_vert*sizeof(Ogre::Real),
		num_verts,
		Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
		vertexShadowBuffer);

	Ogre::HardwareBuffer::Usage indexBufferUsage = Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY;

	Ogre::HardwareIndexBufferSharedPtr ibuf;

	sub->indexData->indexCount = num_verts*2;
	sub->indexData->indexStart = 0;
	sub->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().
		createIndexBuffer(Ogre::HardwareIndexBuffer::IT_32BIT,
		sub->indexData->indexCount, indexBufferUsage);
	ibuf = sub->indexData->indexBuffer;

	Ogre::Real *pReal = (Ogre::Real*) vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD);
	unsigned int* pIndexes = static_cast<unsigned int*>   (ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD) );

	for (int i = 0; i < total_verts_size; ++i)
	{
		*pReal++ = verts[i];
	}

	pReal = (Ogre::Real*)uv_vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD);
	// writing to a vbuf from uv_verts array
	for (int i = 0; i < uv_total_verts_size ; ++i)
	{
		*pReal++ = uv_verts[i];
	}
	*pIndexes++ = 0;	*pIndexes++ = 1;	*pIndexes++ = 2;
	// make it doublesided
	*pIndexes++ = 0;	*pIndexes++ = 2;	*pIndexes++ = 1;

	// create skeleton and bones
	Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().create("skeleton",Ogre::ResourceGroupManager::getSingleton().getWorldResourceGroupName());
	mesh->_notifySkeleton(skel);
	Ogre::Bone* pRootBone = skel->createBone(0);
	pRootBone->resetOrientation();
	pRootBone->setPosition(0,0,0);
	Ogre::Bone* pBone1=pRootBone->createChild(1,Vector3(-100.0, -100.0, 0.0));
	Ogre::Bone* pBone2=pRootBone->createChild(2,Vector3(100.0, -100.0, 0.0));
	Ogre::Bone* pBone3=pRootBone->createChild(3,Vector3(0.0, 100.0, 0.0));

	Ogre::VertexBoneAssignment vba;
	vba.weight = 1.0;
	// first bone
	vba.boneIndex = 1; vba.vertexIndex = 0;
	sub->addBoneAssignment(vba);
	// second bone
	vba.boneIndex = 2; vba.vertexIndex = 1;
	sub->addBoneAssignment(vba);
	// third bone
	vba.boneIndex = 3; vba.vertexIndex = 2;
	sub->addBoneAssignment(vba);

	skel->setBindingPose();
	
	ibuf->unlock();
	vbuf->unlock();
	uv_vbuf->unlock();
	sub->vertexData = new Ogre::VertexData();
	sub->vertexData->vertexStart = 0;
	sub->vertexData->vertexCount = num_verts;
	Ogre::VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
	bind->setBinding(0, vbuf);
	bind->setBinding(1, uv_vbuf);
	size_t offset = 0;
	Ogre::VertexDeclaration* decl = sub->vertexData->vertexDeclaration;
	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
	decl->addElement(1, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
	mesh->_setBounds(Ogre::AxisAlignedBox(-100.0, -100.0, -100.0, 100.0, 100.0, 100.0));
	mesh->load();
	return mesh; 
}

class CTestApplication : public ExampleApplication
{
public:
	CTestApplication() {}
	// Override this function to create camera attached to camNode
	virtual void createCamera(void)
	{
		// Create the camera
		mCamera = mSceneMgr->createCamera("PlayerCam");
		SceneNode* camCtrlNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("camCtrlNode");
		SceneNode* camCtrlNodeYaw=camCtrlNode->createChildSceneNode("camCtrlNodeYaw");
		SceneNode* camNode=camCtrlNodeYaw->createChildSceneNode("camNode");
		camNode->setPosition(Vector3(400,0,0));
		SceneNode* pitchNode=camNode->createChildSceneNode("pitchNode");
		pitchNode->attachObject(mCamera);
		mCamera->lookAt(0,0,0);
		camCtrlNode->setFixedYawAxis(true);
	}
protected:
	// Just override the mandatory create scene method
	void createScene(void)
	{
		// Set ambient light
		mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
		sceneManager=mSceneMgr;
		// Create entity to the scene node
		GenerateMesh();
		ent = mSceneMgr->createEntity("robot1", "Mesh");
		SceneNode* pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("node1",Vector3(0, 0,0));
		pNode->attachObject(ent);
		ent->setMaterialName("2 - Default");
		ent->getSkeleton()->getBone(1)->setManuallyControlled(true);
		// create reference node
		Entity* pRefEnt = mSceneMgr->createEntity("cube", "cube.mesh");
		pRefEnt->setMaterialName("2 - Default");
		SceneNode* pRefNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("RefNode",Vector3(0, 0,0));
		pRefNode->attachObject(pRefEnt);
		pRefNode->setScale(Vector3(0.1,0.1,0.1));
		
	}
	// Create new frame listener
	void createFrameListener(void)
	{
		mFrameListener= new AdvancedFrameListener(mWindow, mCamera);
		mRoot->addFrameListener(mFrameListener);
	}
};

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
    // Create application object
    CTestApplication app;
    try {
        app.go();
    } catch( Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
        std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
    }
    return 0;
}
#ifdef __cplusplus
}
#endif
Thanks.
0 x
Regards, Alexander. http://sjcomp.com

Krulspeld
Kobold
Posts: 35
Joined: Tue Apr 05, 2005 9:51 pm

Post by Krulspeld » Mon Oct 17, 2005 9:11 pm

This seems to be working fine over here. (DirectX9 & OpenGL)
0 x

User avatar
sjcomp
Gnome
Posts: 315
Joined: Sat Apr 23, 2005 2:35 pm
Location: Dover, NH
Contact:

Post by sjcomp » Tue Oct 18, 2005 1:43 pm

Krulspeld wrote:This seems to be working fine over here. (DirectX9 & OpenGL)
Does it mean that a side of the triangle moves from side to side? Because my triangle does not move at all. What version of Ogre are you using?

Thanks for the response.
0 x
Regards, Alexander. http://sjcomp.com

Krulspeld
Kobold
Posts: 35
Joined: Tue Apr 05, 2005 9:51 pm

Post by Krulspeld » Tue Oct 18, 2005 9:38 pm

When looking at the origin from a position on the +Z axis the following happens:

Code: Select all

      
   /\
  /  \
 /____\
<->
Vertex 0 moves as expected since it is directly attached to bone 1.
I am using precompiled Ogre 1.0.5 version for Windows. My graphics card is an ATI Radeon 9800.
0 x

User avatar
sjcomp
Gnome
Posts: 315
Joined: Sat Apr 23, 2005 2:35 pm
Location: Dover, NH
Contact:

Post by sjcomp » Tue Oct 18, 2005 11:46 pm

Krulspeld wrote: I am using precompiled Ogre 1.0.5 version for Windows. My graphics card is an ATI Radeon 9800.
Thanks a lot! I updated to the HEAD and it started to work. Thanks again.
0 x
Regards, Alexander. http://sjcomp.com

genva
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 1603
Joined: Wed Oct 20, 2004 7:54 am
Location: Beijing, China

Post by genva » Wed Oct 19, 2005 2:34 am

I just want to know, what's version you are use previous? Thank you.
0 x

User avatar
sjcomp
Gnome
Posts: 315
Joined: Sat Apr 23, 2005 2:35 pm
Location: Dover, NH
Contact:

Post by sjcomp » Wed Oct 19, 2005 4:16 pm

Now it is hard to say :( I updated to HEAD somewhere in between September 10th and October 10th. I run cvs update yesterday and now I am not sure how I can find out when I ran the previous cvs update. If there is a way, let me know how I can find out.

I guess it did not work because I was using HEAD and something was broken when I checked out the code. But this is my guess.

Thanks a lot for the help.
0 x
Regards, Alexander. http://sjcomp.com

genva
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 1603
Joined: Wed Oct 20, 2004 7:54 am
Location: Beijing, China

Post by genva » Thu Oct 20, 2005 4:13 am

I guess it did not work because I was using HEAD and something was broken when I checked out the code. But this is my guess.
Yes, issues more often occuring in CVS HEAD. And there are some issues around the skeleton animation fixed recently :).
0 x

User avatar
sjcomp
Gnome
Posts: 315
Joined: Sat Apr 23, 2005 2:35 pm
Location: Dover, NH
Contact:

Post by sjcomp » Thu Oct 20, 2005 1:29 pm

But it works now and that is what is important! Thanks a lot for your help.
0 x
Regards, Alexander. http://sjcomp.com

Post Reply