University of Southern CaliforniaUSC
USC ICT TwitterUSC ICT FacebookUSC ICT YouTube

OpenSceneGraph integration with SmartBody(BoneBus) | General SmartBody Discussion | Forum

Avatar

Please consider registering
guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed Topic RSS sp_TopicIcon
OpenSceneGraph integration with SmartBody(BoneBus)
August 10, 2015
8:59 pm
Avatar
Member
Members
Forum Posts: 14
Member Since:
July 25, 2015
sp_UserOfflineSmall Offline

Hello,
I would like to know if is possible to integrate OpenSceneGraph with SmartBody using bonebus?
Other questions is if someone know about about any sample of OSG using bonebus?

August 12, 2015
6:19 am
Avatar
Admin
Forum Posts: 983
Member Since:
December 1, 2011
sp_UserOfflineSmall Offline

Sure, it's possible. OSG would have to do the rendering and either:

a) Have an OSG converted from a SmartBody mesh that was loaded, or
b) Don't let SmartBody load the mesh, instead, create a character in SmartBody from an OSG skeleton
Bonebus is just a network interface that sends updates on the SmartBody state. If you wanted an OSG/SmartBody interface via OSG, then you should just write a BoneBusServer implementation that does that.

 

I don't have any OSG sample code, but you 
can look at the OgreViewer project at the BoneBusHandler.h and .cpp and this part of the OgreRenderer code:

m_bonebus = new bonebus::BoneBusServer();
m_bonebus->SetOnClientConnectCallback( BoneBusHandler::OnClientConnect, this );
m_bonebus->SetOnCreateCharacterFunc( BoneBusHandler::OnCreateCharacter, this );
m_bonebus->SetOnDeleteCharacterFunc( BoneBusHandler::OnDeleteCharacter, this );
m_bonebus->SetOnUpdateCharacterFunc( BoneBusHandler::OnUpdateCharacter, this );
m_bonebus->SetOnSetCharacterPositionFunc( BoneBusHandler::OnSetCharacterPosition, this );
m_bonebus->SetOnSetCharacterRotationFunc( BoneBusHandler::OnSetCharacterRotation, this );
m_bonebus->SetOnBoneRotationsFunc( BoneBusHandler::OnBoneRotations, this );
m_bonebus->SetOnBonePositionsFunc( BoneBusHandler::OnBonePositions, this );
m_bonebus->SetOnBoneIdFunc( BoneBusHandler::OnBoneId, this );
m_bonebus->SetOnVisemeIdFunc( BoneBusHandler::OnVisemeId, this );
m_bonebus->OpenConnection();

Ari

August 14, 2015
12:01 am
Avatar
Member
Members
Forum Posts: 14
Member Since:
July 25, 2015
sp_UserOfflineSmall Offline

I've registered all bonebus callbacks as you told. However, i can't reach any callback function on BoneBusHandler.cpp. When i activate sbgui (bonebus) to establish connection with OsgSmartBody (attached in dropbox: https://www.dropbox.com/s/7ao2r2rmdx6567i/OSG.rar?dl=0) I put breackpoints in all BoneBusHandler to detect when each of then is reached however any of then is reached.
Someone could tell me how i could receive/access into BoneBusHandler functions on OsgSmartBody (attached)?

August 14, 2015
5:07 am
Avatar
Admin
Forum Posts: 983
Member Since:
December 1, 2011
sp_UserOfflineSmall Offline

I looked through your code, and perhaps the architecture isn't clear in the manual:

* There are two ways to run SmartBody with a separate renderer: 

1) You run sbgui (or something like it) on its own, then you create a separate application that doesn't run the SmartBody engine,  but simply renders the results by collecting the SmartBody state data over a network connection, called the BoneBus.

or

2) You embed the entire SmartBody engine inside of your renderer, then every time step, extract the state from the characters and pawns directly.

So the ogresmartbody and irrlichtsmartbody and simplesmartbody projects show how you can embed SmartBody as an engine inside of another renderer. The OgreViewer project has an example of how to use the bonebus (but unfortunately, it also includes another example of how to embed the SmartBody engine as well, so the code is a mix of BoneBus handing and embedded engine handling).

Of the two, I recommend the second (2) if possible, since it offers a direct connection in memory to SmartBody and much greater control and responsiveness. If you want to run SmartBody in a multiple-computer environment (we use this internally for projects where each computer is controlling a separate character) then the BoneBus works well, but otherwise, stay with the embedded engine version.

So the code that you have in BVHViewerApp.cpp in setup:

//carregamento das definições do samrtbody
scene = SmartBody::SBScene::getScene();
scene->setMediaPath( "../Data/" );
scene->addAssetPath( "motion", "ChrBrad");
scene->addAssetPath("mesh", "mesh");
scene->addAssetPath("script", "behaviorsets");
scene->addAssetPath("script", "scripts");
scene->loadAssets();

this is how you would start the use the embedded SmartBody engine, where you are telling SmartBody where to find all the data. In the BoneBus mode, all you are doing is showing the characters and positioning them where SmartBody tells you to find them, so all the setup, asset loading and so forth happen in the separate instantiation of sbgui.

So having said that...

if you want to use the embedded SmartBody, use OgreSmartBody or IrrlichtSmartBody as a template.

if you still want to use the BoneBus, make sure that you launch gui with a command line parameter: -host=127.0.0.1

 

and see if that makes things work for you.

 

Ari

August 14, 2015
4:10 pm
Avatar
Member
Members
Forum Posts: 14
Member Since:
July 25, 2015
sp_UserOfflineSmall Offline

Yes, i understand if my code looks a little bit confuse. About SmartBody render modes i understand implementation two types described in documentation. I'm interested in the first one:

1) You run sbgui (or something like it) on its own, then you create a separate application that doesn't run the SmartBody engine,  but simply renders the results by collecting the SmartBody state data over a network connection, called the BoneBus.

I did what you told:

"if you still want to use the BoneBus, make sure that you launch gui with a command line parameter: -host=127.0.0.1"

Set de IP(loopback) and enabled bonebus connection. It work fine with OgreViewer, however with this new implementation don't receive any entry callback call :S

August 15, 2015
3:17 pm
Avatar
Admin
Forum Posts: 983
Member Since:
December 1, 2011
sp_UserOfflineSmall Offline

I've stripped down your code and gotten it to work. I think you weren't calling:

m_boneBus->Update();

in a loop, which is why you weren't seeing the connection. Here's the strip down version that works:

 

main.cpp:

#include <bonebus.h>

#include "BoneBusHandler.h"

int main(int argc, char* argv[])
{
bonebus::BoneBusServer* m_bonebus = new bonebus::BoneBusServer();
m_bonebus->SetOnClientConnectCallback( BoneBusHandler::OnClientConnect, m_bonebus );
m_bonebus->SetOnCreateCharacterFunc( BoneBusHandler::OnCreateCharacter, m_bonebus );
m_bonebus->SetOnDeleteCharacterFunc( BoneBusHandler::OnDeleteCharacter, m_bonebus );
m_bonebus->SetOnUpdateCharacterFunc( BoneBusHandler::OnUpdateCharacter, m_bonebus );
m_bonebus->SetOnSetCharacterPositionFunc( BoneBusHandler::OnSetCharacterPosition, m_bonebus );
m_bonebus->SetOnSetCharacterRotationFunc( BoneBusHandler::OnSetCharacterRotation, m_bonebus );
m_bonebus->SetOnBoneRotationsFunc( BoneBusHandler::OnBoneRotations, m_bonebus );
m_bonebus->SetOnBonePositionsFunc( BoneBusHandler::OnBonePositions, m_bonebus );
m_bonebus->SetOnBoneIdFunc( BoneBusHandler::OnBoneId, m_bonebus );
m_bonebus->SetOnVisemeIdFunc( BoneBusHandler::OnVisemeId, m_bonebus );

bool val = m_bonebus->OpenConnection();
while (true)
{
m_bonebus->Update();
}
}

 

BoneBusHandler.h

#ifndef _BONEBUSHANDLER_H
#define _BONEBUSHANDLER_H

#include "vhcl.h"
#include <string>
#include "bonebus.h"
#include <vector>

class BoneBusHandler
{
public:
static void OnClientConnect( const std::string & clientName, void * userData );
static void OnCreateCharacter( const int characterID, const std::string & characterType, const std::string & characterName, const int skeletonType, void * userData );
static void OnUpdateCharacter( const int characterID, const std::string & characterType, const std::string & characterName, const int skeletonType, void * userData );
static void OnDeleteCharacter( const int characterID, void * userData );
static void OnSetCharacterPosition( const int characterID, const float x, const float y, const float z, void * userData );
static void OnSetCharacterRotation( const int characterID, const float w, const float x, const float y, const float z, void * userData );
static void OnBoneRotations( const bonebus::BulkBoneRotations * bulkBoneRotations, void * userData );
static void OnBonePositions( const bonebus::BulkBonePositions * bulkBonePositions, void * userData );
static void OnBoneId( const int characterID, const std::string boneName, const int boneId, void * user_data );
static void OnVisemeId( const int characterID, const std::string visemeName, const int visemeId, void * user_data ) ;

};

#endif

 

BoneBusHandler.cpp

#include <iostream>
#include "BoneBusHandler.h"
#include <sstream>

using namespace std;

void BoneBusHandler::OnClientConnect( const std::string & clientName, void * userData )
{
std::cout << "Client Connected! - %s
" << clientName.c_str() << std::endl;
}

void BoneBusHandler::OnCreateCharacter( const int characterID, const std::string & characterType, const std::string & characterName, const int skeletonType, void * userData )
{
std::cout << "Character Create! - %d, %s, %s, %d
" << characterID << characterType.c_str() << characterName.c_str() << skeletonType << std::endl;

}

void BoneBusHandler::OnUpdateCharacter( const int characterID, const std::string & characterType, const std::string & characterName, const int skeletonType, void * userData )
{
std::cout << "Character Update! - %d, %s, %s, %d
" << characterID << characterType.c_str() << characterName.c_str() << skeletonType << std::endl;

}

 

void BoneBusHandler::OnDeleteCharacter( const int characterID, void * userData )
{
std::cout << "Character Delete! - %d
" << characterID << std::endl;

 

}

void BoneBusHandler::OnSetCharacterPosition( const int characterID, const float x, const float y, const float z, void * userData )
{
std::cout << "Set Character Position! - %d - %5.2f %5.2f %5.2f
" << characterID << x << y << z << std::endl;

}

void BoneBusHandler::OnSetCharacterRotation( const int characterID, const float w, const float x, const float y, const float z, void * userData )
{
std::cout << "Set Character Rotation! - %d - %5.2f %5.2f %5.2f %5.2f
" << characterID << x << y << z << std::endl;

}

void BoneBusHandler::OnBoneRotations( const bonebus::BulkBoneRotations * bulkBoneRotations, void * userData )
{
std::cout << "Set Bone Rotations! - %d %d %d
" << bulkBoneRotations->packetId << bulkBoneRotations->charId << bulkBoneRotations->numBoneRotations << std::endl;

}

void BoneBusHandler::OnBonePositions( const bonebus::BulkBonePositions * bulkBonePositions, void * userData )
{
std::cout << "Set Bone Rotations! - %d %d %d
" << bulkBonePositions->packetId << bulkBonePositions->charId << bulkBonePositions->numBonePositions << std::endl;

}

void BoneBusHandler::OnBoneId( const int characterID, const std::string boneName, const int boneId, void * user_data )
{
std::cout << "Bone id!" << std::endl;

}

void BoneBusHandler::OnVisemeId( const int characterID, const std::string visemeName, const int visemeId, void * user_data )
{
std::cout << "Viseme id!" << std::endl;
}

 

 

Then you can run this program, then start sbgui like this:

 

sbgui -host=127.0.0.1

 

and the two processes should be connected with the BoneBus.

 

Ari