Merge branch 'master' of git://github.com/worklist/hifi into 19165

This commit is contained in:
tosh 2013-04-26 05:07:31 +02:00
commit 50eb9a2a54
22 changed files with 1046 additions and 716 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

@ -51,9 +51,9 @@ void attachAvatarDataToAgent(Agent *newAgent) {
}
}
int main(int argc, char* argv[])
int main(int argc, const char* argv[])
{
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
setvbuf(stdout, NULL, _IOLBF, 0);
agentList->linkedDataCreateCallback = attachAvatarDataToAgent;
@ -83,11 +83,11 @@ int main(int argc, 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,9 +113,8 @@ 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,
randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION)));
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
eve.setBodyYaw(0);

View file

@ -520,6 +520,7 @@ float Audio::getInputLoudness() const {
void Audio::render(int screenWidth, int screenHeight)
{
if (initialized) {
glLineWidth(3);
glBegin(GL_LINES);
glColor3f(1,1,1);

File diff suppressed because it is too large Load diff

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,112 +157,114 @@ struct AvatarHead
class Avatar : public AvatarData {
public:
Avatar(bool isMine);
~Avatar();
Avatar(const Avatar &otherAvatar);
Avatar* clone() const;
public:
Avatar(bool isMine);
~Avatar();
Avatar(const Avatar &otherAvatar);
Avatar* clone() const;
void reset();
void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
void setNoise (float mag) { _head.noise = mag; }
void setScale(float s) {_head.scale = s; };
void setRenderYaw(float y) {_renderYaw = y;}
void setRenderPitch(float p) {_renderPitch = p;}
float getRenderYaw() {return _renderYaw;}
float getRenderPitch() {return _renderPitch;}
void setLeanForward(float dist);
void setLeanSideways(float dist);
void addLean(float x, float z);
float getLastMeasuredHeadYaw() const {return _head.yawRate;}
float getBodyYaw() {return _bodyYaw;};
void addBodyYaw(float y) {_bodyYaw += y;};
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();
void reset();
void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
void setNoise (float mag) { _head.noise = mag; }
void setScale(float s) {_head.scale = s; };
void setRenderYaw(float y) {_renderYaw = y;}
void setRenderPitch(float p) {_renderPitch = p;}
float getRenderYaw() {return _renderYaw;}
float getRenderPitch() {return _renderPitch;}
void setLeanForward(float dist);
void setLeanSideways(float dist);
void addLean(float x, float z);
float getLastMeasuredHeadYaw() const {return _head.yawRate;}
float getBodyYaw() {return _bodyYaw;};
void addBodyYaw(float y) {_bodyYaw += y;};
AvatarMode getMode();
glm::vec3 getHeadLookatDirection();
glm::vec3 getHeadLookatDirectionUp();
glm::vec3 getHeadLookatDirectionRight();
glm::vec3 getHeadPosition();
glm::vec3 getBonePosition( AvatarBoneID b );
glm::vec3 getBodyUpDirection();
float getGirth();
float getHeight();
AvatarMode getMode();
void setMousePressed( bool pressed );
void render(bool lookingInMirror);
void renderBody();
void renderHead(bool lookingInMirror);
void simulate(float);
void startHandMovement();
void stopHandMovement();
void setHandMovementValues( glm::vec3 movement );
void updateHandMovement( float deltaTime );
void updateArmIKAndConstraints( float deltaTime );
float getAverageLoudness() {return _head.averageLoudness;};
void setAverageLoudness(float al) {_head.averageLoudness = al;};
void SetNewHeadTarget(float, float);
void setMousePressed( bool pressed );
void render(bool lookingInMirror);
void renderBody();
void renderHead(bool lookingInMirror);
void simulate(float);
void startHandMovement();
void stopHandMovement();
void setHandMovementValues( glm::vec3 movement );
void updateHandMovement( float deltaTime );
void updateArmIKAndConstraints( float deltaTime );
// Set what driving keys are being pressed to control thrust levels
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
bool getDriveKeys(int key) { return _driveKeys[key]; };
float getAverageLoudness() {return _head.averageLoudness;};
void setAverageLoudness(float al) {_head.averageLoudness = al;};
void SetNewHeadTarget(float, float);
// Set what driving keys are being pressed to control thrust levels
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
bool getDriveKeys(int key) { return _driveKeys[key]; };
// Set/Get update the thrust that will move the avatar around
void setThrust(glm::vec3 newThrust) { _thrust = newThrust; };
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
glm::vec3 getThrust() { return _thrust; };
// Related to getting transmitter UDP data used to animate the avatar hand
void processTransmitterData(unsigned char * packetData, int numBytes);
float getTransmitterHz() { return _transmitterHz; };
// Set/Get update the thrust that will move the avatar around
void setThrust(glm::vec3 newThrust) { _thrust = newThrust; };
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
glm::vec3 getThrust() { return _thrust; };
// Find out what the local gravity vector is at this location
glm::vec3 getGravity(glm::vec3 pos);
private:
AvatarHead _head;
bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius;
bool _mousePressed;
float _bodyYawDelta;
bool _usingBodySprings;
glm::vec3 _movedHandOffset;
float _springVelocityDecay;
float _springForce;
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
AvatarBone _bone[ NUM_AVATAR_BONES ];
AvatarMode _mode;
AvatarHandHolding _handHolding;
glm::vec3 _velocity;
glm::vec3 _thrust;
float _speed;
float _maxArmLength;
Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS];
GLUquadric* _sphere;
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head
timeval _transmitterTimer;
float _transmitterHz;
int _transmitterPackets;
Avatar* _interactingOther;
bool _interactingOtherIsNearby;
float _pelvisStandingHeight;
// Related to getting transmitter UDP data used to animate the avatar hand
void processTransmitterData(unsigned char * packetData, int numBytes);
float getTransmitterHz() { return _transmitterHz; };
private:
AvatarHead _head;
bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius;
bool _mousePressed;
float _bodyYawDelta;
bool _usingBodySprings;
glm::vec3 _movedHandOffset;
float _springVelocityDecay;
float _springForce;
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
AvatarBone _bone[ NUM_AVATAR_BONES ];
AvatarMode _mode;
AvatarHandHolding _handHolding;
glm::dvec3 _velocity;
glm::vec3 _thrust;
float _maxArmLength;
Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS];
GLUquadric* _sphere;
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head
timeval _transmitterTimer;
float _transmitterHz;
int _transmitterPackets;
Avatar* _interactingOther;
bool _interactingOtherIsNearby;
// private methods...
void initializeSkeleton();
void updateSkeleton();
void initializeBodySprings();
void updateBodySprings( float deltaTime );
void calculateBoneLengths();
void readSensors();
void renderBoneAsBlock( AvatarBoneID b );
void updateAvatarCollisionDetectionAndResponse
(
glm::vec3 collisionPosition,
float collisionGirth,
float collisionHeight,
glm::vec3 collisionUpVector,
float deltaTime
);
void initializeSkeleton();
void updateSkeleton();
void initializeBodySprings();
void updateBodySprings( float deltaTime );
void calculateBoneLengths();
void readSensors();
void renderBoneAsBlock( AvatarBoneID b );
void updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPosition,
float collisionGirth,
float collisionHeight,
glm::vec3 collisionUpVector,
float deltaTime);
};
#endif

View file

@ -11,63 +11,89 @@
#include "Camera.h"
Camera::Camera() {
_mode = CAMERA_MODE_THIRD_PERSON;
_tightness = DEFAULT_CAMERA_TIGHTNESS;
_fieldOfView = 60.0; // default
_nearClip = 0.08; // default
_farClip = 50.0; // default
_yaw = 0.0;
_pitch = 0.0;
_roll = 0.0;
_up = 0.0;
_distance = 0.0;
_idealYaw = 0.0;
_targetPosition = glm::vec3( 0.0, 0.0, 0.0 );
_position = glm::vec3( 0.0, 0.0, 0.0 );
_idealPosition = glm::vec3( 0.0, 0.0, 0.0 );
_frustumNeedsReshape = false;
_mode = CAMERA_MODE_THIRD_PERSON;
_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;
_upShift = 0.0;
_rightShift = 0.0;
_distance = 0.0;
_idealYaw = 0.0;
_targetPosition = glm::vec3( 0.0, 0.0, 0.0 );
_position = glm::vec3( 0.0, 0.0, 0.0 );
_idealPosition = glm::vec3( 0.0, 0.0, 0.0 );
_orientation.setToIdentity();
}
void Camera::update( float deltaTime ) {
void Camera::update( float deltaTime )
{
//----------------------------------------
// derive t from tightness
//----------------------------------------
float t = _tightness * deltaTime;
if ( t > 1.0 ){
t = 1.0;
}
//----------------------------------------
// update _yaw (before position!)
//----------------------------------------
_yaw += ( _idealYaw - _yaw ) * t;
float radian = ( _yaw / 180.0 ) * PIE;
//----------------------------------------
// update _position
//----------------------------------------
//these need to be checked to make sure they correspond to the coordinate system.
double x = _distance * -sin( radian );
double z = _distance * cos( radian );
double y = _up;
_idealPosition = _targetPosition + glm::vec3( x, y, z );
_position += ( _idealPosition - _position ) * t;
//------------------------------------------------------------------------------
// generate the ortho-normals for the orientation based on the Euler angles
//------------------------------------------------------------------------------
_orientation.setToIdentity();
// generate the ortho-normals for the orientation based on the Euler angles
_orientation.setToIdentity();
_orientation.yaw ( _yaw );
_orientation.pitch( _pitch );
_orientation.roll ( _roll );
_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 );
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 ) {
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 correct coordinate system.
double x = _distance * -sin( radian );
double z = _distance * cos( radian );
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;
}
// 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 setPitch ( float p ) { _pitch = p; }
void setRoll ( float r ) { _roll = r; }
void setUp ( float u ) { _up = u; }
void setDistance ( float d ) { _distance = d; }
void setTargetPosition ( glm::vec3 t ) { _targetPosition = t; };
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 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 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 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; _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; }
CameraMode getMode () { return _mode; }
float getFieldOfView () { return _fieldOfView; }
float getAspectRatio () { return _aspectRatio; }
float getNearClip () { return _nearClip; }
float getFarClip () { return _farClip; }
float getYaw () { return _yaw; }
float getPitch () { return _pitch; }
float getRoll () { return _roll; }
glm::vec3 getPosition () { return _position; }
Orientation getOrientation() { return _orientation; }
CameraMode getMode () { return _mode; }
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;
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

@ -0,0 +1,78 @@
//
// ChatEntry.cpp
// interface
//
// Created by Andrzej Kapolka on 4/24/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "InterfaceConfig.h"
#include "ChatEntry.h"
#include "Util.h"
using namespace std;
const int MAX_CONTENT_LENGTH = 140;
void ChatEntry::clear () {
contents.clear();
cursorPos = 0;
}
bool ChatEntry::key(unsigned char k) {
switch (k) {
case '\r':
return false;
case '\b':
if (cursorPos != 0) {
contents.erase(cursorPos - 1, 1);
cursorPos--;
}
return true;
case 127: // delete
if (cursorPos < contents.size()) {
contents.erase(cursorPos, 1);
}
return true;
default:
if (contents.size() != MAX_CONTENT_LENGTH) {
contents.insert(cursorPos, 1, k);
cursorPos++;
}
return true;
}
}
void ChatEntry::specialKey(unsigned char k) {
switch (k) {
case GLUT_KEY_LEFT:
if (cursorPos != 0) {
cursorPos--;
}
break;
case GLUT_KEY_RIGHT:
if (cursorPos != contents.size()) {
cursorPos++;
}
break;
}
}
void ChatEntry::render(int screenWidth, int screenHeight) {
drawtext(20, screenHeight - 150, 0.10, 0, 1.0, 0, contents.c_str(), 1, 1, 1);
float width = 0;
for (string::iterator it = contents.begin(), end = it + cursorPos; it != end; it++) {
width += glutStrokeWidth(GLUT_STROKE_ROMAN, *it)*0.10;
}
glDisable(GL_LINE_SMOOTH);
glBegin(GL_LINE_STRIP);
glVertex2f(20 + width, screenHeight - 165);
glVertex2f(20 + width, screenHeight - 150);
glEnd();
glEnable(GL_LINE_SMOOTH);
}

33
interface/src/ChatEntry.h Normal file
View file

@ -0,0 +1,33 @@
//
// ChatEntry.h
// interface
//
// Created by Andrzej Kapolka on 4/24/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__ChatEntry__
#define __interface__ChatEntry__
#include <string>
class ChatEntry {
public:
const std::string& getContents () const { return contents; }
void clear ();
bool key(unsigned char k);
void specialKey(unsigned char k);
void render(int screenWidth, int screenHeight);
private:
std::string contents;
int cursorPos;
};
#endif /* defined(__interface__ChatEntry__) */

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

@ -64,6 +64,7 @@
#include "MenuColumn.h"
#include "Menu.h"
#include "Camera.h"
#include "ChatEntry.h"
#include "Avatar.h"
#include "Particle.h"
#include "Texture.h"
@ -180,6 +181,9 @@ int mousePressed = 0; // true if mouse has been pressed (clear when finished)
Menu menu; // main menu
int menuOn = 1; // Whether to show onscreen menu
ChatEntry chatEntry; // chat entry field
bool chatEntryOn = false; // Whether to show the chat entry
struct HandController
{
bool enabled;
@ -240,8 +244,6 @@ void updateHandController( int x, int y ) {
handController.startX = WIDTH / 2;
handController.startY = HEIGHT / 2;
handController.envelope = 0.0;
//prototype
//myAvatar.stopHandMovement();
}
}
}
@ -800,34 +802,66 @@ 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
@ -843,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;
@ -864,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);
@ -909,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);
@ -978,16 +1008,22 @@ void display(void)
menu.render(WIDTH,HEIGHT);
}
// Show chat entry field
if (::chatEntryOn) {
chatEntry.render(WIDTH, HEIGHT);
}
// Stats at upper right of screen about who domain server is telling us about
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);
@ -1322,6 +1358,11 @@ void specialkeyUp(int k, int x, int y) {
void specialkey(int k, int x, int y)
{
if (::chatEntryOn) {
chatEntry.specialKey(k);
return;
}
if (k == GLUT_KEY_UP || k == GLUT_KEY_DOWN || k == GLUT_KEY_LEFT || k == GLUT_KEY_RIGHT) {
if (k == GLUT_KEY_UP) {
if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(UP, 1);
@ -1347,6 +1388,11 @@ void specialkey(int k, int x, int y)
void keyUp(unsigned char k, int x, int y) {
if (::chatEntryOn) {
myAvatar.setKeyState(AvatarData::NoKeyDown);
return;
}
if (k == 'e') myAvatar.setDriveKeys(UP, 0);
if (k == 'c') myAvatar.setDriveKeys(DOWN, 0);
if (k == 'w') myAvatar.setDriveKeys(FWD, 0);
@ -1358,6 +1404,19 @@ void keyUp(unsigned char k, int x, int y) {
void key(unsigned char k, int x, int y)
{
if (::chatEntryOn) {
if (chatEntry.key(k)) {
myAvatar.setKeyState(k == '\b' || k == 127 ? // backspace or delete
AvatarData::DeleteKeyDown : AvatarData::InsertKeyDown);
myAvatar.setChatMessage(string(chatEntry.getContents().size(), 'X'));
} else {
myAvatar.setChatMessage(chatEntry.getContents());
chatEntry.clear();
::chatEntryOn = false;
}
return;
}
// Process keypresses
if (k == 'q' || k == 'Q') ::terminate();
@ -1424,6 +1483,12 @@ void key(unsigned char k, int x, int y)
if (k == 'g') renderPitchRate += KEYBOARD_PITCH_RATE;
if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 1);
if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 1);
if (k == '\r') {
::chatEntryOn = true;
myAvatar.setKeyState(AvatarData::NoKeyDown);
myAvatar.setChatMessage(string());
}
}
// Receive packets from other agents/servers and decide what to do with them!
@ -1496,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);
}
@ -1634,7 +1697,12 @@ int main(int argc, const char * argv[])
return EXIT_SUCCESS;
}
AgentList::createInstance(AGENT_TYPE_AVATAR);
unsigned int listenPort = AGENT_SOCKET_LISTEN_PORT;
const char* portStr = getCmdOption(argc, argv, "--listenPort");
if (portStr) {
listenPort = atoi(portStr);
}
AgentList::createInstance(AGENT_TYPE_AVATAR, listenPort);
gettimeofday(&applicationStartupTime, NULL);
const char* domainIP = getCmdOption(argc, argv, "--domain");

View file

@ -161,10 +161,6 @@ namespace starfield {
#if STARFIELD_HEMISPHERE_ONLY
altitude = std::max(0.0f, altitude);
#endif
unsigned tileIndex =
_objTiling.getTileIndex(azimuth, altitude);
// printLog("Stars.cpp: starting on tile #%d\n", tileIndex);
#if STARFIELD_DEBUG_CULLING
mat4 matrix_debug = glm::translate(glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f),

View file

@ -16,6 +16,7 @@
#include "AvatarData.h"
#include "avatars_Log.h"
using namespace std;
using avatars_lib::printLog;
@ -49,7 +50,8 @@ AvatarData::AvatarData() :
_cameraFov(0.0f),
_cameraAspectRatio(0.0f),
_cameraNearClip(0.0f),
_cameraFarClip(0.0f) {
_cameraFarClip(0.0f),
_keyState(NoKeyDown) {
}
@ -112,7 +114,14 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
memcpy(destinationBuffer, &_cameraFarClip, sizeof(_cameraFarClip));
destinationBuffer += sizeof(_cameraFarClip);
// key state
*destinationBuffer++ = _keyState;
// chat message
*destinationBuffer++ = _chatMessage.size();
memcpy(destinationBuffer, _chatMessage.data(), _chatMessage.size() * sizeof(char));
destinationBuffer += _chatMessage.size() * sizeof(char);
return destinationBuffer - bufferStart;
}
@ -168,13 +177,19 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
memcpy(&_cameraFarClip, sourceBuffer, sizeof(_cameraFarClip));
sourceBuffer += sizeof(_cameraFarClip);
// key state
_keyState = (KeyState)*sourceBuffer++;
// the rest is a chat message
int chatMessageSize = *sourceBuffer++;
_chatMessage = string((char*)sourceBuffer, chatMessageSize);
sourceBuffer += chatMessageSize * sizeof(char);
return sourceBuffer - startPosition;
}
glm::vec3 AvatarData::getPosition() {
return glm::vec3(_position.x,
_position.y,
_position.z);
const glm::vec3& AvatarData::getPosition() const {
return _position;
}
void AvatarData::setPosition(glm::vec3 position) {

View file

@ -9,6 +9,8 @@
#ifndef __hifi__AvatarData__
#define __hifi__AvatarData__
#include <string>
#include <glm/glm.hpp>
#include <AgentData.h>
@ -20,7 +22,7 @@ public:
AvatarData* clone() const;
glm::vec3 getPosition();
const glm::vec3& getPosition() const;
void setPosition(glm::vec3 position);
void setHandPosition(glm::vec3 handPosition);
@ -74,6 +76,16 @@ public:
void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; }
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
enum KeyState { NoKeyDown, InsertKeyDown, DeleteKeyDown };
// key state
void setKeyState(KeyState s) { _keyState = s; }
KeyState keyState() const { return _keyState; }
// chat message
void setChatMessage(const std::string& msg) { _chatMessage = msg; }
const std::string& chatMessage () const { return _chatMessage; }
protected:
glm::vec3 _position;
glm::vec3 _handPosition;
@ -105,6 +117,12 @@ protected:
float _cameraAspectRatio;
float _cameraNearClip;
float _cameraFarClip;
// key state (nothing, down, up, backspace)
KeyState _keyState;
// chat message
std::string _chatMessage;
};
#endif /* defined(__hifi__AvatarData__) */

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();) {
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); ++agent) {
pthread_mutex_t* agentDeleteMutex = agent->deleteMutex;
if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS
&& agent->getType() != AGENT_TYPE_VOXEL
&& pthread_mutex_trylock(agentDeleteMutex) == 0) {
if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS
&& 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