mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 16:36:54 +02:00
move AvatarData class to AvatarAgentData subclass of AgentData
This commit is contained in:
parent
3f64c29bc9
commit
a0f3f161b1
9 changed files with 317 additions and 427 deletions
116
avatar/src/AvatarAgentData.cpp
Normal file
116
avatar/src/AvatarAgentData.cpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
//
|
||||||
|
// AvatarAgentData.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 4/9/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AvatarAgentData.h"
|
||||||
|
|
||||||
|
AvatarAgentData::AvatarAgentData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AvatarAgentData::~AvatarAgentData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AvatarAgentData* AvatarAgentData::clone() const {
|
||||||
|
return new AvatarAgentData(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::parseData(void *data, int size) {
|
||||||
|
char* packetData = (char *)data + 1;
|
||||||
|
|
||||||
|
// Extract data from packet
|
||||||
|
sscanf(packetData,
|
||||||
|
PACKET_FORMAT,
|
||||||
|
&_pitch,
|
||||||
|
&_yaw,
|
||||||
|
&_roll,
|
||||||
|
&_headPositionX,
|
||||||
|
&_headPositionY,
|
||||||
|
&_headPositionZ,
|
||||||
|
&_loudness,
|
||||||
|
&_averageLoudness,
|
||||||
|
&_handPositionX,
|
||||||
|
&_handPositionY,
|
||||||
|
&_handPositionZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getPitch() {
|
||||||
|
return _pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getYaw() {
|
||||||
|
return _yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getRoll() {
|
||||||
|
return _roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHeadPositionX() {
|
||||||
|
return _headPositionX;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHeadPositionY() {
|
||||||
|
return _headPositionY;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHeadPositionZ() {
|
||||||
|
return _headPositionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getLoudness() {
|
||||||
|
return _loudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getAverageLoudness() {
|
||||||
|
return _averageLoudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHandPositionX() {
|
||||||
|
return _handPositionX;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHandPositionY() {
|
||||||
|
return _handPositionY;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHandPositionZ() {
|
||||||
|
return _handPositionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setPitch(float pitch) {
|
||||||
|
_pitch = pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setYaw(float yaw) {
|
||||||
|
_yaw = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setRoll(float roll) {
|
||||||
|
_roll = roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setHeadPosition(float x, float y, float z) {
|
||||||
|
_headPositionX = x;
|
||||||
|
_headPositionY = y;
|
||||||
|
_headPositionZ = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setLoudness(float loudness) {
|
||||||
|
_loudness = loudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setAverageLoudness(float averageLoudness) {
|
||||||
|
_averageLoudness = averageLoudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setHandPosition(float x, float y, float z) {
|
||||||
|
_handPositionX = x;
|
||||||
|
_handPositionY = y;
|
||||||
|
_handPositionZ = z;
|
||||||
|
}
|
58
avatar/src/AvatarAgentData.h
Normal file
58
avatar/src/AvatarAgentData.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// AvatarAgentData.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 4/9/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__AvatarAgentData__
|
||||||
|
#define __hifi__AvatarAgentData__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <AgentData.h>
|
||||||
|
|
||||||
|
const char PACKET_FORMAT[] = "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f";
|
||||||
|
|
||||||
|
class AvatarAgentData : public AgentData {
|
||||||
|
public:
|
||||||
|
AvatarAgentData();
|
||||||
|
~AvatarAgentData();
|
||||||
|
|
||||||
|
void parseData(void *data, int size);
|
||||||
|
AvatarAgentData* clone() const;
|
||||||
|
|
||||||
|
float getPitch();
|
||||||
|
void setPitch(float pitch);
|
||||||
|
float getYaw();
|
||||||
|
void setYaw(float yaw);
|
||||||
|
float getRoll();
|
||||||
|
void setRoll(float roll);
|
||||||
|
float getHeadPositionX();
|
||||||
|
float getHeadPositionY();
|
||||||
|
float getHeadPositionZ();
|
||||||
|
void setHeadPosition(float x, float y, float z);
|
||||||
|
float getLoudness();
|
||||||
|
void setLoudness(float loudness);
|
||||||
|
float getAverageLoudness();
|
||||||
|
void setAverageLoudness(float averageLoudness);
|
||||||
|
float getHandPositionX();
|
||||||
|
float getHandPositionY();
|
||||||
|
float getHandPositionZ();
|
||||||
|
void setHandPosition(float x, float y, float z);
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _pitch;
|
||||||
|
float _yaw;
|
||||||
|
float _roll;
|
||||||
|
float _headPositionX;
|
||||||
|
float _headPositionY;
|
||||||
|
float _headPositionZ;
|
||||||
|
float _loudness;
|
||||||
|
float _averageLoudness;
|
||||||
|
float _handPositionX;
|
||||||
|
float _handPositionY;
|
||||||
|
float _handPositionZ;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__AvatarAgentData__) */
|
|
@ -1,336 +0,0 @@
|
||||||
//
|
|
||||||
// avatar.cpp
|
|
||||||
// Avatar Mixer
|
|
||||||
//
|
|
||||||
// Created by Leonardo Murillo on 03/25/13.
|
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved
|
|
||||||
//
|
|
||||||
// The avatar mixer receives head, hand and positional data from all connected
|
|
||||||
// agents, and broadcasts that data back to them, every BROADCAST_INTERVAL ms.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
|
||||||
#include <AgentList.h>
|
|
||||||
#include <SharedUtil.h>
|
|
||||||
#include <PacketHeaders.h>
|
|
||||||
#include <StdDev.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <UDPSocket.h>
|
|
||||||
#include "avatar.h"
|
|
||||||
|
|
||||||
std::vector<AvatarAgent> *avatarAgentList = new std::vector<AvatarAgent>;
|
|
||||||
UDPSocket *avatarMixerSocket = new UDPSocket(AVATAR_LISTEN_PORT);
|
|
||||||
|
|
||||||
AvatarAgent *findAvatarAgentBySocket(sockaddr *activeSocket) {
|
|
||||||
|
|
||||||
sockaddr *agentSocketHolder = new sockaddr();
|
|
||||||
|
|
||||||
for (std::vector<AvatarAgent>::iterator avatarAgent = avatarAgentList->begin();
|
|
||||||
avatarAgent != avatarAgentList->end();
|
|
||||||
avatarAgent++) {
|
|
||||||
agentSocketHolder = avatarAgent->getActiveSocket();
|
|
||||||
if (agentSocketHolder->sa_family != activeSocket->sa_family) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
sockaddr_in *firstSocket = (sockaddr_in *) activeSocket;
|
|
||||||
sockaddr_in *secondSocket = (sockaddr_in *) agentSocketHolder;
|
|
||||||
|
|
||||||
if (firstSocket->sin_addr.s_addr == secondSocket->sin_addr.s_addr &&
|
|
||||||
firstSocket->sin_port == secondSocket->sin_port) {
|
|
||||||
return &*avatarAgent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor and Destructor
|
|
||||||
AvatarAgent::AvatarAgent(sockaddr activeSocket,
|
|
||||||
float pitch,
|
|
||||||
float yaw,
|
|
||||||
float roll,
|
|
||||||
float headPositionX,
|
|
||||||
float headPositionY,
|
|
||||||
float headPositionZ,
|
|
||||||
float loudness,
|
|
||||||
float averageLoudness,
|
|
||||||
float handPositionX,
|
|
||||||
float handPositionY,
|
|
||||||
float handPositionZ,
|
|
||||||
double lastHeartbeat) {
|
|
||||||
|
|
||||||
this->setActiveSocket(activeSocket);
|
|
||||||
this->setPitch(pitch);
|
|
||||||
this->setYaw(yaw);
|
|
||||||
this->setRoll(roll);
|
|
||||||
this->setHeadPosition(headPositionX, headPositionY, headPositionZ);
|
|
||||||
this->setLoudness(loudness);
|
|
||||||
this->setAverageLoudness(averageLoudness);
|
|
||||||
this->setHandPosition(handPositionX, handPositionY, handPositionZ);
|
|
||||||
this->setLastHeartbeat(lastHeartbeat);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AvatarAgent::~AvatarAgent() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Property getters
|
|
||||||
sockaddr *AvatarAgent::getActiveSocket() {
|
|
||||||
return &_activeSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getPitch() {
|
|
||||||
return _pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getYaw() {
|
|
||||||
return _yaw;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getRoll() {
|
|
||||||
return _roll;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getHeadPositionX() {
|
|
||||||
return _headPositionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getHeadPositionY() {
|
|
||||||
return _headPositionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getHeadPositionZ() {
|
|
||||||
return _headPositionZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getLoudness() {
|
|
||||||
return _loudness;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getAverageLoudness() {
|
|
||||||
return _averageLoudness;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getHandPositionX() {
|
|
||||||
return _handPositionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getHandPositionY() {
|
|
||||||
return _handPositionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AvatarAgent::getHandPositionZ() {
|
|
||||||
return _handPositionZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AvatarAgent::getLastHeartbeat() {
|
|
||||||
return _lastHeartbeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Property setters
|
|
||||||
void AvatarAgent::setActiveSocket(sockaddr activeSocket) {
|
|
||||||
_activeSocket = activeSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setPitch(float pitch) {
|
|
||||||
_pitch = pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setYaw(float yaw) {
|
|
||||||
_yaw = yaw;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setRoll(float roll) {
|
|
||||||
_roll = roll;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setHeadPosition(float x, float y, float z) {
|
|
||||||
_headPositionX = x;
|
|
||||||
_headPositionY = y;
|
|
||||||
_headPositionZ = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setLoudness(float loudness) {
|
|
||||||
_loudness = loudness;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setAverageLoudness(float averageLoudness) {
|
|
||||||
_averageLoudness = averageLoudness;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setHandPosition(float x, float y, float z) {
|
|
||||||
_handPositionX = x;
|
|
||||||
_handPositionY = y;
|
|
||||||
_handPositionZ = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarAgent::setLastHeartbeat(double lastHeartbeat) {
|
|
||||||
_lastHeartbeat = lastHeartbeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *addAgentToBroadcastPacket(unsigned char *currentPosition, AvatarAgent *agentToAdd) {
|
|
||||||
unsigned char *packetData = new unsigned char();
|
|
||||||
|
|
||||||
currentPosition += packSocket(currentPosition, agentToAdd->getActiveSocket());
|
|
||||||
|
|
||||||
sprintf((char *)packetData, PACKET_FORMAT, agentToAdd->getPitch(),
|
|
||||||
agentToAdd->getYaw(),
|
|
||||||
agentToAdd->getRoll(),
|
|
||||||
agentToAdd->getHeadPositionX(),
|
|
||||||
agentToAdd->getHeadPositionY(),
|
|
||||||
agentToAdd->getHeadPositionZ(),
|
|
||||||
agentToAdd->getLoudness(),
|
|
||||||
agentToAdd->getAverageLoudness(),
|
|
||||||
agentToAdd->getHandPositionX(),
|
|
||||||
agentToAdd->getHandPositionY(),
|
|
||||||
agentToAdd->getHandPositionZ());
|
|
||||||
|
|
||||||
memcpy(currentPosition, packetData, strlen((const char*)packetData));
|
|
||||||
currentPosition += strlen((const char*)packetData);
|
|
||||||
|
|
||||||
return currentPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *sendAvatarData(void *args) {
|
|
||||||
timeval startTime;
|
|
||||||
while (true) {
|
|
||||||
gettimeofday(&startTime, NULL);
|
|
||||||
|
|
||||||
unsigned char *currentBufferPosition;
|
|
||||||
unsigned char *startPointer;
|
|
||||||
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
|
||||||
|
|
||||||
broadcastPacket = (unsigned char *)PACKET_HEADER_HEAD_DATA;
|
|
||||||
currentBufferPosition = broadcastPacket + 1;
|
|
||||||
startPointer = currentBufferPosition;
|
|
||||||
|
|
||||||
|
|
||||||
for (std::vector<AvatarAgent>::iterator avatarAgent = avatarAgentList->begin();
|
|
||||||
avatarAgent != avatarAgentList->end();
|
|
||||||
avatarAgent++) {
|
|
||||||
addAgentToBroadcastPacket(currentBufferPosition, &*avatarAgent);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::vector<AvatarAgent>::iterator avatarAgent = avatarAgentList->begin();
|
|
||||||
avatarAgent != avatarAgentList->end();
|
|
||||||
avatarAgent++) {
|
|
||||||
avatarMixerSocket->send(avatarAgent->getActiveSocket(), broadcastPacket, strlen((const char *)broadcastPacket));
|
|
||||||
}
|
|
||||||
|
|
||||||
double usecToSleep = usecTimestamp(&startTime) + (BROADCAST_INTERVAL * 10000000) - usecTimestampNow();
|
|
||||||
usleep(usecToSleep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *popInactiveAvatarAgents(void *args) {
|
|
||||||
|
|
||||||
double checkTime, sleepTime;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
checkTime = usecTimestampNow();
|
|
||||||
|
|
||||||
for (std::vector<AvatarAgent>::iterator avatarAgent = avatarAgentList->begin();
|
|
||||||
avatarAgent != avatarAgentList->end();
|
|
||||||
avatarAgent++) {
|
|
||||||
if ((checkTime - avatarAgent->getLastHeartbeat()) > AGENT_SILENCE_THRESHOLD_USECS) {
|
|
||||||
avatarAgent = avatarAgentList->erase(avatarAgent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
|
||||||
|
|
||||||
pthread_t sendAvatarDataThread;
|
|
||||||
pthread_create(&sendAvatarDataThread, NULL, sendAvatarData, NULL);
|
|
||||||
|
|
||||||
pthread_t popInactiveAvatarAgentsThread;
|
|
||||||
pthread_create(&popInactiveAvatarAgentsThread, NULL, popInactiveAvatarAgents, NULL);
|
|
||||||
|
|
||||||
sockaddr *agentAddress = new sockaddr;
|
|
||||||
char *packetData = new char[MAX_PACKET_SIZE];
|
|
||||||
ssize_t receivedBytes = 0;
|
|
||||||
|
|
||||||
AvatarAgent *matchingAgent = NULL;
|
|
||||||
|
|
||||||
float *pitch;
|
|
||||||
float *yaw;
|
|
||||||
float *roll;
|
|
||||||
float *headPositionX;
|
|
||||||
float *headPositionY;
|
|
||||||
float *headPositionZ;
|
|
||||||
float *loudness;
|
|
||||||
float *averageLoudness;
|
|
||||||
float *handPositionX;
|
|
||||||
float *handPositionY;
|
|
||||||
float *handPositionZ;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (avatarMixerSocket->receive(agentAddress, packetData, &receivedBytes)) {
|
|
||||||
if (packetData[0] == PACKET_HEADER_HEAD_DATA) {
|
|
||||||
// Extract data from packet
|
|
||||||
sscanf(packetData + 1,
|
|
||||||
PACKET_FORMAT,
|
|
||||||
&pitch,
|
|
||||||
&yaw,
|
|
||||||
&roll,
|
|
||||||
&headPositionX,
|
|
||||||
&headPositionY,
|
|
||||||
&headPositionZ,
|
|
||||||
&loudness,
|
|
||||||
&averageLoudness,
|
|
||||||
&handPositionX,
|
|
||||||
&handPositionY,
|
|
||||||
&handPositionZ);
|
|
||||||
|
|
||||||
matchingAgent = findAvatarAgentBySocket(agentAddress);
|
|
||||||
|
|
||||||
if (matchingAgent) {
|
|
||||||
// We already have this agent on our list, just modify positional data
|
|
||||||
matchingAgent->setPitch(*pitch);
|
|
||||||
matchingAgent->setYaw(*yaw);
|
|
||||||
matchingAgent->setRoll(*roll);
|
|
||||||
matchingAgent->setHeadPosition(*headPositionX, *headPositionY, *headPositionZ);
|
|
||||||
matchingAgent->setLoudness(*loudness);
|
|
||||||
matchingAgent->setAverageLoudness(*averageLoudness);
|
|
||||||
matchingAgent->setHandPosition(*handPositionX, *handPositionY, *handPositionZ);
|
|
||||||
matchingAgent->setLastHeartbeat(usecTimestampNow());
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// This is a new agent, we need to add to the list
|
|
||||||
AvatarAgent thisAgentHolder = *new AvatarAgent(*agentAddress,
|
|
||||||
*pitch,
|
|
||||||
*yaw,
|
|
||||||
*roll,
|
|
||||||
*headPositionX,
|
|
||||||
*headPositionY,
|
|
||||||
*headPositionZ,
|
|
||||||
*loudness,
|
|
||||||
*averageLoudness,
|
|
||||||
*handPositionX,
|
|
||||||
*handPositionY,
|
|
||||||
*handPositionZ,
|
|
||||||
usecTimestampNow());
|
|
||||||
avatarAgentList->push_back(thisAgentHolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
//
|
|
||||||
// avatar.h
|
|
||||||
// Avatar Mixer - Main header file
|
|
||||||
//
|
|
||||||
// Created by Leonardo Murillo on 03/25/13.
|
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <math.h>
|
|
||||||
#include <map>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
|
||||||
#include <AgentList.h>
|
|
||||||
#include <SharedUtil.h>
|
|
||||||
#include <StdDev.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
const int AVATAR_LISTEN_PORT = 55444;
|
|
||||||
const unsigned short BROADCAST_INTERVAL = 20;
|
|
||||||
const char *PACKET_FORMAT = "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f";
|
|
||||||
|
|
||||||
class AvatarAgent {
|
|
||||||
private:
|
|
||||||
sockaddr _activeSocket;
|
|
||||||
float _pitch;
|
|
||||||
float _yaw;
|
|
||||||
float _roll;
|
|
||||||
float _headPositionX;
|
|
||||||
float _headPositionY;
|
|
||||||
float _headPositionZ;
|
|
||||||
float _loudness;
|
|
||||||
float _averageLoudness;
|
|
||||||
float _handPositionX;
|
|
||||||
float _handPositionY;
|
|
||||||
float _handPositionZ;
|
|
||||||
double _lastHeartbeat;
|
|
||||||
public:
|
|
||||||
AvatarAgent(sockaddr activeSocket,
|
|
||||||
float pitch,
|
|
||||||
float yaw,
|
|
||||||
float roll,
|
|
||||||
float headPositionX,
|
|
||||||
float headPositionY,
|
|
||||||
float headPositionZ,
|
|
||||||
float loudness,
|
|
||||||
float averageLoudness,
|
|
||||||
float handPositionX,
|
|
||||||
float handPositionY,
|
|
||||||
float handPositionZ,
|
|
||||||
double lastHeartbeat);
|
|
||||||
~AvatarAgent();
|
|
||||||
sockaddr *getActiveSocket();
|
|
||||||
void setActiveSocket(sockaddr activeSocket);
|
|
||||||
float getPitch();
|
|
||||||
void setPitch(float pitch);
|
|
||||||
float getYaw();
|
|
||||||
void setYaw(float yaw);
|
|
||||||
float getRoll();
|
|
||||||
void setRoll(float roll);
|
|
||||||
float getHeadPositionX();
|
|
||||||
float getHeadPositionY();
|
|
||||||
float getHeadPositionZ();
|
|
||||||
void setHeadPosition(float x, float y, float z);
|
|
||||||
float getLoudness();
|
|
||||||
void setLoudness(float loudness);
|
|
||||||
float getAverageLoudness();
|
|
||||||
void setAverageLoudness(float averageLoudness);
|
|
||||||
float getHandPositionX();
|
|
||||||
float getHandPositionY();
|
|
||||||
float getHandPositionZ();
|
|
||||||
void setHandPosition(float x, float y, float z);
|
|
||||||
double getLastHeartbeat();
|
|
||||||
void setLastHeartbeat(double lastHeartbeat);
|
|
||||||
};
|
|
135
avatar/src/main.cpp
Normal file
135
avatar/src/main.cpp
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
//
|
||||||
|
// main.cpp
|
||||||
|
// Avatar Mixer
|
||||||
|
//
|
||||||
|
// Created by Leonardo Murillo on 03/25/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// The avatar mixer receives head, hand and positional data from all connected
|
||||||
|
// agents, and broadcasts that data back to them, every BROADCAST_INTERVAL ms.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <limits>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <AgentList.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <AgentTypes.h>
|
||||||
|
#include <StdDev.h>
|
||||||
|
#include <UDPSocket.h>
|
||||||
|
|
||||||
|
#include "AvatarAgentData.h"
|
||||||
|
|
||||||
|
const int AVATAR_LISTEN_PORT = 55444;
|
||||||
|
const unsigned short BROADCAST_INTERVAL = 20;
|
||||||
|
|
||||||
|
AgentList agentList(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
|
||||||
|
|
||||||
|
unsigned char *addAgentToBroadcastPacket(unsigned char *currentPosition, Agent *agentToAdd) {
|
||||||
|
unsigned char *packetData = new unsigned char();
|
||||||
|
|
||||||
|
currentPosition += packSocket(currentPosition, agentToAdd->getActiveSocket());
|
||||||
|
|
||||||
|
AvatarAgentData *agentData = (AvatarAgentData *)agentToAdd->getLinkedData();
|
||||||
|
|
||||||
|
sprintf((char *)packetData, PACKET_FORMAT, agentData->getPitch(),
|
||||||
|
agentData->getYaw(),
|
||||||
|
agentData->getRoll(),
|
||||||
|
agentData->getHeadPositionX(),
|
||||||
|
agentData->getHeadPositionY(),
|
||||||
|
agentData->getHeadPositionZ(),
|
||||||
|
agentData->getLoudness(),
|
||||||
|
agentData->getAverageLoudness(),
|
||||||
|
agentData->getHandPositionX(),
|
||||||
|
agentData->getHandPositionY(),
|
||||||
|
agentData->getHandPositionZ());
|
||||||
|
|
||||||
|
memcpy(currentPosition, packetData, strlen((const char*)packetData));
|
||||||
|
currentPosition += strlen((const char*)packetData);
|
||||||
|
|
||||||
|
return currentPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *sendAvatarData(void *args) {
|
||||||
|
timeval startTime;
|
||||||
|
while (true) {
|
||||||
|
gettimeofday(&startTime, NULL);
|
||||||
|
|
||||||
|
unsigned char *currentBufferPosition;
|
||||||
|
unsigned char *startPointer;
|
||||||
|
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
||||||
|
|
||||||
|
broadcastPacket = (unsigned char *)PACKET_HEADER_HEAD_DATA;
|
||||||
|
currentBufferPosition = broadcastPacket + 1;
|
||||||
|
startPointer = currentBufferPosition;
|
||||||
|
|
||||||
|
|
||||||
|
for (std::vector<Agent>::iterator avatarAgent = agentList.getAgents().begin();
|
||||||
|
avatarAgent != agentList.getAgents().end();
|
||||||
|
avatarAgent++) {
|
||||||
|
addAgentToBroadcastPacket(currentBufferPosition, &*avatarAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<Agent>::iterator avatarAgent = agentList.getAgents().begin();
|
||||||
|
avatarAgent != agentList.getAgents().end();
|
||||||
|
avatarAgent++) {
|
||||||
|
agentList.getAgentSocket().send(avatarAgent->getActiveSocket(), broadcastPacket, strlen((const char *)broadcastPacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
double usecToSleep = usecTimestamp(&startTime) + (BROADCAST_INTERVAL * 10000000) - usecTimestampNow();
|
||||||
|
usleep(usecToSleep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void attachAvatarDataToAgent(Agent *newAgent) {
|
||||||
|
if (newAgent->getLinkedData() == NULL) {
|
||||||
|
newAgent->setLinkedData(new AvatarAgentData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
|
pthread_t sendAvatarDataThread;
|
||||||
|
pthread_create(&sendAvatarDataThread, NULL, sendAvatarData, NULL);
|
||||||
|
|
||||||
|
agentList.linkedDataCreateCallback = attachAvatarDataToAgent;
|
||||||
|
|
||||||
|
agentList.startDomainServerCheckInThread();
|
||||||
|
agentList.startSilentAgentRemovalThread();
|
||||||
|
|
||||||
|
sockaddr *agentAddress = new sockaddr;
|
||||||
|
char *packetData = new char[MAX_PACKET_SIZE];
|
||||||
|
ssize_t receivedBytes = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) {
|
||||||
|
if (packetData[0] == PACKET_HEADER_HEAD_DATA) {
|
||||||
|
|
||||||
|
if (agentList.addOrUpdateAgent(agentAddress, agentAddress, AGENT_TYPE_INTERFACE, agentList.getLastAgentId())) {
|
||||||
|
agentList.increaseAgentId();
|
||||||
|
}
|
||||||
|
|
||||||
|
agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
agentList.stopDomainServerCheckInThread();
|
||||||
|
agentList.stopSilentAgentRemovalThread();
|
||||||
|
}
|
|
@ -61,7 +61,7 @@ const int AGENT_LOOPBACK_MODIFIER = 307;
|
||||||
|
|
||||||
const int LOOPBACK_SANITY_CHECK = 0;
|
const int LOOPBACK_SANITY_CHECK = 0;
|
||||||
|
|
||||||
AgentList agentList(AGENT_TYPE_MIXER, MIXER_LISTEN_PORT);
|
AgentList agentList(AGENT_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
|
||||||
StDev stdev;
|
StDev stdev;
|
||||||
|
|
||||||
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
||||||
|
|
|
@ -100,7 +100,7 @@ const char* AGENT_TYPE_NAME_DOMAIN = "Domain";
|
||||||
const char* AGENT_TYPE_NAME_VOXEL = "Voxel Server";
|
const char* AGENT_TYPE_NAME_VOXEL = "Voxel Server";
|
||||||
const char* AGENT_TYPE_NAME_INTERFACE = "Client Interface";
|
const char* AGENT_TYPE_NAME_INTERFACE = "Client Interface";
|
||||||
const char* AGENT_TYPE_NAME_HEAD = "Avatar Head"; // Is this needed???
|
const char* AGENT_TYPE_NAME_HEAD = "Avatar Head"; // Is this needed???
|
||||||
const char* AGENT_TYPE_NAME_MIXER = "Audio Mixer";
|
const char* AGENT_TYPE_NAME_AUDIO_MIXER = "Audio Mixer";
|
||||||
const char* AGENT_TYPE_NAME_UNKNOWN = "Unknown";
|
const char* AGENT_TYPE_NAME_UNKNOWN = "Unknown";
|
||||||
|
|
||||||
const char* Agent::getTypeName() const {
|
const char* Agent::getTypeName() const {
|
||||||
|
@ -118,8 +118,8 @@ const char* Agent::getTypeName() const {
|
||||||
case AGENT_TYPE_HEAD:
|
case AGENT_TYPE_HEAD:
|
||||||
name = AGENT_TYPE_NAME_HEAD;
|
name = AGENT_TYPE_NAME_HEAD;
|
||||||
break;
|
break;
|
||||||
case AGENT_TYPE_MIXER:
|
case AGENT_TYPE_AUDIO_MIXER:
|
||||||
name = AGENT_TYPE_NAME_MIXER;
|
name = AGENT_TYPE_NAME_AUDIO_MIXER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
|
|
|
@ -202,7 +202,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
||||||
newAgent.activatePublicSocket();
|
newAgent.activatePublicSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newAgent.getType() == AGENT_TYPE_MIXER && audioMixerSocketUpdate != NULL) {
|
if (newAgent.getType() == AGENT_TYPE_AUDIO_MIXER && audioMixerSocketUpdate != NULL) {
|
||||||
// this is an audio mixer
|
// this is an audio mixer
|
||||||
// for now that means we need to tell the audio class
|
// for now that means we need to tell the audio class
|
||||||
// to use the local socket information the domain server gave us
|
// to use the local socket information the domain server gave us
|
||||||
|
@ -221,7 +221,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (agent->getType() == AGENT_TYPE_MIXER || agent->getType() == AGENT_TYPE_VOXEL) {
|
if (agent->getType() == AGENT_TYPE_AUDIO_MIXER || agent->getType() == AGENT_TYPE_VOXEL) {
|
||||||
// until the Audio class also uses our agentList, we need to update
|
// until the Audio class also uses our agentList, we need to update
|
||||||
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
||||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||||
|
|
|
@ -22,6 +22,7 @@ const char AGENT_TYPE_DOMAIN = 'D';
|
||||||
const char AGENT_TYPE_VOXEL = 'V';
|
const char AGENT_TYPE_VOXEL = 'V';
|
||||||
const char AGENT_TYPE_INTERFACE = 'I'; // could also be injector???
|
const char AGENT_TYPE_INTERFACE = 'I'; // could also be injector???
|
||||||
const char AGENT_TYPE_HEAD = 'H'; // Is this needed???
|
const char AGENT_TYPE_HEAD = 'H'; // Is this needed???
|
||||||
const char AGENT_TYPE_MIXER = 'M';
|
const char AGENT_TYPE_AUDIO_MIXER = 'M';
|
||||||
|
const char AGENT_TYPE_AVATAR_MIXER = 'W';
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue