mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 17:03:58 +02:00
Merge pull request #21 from birarda/19170B
Leo's Avatar Mixer + birarda's AgentData updates
This commit is contained in:
commit
002d35932e
17 changed files with 503 additions and 140 deletions
|
@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.8)
|
|||
project(hifi)
|
||||
|
||||
add_subdirectory(space)
|
||||
add_subdirectory(avatar)
|
||||
add_subdirectory(domain)
|
||||
add_subdirectory(mixer)
|
||||
add_subdirectory(voxel)
|
||||
|
|
17
avatar/CMakeLists.txt
Normal file
17
avatar/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(avatar)
|
||||
|
||||
# grab the implemenation and header files
|
||||
file(GLOB AVATAR_SRCS src/*.cpp src/*.h)
|
||||
|
||||
# add the executable
|
||||
add_executable(avatar ${AVATAR_SRCS})
|
||||
|
||||
# link the shared hifi library
|
||||
include(../LinkHifiShared.cmake)
|
||||
link_hifi_shared_library(avatar)
|
||||
|
||||
# link the threads library
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(avatar ${CMAKE_THREAD_LIBS_INIT})
|
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__) */
|
131
avatar/src/main.cpp
Normal file
131
avatar/src/main.cpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
//
|
||||
// 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_USECS = 20 * 1000 * 1000;
|
||||
|
||||
AgentList agentList(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
|
||||
|
||||
unsigned char *addAgentToBroadcastPacket(unsigned char *currentPosition, Agent *agentToAdd) {
|
||||
currentPosition += packSocket(currentPosition, agentToAdd->getPublicSocket());
|
||||
|
||||
AvatarAgentData *agentData = (AvatarAgentData *)agentToAdd->getLinkedData();
|
||||
|
||||
int bytesWritten = sprintf((char *)currentPosition,
|
||||
PACKET_FORMAT,
|
||||
agentData->getPitch(),
|
||||
agentData->getYaw(),
|
||||
agentData->getRoll(),
|
||||
agentData->getHeadPositionX(),
|
||||
agentData->getHeadPositionY(),
|
||||
agentData->getHeadPositionZ(),
|
||||
agentData->getLoudness(),
|
||||
agentData->getAverageLoudness(),
|
||||
agentData->getHandPositionX(),
|
||||
agentData->getHandPositionY(),
|
||||
agentData->getHandPositionZ());
|
||||
|
||||
currentPosition += bytesWritten;
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
void attachAvatarDataToAgent(Agent *newAgent) {
|
||||
if (newAgent->getLinkedData() == NULL) {
|
||||
newAgent->setLinkedData(new AvatarAgentData());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
|
||||
agentList.linkedDataCreateCallback = attachAvatarDataToAgent;
|
||||
|
||||
agentList.startDomainServerCheckInThread();
|
||||
agentList.startSilentAgentRemovalThread();
|
||||
agentList.startPingUnknownAgentsThread();
|
||||
|
||||
sockaddr *agentAddress = new sockaddr;
|
||||
char *packetData = new char[MAX_PACKET_SIZE];
|
||||
ssize_t receivedBytes = 0;
|
||||
|
||||
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
||||
*broadcastPacket = PACKET_HEADER_AVATAR_SERVER;
|
||||
|
||||
unsigned char* currentBufferPosition = NULL;
|
||||
int agentIndex = 0;
|
||||
|
||||
while (true) {
|
||||
if (agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) {
|
||||
switch (packetData[0]) {
|
||||
case PACKET_HEADER_HEAD_DATA:
|
||||
// this is positional data from an agent
|
||||
agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes);
|
||||
|
||||
currentBufferPosition = broadcastPacket + 1;
|
||||
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();
|
||||
avatarAgent++) {
|
||||
if (avatarAgent->getLinkedData() != NULL
|
||||
&& agentIndex != agentList.indexOfMatchingAgent(agentAddress)) {
|
||||
currentBufferPosition = addAgentToBroadcastPacket(currentBufferPosition, &*avatarAgent);
|
||||
}
|
||||
|
||||
agentIndex++;
|
||||
}
|
||||
|
||||
agentList.getAgentSocket().send(agentAddress,
|
||||
broadcastPacket,
|
||||
currentBufferPosition - broadcastPacket);
|
||||
|
||||
break;
|
||||
default:
|
||||
// hand this off to the AgentList
|
||||
agentList.processAgentData(agentAddress, (void *)packetData, receivedBytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
agentList.stopDomainServerCheckInThread();
|
||||
agentList.stopSilentAgentRemovalThread();
|
||||
agentList.stopPingUnknownAgentsThread();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -127,9 +127,12 @@ 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(std::vector<Agent>::iterator agent = agentList.getAgents().begin();
|
||||
agent != agentList.getAgents().end();
|
||||
agent++) {
|
||||
|
||||
if (DEBUG_TO_SELF || !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
||||
if (DEBUG_TO_SELF ||
|
||||
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
||||
if (strchr(SOLO_AGENT_TYPES_STRING, (int) agent->getType()) == NULL) {
|
||||
// this is an agent of which there can be multiple, just add them to the packet
|
||||
currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent));
|
||||
|
@ -155,7 +158,9 @@ int main(int argc, const char * argv[])
|
|||
}
|
||||
|
||||
if ((packetBytesWithoutLeadingChar = (currentBufferPos - startPointer))) {
|
||||
agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress, broadcastPacket, packetBytesWithoutLeadingChar + 1);
|
||||
agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress,
|
||||
broadcastPacket,
|
||||
packetBytesWithoutLeadingChar + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@ const float DEFAULT_Y = -1.5;
|
|||
const float DEFAULT_Z = 2.0;
|
||||
const float DEFAULT_TRANSMITTER_HZ = 60.0;
|
||||
|
||||
Hand::Hand(glm::vec3 initcolor)
|
||||
{
|
||||
Hand::Hand(glm::vec3 initcolor) {
|
||||
color = initcolor;
|
||||
reset();
|
||||
noise = 0.0; //0.2;
|
||||
|
@ -51,8 +50,7 @@ Hand::Hand(const Hand &otherHand) {
|
|||
renderPointer = otherHand.renderPointer;
|
||||
}
|
||||
|
||||
void Hand::reset()
|
||||
{
|
||||
void Hand::reset() {
|
||||
position.x = DEFAULT_X;
|
||||
position.y = DEFAULT_Y;
|
||||
position.z = DEFAULT_Z;
|
||||
|
@ -64,8 +62,7 @@ void Hand::reset()
|
|||
transmitterHz = DEFAULT_TRANSMITTER_HZ;
|
||||
}
|
||||
|
||||
void Hand::render(int isMine)
|
||||
{
|
||||
void Hand::render(int isMine) {
|
||||
const float POINTER_LENGTH = 20.0;
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
|
@ -89,22 +86,7 @@ void Hand::render(int isMine)
|
|||
glutSolidCube(1.0);
|
||||
glPopMatrix();
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
if (1) {
|
||||
// Render debug info from the transmitter
|
||||
/*
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
//gluOrtho2D(0, WIDTH, HEIGHT, 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glPopMatrix();
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void Hand::addAngularVelocity (float pRate, float yRate, float rRate) {
|
||||
|
@ -159,8 +141,7 @@ void Hand::processTransmitterData(char *packetData, int numBytes) {
|
|||
|
||||
}
|
||||
|
||||
void Hand::simulate(float deltaTime)
|
||||
{
|
||||
void Hand::simulate(float deltaTime) {
|
||||
const float ANGULAR_SPRING_CONSTANT = 0.25;
|
||||
const float ANGULAR_DAMPING_COEFFICIENT = 5*2.0f*powf(ANGULAR_SPRING_CONSTANT,0.5f);
|
||||
const float LINEAR_SPRING_CONSTANT = 100;
|
||||
|
|
|
@ -200,21 +200,6 @@ timeval timerStart, timerEnd;
|
|||
timeval lastTimeIdle;
|
||||
double elapsedTime;
|
||||
|
||||
#ifdef MARKER_CAPTURE
|
||||
|
||||
/*** Marker Capture ***/
|
||||
#define MARKER_CAPTURE_INTERVAL 1
|
||||
MarkerCapture marker_capturer(CV_CAP_ANY); // Create a new marker capturer, attached to any valid camera.
|
||||
MarkerAcquisitionView marker_acq_view(&marker_capturer);
|
||||
bool marker_capture_enabled = true;
|
||||
bool marker_capture_display = true;
|
||||
IplImage* marker_capture_frame;
|
||||
IplImage* marker_capture_blob_frame;
|
||||
pthread_mutex_t frame_lock;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Every second, check the frame rates and other stuff
|
||||
void Timer(int extra)
|
||||
{
|
||||
|
@ -229,9 +214,6 @@ void Timer(int extra)
|
|||
glutTimerFunc(1000,Timer,0);
|
||||
gettimeofday(&timerStart, NULL);
|
||||
|
||||
// Ping the agents we can see
|
||||
agentList.pingAgents();
|
||||
|
||||
// if we haven't detected gyros, check for them now
|
||||
if (!serialPort.active) {
|
||||
serialPort.pair();
|
||||
|
@ -478,11 +460,12 @@ void simulateHead(float frametime)
|
|||
myAvatar.setAverageLoudness(averageLoudness);
|
||||
#endif
|
||||
|
||||
// Send my streaming head data to agents that are nearby and need to see it!
|
||||
const int MAX_BROADCAST_STRING = 200;
|
||||
char broadcast_string[MAX_BROADCAST_STRING];
|
||||
int broadcast_bytes = myAvatar.getBroadcastData(broadcast_string);
|
||||
agentList.broadcastToAgents(broadcast_string, broadcast_bytes,AgentList::AGENTS_OF_TYPE_VOXEL_AND_INTERFACE);
|
||||
// Send my stream of head/hand data to the avatar mixer and voxel server
|
||||
char broadcastString[200];
|
||||
int broadcastBytes = myAvatar.getBroadcastData(broadcastString);
|
||||
const char broadcastReceivers[2] = {AGENT_TYPE_VOXEL, AGENT_TYPE_AVATAR_MIXER};
|
||||
|
||||
agentList.broadcastToAgents(broadcastString, broadcastBytes, broadcastReceivers, 2);
|
||||
|
||||
// If I'm in paint mode, send a voxel out to VOXEL server agents.
|
||||
if (::paintOn) {
|
||||
|
@ -501,8 +484,8 @@ void simulateHead(float frametime)
|
|||
::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 &&
|
||||
::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) {
|
||||
|
||||
if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL,0,1,&::paintingVoxel,bufferOut,sizeOut)){
|
||||
agentList.broadcastToAgents((char*)bufferOut, sizeOut,AgentList::AGENTS_OF_TYPE_VOXEL);
|
||||
if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL, 0, 1, &::paintingVoxel, bufferOut, sizeOut)){
|
||||
agentList.broadcastToAgents((char*)bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1);
|
||||
delete bufferOut;
|
||||
}
|
||||
}
|
||||
|
@ -1023,15 +1006,15 @@ void testPointToVoxel()
|
|||
void sendVoxelServerEraseAll() {
|
||||
char message[100];
|
||||
sprintf(message,"%c%s",'Z',"erase all");
|
||||
int messageSize = strlen(message)+1;
|
||||
::agentList.broadcastToAgents(message, messageSize,AgentList::AGENTS_OF_TYPE_VOXEL);
|
||||
int messageSize = strlen(message) + 1;
|
||||
::agentList.broadcastToAgents(message, messageSize, &AGENT_TYPE_VOXEL, 1);
|
||||
}
|
||||
|
||||
void sendVoxelServerAddScene() {
|
||||
char message[100];
|
||||
sprintf(message,"%c%s",'Z',"add scene");
|
||||
int messageSize = strlen(message)+1;
|
||||
::agentList.broadcastToAgents(message, messageSize,AgentList::AGENTS_OF_TYPE_VOXEL);
|
||||
int messageSize = strlen(message) + 1;
|
||||
::agentList.broadcastToAgents(message, messageSize, &AGENT_TYPE_VOXEL, 1);
|
||||
}
|
||||
|
||||
void shiftPaintingColor()
|
||||
|
@ -1207,9 +1190,7 @@ void key(unsigned char k, int x, int y)
|
|||
if (k == '.') addRandomSphere(wantColorRandomizer);
|
||||
}
|
||||
|
||||
//
|
||||
// Receive packets from other agents/servers and decide what to do with them!
|
||||
//
|
||||
void *networkReceive(void *args)
|
||||
{
|
||||
sockaddr senderAddress;
|
||||
|
@ -1221,19 +1202,26 @@ void *networkReceive(void *args)
|
|||
packetCount++;
|
||||
bytesCount += bytesReceived;
|
||||
|
||||
if (incomingPacket[0] == PACKET_HEADER_TRANSMITTER_DATA) {
|
||||
// Pass everything but transmitter data to the agent list
|
||||
myAvatar.hand->processTransmitterData(incomingPacket, bytesReceived);
|
||||
} else if (incomingPacket[0] == PACKET_HEADER_VOXEL_DATA ||
|
||||
incomingPacket[0] == PACKET_HEADER_Z_COMMAND ||
|
||||
incomingPacket[0] == PACKET_HEADER_ERASE_VOXEL) {
|
||||
voxels.parseData(incomingPacket, bytesReceived);
|
||||
} else {
|
||||
agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
switch (incomingPacket[0]) {
|
||||
case PACKET_HEADER_TRANSMITTER_DATA:
|
||||
myAvatar.hand->processTransmitterData(incomingPacket, bytesReceived);
|
||||
break;
|
||||
case PACKET_HEADER_VOXEL_DATA:
|
||||
case PACKET_HEADER_Z_COMMAND:
|
||||
case PACKET_HEADER_ERASE_VOXEL:
|
||||
voxels.parseData(incomingPacket, bytesReceived);
|
||||
break;
|
||||
case PACKET_HEADER_HEAD_DATA:
|
||||
agentList.processBulkAgentData(&senderAddress, incomingPacket, bytesReceived, sizeof(float) * 11);
|
||||
break;
|
||||
default:
|
||||
agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] incomingPacket;
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1401,9 +1389,10 @@ int main(int argc, const char * argv[])
|
|||
int wsaresult = WSAStartup( MAKEWORD(2,2), &WsaData );
|
||||
#endif
|
||||
|
||||
// start the thread which checks for silent agents
|
||||
// start the agentList threads
|
||||
agentList.startSilentAgentRemovalThread();
|
||||
agentList.startDomainServerCheckInThread();
|
||||
agentList.startPingUnknownAgentsThread();
|
||||
|
||||
glutInit(&argc, (char**)argv);
|
||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace starfield {
|
|||
return false;
|
||||
}
|
||||
fprintf(stderr, "Stars.cpp: read %d stars, rendering %ld\n",
|
||||
_valRecordsRead, _ptrVertices->size());
|
||||
_valRecordsRead, _ptrVertices->size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace starfield {
|
|||
InputVertex(float azimuth, float altitude, unsigned color) {
|
||||
|
||||
_valColor = (color >> 16 & 0xffu) | (color & 0xff00u) |
|
||||
(color << 16 & 0xff0000u) | 0xff000000u;
|
||||
(color << 16 & 0xff0000u) | 0xff000000u;
|
||||
|
||||
azimuth = angleConvert<Degrees,Radians>(azimuth);
|
||||
altitude = angleConvert<Degrees,Radians>(altitude);
|
||||
|
|
|
@ -61,7 +61,7 @@ const int AGENT_LOOPBACK_MODIFIER = 307;
|
|||
|
||||
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;
|
||||
|
||||
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
||||
|
|
|
@ -67,7 +67,7 @@ Agent::Agent(const Agent &otherAgent) {
|
|||
linkedData = NULL;
|
||||
}
|
||||
|
||||
deleteMutex = otherAgent.deleteMutex;
|
||||
pthread_mutex_init(&deleteMutex, NULL);
|
||||
}
|
||||
|
||||
Agent& Agent::operator=(Agent otherAgent) {
|
||||
|
@ -83,7 +83,6 @@ void Agent::swap(Agent &first, Agent &second) {
|
|||
swap(first.type, second.type);
|
||||
swap(first.linkedData, second.linkedData);
|
||||
swap(first.agentId, second.agentId);
|
||||
swap(first.deleteMutex, second.deleteMutex);
|
||||
}
|
||||
|
||||
Agent::~Agent() {
|
||||
|
@ -100,7 +99,8 @@ char Agent::getType() const {
|
|||
const char* AGENT_TYPE_NAME_DOMAIN = "Domain";
|
||||
const char* AGENT_TYPE_NAME_VOXEL = "Voxel Server";
|
||||
const char* AGENT_TYPE_NAME_INTERFACE = "Client Interface";
|
||||
const char* AGENT_TYPE_NAME_MIXER = "Audio Mixer";
|
||||
const char* AGENT_TYPE_NAME_AUDIO_MIXER = "Audio Mixer";
|
||||
const char* AGENT_TYPE_NAME_AVATAR_MIXER = "Avatar Mixer";
|
||||
const char* AGENT_TYPE_NAME_UNKNOWN = "Unknown";
|
||||
|
||||
const char* Agent::getTypeName() const {
|
||||
|
@ -115,9 +115,12 @@ const char* Agent::getTypeName() const {
|
|||
case AGENT_TYPE_INTERFACE:
|
||||
name = AGENT_TYPE_NAME_INTERFACE;
|
||||
break;
|
||||
case AGENT_TYPE_MIXER:
|
||||
name = AGENT_TYPE_NAME_MIXER;
|
||||
case AGENT_TYPE_AUDIO_MIXER:
|
||||
name = AGENT_TYPE_NAME_AUDIO_MIXER;
|
||||
break;
|
||||
case AGENT_TYPE_AVATAR_MIXER:
|
||||
name = AGENT_TYPE_NAME_AVATAR_MIXER;
|
||||
break;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ const int DOMAINSERVER_PORT = 40102;
|
|||
|
||||
bool silentAgentThreadStopFlag = false;
|
||||
bool domainServerCheckinStopFlag = false;
|
||||
bool pingUnknownAgentThreadStopFlag = false;
|
||||
pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
int unpackAgentId(unsigned char *packedData, uint16_t *agentId) {
|
||||
|
@ -50,6 +51,7 @@ AgentList::~AgentList() {
|
|||
// stop the spawned threads, if they were started
|
||||
stopSilentAgentRemovalThread();
|
||||
stopDomainServerCheckInThread();
|
||||
stopPingUnknownAgentsThread();
|
||||
}
|
||||
|
||||
std::vector<Agent>& AgentList::getAgents() {
|
||||
|
@ -71,48 +73,71 @@ unsigned int AgentList::getSocketListenPort() {
|
|||
void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
|
||||
switch (((char *)packetData)[0]) {
|
||||
case PACKET_HEADER_DOMAIN: {
|
||||
// list of agents from domain server
|
||||
updateList((unsigned char *)packetData, dataBytes);
|
||||
break;
|
||||
}
|
||||
case PACKET_HEADER_HEAD_DATA: {
|
||||
// head data from another agent
|
||||
updateAgentWithData(senderAddress, packetData, dataBytes);
|
||||
break;
|
||||
}
|
||||
case PACKET_HEADER_PING: {
|
||||
// ping from another agent
|
||||
//std::cout << "Got ping from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n";
|
||||
agentSocket.send(senderAddress, &PACKET_HEADER_PING_REPLY, 1);
|
||||
break;
|
||||
}
|
||||
case PACKET_HEADER_PING_REPLY: {
|
||||
// ping reply from another agent
|
||||
//std::cout << "Got ping reply from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n";
|
||||
handlePingReply(senderAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AgentList::processBulkAgentData(sockaddr *senderAddress, void *packetData, int numTotalBytes, int numBytesPerAgent) {
|
||||
// find the avatar mixer in our agent list and update the lastRecvTime from it
|
||||
int bulkSendAgentIndex = indexOfMatchingAgent(senderAddress);
|
||||
|
||||
if (bulkSendAgentIndex >= 0) {
|
||||
Agent *bulkSendAgent = &agents[bulkSendAgentIndex];
|
||||
bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
}
|
||||
|
||||
unsigned char *startPosition = (unsigned char *)packetData;
|
||||
unsigned char *currentPosition = startPosition + 1;
|
||||
unsigned char *packetHolder = new unsigned char[numBytesPerAgent + 1];
|
||||
|
||||
packetHolder[0] = PACKET_HEADER_HEAD_DATA;
|
||||
|
||||
uint16_t agentID = -1;
|
||||
|
||||
while ((currentPosition - startPosition) < numTotalBytes) {
|
||||
currentPosition += unpackAgentId(currentPosition, &agentID);
|
||||
memcpy(packetHolder + 1, currentPosition, numBytesPerAgent);
|
||||
|
||||
int matchingAgentIndex = indexOfMatchingAgent(agentID);
|
||||
if (matchingAgentIndex >= 0) {
|
||||
updateAgentWithData(&agents[matchingAgentIndex], packetHolder, numBytesPerAgent + 1);
|
||||
}
|
||||
|
||||
currentPosition += numBytesPerAgent;
|
||||
}
|
||||
|
||||
delete[] packetHolder;
|
||||
}
|
||||
|
||||
void AgentList::updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
|
||||
// find the agent by the sockaddr
|
||||
int agentIndex = indexOfMatchingAgent(senderAddress);
|
||||
|
||||
if (agentIndex != -1) {
|
||||
Agent *matchingAgent = &agents[agentIndex];
|
||||
|
||||
matchingAgent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
|
||||
if (matchingAgent->getLinkedData() == NULL) {
|
||||
if (linkedDataCreateCallback != NULL) {
|
||||
linkedDataCreateCallback(matchingAgent);
|
||||
}
|
||||
}
|
||||
|
||||
matchingAgent->getLinkedData()->parseData(packetData, dataBytes);
|
||||
updateAgentWithData(&agents[agentIndex], packetData, dataBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void AgentList::updateAgentWithData(Agent *agent, void *packetData, int dataBytes) {
|
||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
|
||||
if (agent->getLinkedData() == NULL) {
|
||||
if (linkedDataCreateCallback != NULL) {
|
||||
linkedDataCreateCallback(agent);
|
||||
}
|
||||
}
|
||||
|
||||
agent->getLinkedData()->parseData(packetData, dataBytes);
|
||||
}
|
||||
|
||||
int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
|
||||
|
@ -125,6 +150,16 @@ int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int AgentList::indexOfMatchingAgent(uint16_t agentID) {
|
||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||
if (agent->getActiveSocket() != NULL && agent->getAgentId() == agentID) {
|
||||
return agent - agents.begin();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t AgentList::getLastAgentId() {
|
||||
return lastAgentId;
|
||||
}
|
||||
|
@ -176,12 +211,12 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
|||
Agent newAgent = Agent(publicSocket, localSocket, agentType, agentId);
|
||||
|
||||
if (socketMatch(publicSocket, localSocket)) {
|
||||
// likely debugging scenario with DS + agent on local network
|
||||
// likely debugging scenario with two agents on local network
|
||||
// set the agent active right away
|
||||
newAgent.activatePublicSocket();
|
||||
}
|
||||
|
||||
if (newAgent.getType() == AGENT_TYPE_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
|
||||
|
@ -200,7 +235,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
|||
return true;
|
||||
} 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
|
||||
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
|
@ -211,54 +246,72 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
|||
}
|
||||
}
|
||||
|
||||
// XXXBHG - do we want to move these?
|
||||
const char* AgentList::AGENTS_OF_TYPE_VOXEL = "V";
|
||||
const char* AgentList::AGENTS_OF_TYPE_INTERFACE = "I";
|
||||
const char* AgentList::AGENTS_OF_TYPE_VOXEL_AND_INTERFACE = "VI";
|
||||
|
||||
void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes,const char* agentTypes) {
|
||||
void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes) {
|
||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||
// only send to the AgentTypes we are asked to send to.
|
||||
if (agent->getActiveSocket() != NULL && strchr(agentTypes,agent->getType())) {
|
||||
if (agent->getActiveSocket() != NULL && memchr(agentTypes, agent->getType(), numAgentTypes)) {
|
||||
// we know which socket is good for this agent, send there
|
||||
agentSocket.send(agent->getActiveSocket(), broadcastData, dataBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AgentList::pingAgents() {
|
||||
char payload[1];
|
||||
*payload = PACKET_HEADER_PING;
|
||||
|
||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||
if (agent->getType() == AGENT_TYPE_INTERFACE) {
|
||||
if (agent->getActiveSocket() != NULL) {
|
||||
// we know which socket is good for this agent, send there
|
||||
agentSocket.send(agent->getActiveSocket(), payload, 1);
|
||||
} else {
|
||||
// ping both of the sockets for the agent so we can figure out
|
||||
// which socket we can use
|
||||
agentSocket.send(agent->getPublicSocket(), payload, 1);
|
||||
agentSocket.send(agent->getLocalSocket(), payload, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AgentList::handlePingReply(sockaddr *agentAddress) {
|
||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.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)) {
|
||||
agent->activatePublicSocket();
|
||||
std::cout << "Activated public socket for agent " << &*agent << "\n";
|
||||
break;
|
||||
} else if (socketMatch(agent->getLocalSocket(), agentAddress)) {
|
||||
agent->activateLocalSocket();
|
||||
std::cout << "Activated local socket for agent " << &*agent << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *pingUnknownAgents(void *args) {
|
||||
|
||||
AgentList *agentList = (AgentList *)args;
|
||||
const int PING_INTERVAL_USECS = 1 * 1000000;
|
||||
|
||||
timeval lastSend;
|
||||
|
||||
while (!pingUnknownAgentThreadStopFlag) {
|
||||
gettimeofday(&lastSend, NULL);
|
||||
|
||||
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
|
||||
agent != agentList->getAgents().end();
|
||||
agent++) {
|
||||
if (agent->getActiveSocket() == NULL) {
|
||||
// ping both of the sockets for the agent so we can figure out
|
||||
// which socket we can use
|
||||
agentList->getAgentSocket().send(agent->getPublicSocket(), &PACKET_HEADER_PING, 1);
|
||||
agentList->getAgentSocket().send(agent->getLocalSocket(), &PACKET_HEADER_PING, 1);
|
||||
}
|
||||
}
|
||||
|
||||
double usecToSleep = PING_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSend));
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AgentList::startPingUnknownAgentsThread() {
|
||||
pthread_create(&pingUnknownAgentsThread, NULL, pingUnknownAgents, (void *)this);
|
||||
}
|
||||
|
||||
void AgentList::stopPingUnknownAgentsThread() {
|
||||
pingUnknownAgentThreadStopFlag = true;
|
||||
pthread_join(pingUnknownAgentsThread, NULL);
|
||||
}
|
||||
|
||||
void *removeSilentAgents(void *args) {
|
||||
std::vector<Agent> *agents = (std::vector<Agent> *)args;
|
||||
double checkTimeUSecs, sleepTime;
|
||||
|
@ -289,7 +342,6 @@ void *removeSilentAgents(void *args) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
sleepTime = AGENT_SILENCE_THRESHOLD_USECS - (usecTimestampNow() - checkTimeUSecs);
|
||||
#ifdef _WIN32
|
||||
Sleep( static_cast<int>(1000.0f*sleepTime) );
|
||||
|
@ -313,6 +365,8 @@ void AgentList::stopSilentAgentRemovalThread() {
|
|||
|
||||
void *checkInWithDomainServer(void *args) {
|
||||
|
||||
const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
||||
|
||||
AgentList *parentAgentList = (AgentList *)args;
|
||||
|
||||
timeval lastSend;
|
||||
|
@ -343,7 +397,7 @@ void *checkInWithDomainServer(void *args) {
|
|||
|
||||
parentAgentList->getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
|
||||
|
||||
double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend));
|
||||
double usecToSleep = DOMAIN_SERVER_CHECK_IN_USECS - (usecTimestampNow() - usecTimestamp(&lastSend));
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
|
|
|
@ -28,7 +28,6 @@ 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 AgentList {
|
||||
|
||||
UDPSocket agentSocket;
|
||||
|
@ -38,6 +37,7 @@ class AgentList {
|
|||
uint16_t lastAgentId;
|
||||
pthread_t removeSilentAgentsThread;
|
||||
pthread_t checkInWithDomainServerThread;
|
||||
pthread_t pingUnknownAgentsThread;
|
||||
|
||||
void handlePingReply(sockaddr *agentAddress);
|
||||
public:
|
||||
|
@ -50,15 +50,23 @@ public:
|
|||
std::vector<Agent>& getAgents();
|
||||
UDPSocket& getAgentSocket();
|
||||
|
||||
int updateList(unsigned char *packetData, size_t dataBytes);
|
||||
int indexOfMatchingAgent(sockaddr *senderAddress);
|
||||
uint16_t getLastAgentId();
|
||||
void increaseAgentId();
|
||||
|
||||
int updateList(unsigned char *packetData, size_t dataBytes);
|
||||
|
||||
int indexOfMatchingAgent(sockaddr *senderAddress);
|
||||
int indexOfMatchingAgent(uint16_t agentID);
|
||||
|
||||
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId);
|
||||
|
||||
void processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
||||
void processBulkAgentData(sockaddr *senderAddress, void *packetData, int numTotalBytes, int numBytesPerAgent);
|
||||
|
||||
void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
||||
void broadcastToAgents(char *broadcastData, size_t dataBytes, const char* agentTypes);
|
||||
void pingAgents();
|
||||
void updateAgentWithData(Agent *agent, void *packetData, int dataBytes);
|
||||
|
||||
void broadcastToAgents(char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes);
|
||||
char getOwnerType();
|
||||
unsigned int getSocketListenPort();
|
||||
|
||||
|
@ -66,10 +74,8 @@ public:
|
|||
void stopSilentAgentRemovalThread();
|
||||
void startDomainServerCheckInThread();
|
||||
void stopDomainServerCheckInThread();
|
||||
|
||||
static const char* AGENTS_OF_TYPE_VOXEL;
|
||||
static const char* AGENTS_OF_TYPE_INTERFACE;
|
||||
static const char* AGENTS_OF_TYPE_VOXEL_AND_INTERFACE;
|
||||
void startPingUnknownAgentsThread();
|
||||
void stopPingUnknownAgentsThread();
|
||||
};
|
||||
|
||||
int unpackAgentId(unsigned char *packedData, uint16_t *agentId);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
const char AGENT_TYPE_DOMAIN = 'D';
|
||||
const char AGENT_TYPE_VOXEL = 'V';
|
||||
const char AGENT_TYPE_INTERFACE = 'I'; // could also be injector???
|
||||
const char AGENT_TYPE_MIXER = 'M';
|
||||
const char AGENT_TYPE_AUDIO_MIXER = 'M';
|
||||
const char AGENT_TYPE_AVATAR_MIXER = 'W';
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@ const char PACKET_HEADER_INJECT_AUDIO = 'I';
|
|||
const char PACKET_HEADER_SET_VOXEL = 'S';
|
||||
const char PACKET_HEADER_ERASE_VOXEL = 'E';
|
||||
const char PACKET_HEADER_VOXEL_DATA = 'V';
|
||||
const char PACKET_HEADER_AVATAR_SERVER = 'X';
|
||||
const char PACKET_HEADER_TRANSMITTER_DATA = 't';
|
||||
|
||||
#endif
|
||||
|
|
|
@ -345,7 +345,7 @@ int main(int argc, const char * argv[])
|
|||
|
||||
// Now send this to the connected agents so they know to delete
|
||||
printf("rebroadcasting delete voxel message to connected agents... agentList.broadcastToAgents()\n");
|
||||
agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_INTERFACE);
|
||||
agentList.broadcastToAgents(packetData,receivedBytes, &AGENT_TYPE_INTERFACE, 1);
|
||||
|
||||
}
|
||||
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
|
||||
|
@ -373,7 +373,7 @@ int main(int argc, const char * argv[])
|
|||
|
||||
// Now send this to the connected agents so they can also process these messages
|
||||
printf("rebroadcasting Z message to connected agents... agentList.broadcastToAgents()\n");
|
||||
agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_INTERFACE);
|
||||
agentList.broadcastToAgents(packetData,receivedBytes, &AGENT_TYPE_INTERFACE, 1);
|
||||
}
|
||||
// If we got a PACKET_HEADER_HEAD_DATA, then we're talking to an AGENT_TYPE_INTERFACE, and we
|
||||
// need to make sure we have it in our agentList.
|
||||
|
|
Loading…
Reference in a new issue