mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 09:54:14 +02:00
Merge branch 'master' of git://github.com/worklist/hifi into 19165
This commit is contained in:
commit
50eb9a2a54
22 changed files with 1046 additions and 716 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
78
interface/src/ChatEntry.cpp
Normal file
78
interface/src/ChatEntry.cpp
Normal 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
33
interface/src/ChatEntry.h
Normal 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__) */
|
|
@ -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 );
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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 & );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue