bullet3/examples/SharedMemory/PhysicsDirect.cpp
erwincoumans 03bf78ef49 add physics server loopback (both client and server in the same process, using shared memory)
add physics server direct (client and server in the same process, directly processing commands without shared memory transport mechanism)
2015-11-22 20:50:32 -08:00

331 lines
8.7 KiB
C++

#include "PhysicsDirect.h"
#include "PhysicsClientSharedMemory.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "SharedMemoryCommands.h"
#include "PhysicsServerCommandProcessor.h"
#include "LinearMath/btHashMap.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../../Extras/Serialize/BulletFileLoader/btBulletFile.h"
#include "../../Extras/Serialize/BulletFileLoader/autogenerated/bullet.h"
#include "BodyJointInfoUtility.h"
struct BodyJointInfoCache2
{
btAlignedObjectArray<b3JointInfo> m_jointInfo;
};
struct PhysicsDirectInternalData
{
DummyGUIHelper m_noGfx;
SharedMemoryCommand m_command;
SharedMemoryStatus m_serverStatus;
bool m_hasStatus;
bool m_verboseOutput;
btAlignedObjectArray<TmpFloat3> m_debugLinesFrom;
btAlignedObjectArray<TmpFloat3> m_debugLinesTo;
btAlignedObjectArray<TmpFloat3> m_debugLinesColor;
btHashMap<btHashInt,BodyJointInfoCache2*> m_bodyJointMap;
char m_bulletStreamDataServerToClient[SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE];
PhysicsServerCommandProcessor* m_commandProcessor;
PhysicsDirectInternalData()
:m_hasStatus(false),
m_verboseOutput(false)
{
}
};
PhysicsDirect::PhysicsDirect()
{
m_data = new PhysicsDirectInternalData;
m_data->m_commandProcessor = new PhysicsServerCommandProcessor;
}
PhysicsDirect::~PhysicsDirect()
{
delete m_data->m_commandProcessor;
delete m_data;
}
// return true if connection succesfull, can also check 'isConnected'
bool PhysicsDirect::connect()
{
m_data->m_commandProcessor->setGuiHelper(&m_data->m_noGfx);
return true;
}
////todo: rename to 'disconnect'
void PhysicsDirect::disconnectSharedMemory()
{
m_data->m_commandProcessor->setGuiHelper(0);
}
bool PhysicsDirect::isConnected() const
{
return true;
}
// return non-null if there is a status, nullptr otherwise
const SharedMemoryStatus* PhysicsDirect::processServerStatus()
{
SharedMemoryStatus* stat = 0;
if (m_data->m_hasStatus)
{
stat = &m_data->m_serverStatus;
m_data->m_hasStatus = false;
}
return stat;
}
SharedMemoryCommand* PhysicsDirect::getAvailableSharedMemoryCommand()
{
return &m_data->m_command;
}
bool PhysicsDirect::canSubmitCommand() const
{
return true;
}
bool PhysicsDirect::processDebugLines(const struct SharedMemoryCommand& orgCommand)
{
SharedMemoryCommand command = orgCommand;
const SharedMemoryStatus& serverCmd = m_data->m_serverStatus;
do
{
bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
m_data->m_hasStatus = hasStatus;
if (hasStatus)
{
btAssert(m_data->m_serverStatus.m_type == CMD_DEBUG_LINES_COMPLETED);
if (m_data->m_verboseOutput)
{
b3Printf("Success receiving %d debug lines",
serverCmd.m_sendDebugLinesArgs.m_numDebugLines);
}
int numLines = serverCmd.m_sendDebugLinesArgs.m_numDebugLines;
float* linesFrom =
(float*)&m_data->m_bulletStreamDataServerToClient[0];
float* linesTo =
(float*)(&m_data->m_bulletStreamDataServerToClient[0] +
numLines * 3 * sizeof(float));
float* linesColor =
(float*)(&m_data->m_bulletStreamDataServerToClient[0] +
2 * numLines * 3 * sizeof(float));
m_data->m_debugLinesFrom.resize(serverCmd.m_sendDebugLinesArgs.m_startingLineIndex +
numLines);
m_data->m_debugLinesTo.resize(serverCmd.m_sendDebugLinesArgs.m_startingLineIndex +
numLines);
m_data->m_debugLinesColor.resize(
serverCmd.m_sendDebugLinesArgs.m_startingLineIndex + numLines);
for (int i = 0; i < numLines; i++)
{
TmpFloat3 from = CreateTmpFloat3(linesFrom[i * 3], linesFrom[i * 3 + 1],
linesFrom[i * 3 + 2]);
TmpFloat3 to =
CreateTmpFloat3(linesTo[i * 3], linesTo[i * 3 + 1], linesTo[i * 3 + 2]);
TmpFloat3 color = CreateTmpFloat3(linesColor[i * 3], linesColor[i * 3 + 1],
linesColor[i * 3 + 2]);
m_data
->m_debugLinesFrom[serverCmd.m_sendDebugLinesArgs.m_startingLineIndex + i] =
from;
m_data->m_debugLinesTo[serverCmd.m_sendDebugLinesArgs.m_startingLineIndex + i] =
to;
m_data->m_debugLinesColor[serverCmd.m_sendDebugLinesArgs.m_startingLineIndex +
i] = color;
}
if (serverCmd.m_sendDebugLinesArgs.m_numRemainingDebugLines > 0)
{
command.m_type = CMD_REQUEST_DEBUG_LINES;
command.m_requestDebugLinesArguments.m_startingLineIndex =
serverCmd.m_sendDebugLinesArgs.m_numDebugLines +
serverCmd.m_sendDebugLinesArgs.m_startingLineIndex;
}
}
} while (serverCmd.m_sendDebugLinesArgs.m_numRemainingDebugLines > 0);
return m_data->m_hasStatus;
}
bool PhysicsDirect::submitClientCommand(const struct SharedMemoryCommand& command)
{
if (command.m_type==CMD_REQUEST_DEBUG_LINES)
{
return processDebugLines(command);
}
bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
m_data->m_hasStatus = hasStatus;
if (hasStatus)
{
const SharedMemoryStatus& serverCmd = m_data->m_serverStatus;
switch (m_data->m_serverStatus.m_type)
{
case CMD_RESET_SIMULATION_COMPLETED:
{
m_data->m_debugLinesFrom.clear();
m_data->m_debugLinesTo.clear();
m_data->m_debugLinesColor.clear();
for (int i=0;i<m_data->m_bodyJointMap.size();i++)
{
BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap.getAtIndex(i);
if (bodyJointsPtr && *bodyJointsPtr)
{
BodyJointInfoCache2* bodyJoints = *bodyJointsPtr;
for (int j=0;j<bodyJoints->m_jointInfo.size();j++) {
if (bodyJoints->m_jointInfo[j].m_jointName)
{
free(bodyJoints->m_jointInfo[j].m_jointName);
}
if (bodyJoints->m_jointInfo[j].m_linkName)
{
free(bodyJoints->m_jointInfo[j].m_linkName);
}
}
delete (*bodyJointsPtr);
}
}
m_data->m_bodyJointMap.clear();
break;
}
case CMD_URDF_LOADING_COMPLETED:
{
if (serverCmd.m_dataStreamArguments.m_streamChunkLength > 0)
{
bParse::btBulletFile bf(
&m_data->m_bulletStreamDataServerToClient[0],
serverCmd.m_dataStreamArguments.m_streamChunkLength);
bf.setFileDNAisMemoryDNA();
bf.parse(false);
int bodyIndex = serverCmd.m_dataStreamArguments.m_bodyUniqueId;
BodyJointInfoCache2* bodyJoints = new BodyJointInfoCache2;
m_data->m_bodyJointMap.insert(bodyIndex,bodyJoints);
for (int i = 0; i < bf.m_multiBodies.size(); i++)
{
int flag = bf.getFlags();
if ((flag & bParse::FD_DOUBLE_PRECISION) != 0)
{
Bullet::btMultiBodyDoubleData* mb =
(Bullet::btMultiBodyDoubleData*)bf.m_multiBodies[i];
addJointInfoFromMultiBodyData(mb,bodyJoints, m_data->m_verboseOutput);
} else
{
Bullet::btMultiBodyFloatData* mb =
(Bullet::btMultiBodyFloatData*)bf.m_multiBodies[i];
addJointInfoFromMultiBodyData(mb,bodyJoints, m_data->m_verboseOutput);
}
}
if (bf.ok()) {
if (m_data->m_verboseOutput)
{
b3Printf("Received robot description ok!\n");
}
} else
{
b3Warning("Robot description not received");
}
}
break;
}
default:
{
// b3Error("Unknown server status type");
}
};
}
return hasStatus;
}
int PhysicsDirect::getNumJoints(int bodyIndex) const
{
BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap[bodyIndex];
if (bodyJointsPtr && *bodyJointsPtr)
{
BodyJointInfoCache2* bodyJoints = *bodyJointsPtr;
return bodyJoints->m_jointInfo.size();
}
btAssert(0);
return 0;
}
void PhysicsDirect::getJointInfo(int bodyIndex, int jointIndex, struct b3JointInfo& info) const
{
BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap[bodyIndex];
if (bodyJointsPtr && *bodyJointsPtr)
{
BodyJointInfoCache2* bodyJoints = *bodyJointsPtr;
info = bodyJoints->m_jointInfo[jointIndex];
}
}
///todo: move this out of the
void PhysicsDirect::setSharedMemoryKey(int key)
{
//m_data->m_physicsServer->setSharedMemoryKey(key);
//m_data->m_physicsClient->setSharedMemoryKey(key);
}
void PhysicsDirect::uploadBulletFileToSharedMemory(const char* data, int len)
{
//m_data->m_physicsClient->uploadBulletFileToSharedMemory(data,len);
}
int PhysicsDirect::getNumDebugLines() const
{
return m_data->m_debugLinesFrom.size();
}
const float* PhysicsDirect::getDebugLinesFrom() const
{
if (getNumDebugLines())
{
return &m_data->m_debugLinesFrom[0].m_x;
}
return 0;
}
const float* PhysicsDirect::getDebugLinesTo() const
{
if (getNumDebugLines())
{
return &m_data->m_debugLinesTo[0].m_x;
}
return 0;
}
const float* PhysicsDirect::getDebugLinesColor() const
{
if (getNumDebugLines())
{
return &m_data->m_debugLinesColor[0].m_x;
}
return 0;
}