Andrew n marshall wrote:
// [BMLR] Get command from renderer and external programs
vector<string>* BoneBusClient::GetCommand() { std::string result = "";
if ( m_sockTCP != NULL ) { fd_set SocketSet; FD_ZERO(&SocketSet);
...
Crud... Okay, it the last three methods of this file:
Anm
/*
This file is part of VHMsg written by Edward Fast at
University of Southern California's Institute for Creative Technologies.
http://www.ict.usc.edu
Copyright 2008 Edward Fast, University of Southern California
VHMsg is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
VHMsg is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with VHMsg. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <winsock.h>
#include <string>
#include "bonebus.h"
using std::string;
using std::vector;
BoneBusCharacter::BoneBusCharacter( const bool useFaceBones, SOCKET sockUDP,
sockaddr_in toAddrUDP, SOCKET sockTCP )
{
m_sockUDP = sockUDP;
m_toAddrUDP = toAddrUDP;
m_sockTCP = sockTCP;
NetworkMapBoneNames( m_boneNameMap, useFaceBones );
if ( !useFaceBones )
NetworkMapVisemeNames( m_visemeNameMap );
}
BoneBusCharacter::~BoneBusCharacter()
{
}
void BoneBusCharacter::StartSendBoneRotations()
{
m_bulkBoneRotations.numBoneRotations = 0;
}
void BoneBusCharacter::EndSendBoneRotations()
{
if ( m_bulkBoneRotations.numBoneRotations <= 0 )
{
return;
}
int packetSize = BulkBoneRotationsHeaderSize + ( sizeof( BulkBoneRotation )
* m_bulkBoneRotations.numBoneRotations );
//printf( "Rotation Packet size: %d\n", packetSize );
int bytesSent;
bytesSent = sendto( m_sockUDP, (const char *)&m_bulkBoneRotations,
packetSize, 0, (SOCKADDR*)&m_toAddrUDP, sizeof( m_toAddrUDP ) );
if ( bytesSent < 0 )
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if ( bytesSent > 0 )
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusCharacter::AddBoneRotation( const char * boneName, const float w,
const float x, const float y, const float z )
{
int packetSize = BulkBoneRotationsHeaderSize + ( sizeof( BulkBoneRotation )
* m_bulkBoneRotations.numBoneRotations );
if ( packetSize > 2000 )
{
//return;
EndSendBonePositions();
StartSendBoneRotations();
packetSize = BulkBoneRotationsHeaderSize + ( sizeof( BulkBoneRotation ) *
m_bulkBoneRotations.numBoneRotations );
}
BoneNameMapIter iter = m_boneNameMap.find( boneName );
if ( iter == m_boneNameMap.end() )
{
return;
}
BoneNameMapData & data = iter->second;
// check to see if we've sent this data before
// if we have, send it again to account for packet loss
// and then don't send it again until the bone has moved
if ( data.cacheQuatW == w &&
data.cacheQuatX == x &&
data.cacheQuatY == y &&
data.cacheQuatZ == z )
{
data.cacheQuatHits++;
if ( data.cacheQuatHits > 1 )
{
//return;
}
}
else
{
data.cacheQuatW = w;
data.cacheQuatX = x;
data.cacheQuatY = y;
data.cacheQuatZ = z;
data.cacheQuatHits = 0;
}
BulkBoneRotation * item = &m_bulkBoneRotations.bones[
m_bulkBoneRotations.numBoneRotations ];
item->boneId = data.networkId;
item->rot_w = w;
item->rot_x = x;
item->rot_y = y;
item->rot_z = z;
m_bulkBoneRotations.numBoneRotations++;
}
void BoneBusCharacter::StartSendBonePositions()
{
m_bulkBonePositions.charId = m_charId;
m_bulkBonePositions.numBonePositions = 0;
}
void BoneBusCharacter::EndSendBonePositions()
{
if ( m_bulkBonePositions.numBonePositions <= 0 )
{
return;
}
int packetSize = BulkBonePositionsHeaderSize + ( sizeof( BulkBonePosition )
* m_bulkBonePositions.numBonePositions );
//printf( "Position Packet size: %d\n", packetSize );
int bytesSent;
bytesSent = sendto( m_sockUDP, (const char *)&m_bulkBonePositions,
packetSize, 0, (SOCKADDR*)&m_toAddrUDP, sizeof( m_toAddrUDP ) );
if ( bytesSent < 0 )
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if ( bytesSent > 0 )
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusCharacter::AddBonePosition( const char * boneName, const float x,
const float y, const float z )
{
int packetSize = BulkBonePositionsHeaderSize + ( sizeof( BulkBonePosition )
* m_bulkBonePositions.numBonePositions );
if ( packetSize > 2000 )
{
//return;
EndSendBonePositions();
StartSendBonePositions();
packetSize = BulkBonePositionsHeaderSize + ( sizeof( BulkBonePosition ) *
m_bulkBonePositions.numBonePositions );
}
BoneNameMapIter iter = m_boneNameMap.find( boneName );
if ( iter == m_boneNameMap.end() )
{
return;
}
BoneNameMapData & data = iter->second;
// check to see if we've sent this data before
// if we have, send it again to account for packet loss
// and then don't send it again until the bone has moved
if ( data.cachePosX == x &&
data.cachePosY == y &&
data.cachePosZ == z )
{
data.cachePosHits++;
if ( data.cachePosHits > 1 )
{
//return;
}
}
else
{
data.cachePosX = x;
data.cachePosY = y;
data.cachePosZ = z;
data.cachePosHits = 0;
}
BulkBonePosition * item = &m_bulkBonePositions.bones[
m_bulkBonePositions.numBonePositions ];
item->boneId = data.networkId;
item->pos_x = x;
item->pos_y = y;
item->pos_z = z;
m_bulkBonePositions.numBonePositions++;
}
void BoneBusCharacter::SetViseme( const char * viseme, const float weight,
const float blendTime )
{
if ( m_visemeNameMap.find( viseme ) == m_visemeNameMap.end() )
{
return;
}
char b[ 512 ];
int blen;
sprintf( b, "SetActorViseme|%d|%d|%f|%f;", m_charId, m_visemeNameMap[ viseme
], weight, blendTime );
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusCharacter::SetPosition( const float x, const float y, const float z
)
{
// check to see if we've sent this data before
// if we have, send it again to account for packet loss
// and then don't send it again until the bone has moved
if ( m_cachePosX == x &&
m_cachePosY == y &&
m_cachePosZ == z )
{
m_cachePosHits++;
if ( m_cachePosHits > 1 )
{
return;
}
}
else
{
m_cachePosX = x;
m_cachePosY = y;
m_cachePosZ = z;
m_cachePosHits = 0;
}
//printf( "Calling 'SetActorPos %d %f %f %f'\n", character->charId, x, y, z
);
char b[ 512 ];
int blen;
sprintf( b, "SetActorPos|%d|%f|%f|%f;", m_charId, x, y, z );
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusCharacter::SetRotation( const float w, const float x, const float
y, const float z )
{
// check to see if we've sent this data before
// if we have, send it again to account for packet loss
// and then don't send it again until the bone has moved
if ( m_cacheQuatW == w &&
m_cacheQuatX == x &&
m_cacheQuatY == y &&
m_cacheQuatZ == z )
{
m_cacheQuatHits++;
if ( m_cacheQuatHits > 1 )
{
return;
}
}
else
{
m_cacheQuatW = w;
m_cacheQuatX = x;
m_cacheQuatY = y;
m_cacheQuatZ = z;
m_cacheQuatHits = 0;
}
//printf( "Calling 'SetActorRot %d %f %f %f %f'\n", character->charId, w, x,
y, z );
char b[ 512 ];
int blen;
sprintf( b, "SetActorRot|%d|%f|%f|%f|%f;", m_charId, w, x, y, z );
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusCharacter::NetworkMapBoneNames( BoneNameMap & boneNameMap, const
bool faceBones )
{
boneNameMap.clear();
// smartbody doctor
boneNameMap[ "skeleton" ] = BoneNameMapData( 1 );
boneNameMap[ "base" ] = BoneNameMapData( 2 );
boneNameMap[ "l_hip" ] = BoneNameMapData( 3 );
boneNameMap[ "l_knee" ] = BoneNameMapData( 4 );
boneNameMap[ "l_ankle" ] = BoneNameMapData( 5 );
boneNameMap[ "l_forefoot" ] = BoneNameMapData( 6 );
boneNameMap[ "l_toe" ] = BoneNameMapData( 7 );
boneNameMap[ "r_hip" ] = BoneNameMapData( 8 );
boneNameMap[ "r_knee" ] = BoneNameMapData( 9 );
boneNameMap[ "r_ankle" ] = BoneNameMapData( 10 );
boneNameMap[ "r_forefoot" ] = BoneNameMapData( 11 );
boneNameMap[ "r_toe" ] = BoneNameMapData( 12 );
boneNameMap[ "spine1" ] = BoneNameMapData( 13 );
boneNameMap[ "spine2" ] = BoneNameMapData( 14 );
boneNameMap[ "spine3" ] = BoneNameMapData( 15 );
boneNameMap[ "spine4" ] = BoneNameMapData( 16 );
boneNameMap[ "spine5" ] = BoneNameMapData( 17 );
boneNameMap[ "skullbase" ] = BoneNameMapData( 18 );
if ( faceBones )
{
boneNameMap[ "face_top_parent" ] = BoneNameMapData( 19 );
boneNameMap[ "brow_parent_left" ] = BoneNameMapData( 20 );
boneNameMap[ "brow01_left" ] = BoneNameMapData( 21 );
boneNameMap[ "brow02_left" ] = BoneNameMapData( 22 );
boneNameMap[ "brow03_left" ] = BoneNameMapData( 23 );
boneNameMap[ "brow04_left" ] = BoneNameMapData( 24 );
boneNameMap[ "brow_parent_right" ] = BoneNameMapData( 25 );
boneNameMap[ "brow01_right" ] = BoneNameMapData( 26 );
boneNameMap[ "brow02_right" ] = BoneNameMapData( 27 );
boneNameMap[ "brow03_right" ] = BoneNameMapData( 28 );
boneNameMap[ "brow05_right" ] = BoneNameMapData( 29 );
boneNameMap[ "ear_left" ] = BoneNameMapData( 30 );
boneNameMap[ "eyeball_left" ] = BoneNameMapData( 31 );
boneNameMap[ "upper_nose_left" ] = BoneNameMapData( 32 );
boneNameMap[ "lower_nose_left" ] = BoneNameMapData( 33 );
boneNameMap[ "upper_nose_right" ] = BoneNameMapData( 34 );
boneNameMap[ "lower_nose_right" ] = BoneNameMapData( 35 );
boneNameMap[ "lower_eyelid_right" ] = BoneNameMapData( 36 );
boneNameMap[ "upper_eyelid_right" ] = BoneNameMapData( 37 );
boneNameMap[ "eyeball_right" ] = BoneNameMapData( 38 );
boneNameMap[ "ear_right" ] = BoneNameMapData( 39 );
boneNameMap[ "lower_eyelid_left" ] = BoneNameMapData( 40 );
boneNameMap[ "upper_eyelid_left" ] = BoneNameMapData( 41 );
boneNameMap[ "joint18" ] = BoneNameMapData( 42 );
boneNameMap[ "face_bottom_parent" ] = BoneNameMapData( 43 );
boneNameMap[ "Jaw" ] = BoneNameMapData( 44 );
boneNameMap[ "Jaw_back" ] = BoneNameMapData( 45 );
boneNameMap[ "Jaw_front" ] = BoneNameMapData( 46 );
boneNameMap[ "Lip_bttm_mid" ] = BoneNameMapData( 47 );
boneNameMap[ "Lip_bttm_right" ] = BoneNameMapData( 48 );
boneNameMap[ "Lip_bttm_left" ] = BoneNameMapData( 49 );
boneNameMap[ "Tongue_back" ] = BoneNameMapData( 50 );
boneNameMap[ "Tongue_mid" ] = BoneNameMapData( 51 );
boneNameMap[ "Tongue_front" ] = BoneNameMapData( 52 );
boneNameMap[ "Lip_top_left" ] = BoneNameMapData( 53 );
boneNameMap[ "Lip_top_right" ] = BoneNameMapData( 54 );
boneNameMap[ "Cheek_low_right" ] = BoneNameMapData( 55 );
boneNameMap[ "Cheek_up_right" ] = BoneNameMapData( 56 );
boneNameMap[ "cheek_low_left" ] = BoneNameMapData( 57 );
boneNameMap[ "Cheek_up_left" ] = BoneNameMapData( 58 );
boneNameMap[ "Lip_out_left" ] = BoneNameMapData( 59 );
boneNameMap[ "Lip_out_right" ] = BoneNameMapData( 60 );
boneNameMap[ "Lip_top_mid" ] = BoneNameMapData( 61 );
}
else
{
boneNameMap[ "eyeball_left" ] = BoneNameMapData( 31 );
boneNameMap[ "eyeball_right" ] = BoneNameMapData( 38 );
}
boneNameMap[ "l_sternoclavicular" ] = BoneNameMapData( 62 );
boneNameMap[ "l_acromioclavicular" ] = BoneNameMapData( 63 );
boneNameMap[ "l_shoulder" ] = BoneNameMapData( 64 );
boneNameMap[ "l_elbow" ] = BoneNameMapData( 65 );
boneNameMap[ "l_forearm" ] = BoneNameMapData( 66 );
boneNameMap[ "l_wrist" ] = BoneNameMapData( 67 );
boneNameMap[ "l_pinky1" ] = BoneNameMapData( 68 );
boneNameMap[ "l_pinky2" ] = BoneNameMapData( 69 );
boneNameMap[ "l_pinky3" ] = BoneNameMapData( 70 );
boneNameMap[ "l_pinky4" ] = BoneNameMapData( 71 );
boneNameMap[ "l_ring1" ] = BoneNameMapData( 72 );
boneNameMap[ "l_ring2" ] = BoneNameMapData( 73 );
boneNameMap[ "l_ring3" ] = BoneNameMapData( 74 );
boneNameMap[ "l_ring4" ] = BoneNameMapData( 75 );
boneNameMap[ "l_middle1" ] = BoneNameMapData( 76 );
boneNameMap[ "l_middle2" ] = BoneNameMapData( 77 );
boneNameMap[ "l_middle3" ] = BoneNameMapData( 78 );
boneNameMap[ "l_middle4" ] = BoneNameMapData( 79 );
boneNameMap[ "l_index1" ] = BoneNameMapData( 80 );
boneNameMap[ "l_index2" ] = BoneNameMapData( 81 );
boneNameMap[ "l_index3" ] = BoneNameMapData( 82 );
boneNameMap[ "l_index4" ] = BoneNameMapData( 83 );
boneNameMap[ "l_thumb1" ] = BoneNameMapData( 84 );
boneNameMap[ "l_thumb2" ] = BoneNameMapData( 85 );
boneNameMap[ "l_thumb3" ] = BoneNameMapData( 86 );
boneNameMap[ "l_thumb4" ] = BoneNameMapData( 87 );
boneNameMap[ "r_sternoclavicular" ] = BoneNameMapData( 88 );
boneNameMap[ "r_acromioclavicular" ] = BoneNameMapData( 89 );
boneNameMap[ "r_shoulder" ] = BoneNameMapData( 90 );
boneNameMap[ "r_elbow" ] = BoneNameMapData( 91 );
boneNameMap[ "r_forearm" ] = BoneNameMapData( 92 );
boneNameMap[ "r_wrist" ] = BoneNameMapData( 93 );
boneNameMap[ "r_pinky1" ] = BoneNameMapData( 94 );
boneNameMap[ "r_pinky2" ] = BoneNameMapData( 95 );
boneNameMap[ "r_pinky3" ] = BoneNameMapData( 96 );
boneNameMap[ "r_pinky4" ] = BoneNameMapData( 97 );
boneNameMap[ "r_ring1" ] = BoneNameMapData( 98 );
boneNameMap[ "r_ring2" ] = BoneNameMapData( 99 );
boneNameMap[ "r_ring3" ] = BoneNameMapData( 100 );
boneNameMap[ "r_ring4" ] = BoneNameMapData( 101 );
boneNameMap[ "r_middle1" ] = BoneNameMapData( 102 );
boneNameMap[ "r_middle2" ] = BoneNameMapData( 103 );
boneNameMap[ "r_middle3" ] = BoneNameMapData( 104 );
boneNameMap[ "r_middle4" ] = BoneNameMapData( 105 );
boneNameMap[ "r_index1" ] = BoneNameMapData( 106 );
boneNameMap[ "r_index2" ] = BoneNameMapData( 107 );
boneNameMap[ "r_index3" ] = BoneNameMapData( 108 );
boneNameMap[ "r_index4" ] = BoneNameMapData( 109 );
boneNameMap[ "r_thumb1" ] = BoneNameMapData( 110 );
boneNameMap[ "r_thumb2" ] = BoneNameMapData( 111 );
boneNameMap[ "r_thumb3" ] = BoneNameMapData( 112 );
boneNameMap[ "r_thumb4" ] = BoneNameMapData( 113 );
}
void BoneBusCharacter::NetworkMapVisemeNames( VisemeNameMap & visemeNameMap )
{
visemeNameMap.clear();
// smartbody doctor
visemeNameMap[ "EE" ] = 5;
visemeNameMap[ "Er" ] = 6;
visemeNameMap[ "Ih" ] = 7;
visemeNameMap[ "Ao" ] = 8;
visemeNameMap[ "oh" ] = 9;
visemeNameMap[ "OO" ] = 10;
visemeNameMap[ "Z" ] = 11;
visemeNameMap[ "j" ] = 12;
visemeNameMap[ "f" ] = 13;
visemeNameMap[ "Th" ] = 14;
visemeNameMap[ "D" ] = 15;
visemeNameMap[ "BMP" ] = 16;
visemeNameMap[ "NG" ] = 17;
visemeNameMap[ "R" ] = 18;
visemeNameMap[ "KG" ] = 19;
visemeNameMap[ "brow_rt_up" ] = 20;
visemeNameMap[ "brow_lf_up" ] = 21;
visemeNameMap[ "blink_rt" ] = 22;
//visemeNameMap[ "blink_rt" ] = 23;
visemeNameMap[ "blink_lf" ] = 24;
//visemeNameMap[ "blink_lf" ] = 25;
visemeNameMap[ "angry" ] = 26;
visemeNameMap[ "surprised" ] = 27;
visemeNameMap[ "thinking" ] = 28;
visemeNameMap[ "blink" ] = 29;
//visemeNameMap[ "blink" ] = 30;
//visemeNameMap[ "blink" ] = 31;
//visemeNameMap[ "blink" ] = 32;
visemeNameMap[ "unit4_inner_brow_lowerer" ] = 33;
visemeNameMap[ "unit1_inner_brow_raiser" ] = 34;
visemeNameMap[ "unit2_outer_brow_raiser" ] = 35;
visemeNameMap[ "unit5_upper_lid_raiser" ] = 36;
visemeNameMap[ "unit1_plus_unit4" ] = 37;
visemeNameMap[ "unit1_plus_unit2" ] = 38;
visemeNameMap[ "unit1_unit2_unit4" ] = 39;
visemeNameMap[ "unit6_eye_squint" ] = 40;
visemeNameMap[ "unit12_smile_mouth" ] = 41;
visemeNameMap[ "unit25_lip_parser" ] = 42;
visemeNameMap[ "unit26_jaw_drop" ] = 43;
visemeNameMap[ "unit27_jaw_stretch_open" ] = 44;
visemeNameMap[ "unit20_mouth_stretch" ] = 45;
visemeNameMap[ "unit38_nostril_dilator" ] = 46;
visemeNameMap[ "unit7_lid_tightener" ] = 47;
visemeNameMap[ "unit9_nose_wrinkle" ] = 48;
visemeNameMap[ "unit10_upper_lip_raiser" ] = 49;
visemeNameMap[ "unit15_lip_corner_depressor" ] = 50;
visemeNameMap[ "unit23_lip_tightener" ] = 51;
visemeNameMap[ "unit39_nostril_compressor" ] = 52;
}
BoneBusClient::BoneBusClient()
{
m_wsaStartupCalled = false;
m_sockUDP = NULL;
m_sockTCP = NULL;
}
BoneBusClient::~BoneBusClient()
{
CloseConnection();
}
bool BoneBusClient::OpenConnection( const char * server )
{
// TODO: cleanup udp if tcp error
if ( strcmp( server, "" ) == 0 )
return false;
WSADATA wsaData;
int err = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( err != 0 )
{
printf( "WSAStartup failed. Code: %d\n", err );
return false;
}
m_wsaStartupCalled = true;
m_sockUDP = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( m_sockUDP == INVALID_SOCKET )
{
printf( "Couldn't create socket.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
m_sockUDP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
// see if we're specifying a host by name or by number
if ( isalpha( server[ 0 ] ) )
{
hostent * host = gethostbyname( server );
if ( host == NULL )
{
printf( "gethostbyname() failed.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
closesocket( m_sockUDP );
m_sockUDP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
m_toAddrUDP.sin_family = AF_INET;
m_toAddrUDP.sin_addr = *( (in_addr *)host->h_addr );
m_toAddrUDP.sin_port = htons( NETWORK_PORT_UDP );
}
else
{
m_toAddrUDP.sin_family = AF_INET;
m_toAddrUDP.sin_addr.s_addr = inet_addr( server );
m_toAddrUDP.sin_port = htons( NETWORK_PORT_UDP );
}
m_sockTCP = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( m_sockTCP == INVALID_SOCKET )
{
printf( "Couldn't create socket2.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
m_sockTCP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
// see if we're specifying a host by name or by number
if ( isalpha( server[ 0 ] ) )
{
hostent * host = gethostbyname( server );
if ( host == NULL )
{
printf( "gethostbyname() failed.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
closesocket( m_sockTCP );
m_sockTCP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
m_toAddrTCP.sin_family = AF_INET;
m_toAddrTCP.sin_addr = *( (in_addr *)host->h_addr );
m_toAddrTCP.sin_port = htons( NETWORK_PORT_TCP );
}
else
{
m_toAddrTCP.sin_family = AF_INET;
m_toAddrTCP.sin_addr.s_addr = inet_addr( server );
m_toAddrTCP.sin_port = htons( NETWORK_PORT_TCP );
}
{
int ret;
ret = connect( m_sockTCP, (SOCKADDR*)&m_toAddrTCP, sizeof( m_toAddrTCP )
);
if ( ret < 0 )
{
printf( "connect() failed.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
closesocket( m_sockTCP );
m_sockTCP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
}
return true;
}
bool BoneBusClient::CloseConnection()
{
if ( m_sockUDP )
{
closesocket( m_sockUDP );
m_sockUDP = NULL;
}
if ( m_sockTCP )
{
closesocket( m_sockTCP );
m_sockTCP = NULL;
}
if ( m_wsaStartupCalled )
{
WSACleanup();
m_wsaStartupCalled = false;
}
return true;
}
bool BoneBusClient::Update()
{
return true;
}
BoneBusCharacter * BoneBusClient::CreateCharacter( const char * charName, const
char * objectClass, const bool useFaceBones )
{
if ( !IsOpen() )
{
return NULL;
}
// TODO: This creates a unique_id based on the size of the list
// This will fail if we operate multiple Smartbody processes at the
same time
// We'll get the same ID. Need to come up with an algorithm that
will handle this.
if ( m_characterNameMap.find( charName ) == m_characterNameMap.end() )
{
m_characterNameMap[ charName ] = (int)m_characterNameMap.size() + 1;
}
BoneBusCharacter * character = new BoneBusCharacter( useFaceBones,
m_sockUDP, m_toAddrUDP, m_sockTCP );
character->m_name = charName;
character->m_charId = m_characterNameMap[ charName ];
//NetworkMapBoneNames( character->m_boneNameMap, useFaceBones );
//
//if ( !useFaceBones )
// NetworkMapVisemeNames( character->m_visemeNameMap );
character->m_bulkBoneRotations.packetId = 0x10;
character->m_bulkBoneRotations.charId = character->m_charId;
character->m_bulkBoneRotations.numBoneRotations = 0;
character->m_bulkBoneRotations.numBonePositions_unused = 0;
memset( character->m_bulkBoneRotations.bones, 0,
sizeof(character->m_bulkBoneRotations.bones) );
character->m_bulkBonePositions.packetId = 0x11;
character->m_bulkBonePositions.charId = character->m_charId;
character->m_bulkBonePositions.numBonePositions = 0;
memset( character->m_bulkBonePositions.bones, 0,
sizeof(character->m_bulkBonePositions.bones) );
character->m_cachePosX = 0;
character->m_cachePosY = 0;
character->m_cachePosZ = 0;
character->m_cachePosHits = 0;
character->m_cacheQuatW = 1;
character->m_cacheQuatX = 0;
character->m_cacheQuatY = 0;
character->m_cacheQuatZ = 0;
character->m_cacheQuatHits = 0;
if ( m_sockTCP != NULL )
{
printf( "Calling 'CreateActor %d %s %s %d'\n", character->m_charId,
objectClass, charName, 1 );
char b[ 512 ];
int blen;
sprintf( b, "CreateActor|%d|%s|%s|%d;", character->m_charId, objectClass,
charName, 1 );
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if ( bytesSent < 0 )
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if ( bytesSent > 0 )
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
m_characterDataMap[ character->m_charId ] = character;
return character;
}
bool BoneBusClient::DeleteCharacter( BoneBusCharacter * character )
{
if ( IsOpen() )
{
printf( "Calling 'DeleteActor %d'\n", character->m_charId );
char b[ 512 ];
int blen;
sprintf( b, "DeleteActor|%d;", character->m_charId );
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if ( bytesSent < 0 )
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if ( bytesSent > 0 )
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
m_characterDataMap.erase( character->m_charId );
m_characterNameMap.erase( character->m_name );
delete character;
character = NULL;
return true;
}
BoneBusCharacter * BoneBusClient::FindCharacter( const int charID )
{
return m_characterDataMap[ charID ];
}
BoneBusCharacter * BoneBusClient::FindCharacterByName( const char * name )
{
CharacterDataMap::const_iterator it;
for ( it = m_characterDataMap.begin(); it != m_characterDataMap.end(); it++ )
{
if ( (*it).second->m_name == (string)name )
{
return (*it).second;
}
}
return NULL;
}
void BoneBusClient::SetCameraPosition( const float x, const float y, const
float z )
{
if ( !IsOpen() )
{
return;
}
char b[ 512 ];
int blen;
sprintf( b, "SetActorPos|%d|%f|%f|%f;", -1, x, y, z );
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusClient::SetCameraRotation( const float w, const float x, const
float y, const float z )
{
if ( !IsOpen() )
{
return;
}
char b[ 512 ];
int blen;
sprintf( b, "SetActorRot|%d|%f|%f|%f|%f;", -1, w, x, y, z );
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusClient::ExecScript( const char * command )
{
if ( !IsOpen() )
{
return;
}
ExecScriptData data;
data.packetID = 0x04;
strcpy( data.command, command ); // watch buffer length!
int bytesSent;
bytesSent = sendto( m_sockUDP, (const char *)&data, sizeof( data ), 0,
(SOCKADDR*)&m_toAddrUDP, sizeof( m_toAddrUDP ) );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusClient::SendPlaySound( const char * sound_file )
{
if ( !IsOpen() )
{
return;
}
char b[512];
int blen;
//printf( "Calling 'PlaySoundDynamic %s'\n", filename );
sprintf( b, "PlaySoundDynamic|%s;", sound_file);
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
void BoneBusClient::SendStopSound( const char * sound_file )
{
if ( !IsOpen() )
{
return;
}
char b[512];
int blen;
//printf( "Calling 'StopSoundDynamic %s'\n", filename );
sprintf( b, "StopSoundDynamic|%s;", sound_file);
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
//fprintf( fp, "socket error: %d\n", errnum );
}
if (bytesSent > 0)
{
//printf( "send: %ld\n", bytesSent );
//fprintf( fp, "send: %ld\n", bytesSent );
}
}
BoneBusServer::BoneBusServer()
{
m_sockUDP = NULL;
m_sockTCP = NULL;
m_wsaStartupCalled = false;
m_onClientConnectFunc = NULL;
m_onClientConnectUserData = NULL;
m_onClientDisconnectFunc = NULL;
m_onClientDisconnectUserData = NULL;
m_onCreateCharacterFunc = NULL;
m_onCreateCharacterUserData = NULL;
m_onDeleteCharacterFunc = NULL;
m_onDeleteCharacterUserData = NULL;
m_onSetCharacterPositionFunc = NULL;
m_onSetCharacterPositionUserData = NULL;
m_onSetCharacterRotationFunc = NULL;
m_onSetCharacterRotationUserData = NULL;
m_onBoneRotationsFunc = NULL;
m_onBoneRotationsUserData = NULL;
m_onBonePositionsFunc = NULL;
m_onBonePositionsUserData = NULL;
}
BoneBusServer::~BoneBusServer()
{
CloseConnection();
}
bool BoneBusServer::OpenConnection()
{
// TODO: cleanup udp if tcp error
WSADATA wsaData;
int err = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( err != 0 )
{
printf( "WSAStartup failed. Code: %d\n", err );
return false;
}
m_wsaStartupCalled = true;
m_sockUDP = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( m_sockUDP == INVALID_SOCKET )
{
printf( "Couldn't create socket.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
m_sockUDP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
// Bind
m_addrUDP.sin_addr.s_addr = INADDR_ANY;
m_addrUDP.sin_family = AF_INET;
m_addrUDP.sin_port = htons( NETWORK_PORT_UDP );
memset( m_addrUDP.sin_zero, 0, sizeof( m_addrUDP.sin_zero ) );
if ( bind( m_sockUDP, (const sockaddr *)&m_addrUDP, sizeof( m_addrUDP ) ) ==
SOCKET_ERROR )
{
printf( "bind() failed.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
closesocket( m_sockUDP );
m_sockUDP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
u_long nonBlocking = 1;
ioctlsocket( m_sockUDP, FIONBIO, &nonBlocking );
m_sockTCP = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( m_sockTCP == INVALID_SOCKET )
{
printf( "Couldn't create socket tcp.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
m_sockTCP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
int reuseAddr = 1;
setsockopt( m_sockTCP, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(
int ) );
m_addrTCP.sin_family = AF_INET;
m_addrTCP.sin_addr.s_addr = INADDR_ANY;
m_addrTCP.sin_port = htons( NETWORK_PORT_TCP );
memset( m_addrTCP.sin_zero, 0, sizeof( m_addrTCP.sin_zero ) );
if ( bind( m_sockTCP, (sockaddr *)&m_addrTCP, sizeof( m_addrTCP ) ) ==
SOCKET_ERROR )
{
printf( "bind() failed.\n" );
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
closesocket( m_sockTCP );
m_sockTCP = NULL;
WSACleanup();
m_wsaStartupCalled = false;
return false;
}
{
u_long nonBlocking = 1;
ioctlsocket( m_sockTCP, FIONBIO, &nonBlocking );
}
listen( m_sockTCP, 10 );
return true;
}
bool BoneBusServer::CloseConnection()
{
if ( m_sockUDP )
{
closesocket( m_sockUDP );
m_sockUDP = NULL;
}
if ( m_sockTCP )
{
closesocket( m_sockTCP );
m_sockTCP = NULL;
}
if ( m_wsaStartupCalled )
{
WSACleanup();
m_wsaStartupCalled = false;
}
return true;
}
bool BoneBusServer::Update()
{
if ( !IsOpen() )
{
return false;
}
{
fd_set readfds;
FD_ZERO( &readfds );
FD_SET( m_sockTCP, &readfds );
timeval timeout = { 0, 0 }; // return immediately
int error = select( 0, &readfds, 0, 0, &timeout ); // 1st parameter
ignored by winsock
if ( error == SOCKET_ERROR )
{
printf( "TCP - Error checking status\n" );
}
else if ( error != 0 )
{
int newSock;
sockaddr_in newToAddr;
int i = sizeof( sockaddr_in );
newSock = (int)accept( m_sockTCP, (sockaddr *)&newToAddr, &i );
u_long nonBlocking = 1;
ioctlsocket( newSock, FIONBIO, &nonBlocking );
m_sockConnectionsTCP.push_back( newSock );
//printf( "New Connection!\n" );
if ( m_onClientConnectFunc )
{
string clientIP = inet_ntoa( newToAddr.sin_addr );
m_onClientConnectFunc( clientIP, m_onClientConnectUserData );
}
}
}
for ( int i = 0; i < (int)m_sockConnectionsTCP.size(); i++ )
{
int tcpDataPending;
SOCKET s = m_sockConnectionsTCP[ i ];
fd_set readfds;
FD_ZERO( &readfds );
FD_SET( s, &readfds );
timeval timeout = { 0, 0 }; // return immediately
int error = select( 0, &readfds, 0, 0, &timeout ); // 1st parameter
ignored by winsock
if ( error == SOCKET_ERROR )
{
//printf( "TCP - Error checking status\n" );
tcpDataPending = 0;
}
else if ( error == 0 )
{
tcpDataPending = 0;
}
else
{
tcpDataPending = 1;
}
if ( tcpDataPending )
{
char str[ 1000 ];
memset( str, 0, sizeof( char ) * 1000 );
int bytesReceived = recv( (SOCKET)s, str, sizeof( str ) - 1, 0 );
if ( bytesReceived > 0 )
{
str[ bytesReceived ] = 0;
string recvStr = str;
OutputDebugString( string( recvStr + "\n" ).c_str() );
vector< string > tokens;
Tokenize( recvStr, tokens, ";" );
for ( int t = 0; t < (int)tokens.size(); t++ )
{
vector< string > msgTokens;
Tokenize( tokens[ t ], msgTokens, "|" );
if ( msgTokens.size() > 0 )
{
if ( msgTokens[ 0 ] == "CreateActor" )
{
if ( msgTokens.size() > 4 )
{
string charIdStr = msgTokens[ 1 ];
int charId = atoi( charIdStr.c_str() );
string uClass = msgTokens[ 2 ];
string name = msgTokens[ 3 ];
int skeletonType = atoi( msgTokens[ 4 ].c_str() );
if ( m_onCreateCharacterFunc )
{
m_onCreateCharacterFunc( charId, uClass, name,
skeletonType, m_onClientConnectUserData );
}
}
}
else if ( msgTokens[ 0 ] == "DeleteActor" )
{
if ( msgTokens.size() > 1 )
{
string charIdStr = msgTokens[ 1 ];
int charId = atoi( charIdStr.c_str() );
if ( m_onDeleteCharacterFunc )
{
m_onDeleteCharacterFunc( charId,
m_onDeleteCharacterUserData );
}
}
}
else if ( msgTokens[ 0 ] == "SetActorPos" )
{
if ( msgTokens.size() > 4 )
{
string charIdStr = msgTokens[ 1 ];
int charId = atoi( charIdStr.c_str() );
float x = (float)atof( msgTokens[ 2 ].c_str()
);
float y = (float)atof( msgTokens[ 3 ].c_str()
);
float z = (float)atof( msgTokens[ 4 ].c_str()
);
if ( m_onSetCharacterPositionFunc )
{
m_onSetCharacterPositionFunc( charId, x, y, z,
m_onSetCharacterPositionUserData );
}
}
}
else if ( msgTokens[ 0 ] == "SetActorRot" )
{
if ( msgTokens.size() > 5 )
{
string charIdStr = msgTokens[ 1 ];
int charId = atoi( charIdStr.c_str() );
float w = (float)atof( msgTokens[ 2 ].c_str()
);
float x = (float)atof( msgTokens[ 3 ].c_str()
);
float y = (float)atof( msgTokens[ 4 ].c_str()
);
float z = (float)atof( msgTokens[ 5 ].c_str()
);
if ( m_onSetCharacterRotationFunc )
{
m_onSetCharacterRotationFunc( charId, w, x, y, z,
m_onSetCharacterRotationUserData );
}
}
}
else if ( msgTokens[ 0 ] == "SetActorViseme" )
{
if ( msgTokens.size() > 4 )
{
string charIdStr = msgTokens[ 1 ];
int charId = atoi( charIdStr.c_str() );
string visemeStr = msgTokens[ 2 ];
int visemeId = atoi( visemeStr.c_str() );
float weight = (float)atof( msgTokens[ 3 ].c_str()
);
float blendTime = (float)atof( msgTokens[ 4 ].c_str()
);
//if ( m_onSetCharacterVisemeFunc )
//{
// m_onSetCharacterVisemeFunc( charId, visemeId,
weight, blendTime, m_onSetCharacterVisemeUserData );
//}
}
}
}
}
}
}
}
int udpDataPending;
fd_set readfds;
FD_ZERO( &readfds );
FD_SET( m_sockUDP, &readfds );
timeval timeout = { 0, 0 }; // return immediately
int error = select( 0, &readfds, 0, 0, &timeout ); // 1st parameter
ignored by winsock
if ( error == SOCKET_ERROR )
{
//printf( "TCP - Error checking status\n" );
udpDataPending = 0;
}
else if ( error == 0 )
{
udpDataPending = 0;
}
else
{
udpDataPending = 1;
}
int dataReceived = 0;
char buffer[ 2048 ] = {0};
int bytesReceived = 1;
while ( bytesReceived > 0 )
{
bytesReceived = 0;
dataReceived = 0;
if ( udpDataPending )
{
sockaddr_in fromAddr;
int fromAddrSize = sizeof(sockaddr_in);
//char buffer[ 2048 ];
//memset( buffer, 0, 2048 );
bytesReceived = recvfrom( m_sockUDP, buffer, 2047 * sizeof(char), 0,
(sockaddr *)&fromAddr, &fromAddrSize );
if ( bytesReceived < 0 )
{
//Warning( "Could not receive datagram\n" );
dataReceived = 0;
}
else
{
dataReceived = 1;
}
}
if ( dataReceived && ( bytesReceived > 3 ) )
{
int opcode = ((int *)buffer)[ 0 ];
if ( opcode == 0x10 )
{
//printf( "BULK_BONE_DATA\n" );
BulkBoneRotations * bulkBoneRotations;
bulkBoneRotations = (BulkBoneRotations *)buffer;
if ( m_onBoneRotationsFunc )
{
m_onBoneRotationsFunc( bulkBoneRotations,
m_onBoneRotationsUserData );
}
}
else if ( opcode == 0x11 )
{
//printf( "BULK_POSITION_DATA\n" );
BulkBonePositions * bulkBonePositions;
bulkBonePositions = (BulkBonePositions *)buffer;
if ( m_onBonePositionsFunc )
{
m_onBonePositionsFunc( bulkBonePositions,
m_onBonePositionsUserData );
}
}
}
}
return true;
}
// taken from:
http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
void BoneBusServer::Tokenize( const string & str, vector<string> & tokens,
const string & delimiters )
{
// Skip delimiters at beginning.
string::size_type lastPos = str.find_first_not_of( delimiters, 0 );
// Find first "non-delimiter".
string::size_type pos = str.find_first_of( delimiters, lastPos );
while ( string::npos != pos || string::npos != lastPos )
{
// Found a token, add it to the vector.
tokens.push_back( str.substr( lastPos, pos - lastPos ) );
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of( delimiters, pos );
// Find next "non-delimiter"
pos = str.find_first_of( delimiters, lastPos );
}
}
// [BMLR] Get command from renderer and external programs
vector<string>* BoneBusClient::GetCommand()
{
std::string result = "";
if ( m_sockTCP != NULL )
{
fd_set SocketSet;
FD_ZERO(&SocketSet);
FD_SET(m_sockTCP, &SocketSet);
TIMEVAL SelectTime = {0, 0};
int error = select(m_sockTCP + 1, &SocketSet, 0, 0,
&SelectTime);
if (error > 0)
{
char b[10000]; // Todo: use a while loop instead
int bytesRecv = recv(m_sockTCP, b, sizeof(b), 0);
if (bytesRecv > 0)
{
result.append(b);
result = result.substr(0, bytesRecv);
}
}
}
if (result.length() > 0)
{
vector<string>* results = new vector<string>();
BoneBusServer::Tokenize(result, *results, "\r\r\r"); // we use
\r\r\r as a separator between commands :)
return results;
}
return NULL;
}
// [BMLR] Send text to speak to the renderer
void BoneBusClient::SendSpeakText( const unsigned int msgNumber, const char *
agent, const char * text )
{
if ( !IsOpen() )
{
return;
}
char b[512];
int blen;
sprintf( b, "SpeakText|%d|%s|%s;", msgNumber, agent, text);
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
}
}
// [BMLR] Sends create pawn requests to renderer
void BoneBusClient::SendCreatePawn(std::string name, double locx, double locy,
double locz)
{
if ( !IsOpen() )
{
return;
}
char b[1024];
int blen;
sprintf( b, "CreatePawn|%s|%f|%f|%f;", name.c_str(), (float)locx,
(float)locy, (float)locz);
blen = (int)strlen( b );
int bytesSent = send( m_sockTCP, (const char *)b, blen, 0 );
if (bytesSent < 0)
{
int errnum = WSAGetLastError();
printf( "socket error: %d\n", errnum );
}
}
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Smartbody-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/smartbody-developer