Conflicts:
	avatar-mixer/src/main.cpp
This commit is contained in:
Andrzej Kapolka 2013-04-25 17:40:55 -07:00
commit c6af08d883
16 changed files with 786 additions and 699 deletions

View file

@ -78,23 +78,23 @@ void *sendBuffer(void *args)
int nextFrame = 0;
timeval startTime;
AgentList *agentList = AgentList::getInstance();
AgentList* agentList = AgentList::getInstance();
gettimeofday(&startTime, NULL);
while (true) {
sentBytes = 0;
for (int i = 0; i < agentList->getAgents().size(); i++) {
AudioRingBuffer *agentBuffer = (AudioRingBuffer *) agentList->getAgents()[i].getLinkedData();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
AudioRingBuffer* agentBuffer = (AudioRingBuffer*) agent->getLinkedData();
if (agentBuffer != NULL && agentBuffer->getEndOfLastWrite() != NULL) {
if (!agentBuffer->isStarted()
&& agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES_PER_CHANNEL + JITTER_BUFFER_SAMPLES) {
printf("Held back buffer %d.\n", i);
printf("Held back buffer for agent with ID %d.\n", agent->getAgentId());
} else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
printf("Buffer %d starved.\n", i);
printf("Buffer from agent with ID %d starved.\n", agent->getAgentId());
agentBuffer->setStarted(false);
} else {
// good buffer, add this to the mix
@ -104,14 +104,12 @@ void *sendBuffer(void *args)
}
}
int numAgents = agentList->getAgents().size();
int numAgents = agentList->size();
float distanceCoeffs[numAgents][numAgents];
memset(distanceCoeffs, 0, sizeof(distanceCoeffs));
for (int i = 0; i < agentList->getAgents().size(); i++) {
Agent *agent = &agentList->getAgents()[i];
AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
AudioRingBuffer* agentRingBuffer = (AudioRingBuffer*) agent->getLinkedData();
float agentBearing = agentRingBuffer->getBearing();
bool agentWantsLoopback = false;
@ -128,9 +126,9 @@ void *sendBuffer(void *args)
int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {};
for (int j = 0; j < agentList->getAgents().size(); j++) {
if (i != j || ( i == j && agentWantsLoopback)) {
AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList->getAgents()[j].getLinkedData();
for (AgentList::iterator otherAgent = agentList->begin(); agent != agentList->end(); agent++) {
if (otherAgent != agent || ( otherAgent == agent && agentWantsLoopback)) {
AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData();
float *agentPosition = agentRingBuffer->getPosition();
float *otherAgentPosition = otherAgentBuffer->getPosition();
@ -138,8 +136,8 @@ void *sendBuffer(void *args)
// calculate the distance to the other agent
// use the distance to the other agent to calculate the change in volume for this frame
int lowAgentIndex = std::min(i, j);
int highAgentIndex = std::max(i, j);
int lowAgentIndex = std::min(agent.getAgentIndex(), otherAgent.getAgentIndex());
int highAgentIndex = std::max(agent.getAgentIndex(), otherAgent.getAgentIndex());
if (distanceCoeffs[lowAgentIndex][highAgentIndex] == 0) {
float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) +
@ -223,8 +221,8 @@ void *sendBuffer(void *args)
agentList->getAgentSocket().send(agent->getPublicSocket(), clientMix, BUFFER_LENGTH_BYTES);
}
for (int i = 0; i < agentList->getAgents().size(); i++) {
AudioRingBuffer *agentBuffer = (AudioRingBuffer *)agentList->getAgents()[i].getLinkedData();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
AudioRingBuffer* agentBuffer = (AudioRingBuffer*) agent->getLinkedData();
if (agentBuffer->wasAddedToMix()) {
agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
@ -256,7 +254,7 @@ void attachNewBufferToAgent(Agent *newAgent) {
int main(int argc, const char * argv[])
{
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
setvbuf(stdout, NULL, _IOLBF, 0);
ssize_t receivedBytes = 0;

View file

@ -53,12 +53,7 @@ void attachAvatarDataToAgent(Agent *newAgent) {
int main(int argc, const char* argv[])
{
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
if (cmdOptionExists(argc, argv, "--local")) {
printf("Local Domain MODE!\n");
int ip = getLocalAddress();
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
}
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
setvbuf(stdout, NULL, _IOLBF, 0);
agentList->linkedDataCreateCallback = attachAvatarDataToAgent;
@ -88,11 +83,11 @@ int main(int argc, const char* argv[])
agentIndex = 0;
// send back a packet with other active agent data to this agent
for (std::vector<Agent>::iterator avatarAgent = agentList->getAgents().begin();
avatarAgent != agentList->getAgents().end();
for (AgentList::iterator avatarAgent = agentList->begin();
avatarAgent != agentList->end();
avatarAgent++) {
if (avatarAgent->getLinkedData() != NULL
&& agentIndex != agentList->indexOfMatchingAgent(agentAddress)) {
&& !socketMatch(agentAddress, avatarAgent->getActiveSocket())) {
currentBufferPosition = addAgentToBroadcastPacket(currentBufferPosition, &*avatarAgent);
}

View file

@ -49,7 +49,7 @@ const int LOGOFF_CHECK_INTERVAL = 5000;
int lastActiveCount = 0;
unsigned char * addAgentToBroadcastPacket(unsigned char *currentPosition, Agent *agentToAdd) {
unsigned char* addAgentToBroadcastPacket(unsigned char* currentPosition, Agent* agentToAdd) {
*currentPosition++ = agentToAdd->getType();
currentPosition += packAgentId(currentPosition, agentToAdd->getAgentId());
@ -62,7 +62,7 @@ unsigned char * addAgentToBroadcastPacket(unsigned char *currentPosition, Agent
int main(int argc, const char * argv[])
{
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_DOMAIN, DOMAIN_LISTEN_PORT);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_DOMAIN, DOMAIN_LISTEN_PORT);
// If user asks to run in "local" mode then we do NOT replace the IP
// with the EC2 IP. Otherwise, we will replace the IP like we used to
// this allows developers to run a local domain without recompiling the
@ -127,10 +127,7 @@ int main(int argc, const char * argv[])
currentBufferPos = broadcastPacket + 1;
startPointer = currentBufferPos;
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
agent != agentList->getAgents().end();
agent++) {
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (DEBUG_TO_SELF ||
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) {

View file

@ -113,8 +113,7 @@ int main(int argc, const char* argv[]) {
// move eve away from the origin
// pick a random point inside a 10x10 grid
eve.setPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION),
0,
eve.setPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION), 0.4,
randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION)));
// face any instance of eve down the z-axis

View file

@ -61,8 +61,8 @@ Avatar::Avatar(bool isMine) {
//_transmitterTimer = 0;
_transmitterHz = 0.0;
_transmitterPackets = 0;
initializeSkeleton();
_speed = 0.0;
_pelvisStandingHeight = 0.0f;
_TEST_bigSphereRadius = 0.3f;
_TEST_bigSpherePosition = glm::vec3( 0.0f, _TEST_bigSphereRadius, 2.0f );
@ -119,6 +119,8 @@ Avatar::Avatar(bool isMine) {
_handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 );
_handHolding.force = 10.0f;
initializeSkeleton();
if (iris_texture.size() == 0) {
switchToResourcesParentIfRequired();
unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
@ -129,7 +131,6 @@ Avatar::Avatar(bool isMine) {
}
Avatar::Avatar(const Avatar &otherAvatar) {
_velocity = otherAvatar._velocity;
@ -200,6 +201,9 @@ Avatar::Avatar(const Avatar &otherAvatar) {
_head.browAudioLift = otherAvatar._head.browAudioLift;
_head.noise = otherAvatar._head.noise;
initializeSkeleton();
if (iris_texture.size() == 0) {
switchToResourcesParentIfRequired();
unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
@ -306,30 +310,25 @@ void Avatar::simulate(float deltaTime) {
{
float closestDistance = 10000.0f;
AgentList * agentList = AgentList::getInstance();
AgentList* agentList = AgentList::getInstance();
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
agent != agentList->getAgents().end();
agent++) {
if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) {
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
Avatar *otherAvatar = (Avatar *)agent->getLinkedData();
// check for collisions with other avatars and respond
updateAvatarCollisionDetectionAndResponse
(
otherAvatar->getBonePosition( AVATAR_BONE_PELVIS_SPINE ),
0.2,
0.2,
updateAvatarCollisionDetectionAndResponse(otherAvatar->getPosition(),
0.1,
0.1,
otherAvatar->getBodyUpDirection(),
deltaTime
);
deltaTime);
// test other avatar hand position for proximity
glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position );
v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
float distance = glm::length( v );
if ( distance < _maxArmLength ) {
if ( distance < _maxArmLength + _maxArmLength ) {
//if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions
{
@ -356,8 +355,7 @@ void Avatar::simulate(float deltaTime) {
// Set the vector we send for hand position to other people to be our right hand
setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position);
}//if ( _isMine )
}
updateArmIKAndConstraints( deltaTime );
@ -365,30 +363,23 @@ void Avatar::simulate(float deltaTime) {
_interactingOther = NULL;
}
if ( usingBigSphereCollisionTest ) {
if (usingBigSphereCollisionTest) {
// test for avatar collision response (using a big sphere :)
updateAvatarCollisionDetectionAndResponse
(
_TEST_bigSpherePosition,
updateAvatarCollisionDetectionAndResponse(_TEST_bigSpherePosition,
_TEST_bigSphereRadius,
_TEST_bigSphereRadius,
glm::vec3( 0.0, 1.0, 0.0 ),
deltaTime
);
deltaTime);
}
if ( AVATAR_GRAVITY ) {
if ( _position.y > _bone[ AVATAR_BONE_RIGHT_FOOT ].radius * 2.0 ) {
if ( _position.y > _pelvisStandingHeight + 0.01 ) {
_velocity += glm::dvec3(getGravity(getPosition())) * ( 6.0 * deltaTime );
}
else {
if ( _position.y < _bone[ AVATAR_BONE_RIGHT_FOOT ].radius ) {
_position.y = _bone[ AVATAR_BONE_RIGHT_FOOT ].radius;
} else if ( _position.y < _pelvisStandingHeight ) {
_position.y = _pelvisStandingHeight;
_velocity.y = 0.0;
}
}
}
// update body springs
updateBodySprings( deltaTime );
@ -424,17 +415,6 @@ void Avatar::simulate(float deltaTime) {
}
}
float translationalSpeed = glm::length( _velocity );
float rotationalSpeed = fabs( _bodyYawDelta );
if ( translationalSpeed + rotationalSpeed > 0.2 )
{
_mode = AVATAR_MODE_WALKING;
}
else
{
_mode = AVATAR_MODE_INTERACTING;
}
// update body yaw by body yaw delta
if (_isMine) {
_bodyYaw += _bodyYawDelta * deltaTime;
@ -548,8 +528,16 @@ void Avatar::simulate(float deltaTime) {
const float AUDIO_AVERAGING_SECS = 0.05;
_head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness +
(deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness;
}
_speed = glm::length( _velocity );
float rotationalSpeed = fabs( _bodyYawDelta );
if ( _speed + rotationalSpeed > 0.2 ) {
_mode = AVATAR_MODE_WALKING;
} else {
_mode = AVATAR_MODE_INTERACTING;
}
}
float Avatar::getGirth() {
return COLLISION_BODY_RADIUS;
@ -559,32 +547,27 @@ float Avatar::getHeight() {
return COLLISION_HEIGHT;
}
glm::vec3 Avatar::getBodyUpDirection() {
return _orientation.getUp();
}
// This is a workspace for testing avatar body collision detection and response
void Avatar::updateAvatarCollisionDetectionAndResponse
( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) {
void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPosition,
float collisionGirth,
float collisionHeight,
glm::vec3 collisionUpVector,
float deltaTime) {
float myBodyApproximateBoundingRadius = 1.0f;
glm::vec3 vectorFromMyBodyToBigSphere(_position - collisionPosition);
bool jointCollision = false;
float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere);
if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth )
{
for (int b=0; b<NUM_AVATAR_BONES; b++)
{
if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth ) {
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - collisionPosition);
float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter);
float combinedRadius = _bone[b].radius + collisionGirth;
if ( distanceToBigSphereCenter < combinedRadius )
{
if ( distanceToBigSphereCenter < combinedRadius ) {
jointCollision = true;
if (distanceToBigSphereCenter > 0.0)
{
if (distanceToBigSphereCenter > 0.0) {
glm::vec3 directionVector = vectorFromJointToBigSphereCenter / distanceToBigSphereCenter;
float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius);
@ -607,7 +590,7 @@ void Avatar::updateAvatarCollisionDetectionAndResponse
}
void Avatar::render(bool lookingInMirror) {
/*
// show avatar position
glColor4f( 0.5f, 0.5f, 0.5f, 0.6 );
glPushMatrix();
@ -615,6 +598,7 @@ void Avatar::render(bool lookingInMirror) {
glScalef( 0.03, 0.03, 0.03 );
glutSolidSphere( 1, 10, 10 );
glPopMatrix();
*/
if ( usingBigSphereCollisionTest ) {
@ -851,7 +835,7 @@ void Avatar::renderHead(bool lookingInMirror) {
glPopMatrix();
}
}
void Avatar::startHandMovement() {
@ -862,7 +846,7 @@ void Avatar::startHandMovement() {
}
void Avatar::stopHandMovement() {
//_usingBodySprings = false;
//_usingBodySprings = false;
}
void Avatar::setHandMovementValues( glm::vec3 handOffset ) {
@ -919,7 +903,7 @@ void Avatar::initializeSkeleton() {
_bone[ AVATAR_BONE_RIGHT_FOOT ].parent = AVATAR_BONE_RIGHT_SHIN;
// specify the default pose position
_bone[ AVATAR_BONE_PELVIS_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.3, 0.0 );
_bone[ AVATAR_BONE_PELVIS_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 );
_bone[ AVATAR_BONE_MID_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.1, 0.0 );
_bone[ AVATAR_BONE_CHEST_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 );
_bone[ AVATAR_BONE_NECK ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 );
@ -971,12 +955,19 @@ void Avatar::initializeSkeleton() {
// calculate bone length
calculateBoneLengths();
_pelvisStandingHeight =
_bone[ AVATAR_BONE_PELVIS_SPINE ].length +
_bone[ AVATAR_BONE_LEFT_THIGH ].length +
_bone[ AVATAR_BONE_LEFT_SHIN ].length +
_bone[ AVATAR_BONE_LEFT_FOOT ].length +
_bone[ AVATAR_BONE_RIGHT_FOOT ].radius;
// generate world positions
updateSkeleton();
}
void Avatar::calculateBoneLengths() {
for (int b=0; b<NUM_AVATAR_BONES; b++) {
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
_bone[b].length = glm::length( _bone[b].defaultPosePosition );
}
@ -992,7 +983,7 @@ void Avatar::updateSkeleton() {
_orientation.yaw( _bodyYaw );
// calculate positions of all bones by traversing the skeleton tree:
for (int b=0; b<NUM_AVATAR_BONES; b++) {
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
if ( _bone[b].parent == AVATAR_BONE_NULL ) {
_bone[b].orientation.set( _orientation );
_bone[b].position = _position;
@ -1022,7 +1013,7 @@ void Avatar::updateSkeleton() {
}
void Avatar::initializeBodySprings() {
for (int b=0; b<NUM_AVATAR_BONES; b++) {
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
_bone[b].springyPosition = _bone[b].position;
_bone[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f );
}
@ -1030,7 +1021,7 @@ void Avatar::initializeBodySprings() {
void Avatar::updateBodySprings( float deltaTime ) {
for (int b=0; b<NUM_AVATAR_BONES; b++) {
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
glm::vec3 springVector( _bone[b].springyPosition );
if ( _bone[b].parent == AVATAR_BONE_NULL ) {
@ -1069,49 +1060,15 @@ void Avatar::updateBodySprings( float deltaTime ) {
}
}
glm::vec3 Avatar::getHeadLookatDirection() {
return glm::vec3
(
_orientation.getFront().x,
_orientation.getFront().y,
_orientation.getFront().z
);
}
const glm::vec3& Avatar::getHeadPosition() const {
glm::vec3 Avatar::getHeadLookatDirectionUp() {
return glm::vec3
(
_orientation.getUp().x,
_orientation.getUp().y,
_orientation.getUp().z
);
}
glm::vec3 Avatar::getHeadLookatDirectionRight() {
return glm::vec3
(
_orientation.getRight().x,
_orientation.getRight().y,
_orientation.getRight().z
);
}
glm::vec3 Avatar::getHeadPosition() {
if ( _usingBodySprings ) {
if (_usingBodySprings) {
return _bone[ AVATAR_BONE_HEAD ].springyPosition;
}
return _bone[ AVATAR_BONE_HEAD ].position;
}
glm::vec3 Avatar::getBonePosition( AvatarBoneID b ) {
return _bone[b].position;
}
void Avatar::updateHandMovement( float deltaTime ) {
glm::vec3 transformedHandMovement;
@ -1170,7 +1127,7 @@ void Avatar::updateArmIKAndConstraints( float deltaTime ) {
void Avatar::renderBody() {
// Render bone positions as spheres
for (int b=0; b<NUM_AVATAR_BONES; b++) {
for (int b = 0; b < NUM_AVATAR_BONES; b++) {
//renderBoneAsBlock( (AvatarBoneID)b);
//render bone orientation
@ -1197,7 +1154,7 @@ void Avatar::renderBody() {
glColor3f( 0.4f, 0.5f, 0.6f );
glLineWidth(3.0);
for (int b=1; b<NUM_AVATAR_BONES; b++) {
for (int b = 1; b < NUM_AVATAR_BONES; b++) {
if ( _bone[b].parent != AVATAR_BONE_NULL ) {
glBegin( GL_LINE_STRIP );
glVertex3fv( &_bone[ _bone[ b ].parent ].springyPosition.x );
@ -1210,7 +1167,7 @@ void Avatar::renderBody() {
glColor3fv( skinColor );
glLineWidth(3.0);
for (int b=1; b<NUM_AVATAR_BONES; b++) {
for (int b = 1; b < NUM_AVATAR_BONES; b++) {
if ( _bone[b].parent != AVATAR_BONE_NULL ) {
glBegin( GL_LINE_STRIP );
glVertex3fv( &_bone[ _bone[ b ].parent ].position.x );
@ -1223,12 +1180,9 @@ void Avatar::renderBody() {
// if the hand is grasping, show it...
if (( _usingBodySprings ) && ( _handState == 1 )) {
glPushMatrix();
glTranslatef
(
_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.x,
glTranslatef(_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.x,
_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.y,
_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.z
);
_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.z);
glColor4f( 1.0, 1.0, 0.8, 0.3 ); glutSolidSphere( 0.020f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.4, 0.2 ); glutSolidSphere( 0.025f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.2, 0.1 ); glutSolidSphere( 0.030f, 10.0f, 10.0f );
@ -1299,7 +1253,6 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) {
glm::vec3 linVel(linX*linVelScale, linZ*linVelScale, -linY*linVelScale);
addVelocity(linVel);
*/
}
// Find and return the gravity vector at my location
@ -1316,4 +1269,3 @@ glm::vec3 Avatar::getGravity(glm::vec3 pos) {
return glm::vec3(0.f, 0.f, 0.f);
}
}

View file

@ -25,7 +25,7 @@
const bool AVATAR_GRAVITY = true;
const float DECAY = 0.1;
const float THRUST_MAG = 10.0;
const float YAW_MAG = 300.0;
const float YAW_MAG = 500.0; //JJV - changed from 300.0;
const float TEST_YAW_DECAY = 5.0;
const float LIN_VEL_DECAY = 5.0;
@ -157,7 +157,7 @@ struct AvatarHead
class Avatar : public AvatarData {
public:
public:
Avatar(bool isMine);
~Avatar();
Avatar(const Avatar &otherAvatar);
@ -178,12 +178,13 @@ class Avatar : public AvatarData {
float getBodyYaw() {return _bodyYaw;};
void addBodyYaw(float y) {_bodyYaw += y;};
glm::vec3 getHeadLookatDirection();
glm::vec3 getHeadLookatDirectionUp();
glm::vec3 getHeadLookatDirectionRight();
glm::vec3 getHeadPosition();
glm::vec3 getBonePosition( AvatarBoneID b );
glm::vec3 getBodyUpDirection();
const glm::vec3& getHeadLookatDirection() const { return _orientation.getFront(); };
const glm::vec3& getHeadLookatDirectionUp() const { return _orientation.getUp(); };
const glm::vec3& getHeadLookatDirectionRight() const { return _orientation.getRight(); };
const glm::vec3& getHeadPosition() const ;
const glm::vec3& getBonePosition(AvatarBoneID b) const { return _bone[b].position; };
const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); };
float getSpeed() const { return _speed; };
float getGirth();
float getHeight();
@ -221,7 +222,7 @@ class Avatar : public AvatarData {
// Find out what the local gravity vector is at this location
glm::vec3 getGravity(glm::vec3 pos);
private:
private:
AvatarHead _head;
bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
@ -238,6 +239,7 @@ class Avatar : public AvatarData {
AvatarHandHolding _handHolding;
glm::vec3 _velocity;
glm::vec3 _thrust;
float _speed;
float _maxArmLength;
Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS];
@ -249,8 +251,8 @@ class Avatar : public AvatarData {
int _transmitterPackets;
Avatar* _interactingOther;
bool _interactingOtherIsNearby;
float _pelvisStandingHeight;
// private methods...
void initializeSkeleton();
void updateSkeleton();
void initializeBodySprings();
@ -258,14 +260,11 @@ class Avatar : public AvatarData {
void calculateBoneLengths();
void readSensors();
void renderBoneAsBlock( AvatarBoneID b );
void updateAvatarCollisionDetectionAndResponse
(
glm::vec3 collisionPosition,
void updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPosition,
float collisionGirth,
float collisionHeight,
glm::vec3 collisionUpVector,
float deltaTime
);
float deltaTime);
};
#endif

View file

@ -11,15 +11,18 @@
#include "Camera.h"
Camera::Camera() {
_frustumNeedsReshape = false;
_mode = CAMERA_MODE_THIRD_PERSON;
_tightness = DEFAULT_CAMERA_TIGHTNESS;
_tightness = 10.0; // default
_fieldOfView = 60.0; // default
_nearClip = 0.08; // default
_farClip = 50.0; // default
_modeShift = 0.0;
_yaw = 0.0;
_pitch = 0.0;
_roll = 0.0;
_up = 0.0;
_upShift = 0.0;
_rightShift = 0.0;
_distance = 0.0;
_idealYaw = 0.0;
_targetPosition = glm::vec3( 0.0, 0.0, 0.0 );
@ -29,45 +32,68 @@ Camera::Camera() {
}
void Camera::update( float deltaTime ) {
void Camera::update( float deltaTime )
{
//----------------------------------------
// generate the ortho-normals for the orientation based on the Euler angles
_orientation.setToIdentity();
_orientation.yaw ( _yaw );
_orientation.pitch( _pitch );
_orientation.roll ( _roll );
if ( _mode == CAMERA_MODE_NULL ) {
_modeShift = 0.0;
} else {
// use iterative forces to keep the camera at the desired position and angle
updateFollowMode( deltaTime );
if ( _modeShift < 1.0f ) {
_modeShift += MODE_SHIFT_RATE * deltaTime;
if ( _modeShift > 1.0f ) {
_modeShift = 1.0f;
}
}
}
}
// use iterative forces to keep the camera at the desired position and angle
void Camera::updateFollowMode( float deltaTime ) {
// derive t from tightness
//----------------------------------------
float t = _tightness * deltaTime;
if ( t > 1.0 ){
if ( t > 1.0 ) {
t = 1.0;
}
//----------------------------------------
// update _yaw (before position!)
//----------------------------------------
_yaw += ( _idealYaw - _yaw ) * t;
_orientation.yaw ( _yaw );
float radian = ( _yaw / 180.0 ) * PIE;
//----------------------------------------
// update _position
//----------------------------------------
//these need to be checked to make sure they correspond to the coordinate system.
//these need to be checked to make sure they correspond to the correct coordinate system.
double x = _distance * -sin( radian );
double z = _distance * cos( radian );
double y = _up;
double y = _upShift;
_idealPosition = _targetPosition + glm::vec3( x, y, z );
//_idealPosition += _orientation.getRight() * _rightShift;
//_idealPosition += _orientation.getUp () * _upShift;
// pull position towards ideal position
_position += ( _idealPosition - _position ) * t;
//------------------------------------------------------------------------------
// generate the ortho-normals for the orientation based on the Euler angles
//------------------------------------------------------------------------------
_orientation.setToIdentity();
_orientation.yaw ( _yaw );
_orientation.pitch ( _pitch );
_orientation.roll ( _roll );
//printLog( "orientation.front = %f, %f, %f\n", _orientation.front.x, _orientation.front.y, _orientation.front.z );
}
// call to find out if the view frustum needs to be reshaped
bool Camera::getFrustumNeedsReshape() {
return _frustumNeedsReshape;
}
// call this after reshaping the view frustum
void Camera::setFrustumWasReshaped() {
_frustumNeedsReshape = false;
}

View file

@ -14,13 +14,13 @@
enum CameraMode
{
CAMERA_MODE_NULL = -1,
CAMERA_MODE_FIRST_PERSON,
CAMERA_MODE_THIRD_PERSON,
CAMERA_MODE_FIRST_PERSON,
CAMERA_MODE_MY_OWN_FACE,
NUM_CAMERA_MODES
};
static const float DEFAULT_CAMERA_TIGHTNESS = 10.0f;
const float MODE_SHIFT_RATE = 2.0f;
class Camera
{
@ -29,35 +29,42 @@ public:
void update( float deltaTime );
void setMode ( CameraMode m ) { _mode = m; }
void setYaw ( float y ) { _idealYaw = y; }
void setMode ( CameraMode m ) { _mode = m; _modeShift = 0.0f; }
void setYaw ( float y ) { _yaw = y; }
void setPitch ( float p ) { _pitch = p; }
void setRoll ( float r ) { _roll = r; }
void setUp ( float u ) { _up = u; }
void setUpShift ( float u ) { _upShift = u; }
void setRightShift ( float r ) { _rightShift = r; }
void setDistance ( float d ) { _distance = d; }
void setTargetPosition ( glm::vec3 t ) { _targetPosition = t; };
void setPosition ( glm::vec3 p ) { _position = p; };
void setTargetPosition( glm::vec3 t ) { _targetPosition = t; }
void setTargetYaw ( float y ) { _idealYaw = y; }
void setPosition ( glm::vec3 p ) { _position = p; }
void setOrientation ( Orientation o ) { _orientation.set(o); }
void setTightness ( float t ) { _tightness = t; }
void setFieldOfView ( float f ) { _fieldOfView = f; }
void setAspectRatio ( float a ) { _aspectRatio = a; }
void setNearClip ( float n ) { _nearClip = n; }
void setFarClip ( float f ) { _farClip = f; }
void setFieldOfView ( float f ) { _fieldOfView = f; _frustumNeedsReshape = true; }
void setAspectRatio ( float a ) { _aspectRatio = a; _frustumNeedsReshape = true; }
void setNearClip ( float n ) { _nearClip = n; _frustumNeedsReshape = true; }
void setFarClip ( float f ) { _farClip = f; _frustumNeedsReshape = true; }
float getYaw () { return _yaw; }
float getPitch () { return _pitch; }
float getRoll () { return _roll; }
glm::vec3 getPosition () { return _position; }
Orientation getOrientation () { return _orientation; }
Orientation getOrientation() { return _orientation; }
CameraMode getMode () { return _mode; }
float getFieldOfView () { return _fieldOfView; }
float getAspectRatio () { return _aspectRatio; }
float getModeShift () { return _modeShift; }
float getFieldOfView() { return _fieldOfView; }
float getAspectRatio() { return _aspectRatio; }
float getNearClip () { return _nearClip; }
float getFarClip () { return _farClip; }
bool getFrustumNeedsReshape(); // call to find out if the view frustum needs to be reshaped
void setFrustumWasReshaped(); // call this after reshaping the view frustum.
private:
CameraMode _mode;
float _modeShift; // 0.0 to 1.0
bool _frustumNeedsReshape;
glm::vec3 _position;
glm::vec3 _idealPosition;
glm::vec3 _targetPosition;
@ -68,11 +75,14 @@ private:
float _yaw;
float _pitch;
float _roll;
float _up;
float _upShift;
float _rightShift;
float _idealYaw;
float _distance;
float _tightness;
Orientation _orientation;
void updateFollowMode( float deltaTime );
};
#endif

View file

@ -278,9 +278,9 @@ void drawGroundPlaneGrid( float size, int resolution )
void renderOrientationDirections( glm::vec3 position, Orientation orientation, float size ) {
glm::vec3 pRight = position + orientation.right * size;
glm::vec3 pUp = position + orientation.up * size;
glm::vec3 pFront = position + orientation.front * size;
glm::vec3 pRight = position + orientation.getRight() * size;
glm::vec3 pUp = position + orientation.getUp() * size;
glm::vec3 pFront = position + orientation.getFront() * size;
glColor3f( 1.0f, 0.0f, 0.0f );
glBegin( GL_LINE_STRIP );

View file

@ -244,8 +244,6 @@ void updateHandController( int x, int y ) {
handController.startX = WIDTH / 2;
handController.startY = HEIGHT / 2;
handController.envelope = 0.0;
//prototype
//myAvatar.stopHandMovement();
}
}
}
@ -804,35 +802,67 @@ void display(void)
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
glMateriali(GL_FRONT, GL_SHININESS, 96);
//--------------------------------------------------------
// camera settings
//--------------------------------------------------------
if ( ::lookingInMirror ) {
//-----------------------------------------------
// set the camera to looking at my own face
//-----------------------------------------------
myCamera.setTargetPosition ( myAvatar.getHeadPosition() );
myCamera.setYaw ( - myAvatar.getBodyYaw() );
myCamera.setTargetYaw ( - myAvatar.getBodyYaw() );
myCamera.setPitch ( 0.0 );
myCamera.setRoll ( 0.0 );
myCamera.setUp ( 0.0 );
myCamera.setUpShift ( 0.0 );
myCamera.setDistance ( 0.2 );
myCamera.setTightness ( 100.0f );
myCamera.update ( 1.f/FPS );
} else {
//----------------------------------------------------
// set the camera to third-person view behind my av
//----------------------------------------------------
myCamera.setTargetPosition ( myAvatar.getPosition() );
myCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() );
myCamera.setPitch ( 0.0 ); // temporarily, this must be 0.0 or else bad juju
myCamera.setRoll ( 0.0 );
myCamera.setUp ( 0.45 );
myCamera.setDistance ( 1.0 );
myCamera.setTightness ( 8.0f );
myCamera.update ( 1.f/FPS);
// float firstPersonPitch = 20.0f;
// float firstPersonUpShift = 0.1f;
// float firstPersonDistance = 0.0f;
// float firstPersonT ightness = 100.0f;
float thirdPersonPitch = 0.0f;
float thirdPersonUpShift = -0.1f;
float thirdPersonDistance = 1.f;
float thirdPersonTightness = 8.0f;
myCamera.setPitch (thirdPersonPitch );
myCamera.setUpShift (thirdPersonUpShift );
myCamera.setDistance (thirdPersonDistance );
myCamera.setTightness(thirdPersonTightness);
/*
if ( myAvatar.getSpeed() < 0.02 ) {
if (myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
}
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
myCamera.setPitch ( thirdPersonPitch + myCamera.getModeShift() * ( firstPersonPitch - thirdPersonPitch ));
myCamera.setUpShift ( thirdPersonUpShift + myCamera.getModeShift() * ( firstPersonUpShift - thirdPersonUpShift ));
myCamera.setDistance ( thirdPersonDistance + myCamera.getModeShift() * ( firstPersonDistance - thirdPersonDistance ));
myCamera.setTightness ( thirdPersonTightness + myCamera.getModeShift() * ( firstPersonTightness - thirdPersonTightness ));
} else {
if (myCamera.getMode() != CAMERA_MODE_THIRD_PERSON ) {
myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
}
printf( "myCamera.getModeShift() = %f\n", myCamera.getModeShift());
myCamera.setPitch ( firstPersonPitch + myCamera.getModeShift() * ( thirdPersonPitch - firstPersonPitch ));
myCamera.setUpShift ( firstPersonUpShift + myCamera.getModeShift() * ( thirdPersonUpShift - firstPersonUpShift ));
myCamera.setDistance ( firstPersonDistance + myCamera.getModeShift() * ( thirdPersonDistance - firstPersonDistance ));
myCamera.setTightness ( firstPersonTightness + myCamera.getModeShift() * ( thirdPersonTightness - firstPersonTightness ));
}
*/
myCamera.setTargetPosition( myAvatar.getHeadPosition() );
myCamera.setTargetYaw ( 180.0 - myAvatar.getBodyYaw() );
myCamera.setRoll ( 0.0 );
}
// important...
myCamera.update( 1.f/FPS );
// Note: whichCamera is used to pick between the normal camera myCamera for our
// main camera, vs, an alternate camera. The alternate camera we support right now
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
@ -847,10 +877,10 @@ void display(void)
if (::viewFrustumFromOffset && ::frustumOn) {
// set the camera to third-person view but offset so we can see the frustum
viewFrustumOffsetCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() + ::viewFrustumOffsetYaw );
viewFrustumOffsetCamera.setTargetYaw( 180.0 - myAvatar.getBodyYaw() + ::viewFrustumOffsetYaw );
viewFrustumOffsetCamera.setPitch ( ::viewFrustumOffsetPitch );
viewFrustumOffsetCamera.setRoll ( ::viewFrustumOffsetRoll );
viewFrustumOffsetCamera.setUp ( ::viewFrustumOffsetUp );
viewFrustumOffsetCamera.setUpShift ( ::viewFrustumOffsetUp );
viewFrustumOffsetCamera.setDistance ( ::viewFrustumOffsetDistance );
viewFrustumOffsetCamera.update(1.f/FPS);
whichCamera = viewFrustumOffsetCamera;
@ -868,10 +898,8 @@ void display(void)
if (::starsOn) {
// should be the first rendering pass - w/o depth buffer / lighting
// finally render the starfield
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
}
glEnable(GL_LIGHTING);
@ -913,10 +941,8 @@ void display(void)
if (displayField) field.render();
// Render avatars of other agents
AgentList *agentList = AgentList::getInstance();
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
agent != agentList->getAgents().end();
agent++) {
AgentList* agentList = AgentList::getInstance();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
Avatar *avatar = (Avatar *)agent->getLinkedData();
avatar->render(0);
@ -991,12 +1017,13 @@ void display(void)
glPointSize(1.0f);
char agents[100];
int totalAgents = AgentList::getInstance()->getAgents().size();
AgentList* agentList = AgentList::getInstance();
int totalAvatars = 0, totalServers = 0;
for (int i = 0; i < totalAgents; i++) {
(AgentList::getInstance()->getAgents()[i].getType() == AGENT_TYPE_AVATAR)
? totalAvatars++ : totalServers++;
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++;
}
sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
@ -1534,11 +1561,9 @@ void idle(void) {
updateAvatar(deltaTime);
//loop through all the other avatars and simulate them...
AgentList * agentList = AgentList::getInstance();
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++)
{
if (agent->getLinkedData() != NULL)
{
AgentList* agentList = AgentList::getInstance();
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL) {
Avatar *avatar = (Avatar *)agent->getLinkedData();
avatar->simulate(deltaTime);
}

View file

@ -25,6 +25,10 @@ private:
float _pitch;
float _roll;
glm::vec3 right;
glm::vec3 up;
glm::vec3 front;
void update(); // actually updates the vectors from yaw, pitch, roll
public:
@ -41,13 +45,9 @@ public:
void set( Orientation );
void setToIdentity();
glm::vec3 right;
glm::vec3 up;
glm::vec3 front;
glm::vec3 getRight() { return right; }
glm::vec3 getUp() { return up; }
glm::vec3 getFront() { return front; }
const glm::vec3& getRight() const { return right; }
const glm::vec3& getUp() const { return up; }
const glm::vec3& getFront() const { return front; }
void setRightUpFront( const glm::vec3 &, const glm::vec3 &, const glm::vec3 & );

View file

@ -22,7 +22,19 @@
using shared_lib::printLog;
Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType, uint16_t thisAgentId) {
int unpackAgentId(unsigned char *packedData, uint16_t *agentId) {
memcpy(agentId, packedData, sizeof(uint16_t));
return sizeof(uint16_t);
}
int packAgentId(unsigned char *packStore, uint16_t agentId) {
memcpy(packStore, &agentId, sizeof(uint16_t));
return sizeof(uint16_t);
}
Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType, uint16_t thisAgentId) :
_isAlive(true)
{
if (agentPublicSocket != NULL) {
publicSocket = new sockaddr;
memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr));
@ -46,12 +58,11 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent
activeSocket = NULL;
linkedData = NULL;
_bytesReceivedMovingAverage = NULL;
deleteMutex = new pthread_mutex_t;
pthread_mutex_init(deleteMutex, NULL);
}
Agent::Agent(const Agent &otherAgent) {
_isAlive = otherAgent._isAlive;
if (otherAgent.publicSocket != NULL) {
publicSocket = new sockaddr;
memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr));
@ -92,9 +103,6 @@ Agent::Agent(const Agent &otherAgent) {
} else {
_bytesReceivedMovingAverage = NULL;
}
deleteMutex = new pthread_mutex_t;
pthread_mutex_init(deleteMutex, NULL);
}
Agent& Agent::operator=(Agent otherAgent) {
@ -105,6 +113,7 @@ Agent& Agent::operator=(Agent otherAgent) {
void Agent::swap(Agent &first, Agent &second) {
using std::swap;
swap(first._isAlive, second._isAlive);
swap(first.publicSocket, second.publicSocket);
swap(first.localSocket, second.localSocket);
swap(first.activeSocket, second.activeSocket);
@ -114,13 +123,9 @@ void Agent::swap(Agent &first, Agent &second) {
swap(first.firstRecvTimeUsecs, second.firstRecvTimeUsecs);
swap(first.lastRecvTimeUsecs, second.lastRecvTimeUsecs);
swap(first._bytesReceivedMovingAverage, second._bytesReceivedMovingAverage);
swap(first.deleteMutex, second.deleteMutex);
}
Agent::~Agent() {
// the deleteMutex isn't destroyed here
// that's handled by the agent list silent agent removal thread
delete publicSocket;
delete localSocket;
delete linkedData;

View file

@ -31,8 +31,6 @@ public:
bool matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType);
pthread_mutex_t *deleteMutex;
char getType() const;
const char* getTypeName() const;
void setType(char newType);
@ -58,6 +56,9 @@ public:
AgentData* getLinkedData();
void setLinkedData(AgentData *newData);
bool isAlive() const { return _isAlive; };
void setAlive(bool isAlive) { _isAlive = isAlive; };
void recordBytesReceived(int bytesReceived);
float getAverageKilobitsPerSecond();
float getAveragePacketsPerSecond();
@ -73,9 +74,11 @@ private:
double lastRecvTimeUsecs;
SimpleMovingAverage* _bytesReceivedMovingAverage;
AgentData* linkedData;
bool _isAlive;
};
std::ostream& operator<<(std::ostream& os, const Agent* agent);
int unpackAgentId(unsigned char *packedData, uint16_t *agentId);
int packAgentId(unsigned char *packStore, uint16_t agentId);
#endif /* defined(__hifi__Agent__) */

View file

@ -37,7 +37,6 @@ const int DOMAINSERVER_PORT = 40102;
bool silentAgentThreadStopFlag = false;
bool domainServerCheckinStopFlag = false;
bool pingUnknownAgentThreadStopFlag = false;
pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER;
AgentList* AgentList::_sharedInstance = NULL;
@ -59,11 +58,15 @@ AgentList* AgentList::getInstance() {
return _sharedInstance;
}
AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) :
_agentBuckets(),
_numAgents(0),
agentSocket(newSocketListenPort),
ownerType(newOwnerType),
socketListenPort(newSocketListenPort),
lastAgentId(0)
{
AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) : agentSocket(newSocketListenPort) {
ownerType = newOwnerType;
socketListenPort = newSocketListenPort;
lastAgentId = 0;
}
AgentList::~AgentList() {
@ -73,10 +76,6 @@ AgentList::~AgentList() {
stopPingUnknownAgentsThread();
}
std::vector<Agent>& AgentList::getAgents() {
return agents;
}
UDPSocket& AgentList::getAgentSocket() {
return agentSocket;
}
@ -108,10 +107,9 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD
void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) {
// find the avatar mixer in our agent list and update the lastRecvTime from it
int bulkSendAgentIndex = indexOfMatchingAgent(senderAddress);
Agent* bulkSendAgent = agentWithAddress(senderAddress);
if (bulkSendAgentIndex >= 0) {
Agent *bulkSendAgent = &agents[bulkSendAgentIndex];
if (bulkSendAgent) {
bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow());
bulkSendAgent->recordBytesReceived(numTotalBytes);
}
@ -128,17 +126,18 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac
currentPosition += unpackAgentId(currentPosition, &agentID);
memcpy(packetHolder + 1, currentPosition, numTotalBytes - (currentPosition - startPosition));
int matchingAgentIndex = indexOfMatchingAgent(agentID);
Agent* matchingAgent = agentWithID(agentID);
if (matchingAgentIndex < 0) {
if (!matchingAgent) {
// we're missing this agent, we need to add it to the list
addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID);
// theoretically if we can lock the vector we could assume this is size - 1
matchingAgentIndex = indexOfMatchingAgent(agentID);
// TODO: this is a really stupid way to do this
// Add a reverse iterator and go from the end of the list
matchingAgent = agentWithID(agentID);
}
currentPosition += updateAgentWithData(&agents[matchingAgentIndex],
currentPosition += updateAgentWithData(matchingAgent,
packetHolder,
numTotalBytes - (currentPosition - startPosition));
}
@ -146,10 +145,10 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac
int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
// find the agent by the sockaddr
int agentIndex = indexOfMatchingAgent(senderAddress);
Agent* matchingAgent = agentWithAddress(senderAddress);
if (agentIndex != -1) {
return updateAgentWithData(&agents[agentIndex], packetData, dataBytes);
if (matchingAgent) {
return updateAgentWithData(matchingAgent, packetData, dataBytes);
} else {
return 0;
}
@ -171,24 +170,24 @@ int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int
return agent->getLinkedData()->parseData(packetData, dataBytes);
}
int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
Agent* AgentList::agentWithAddress(sockaddr *senderAddress) {
for(AgentList::iterator agent = begin(); agent != end(); agent++) {
if (agent->getActiveSocket() != NULL && socketMatch(agent->getActiveSocket(), senderAddress)) {
return agent - agents.begin();
return &(*agent);
}
}
return -1;
return NULL;
}
int AgentList::indexOfMatchingAgent(uint16_t agentID) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
Agent* AgentList::agentWithID(uint16_t agentID) {
for(AgentList::iterator agent = begin(); agent != end(); agent++) {
if (agent->getAgentId() == agentID) {
return agent - agents.begin();
return &(*agent);
}
}
return -1;
return NULL;
}
uint16_t AgentList::getLastAgentId() {
@ -227,45 +226,38 @@ int AgentList::updateList(unsigned char *packetData, size_t dataBytes) {
}
bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId) {
std::vector<Agent>::iterator agent;
AgentList::iterator agent = end();
if (publicSocket != NULL) {
for (agent = agents.begin(); agent != agents.end(); agent++) {
for (agent = begin(); agent != end(); agent++) {
if (agent->matches(publicSocket, localSocket, agentType)) {
// we already have this agent, stop checking
break;
}
}
} else {
agent = agents.end();
}
if (agent == agents.end()) {
if (agent == end()) {
// we didn't have this agent, so add them
Agent newAgent = Agent(publicSocket, localSocket, agentType, agentId);
Agent* newAgent = new Agent(publicSocket, localSocket, agentType, agentId);
if (socketMatch(publicSocket, localSocket)) {
// likely debugging scenario with two agents on local network
// set the agent active right away
newAgent.activatePublicSocket();
newAgent->activatePublicSocket();
}
if (newAgent.getType() == AGENT_TYPE_AUDIO_MIXER && audioMixerSocketUpdate != NULL) {
if (newAgent->getType() == AGENT_TYPE_AUDIO_MIXER && audioMixerSocketUpdate != NULL) {
// this is an audio mixer
// for now that means we need to tell the audio class
// to use the local socket information the domain server gave us
sockaddr_in *publicSocketIn = (sockaddr_in *)publicSocket;
audioMixerSocketUpdate(publicSocketIn->sin_addr.s_addr, publicSocketIn->sin_port);
} else if (newAgent.getType() == AGENT_TYPE_VOXEL) {
newAgent.activatePublicSocket();
} else if (newAgent->getType() == AGENT_TYPE_VOXEL) {
newAgent->activatePublicSocket();
}
printLog("Added agent - ");
Agent::printLog(newAgent);
pthread_mutex_lock(&vectorChangeMutex);
agents.push_back(newAgent);
pthread_mutex_unlock(&vectorChangeMutex);
addAgentToList(newAgent);
return true;
} else {
@ -281,8 +273,24 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
}
}
void AgentList::addAgentToList(Agent* newAgent) {
// find the correct array to add this agent to
int bucketIndex = _numAgents / AGENTS_PER_BUCKET;
if (!_agentBuckets[bucketIndex]) {
_agentBuckets[bucketIndex] = new Agent*[AGENTS_PER_BUCKET]();
}
_agentBuckets[bucketIndex][_numAgents % AGENTS_PER_BUCKET] = newAgent;
++_numAgents;
printLog("Added agent - ");
Agent::printLog(*newAgent);
}
void AgentList::broadcastToAgents(unsigned char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
for(AgentList::iterator agent = begin(); agent != end(); agent++) {
// only send to the AgentTypes we are asked to send to.
if (agent->getActiveSocket() != NULL && memchr(agentTypes, agent->getType(), numAgentTypes)) {
// we know which socket is good for this agent, send there
@ -292,7 +300,7 @@ void AgentList::broadcastToAgents(unsigned char *broadcastData, size_t dataBytes
}
void AgentList::handlePingReply(sockaddr *agentAddress) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
for(AgentList::iterator agent = begin(); agent != end(); agent++) {
// check both the public and local addresses for each agent to see if we find a match
// prioritize the private address so that we prune erroneous local matches
if (socketMatch(agent->getPublicSocket(), agentAddress)) {
@ -307,9 +315,9 @@ void AgentList::handlePingReply(sockaddr *agentAddress) {
Agent* AgentList::soloAgentOfType(char agentType) {
if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
for(AgentList::iterator agent = begin(); agent != end(); agent++) {
if (agent->getType() == agentType) {
return &*agent;
return &(*agent);
}
}
}
@ -319,7 +327,7 @@ Agent* AgentList::soloAgentOfType(char agentType) {
void *pingUnknownAgents(void *args) {
AgentList *agentList = (AgentList *)args;
AgentList* agentList = (AgentList*) args;
const int PING_INTERVAL_USECS = 1 * 1000000;
timeval lastSend;
@ -327,8 +335,8 @@ void *pingUnknownAgents(void *args) {
while (!pingUnknownAgentThreadStopFlag) {
gettimeofday(&lastSend, NULL);
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
agent != agentList->getAgents().end();
for(AgentList::iterator agent = agentList->begin();
agent != agentList->end();
agent++) {
if (agent->getActiveSocket() == NULL
&& (agent->getPublicSocket() != NULL && agent->getLocalSocket() != NULL)) {
@ -359,33 +367,21 @@ void AgentList::stopPingUnknownAgentsThread() {
}
void *removeSilentAgents(void *args) {
std::vector<Agent> *agents = (std::vector<Agent> *)args;
AgentList* agentList = (AgentList*) args;
double checkTimeUSecs, sleepTime;
while (!silentAgentThreadStopFlag) {
checkTimeUSecs = usecTimestampNow();
for(std::vector<Agent>::iterator agent = agents->begin(); agent != agents->end();) {
pthread_mutex_t* agentDeleteMutex = agent->deleteMutex;
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); ++agent) {
if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS
&& agent->getType() != AGENT_TYPE_VOXEL
&& pthread_mutex_trylock(agentDeleteMutex) == 0) {
&& agent->getType() != AGENT_TYPE_VOXEL) {
printLog("Killing agent - ");
Agent::printLog(*agent);
// make sure the vector isn't currently adding an agent
pthread_mutex_lock(&vectorChangeMutex);
agent = agents->erase(agent);
pthread_mutex_unlock(&vectorChangeMutex);
// release the delete mutex and destroy it
pthread_mutex_unlock(agentDeleteMutex);
pthread_mutex_destroy(agentDeleteMutex);
} else {
agent++;
agent->setAlive(false);
}
}
@ -402,7 +398,7 @@ void *removeSilentAgents(void *args) {
}
void AgentList::startSilentAgentRemovalThread() {
pthread_create(&removeSilentAgentsThread, NULL, removeSilentAgents, (void *)&agents);
pthread_create(&removeSilentAgentsThread, NULL, removeSilentAgents, (void*) this);
}
void AgentList::stopSilentAgentRemovalThread() {
@ -414,7 +410,7 @@ void *checkInWithDomainServer(void *args) {
const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
AgentList *parentAgentList = (AgentList *)args;
AgentList* parentAgentList = (AgentList*) args;
timeval lastSend;
unsigned char output[7];
@ -456,7 +452,7 @@ void *checkInWithDomainServer(void *args) {
}
void AgentList::startDomainServerCheckInThread() {
pthread_create(&checkInWithDomainServerThread, NULL, checkInWithDomainServer, (void *)this);
pthread_create(&checkInWithDomainServerThread, NULL, checkInWithDomainServer, (void*) this);
}
void AgentList::stopDomainServerCheckInThread() {
@ -464,12 +460,75 @@ void AgentList::stopDomainServerCheckInThread() {
pthread_join(checkInWithDomainServerThread, NULL);
}
int unpackAgentId(unsigned char *packedData, uint16_t *agentId) {
memcpy(agentId, packedData, sizeof(uint16_t));
return sizeof(uint16_t);
AgentList::iterator AgentList::begin() const {
Agent** agentBucket = NULL;
for (int i = 0; i < _numAgents; i++) {
if (i % AGENTS_PER_BUCKET == 0) {
agentBucket = _agentBuckets[i / AGENTS_PER_BUCKET];
}
if (agentBucket[i % AGENTS_PER_BUCKET]->isAlive()) {
return AgentListIterator(this, i);
}
}
return AgentListIterator(this, 0);
}
int packAgentId(unsigned char *packStore, uint16_t agentId) {
memcpy(packStore, &agentId, sizeof(uint16_t));
return sizeof(uint16_t);
AgentList::iterator AgentList::end() const {
return AgentListIterator(this, _numAgents);
}
AgentListIterator::AgentListIterator(const AgentList* agentList, int agentIndex) :
_agentIndex(agentIndex) {
_agentList = agentList;
}
AgentListIterator& AgentListIterator::operator=(const AgentListIterator& otherValue) {
_agentList = otherValue._agentList;
_agentIndex = otherValue._agentIndex;
return *this;
}
bool AgentListIterator::operator==(const AgentListIterator &otherValue) {
return _agentIndex == otherValue._agentIndex;
}
bool AgentListIterator::operator!=(const AgentListIterator &otherValue) {
return !(*this == otherValue);
}
Agent& AgentListIterator::operator*() {
Agent** agentBucket = _agentList->_agentBuckets[_agentIndex / AGENTS_PER_BUCKET];
return *agentBucket[_agentIndex % AGENTS_PER_BUCKET];
}
Agent* AgentListIterator::operator->() {
Agent** agentBucket = _agentList->_agentBuckets[_agentIndex / AGENTS_PER_BUCKET];
return agentBucket[_agentIndex % AGENTS_PER_BUCKET];
}
AgentListIterator& AgentListIterator::operator++() {
skipDeadAndStopIncrement();
return *this;
}
AgentList::iterator AgentListIterator::operator++(int) {
AgentListIterator newIterator = AgentListIterator(*this);
skipDeadAndStopIncrement();
return newIterator;
}
void AgentListIterator::skipDeadAndStopIncrement() {
while (_agentIndex != _agentList->_numAgents) {
++_agentIndex;
if (_agentIndex == _agentList->_numAgents) {
break;
} else if ((*(*this)).isAlive()) {
// skip over the dead agents
break;
}
}
}

View file

@ -9,8 +9,8 @@
#ifndef __hifi__AgentList__
#define __hifi__AgentList__
#include <vector>
#include <stdint.h>
#include <iterator>
#include "Agent.h"
#include "UDPSocket.h"
@ -19,6 +19,9 @@
#include "pthread.h"
#endif
const int MAX_NUM_AGENTS = 10000;
const int AGENTS_PER_BUCKET = 100;
const int MAX_PACKET_SIZE = 1500;
const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103;
const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000;
@ -28,15 +31,23 @@ extern char DOMAIN_HOSTNAME[];
extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup
extern const int DOMAINSERVER_PORT;
class AgentListIterator;
class AgentList {
public:
static AgentList* createInstance(char ownerType, unsigned int socketListenPort = AGENT_SOCKET_LISTEN_PORT);
static AgentList* getInstance();
typedef AgentListIterator iterator;
AgentListIterator begin() const;
AgentListIterator end() const;
void(*linkedDataCreateCallback)(Agent *);
void(*audioMixerSocketUpdate)(in_addr_t, in_port_t);
std::vector<Agent>& getAgents();
int size() { return _numAgents; }
UDPSocket& getAgentSocket();
uint16_t getLastAgentId();
@ -44,8 +55,8 @@ public:
int updateList(unsigned char *packetData, size_t dataBytes);
int indexOfMatchingAgent(sockaddr *senderAddress);
int indexOfMatchingAgent(uint16_t agentID);
Agent* agentWithAddress(sockaddr *senderAddress);
Agent* agentWithID(uint16_t agentID);
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId);
@ -67,6 +78,8 @@ public:
void stopDomainServerCheckInThread();
void startPingUnknownAgentsThread();
void stopPingUnknownAgentsThread();
friend class AgentListIterator;
private:
static AgentList* _sharedInstance;
@ -75,10 +88,13 @@ private:
AgentList(AgentList const&); // Don't implement, needed to avoid copies of singleton
void operator=(AgentList const&); // Don't implement, needed to avoid copies of singleton
void addAgentToList(Agent* newAgent);
Agent** _agentBuckets[MAX_NUM_AGENTS / AGENTS_PER_BUCKET];
int _numAgents;
UDPSocket agentSocket;
char ownerType;
unsigned int socketListenPort;
std::vector<Agent> agents;
uint16_t lastAgentId;
pthread_t removeSilentAgentsThread;
pthread_t checkInWithDomainServerThread;
@ -87,7 +103,28 @@ private:
void handlePingReply(sockaddr *agentAddress);
};
int unpackAgentId(unsigned char *packedData, uint16_t *agentId);
int packAgentId(unsigned char *packStore, uint16_t agentId);
class AgentListIterator : public std::iterator<std::input_iterator_tag, Agent> {
public:
AgentListIterator(const AgentList* agentList, int agentIndex);
~AgentListIterator() {};
int getAgentIndex() { return _agentIndex; };
AgentListIterator& operator=(const AgentListIterator& otherValue);
bool operator==(const AgentListIterator& otherValue);
bool operator!= (const AgentListIterator& otherValue);
Agent& operator*();
Agent* operator->();
AgentListIterator& operator++();
AgentListIterator operator++(int);
private:
void skipDeadAndStopIncrement();
const AgentList* _agentList;
int _agentIndex;
};
#endif /* defined(__hifi__AgentList__) */

View file

@ -122,30 +122,22 @@ void eraseVoxelTreeAndCleanupAgentVisitData() {
::randomTree.eraseAllVoxels();
// enumerate the agents clean up their marker nodes
for (int i = 0; i < AgentList::getInstance()->getAgents().size(); i++) {
for (AgentList::iterator agent = AgentList::getInstance()->begin(); agent != AgentList::getInstance()->end(); agent++) {
//printf("eraseVoxelTreeAndCleanupAgentVisitData() agent[%d]\n",i);
Agent *thisAgent = (Agent *)&AgentList::getInstance()->getAgents()[i];
VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData());
// lock this agent's delete mutex so that the delete thread doesn't
// kill the agent while we are working with it
pthread_mutex_lock(thisAgent->deleteMutex);
VoxelAgentData *agentData = (VoxelAgentData *)agent->getLinkedData();
// clean up the agent visit data
delete agentData->rootMarkerNode;
agentData->rootMarkerNode = new MarkerNode();
// unlock the delete mutex so the other thread can
// kill the agent if it has dissapeared
pthread_mutex_unlock(thisAgent->deleteMutex);
}
}
void *distributeVoxelsToListeners(void *args) {
AgentList *agentList = AgentList::getInstance();
AgentList* agentList = AgentList::getInstance();
timeval lastSendTime;
unsigned char *stopOctal;
@ -162,10 +154,8 @@ void *distributeVoxelsToListeners(void *args) {
gettimeofday(&lastSendTime, NULL);
// enumerate the agents to send 3 packets to each
for (int i = 0; i < agentList->getAgents().size(); i++) {
Agent *thisAgent = (Agent *)&agentList->getAgents()[i];
VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData());
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
VoxelAgentData *agentData = (VoxelAgentData *)agent->getLinkedData();
ViewFrustum viewFrustum;
// get position and orientation details from the camera
@ -185,10 +175,6 @@ void *distributeVoxelsToListeners(void *args) {
viewFrustum.dump();
}
// lock this agent's delete mutex so that the delete thread doesn't
// kill the agent while we are working with it
pthread_mutex_lock(thisAgent->deleteMutex);
stopOctal = NULL;
packetCount = 0;
totalBytesSent = 0;
@ -205,7 +191,7 @@ void *distributeVoxelsToListeners(void *args) {
::viewFrustumCulling,
stopOctal);
agentList->getAgentSocket().send(thisAgent->getActiveSocket(), voxelPacket, voxelPacketEnd - voxelPacket);
agentList->getAgentSocket().send(agent->getActiveSocket(), voxelPacket, voxelPacketEnd - voxelPacket);
packetCount++;
totalBytesSent += voxelPacketEnd - voxelPacket;
@ -226,10 +212,6 @@ void *distributeVoxelsToListeners(void *args) {
delete agentData->rootMarkerNode;
agentData->rootMarkerNode = new MarkerNode();
}
// unlock the delete mutex so the other thread can
// kill the agent if it has dissapeared
pthread_mutex_unlock(thisAgent->deleteMutex);
}
// dynamically sleep until we need to fire off the next set of voxels
@ -254,7 +236,7 @@ void attachVoxelAgentDataToAgent(Agent *newAgent) {
int main(int argc, const char * argv[])
{
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_VOXEL, VOXEL_LISTEN_PORT);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_VOXEL, VOXEL_LISTEN_PORT);
setvbuf(stdout, NULL, _IOLBF, 0);
// Handle Local Domain testing with the --local command line