mirror of
https://github.com/overte-org/overte.git
synced 2025-07-24 09:23:49 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into render_voxels_optimization
This commit is contained in:
commit
043a284d4d
21 changed files with 541 additions and 346 deletions
|
@ -10,5 +10,5 @@ add_subdirectory(interface)
|
|||
add_subdirectory(injector)
|
||||
add_subdirectory(pairing-server)
|
||||
add_subdirectory(space-server)
|
||||
add_subdirectory(voxel-server)
|
||||
add_subdirectory(voxel-edit)
|
||||
add_subdirectory(voxel-server)
|
|
@ -45,8 +45,6 @@ unsigned char packetData[MAX_PACKET_SIZE];
|
|||
|
||||
const int LOGOFF_CHECK_INTERVAL = 5000;
|
||||
|
||||
#define DEBUG_TO_SELF 0
|
||||
|
||||
int lastActiveCount = 0;
|
||||
|
||||
unsigned char* addAgentToBroadcastPacket(unsigned char* currentPosition, Agent* agentToAdd) {
|
||||
|
@ -81,10 +79,10 @@ int main(int argc, const char * argv[])
|
|||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
|
||||
ssize_t receivedBytes = 0;
|
||||
char agentType;
|
||||
char agentType = '\0';
|
||||
|
||||
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
||||
*broadcastPacket = PACKET_HEADER_DOMAIN;
|
||||
unsigned char broadcastPacket[MAX_PACKET_SIZE];
|
||||
broadcastPacket[0] = PACKET_HEADER_DOMAIN;
|
||||
|
||||
unsigned char* currentBufferPos;
|
||||
unsigned char* startPointer;
|
||||
|
@ -101,8 +99,8 @@ int main(int argc, const char * argv[])
|
|||
if (agentList->getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) {
|
||||
std::map<char, Agent *> newestSoloAgents;
|
||||
|
||||
agentType = packetData[0];
|
||||
unpackSocket(&packetData[1], (sockaddr *)&agentLocalAddress);
|
||||
agentType = packetData[1];
|
||||
unpackSocket(&packetData[2], (sockaddr*) &agentLocalAddress);
|
||||
|
||||
// check the agent public address
|
||||
// if it matches our local address we're on the same box
|
||||
|
@ -119,17 +117,19 @@ int main(int argc, const char * argv[])
|
|||
(sockaddr*) &agentLocalAddress,
|
||||
agentType,
|
||||
agentList->getLastAgentId())) {
|
||||
|
||||
agentList->increaseAgentId();
|
||||
|
||||
} else if (packetData[0] == PACKET_HEADER_DOMAIN_RFD) {
|
||||
// if this is a previous agent, and they are re-reporting for duty
|
||||
// then we need to update the first receive time
|
||||
Agent* refreshedAgent = agentList->agentWithAddress((sockaddr*) &agentLocalAddress);
|
||||
refreshedAgent->setWakeMicrostamp(usecTimestampNow());
|
||||
}
|
||||
|
||||
currentBufferPos = broadcastPacket + 1;
|
||||
currentBufferPos = broadcastPacket + 2;
|
||||
startPointer = currentBufferPos;
|
||||
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
if (DEBUG_TO_SELF ||
|
||||
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
||||
if (!agent->matches((sockaddr*) &agentPublicAddress, (sockaddr*) &agentLocalAddress, agentType)) {
|
||||
if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) {
|
||||
// this is an agent of which there can be multiple, just add them to the packet
|
||||
// don't send avatar agents to other avatars, that will come from avatar mixer
|
||||
|
@ -140,22 +140,22 @@ int main(int argc, const char * argv[])
|
|||
} else {
|
||||
// solo agent, we need to only send newest
|
||||
if (newestSoloAgents[agent->getType()] == NULL ||
|
||||
newestSoloAgents[agent->getType()]->getFirstRecvTimeUsecs() < agent->getFirstRecvTimeUsecs()) {
|
||||
newestSoloAgents[agent->getType()]->getWakeMicrostamp() < agent->getWakeMicrostamp()) {
|
||||
// we have to set the newer solo agent to add it to the broadcast later
|
||||
newestSoloAgents[agent->getType()] = &(*agent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this is the agent, just update last receive to now
|
||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
agent->setLastHeardMicrostamp(usecTimestampNow());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::map<char, Agent *>::iterator agentIterator = newestSoloAgents.begin();
|
||||
agentIterator != newestSoloAgents.end();
|
||||
agentIterator++) {
|
||||
for (std::map<char, Agent *>::iterator soloAgent = newestSoloAgents.begin();
|
||||
soloAgent != newestSoloAgents.end();
|
||||
soloAgent++) {
|
||||
// this is the newest alive solo agent, add them to the packet
|
||||
currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, agentIterator->second);
|
||||
currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, soloAgent->second);
|
||||
}
|
||||
|
||||
if ((packetBytesWithoutLeadingChar = (currentBufferPos - startPointer))) {
|
||||
|
|
|
@ -49,7 +49,7 @@ void *receiveAgentData(void *args) {
|
|||
avatarMixer = agentList->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
|
||||
if (avatarMixer != NULL) {
|
||||
avatarMixer->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
using namespace std;
|
||||
|
||||
const bool BALLS_ON = false;
|
||||
const bool AVATAR_GRAVITY = true;
|
||||
const bool USING_AVATAR_GRAVITY = true;
|
||||
const float GRAVITY_SCALE = 6.0f;
|
||||
const float BOUNCE = 0.3f;
|
||||
const float DECAY = 0.1;
|
||||
const float THRUST_MAG = 1200.0;
|
||||
const float YAW_MAG = 500.0;
|
||||
|
@ -32,9 +34,14 @@ const float BODY_ROLL_WHILE_TURNING = 0.1;
|
|||
const float LIN_VEL_DECAY = 5.0;
|
||||
const float MY_HAND_HOLDING_PULL = 0.2;
|
||||
const float YOUR_HAND_HOLDING_PULL = 1.0;
|
||||
const float BODY_SPRING_FORCE = 6.0f;
|
||||
|
||||
//const float BODY_SPRING_DEFAULT_TIGHTNESS = 20.0f;
|
||||
//const float BODY_SPRING_FORCE = 6.0f;
|
||||
|
||||
const float BODY_SPRING_DEFAULT_TIGHTNESS = 1500.0f;
|
||||
const float BODY_SPRING_FORCE = 300.0f;
|
||||
|
||||
const float BODY_SPRING_DECAY = 16.0f;
|
||||
const float BODY_SPRING_DEFAULT_TIGHTNESS = 10.0f;
|
||||
const float COLLISION_RADIUS_SCALAR = 1.8;
|
||||
const float COLLISION_BALL_FORCE = 1.0;
|
||||
const float COLLISION_BODY_FORCE = 6.0;
|
||||
|
@ -70,8 +77,8 @@ Avatar::Avatar(bool isMine) {
|
|||
|
||||
_orientation.setToIdentity();
|
||||
|
||||
_velocity = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_thrust = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
_thrust = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
_rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
_bodyYaw = -90.0;
|
||||
_bodyPitch = 0.0;
|
||||
|
@ -91,7 +98,7 @@ Avatar::Avatar(bool isMine) {
|
|||
_pelvisStandingHeight = 0.0f;
|
||||
_displayingHead = true;
|
||||
_TEST_bigSphereRadius = 0.4f;
|
||||
_TEST_bigSpherePosition = glm::vec3( 0.0f, _TEST_bigSphereRadius, 2.0f );
|
||||
_TEST_bigSpherePosition = glm::vec3(5.0f, _TEST_bigSphereRadius, 5.0f);
|
||||
|
||||
for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false;
|
||||
|
||||
|
@ -132,14 +139,15 @@ Avatar::Avatar(bool isMine) {
|
|||
_head.browAudioLift = 0.0;
|
||||
_head.noise = 0;
|
||||
_head.returnSpringScale = 1.0;
|
||||
_movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_movedHandOffset = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
_usingBodySprings = true;
|
||||
_renderYaw = 0.0;
|
||||
_renderPitch = 0.0;
|
||||
_sphere = NULL;
|
||||
_interactingOther = NULL;
|
||||
_handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_handHoldingPosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
_distanceToNearestAvatar = std::numeric_limits<float>::max();
|
||||
_gravity = glm::vec3(0.0f, -1.0f, 0.0f); // default
|
||||
|
||||
initializeSkeleton();
|
||||
|
||||
|
@ -255,45 +263,39 @@ void Avatar::reset() {
|
|||
_head.leanForward = _head.leanSideways = 0;
|
||||
}
|
||||
|
||||
|
||||
// this pertains to moving the head with the glasses
|
||||
void Avatar::UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity)
|
||||
// Using serial data, update avatar/render position and angles
|
||||
{
|
||||
const float PITCH_ACCEL_COUPLING = 0.5;
|
||||
const float ROLL_ACCEL_COUPLING = -1.0;
|
||||
float measured_pitch_rate = serialInterface->getRelativeValue(HEAD_PITCH_RATE);
|
||||
void Avatar::UpdateGyros(float frametime, SerialInterface* serialInterface, glm::vec3* gravity) {
|
||||
float measured_pitch_rate = 0.0f;
|
||||
float measured_roll_rate = 0.0f;
|
||||
if (serialInterface->active && USING_INVENSENSE_MPU9150) {
|
||||
measured_pitch_rate = serialInterface->getLastPitch();
|
||||
_head.yawRate = serialInterface->getLastYaw();
|
||||
measured_roll_rate = -1 * serialInterface->getLastRoll();
|
||||
} else {
|
||||
measured_pitch_rate = serialInterface->getRelativeValue(HEAD_PITCH_RATE);
|
||||
_head.yawRate = serialInterface->getRelativeValue(HEAD_YAW_RATE);
|
||||
float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) -
|
||||
ROLL_ACCEL_COUPLING * serialInterface->getRelativeValue(HEAD_ROLL_RATE);
|
||||
float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) -
|
||||
PITCH_ACCEL_COUPLING * serialInterface->getRelativeValue(HEAD_PITCH_RATE);
|
||||
float measured_roll_rate = serialInterface->getRelativeValue(HEAD_ROLL_RATE);
|
||||
|
||||
//printLog("Pitch Rate: %d ACCEL_Z: %d\n", serialInterface->getRelativeValue(PITCH_RATE),
|
||||
// serialInterface->getRelativeValue(ACCEL_Z));
|
||||
//printLog("Pitch Rate: %d ACCEL_X: %d\n", serialInterface->getRelativeValue(PITCH_RATE),
|
||||
// serialInterface->getRelativeValue(ACCEL_Z));
|
||||
//printLog("Pitch: %f\n", Pitch);
|
||||
measured_roll_rate = serialInterface->getRelativeValue(HEAD_ROLL_RATE);
|
||||
}
|
||||
|
||||
// Update avatar head position based on measured gyro rates
|
||||
const float HEAD_ROTATION_SCALE = 0.70;
|
||||
const float HEAD_ROLL_SCALE = 0.40;
|
||||
const float HEAD_LEAN_SCALE = 0.01;
|
||||
const float MAX_PITCH = 45;
|
||||
const float MIN_PITCH = -45;
|
||||
const float MAX_YAW = 85;
|
||||
const float MIN_YAW = -85;
|
||||
|
||||
if ((_headPitch < MAX_PITCH) && (_headPitch > MIN_PITCH))
|
||||
if ((_headPitch < MAX_PITCH) && (_headPitch > MIN_PITCH)) {
|
||||
addHeadPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime);
|
||||
}
|
||||
|
||||
addHeadRoll(measured_roll_rate * HEAD_ROLL_SCALE * frametime);
|
||||
|
||||
if ((_headYaw < MAX_YAW) && (_headYaw > MIN_YAW))
|
||||
if ((_headYaw < MAX_YAW) && (_headYaw > MIN_YAW)) {
|
||||
addHeadYaw(_head.yawRate * HEAD_ROTATION_SCALE * frametime);
|
||||
}
|
||||
|
||||
addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
|
||||
}
|
||||
|
||||
float Avatar::getAbsoluteHeadYaw() const {
|
||||
|
@ -336,28 +338,29 @@ void Avatar::simulate(float deltaTime) {
|
|||
//update the movement of the hand and process handshaking with other avatars...
|
||||
updateHandMovementAndTouching(deltaTime);
|
||||
|
||||
// test for avatar collision response with the big sphere
|
||||
if (usingBigSphereCollisionTest) {
|
||||
updateCollisionWithSphere( _TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime );
|
||||
}
|
||||
|
||||
// apply gravity and collision wiht the ground/floor
|
||||
if ( AVATAR_GRAVITY ) {
|
||||
if ( _position.y > _pelvisStandingHeight + 0.01 ) {
|
||||
_velocity += glm::dvec3(getGravity(getPosition())) * ( 6.0 * deltaTime );
|
||||
// apply gravity and collision with the ground/floor
|
||||
if (USING_AVATAR_GRAVITY) {
|
||||
if (_position.y > _pelvisStandingHeight + 0.01f) {
|
||||
_velocity += _gravity * (GRAVITY_SCALE * deltaTime);
|
||||
} else if (_position.y < _pelvisStandingHeight) {
|
||||
_position.y = _pelvisStandingHeight;
|
||||
_velocity.y = 0.0;
|
||||
_velocity.y = -_velocity.y * BOUNCE;
|
||||
}
|
||||
}
|
||||
|
||||
// update body springs
|
||||
updateBodySprings(deltaTime);
|
||||
|
||||
// test for avatar collision response with the big sphere
|
||||
if (usingBigSphereCollisionTest) {
|
||||
updateCollisionWithSphere(_TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime);
|
||||
}
|
||||
|
||||
// driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely)
|
||||
if (_isMine) {
|
||||
|
||||
_thrust = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
_thrust = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (_driveKeys[FWD ]) {_thrust += THRUST_MAG * deltaTime * _orientation.getFront();}
|
||||
if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG * deltaTime * _orientation.getFront();}
|
||||
|
@ -670,8 +673,8 @@ void Avatar::updateCollisionWithSphere( glm::vec3 position, float radius, float
|
|||
float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius);
|
||||
glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration;
|
||||
|
||||
_joint[b].springyVelocity += collisionForce * 30.0f * deltaTime;
|
||||
_velocity += collisionForce * 100.0f * deltaTime;
|
||||
_joint[b].springyVelocity += collisionForce * 0.0f * deltaTime;
|
||||
_velocity += collisionForce * 40.0f * deltaTime;
|
||||
_joint[b].springyPosition = position + directionVector * combinedRadius;
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +698,7 @@ void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTi
|
|||
if (glm::length(vectorBetweenBoundingSpheres) < _height * ONE_HALF + otherAvatar->_height * ONE_HALF) {
|
||||
|
||||
float bodyMomentum = 1.0f;
|
||||
glm::vec3 bodyPushForce = glm::vec3( 0.0, 0.0, 0.0 );
|
||||
glm::vec3 bodyPushForce = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// loop through the joints of each avatar to check for every possible collision
|
||||
for (int b=1; b<NUM_AVATAR_JOINTS; b++) {
|
||||
|
@ -759,8 +762,16 @@ static TextRenderer* textRenderer() {
|
|||
return renderer;
|
||||
}
|
||||
|
||||
|
||||
void Avatar::setGravity(glm::vec3 gravity) {
|
||||
_gravity = gravity;
|
||||
}
|
||||
|
||||
|
||||
void Avatar::render(bool lookingInMirror) {
|
||||
|
||||
// render a simple round on the ground projected down from the avatar's position
|
||||
renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f ), 0.1f, 0.2f );
|
||||
|
||||
/*
|
||||
// show avatar position
|
||||
|
@ -1276,7 +1287,7 @@ void Avatar::updateBodySprings( float deltaTime ) {
|
|||
_joint[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
_joint[b].springyPosition += _joint[b].springyVelocity;
|
||||
_joint[b].springyPosition += _joint[b].springyVelocity * deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1520,25 +1531,7 @@ void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity
|
|||
}
|
||||
}
|
||||
|
||||
// Find and return the gravity vector at my location
|
||||
glm::vec3 Avatar::getGravity(glm::vec3 pos) {
|
||||
//
|
||||
// For now, we'll test this with a simple global lookup, but soon we will add getting this
|
||||
// from the domain/voxelserver (or something similar)
|
||||
//
|
||||
if ((pos.x > 0.f) &&
|
||||
(pos.x < 10.f) &&
|
||||
(pos.z > 0.f) &&
|
||||
(pos.z < 10.f) &&
|
||||
(pos.y > 0.f) &&
|
||||
(pos.y < 3.f)) {
|
||||
// If above ground plane, turn gravity on
|
||||
return glm::vec3(0.f, -1.f, 0.f);
|
||||
} else {
|
||||
// If flying in space, turn gravity OFF
|
||||
return glm::vec3(0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char AVATAR_DATA_FILENAME[] = "avatar.ifd";
|
||||
|
||||
|
@ -1568,3 +1561,4 @@ void Avatar::readAvatarDataFromFile() {
|
|||
fclose(avatarFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ public:
|
|||
float getLastMeasuredHeadYaw() const {return _head.yawRate;}
|
||||
float getBodyYaw() {return _bodyYaw;};
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
void setGravity(glm::vec3 gravity);
|
||||
|
||||
bool getIsNearInteractingOther();
|
||||
|
||||
|
@ -143,9 +144,6 @@ public:
|
|||
void processTransmitterData(unsigned char * packetData, int numBytes);
|
||||
float getTransmitterHz() { return _transmitterHz; };
|
||||
|
||||
// Find out what the local gravity vector is at this location
|
||||
glm::vec3 getGravity(glm::vec3 pos);
|
||||
|
||||
void writeAvatarDataToFile();
|
||||
void readAvatarDataFromFile();
|
||||
|
||||
|
@ -251,6 +249,7 @@ private:
|
|||
bool _displayingHead; // should be false if in first-person view
|
||||
bool _returnHeadToCenter;
|
||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||
glm::vec3 _gravity;
|
||||
|
||||
// private methods...
|
||||
void initializeSkeleton();
|
||||
|
|
|
@ -11,13 +11,11 @@
|
|||
#include "AvatarRenderer.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
|
||||
AvatarRenderer::AvatarRenderer() {
|
||||
}
|
||||
|
||||
// this method renders the avatar
|
||||
void AvatarRenderer::render(Avatar *avatar, bool lookingInMirror) {
|
||||
|
||||
/*
|
||||
// show avatar position
|
||||
glColor4f( 0.5f, 0.5f, 0.5f, 0.6 );
|
||||
|
@ -28,5 +26,3 @@ void AvatarRenderer::render(Avatar *avatar, bool lookingInMirror) {
|
|||
glPopMatrix();
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
#include <string>
|
||||
#endif
|
||||
|
||||
int serialFd;
|
||||
const int MAX_BUFFER = 255;
|
||||
char serialBuffer[MAX_BUFFER];
|
||||
int serialBufferPos = 0;
|
||||
|
@ -32,6 +31,12 @@ const short NO_READ_MAXIMUM_MSECS = 3000;
|
|||
const short SAMPLES_TO_DISCARD = 100; // Throw out the first few samples
|
||||
const int GRAVITY_SAMPLES = 200; // Use the first samples to compute gravity vector
|
||||
|
||||
const bool USING_INVENSENSE_MPU9150 = 1;
|
||||
|
||||
SerialInterface::~SerialInterface() {
|
||||
close(_serialDescriptor);
|
||||
}
|
||||
|
||||
void SerialInterface::pair() {
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -41,6 +46,9 @@ void SerialInterface::pair() {
|
|||
int matchStatus;
|
||||
regex_t regex;
|
||||
|
||||
if (_failedOpenAttempts < 2) {
|
||||
// if we've already failed to open the detected interface twice then don't try again
|
||||
|
||||
// for now this only works on OS X, where the usb serial shows up as /dev/tty.usb*
|
||||
if((devDir = opendir("/dev"))) {
|
||||
while((entry = readdir(devDir))) {
|
||||
|
@ -58,26 +66,27 @@ void SerialInterface::pair() {
|
|||
}
|
||||
closedir(devDir);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Connect to the serial port
|
||||
int SerialInterface::initializePort(char* portname, int baud)
|
||||
{
|
||||
#endif
|
||||
}
|
||||
|
||||
// connect to the serial port
|
||||
void SerialInterface::initializePort(char* portname, int baud) {
|
||||
#ifdef __APPLE__
|
||||
serialFd = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
_serialDescriptor = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
printLog("Opening SerialUSB %s: ", portname);
|
||||
|
||||
if (serialFd == -1) {
|
||||
if (_serialDescriptor == -1) {
|
||||
printLog("Failed.\n");
|
||||
return -1; // Failed to open port
|
||||
_failedOpenAttempts++;
|
||||
return;
|
||||
}
|
||||
struct termios options;
|
||||
tcgetattr(serialFd,&options);
|
||||
switch(baud)
|
||||
{
|
||||
tcgetattr(_serialDescriptor, &options);
|
||||
|
||||
switch(baud) {
|
||||
case 9600: cfsetispeed(&options,B9600);
|
||||
cfsetospeed(&options,B9600);
|
||||
break;
|
||||
|
@ -94,20 +103,39 @@ int SerialInterface::initializePort(char* portname, int baud)
|
|||
cfsetospeed(&options,B9600);
|
||||
break;
|
||||
}
|
||||
|
||||
options.c_cflag |= (CLOCAL | CREAD);
|
||||
options.c_cflag &= ~PARENB;
|
||||
options.c_cflag &= ~CSTOPB;
|
||||
options.c_cflag &= ~CSIZE;
|
||||
options.c_cflag |= CS8;
|
||||
tcsetattr(serialFd,TCSANOW,&options);
|
||||
tcsetattr(_serialDescriptor, TCSANOW, &options);
|
||||
|
||||
if (USING_INVENSENSE_MPU9150) {
|
||||
// block on invensense reads until there is data to read
|
||||
int currentFlags = fcntl(_serialDescriptor, F_GETFL);
|
||||
fcntl(_serialDescriptor, F_SETFL, currentFlags & ~O_NONBLOCK);
|
||||
|
||||
// there are extra commands to send to the invensense when it fires up
|
||||
|
||||
// this takes it out of SLEEP
|
||||
write(_serialDescriptor, "WR686B01\n", 9);
|
||||
|
||||
// delay after the wakeup
|
||||
usleep(10000);
|
||||
|
||||
// this disables streaming so there's no garbage data on reads
|
||||
write(_serialDescriptor, "SD\n", 3);
|
||||
|
||||
// flush whatever was produced by the last two commands
|
||||
tcflush(_serialDescriptor, TCIOFLUSH);
|
||||
}
|
||||
|
||||
printLog("Connected.\n");
|
||||
resetSerial();
|
||||
|
||||
active = true;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reset Trailing averages to the current measurement
|
||||
|
@ -121,9 +149,7 @@ void SerialInterface::renderLevels(int width, int height) {
|
|||
int disp_x = 10;
|
||||
const int GAP = 16;
|
||||
char val[10];
|
||||
for(i = 0; i < NUM_CHANNELS; i++)
|
||||
{
|
||||
|
||||
for(i = 0; i < NUM_CHANNELS; i++) {
|
||||
// Actual value
|
||||
glLineWidth(2.0);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
|
@ -157,18 +183,44 @@ void SerialInterface::renderLevels(int width, int height) {
|
|||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void convertHexToInt(unsigned char* sourceBuffer, int& destinationInt) {
|
||||
unsigned int byte[2];
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
sscanf((char*) sourceBuffer + 2 * i, "%2x", &byte[i]);
|
||||
}
|
||||
|
||||
int16_t result = (byte[0] << 8);
|
||||
result += byte[1];
|
||||
|
||||
destinationInt = result;
|
||||
}
|
||||
void SerialInterface::readData() {
|
||||
#ifdef __APPLE__
|
||||
|
||||
int initialSamples = totalSamples;
|
||||
|
||||
if (USING_INVENSENSE_MPU9150) {
|
||||
unsigned char gyroBuffer[20];
|
||||
|
||||
// ask the invensense for raw gyro data
|
||||
write(_serialDescriptor, "RD684306\n", 9);
|
||||
read(_serialDescriptor, gyroBuffer, 20);
|
||||
|
||||
convertHexToInt(gyroBuffer + 6, _lastYaw);
|
||||
convertHexToInt(gyroBuffer + 10, _lastRoll);
|
||||
convertHexToInt(gyroBuffer + 14, _lastPitch);
|
||||
|
||||
totalSamples++;
|
||||
} else {
|
||||
// This array sets the rate of trailing averaging for each channel:
|
||||
// If the sensor rate is 100Hz, 0.001 will make the long term average a 10-second average
|
||||
const float AVG_RATE[] = {0.002, 0.002, 0.002, 0.002, 0.002, 0.002};
|
||||
char bufchar[1];
|
||||
|
||||
int initialSamples = totalSamples;
|
||||
|
||||
while (read(serialFd, &bufchar, 1) > 0) {
|
||||
while (read(_serialDescriptor, &bufchar, 1) > 0) {
|
||||
serialBuffer[serialBufferPos] = bufchar[0];
|
||||
serialBufferPos++;
|
||||
// Have we reached end of a line of input?
|
||||
|
@ -215,6 +267,7 @@ void SerialInterface::readData() {
|
|||
serialBufferPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initialSamples == totalSamples) {
|
||||
timeval now;
|
||||
|
@ -234,10 +287,12 @@ void SerialInterface::resetSerial() {
|
|||
#ifdef __APPLE__
|
||||
active = false;
|
||||
totalSamples = 0;
|
||||
gravity = glm::vec3(0,-1,0);
|
||||
|
||||
gettimeofday(&lastGoodRead, NULL);
|
||||
|
||||
if (!USING_INVENSENSE_MPU9150) {
|
||||
gravity = glm::vec3(0, -1, 0);
|
||||
|
||||
// Clear the measured and average channel data
|
||||
for (int i = 0; i < NUM_CHANNELS; i++) {
|
||||
lastMeasured[i] = 0;
|
||||
|
@ -247,6 +302,8 @@ void SerialInterface::resetSerial() {
|
|||
for (int i = 1; i < MAX_BUFFER; i++) {
|
||||
serialBuffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -32,24 +32,37 @@
|
|||
#define HEAD_YAW_RATE 0
|
||||
#define HEAD_ROLL_RATE 2
|
||||
|
||||
extern const bool USING_INVENSENSE_MPU9150;
|
||||
|
||||
class SerialInterface {
|
||||
public:
|
||||
SerialInterface() { active = false; };
|
||||
SerialInterface() : active(false),
|
||||
_failedOpenAttempts(0) {}
|
||||
~SerialInterface();
|
||||
|
||||
void pair();
|
||||
void readData();
|
||||
|
||||
int getLastYaw() const { return _lastYaw; }
|
||||
int getLastPitch() const { return _lastPitch; }
|
||||
int getLastRoll() const { return _lastRoll; }
|
||||
|
||||
int getLED() {return LED;};
|
||||
int getNumSamples() {return samplesAveraged;};
|
||||
int getValue(int num) {return lastMeasured[num];};
|
||||
int getRelativeValue(int num) {return static_cast<int>(lastMeasured[num] - trailingAverage[num]);};
|
||||
float getTrailingValue(int num) {return trailingAverage[num];};
|
||||
|
||||
void resetTrailingAverages();
|
||||
void renderLevels(int width, int height);
|
||||
bool active;
|
||||
glm::vec3 getGravity() {return gravity;};
|
||||
|
||||
private:
|
||||
int initializePort(char * portname, int baud);
|
||||
void initializePort(char* portname, int baud);
|
||||
void resetSerial();
|
||||
|
||||
int _serialDescriptor;
|
||||
int lastMeasured[NUM_CHANNELS];
|
||||
float trailingAverage[NUM_CHANNELS];
|
||||
int samplesAveraged;
|
||||
|
@ -57,6 +70,10 @@ private:
|
|||
int totalSamples;
|
||||
timeval lastGoodRead;
|
||||
glm::vec3 gravity;
|
||||
int _lastYaw;
|
||||
int _lastPitch;
|
||||
int _lastRoll;
|
||||
int _failedOpenAttempts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -237,6 +237,36 @@ void drawGroundPlaneGrid(float size)
|
|||
}
|
||||
|
||||
|
||||
|
||||
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness) {
|
||||
|
||||
glColor4f( 0.0f, 0.0f, 0.0f, darkness );
|
||||
|
||||
int num = 20;
|
||||
float y = 0.001f;
|
||||
float x2 = 0.0f;
|
||||
float z2 = radius;
|
||||
float x1;
|
||||
float z1;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
for (int i=1; i<num+1; i++) {
|
||||
x1 = x2;
|
||||
z1 = z2;
|
||||
float r = ((float)i / (float)num) * PI * 2.0;
|
||||
x2 = radius * sin(r);
|
||||
z2 = radius * cos(r);
|
||||
|
||||
glVertex3f(position.x, y, position.z );
|
||||
glVertex3f(position.x + x1, y, position.z + z1);
|
||||
glVertex3f(position.x + x2, y, position.z + z2);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void renderOrientationDirections( glm::vec3 position, Orientation orientation, float size ) {
|
||||
glm::vec3 pRight = position + orientation.getRight() * size;
|
||||
glm::vec3 pUp = position + orientation.getUp() * size;
|
||||
|
|
|
@ -44,6 +44,8 @@ double diffclock(timeval *clock1,timeval *clock2);
|
|||
|
||||
void drawGroundPlaneGrid(float size);
|
||||
|
||||
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness);
|
||||
|
||||
void renderOrientationDirections( glm::vec3 position, Orientation orientation, float size );
|
||||
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
|
||||
#include "Camera.h"
|
||||
#include "Avatar.h"
|
||||
#include "AvatarRenderer.h"
|
||||
#include "Texture.h"
|
||||
#include <AgentList.h>
|
||||
#include <AgentTypes.h>
|
||||
|
@ -91,6 +90,8 @@ using namespace std;
|
|||
void reshape(int width, int height); // will be defined below
|
||||
void loadViewFrustum(ViewFrustum& viewFrustum); // will be defined below
|
||||
|
||||
glm::vec3 getGravity(glm::vec3 pos); //get the local gravity vector at this location in the universe
|
||||
|
||||
QApplication* app;
|
||||
|
||||
bool enableNetworkThread = true;
|
||||
|
@ -120,9 +121,6 @@ Avatar myAvatar(true); // The rendered avatar of oneself
|
|||
Camera myCamera; // My view onto the world (sometimes on myself :)
|
||||
Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
||||
|
||||
|
||||
AvatarRenderer avatarRenderer;
|
||||
|
||||
// Starfield information
|
||||
char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
|
||||
char starCacheFile[] = "cachedStars.txt";
|
||||
|
@ -208,8 +206,7 @@ bool justStarted = true;
|
|||
|
||||
|
||||
// Every second, check the frame rates and other stuff
|
||||
void Timer(int extra)
|
||||
{
|
||||
void Timer(int extra) {
|
||||
gettimeofday(&timerEnd, NULL);
|
||||
FPS = (float)frameCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
|
||||
packetsPerSecond = (float)packetCount / ((float)diffclock(&timerStart, &timerEnd) / 1000.f);
|
||||
|
@ -227,8 +224,7 @@ void Timer(int extra)
|
|||
}
|
||||
}
|
||||
|
||||
void displayStats(void)
|
||||
{
|
||||
void displayStats(void) {
|
||||
int statsVerticalOffset = 50;
|
||||
if (::menuOn == 0) {
|
||||
statsVerticalOffset = 8;
|
||||
|
@ -269,6 +265,7 @@ void displayStats(void)
|
|||
|
||||
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
char avatarMixerStats[200];
|
||||
|
||||
if (avatarMixer) {
|
||||
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
|
@ -276,6 +273,7 @@ void displayStats(void)
|
|||
} else {
|
||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||
}
|
||||
|
||||
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
||||
|
||||
if (::perfStatsOn) {
|
||||
|
@ -293,8 +291,7 @@ void displayStats(void)
|
|||
}
|
||||
}
|
||||
|
||||
void initDisplay(void)
|
||||
{
|
||||
void initDisplay(void) {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
@ -306,8 +303,7 @@ void initDisplay(void)
|
|||
if (fullscreen) glutFullScreen();
|
||||
}
|
||||
|
||||
void init(void)
|
||||
{
|
||||
void init(void) {
|
||||
voxels.init();
|
||||
voxels.setViewerAvatar(&myAvatar);
|
||||
voxels.setCamera(&myCamera);
|
||||
|
@ -360,8 +356,7 @@ void terminate () {
|
|||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void reset_sensors()
|
||||
{
|
||||
void reset_sensors() {
|
||||
|
||||
myAvatar.setPosition(start_location);
|
||||
headMouseX = WIDTH/2;
|
||||
|
@ -377,16 +372,13 @@ void reset_sensors()
|
|||
//
|
||||
// Using gyro data, update both view frustum and avatar head position
|
||||
//
|
||||
void updateAvatar(float frametime)
|
||||
{
|
||||
void updateAvatar(float frametime) {
|
||||
float gyroPitchRate = serialPort.getRelativeValue(HEAD_PITCH_RATE);
|
||||
float gyroYawRate = serialPort.getRelativeValue(HEAD_YAW_RATE );
|
||||
|
||||
myAvatar.UpdateGyros(frametime, &serialPort, &gravity);
|
||||
|
||||
//
|
||||
// Update gyro-based mouse (X,Y on screen)
|
||||
//
|
||||
const float MIN_MOUSE_RATE = 30.0;
|
||||
const float MOUSE_SENSITIVITY = 0.1f;
|
||||
if (powf(gyroYawRate*gyroYawRate +
|
||||
|
@ -720,7 +712,6 @@ void displaySide(Camera& whichCamera) {
|
|||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||
avatar->render(0);
|
||||
//avatarRenderer.render(avatar, 0); // this will replace the above call
|
||||
}
|
||||
}
|
||||
agentList->unlock();
|
||||
|
@ -733,7 +724,6 @@ void displaySide(Camera& whichCamera) {
|
|||
|
||||
//Render my own avatar
|
||||
myAvatar.render(::lookingInMirror);
|
||||
//avatarRenderer.render(&myAvatar, lookingInMirror); // this will replace the above call
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
@ -1017,7 +1007,7 @@ void display(void)
|
|||
float firstPersonTightness = 100.0f;
|
||||
|
||||
float thirdPersonPitch = 0.0f;
|
||||
float thirdPersonUpShift = -0.1f;
|
||||
float thirdPersonUpShift = -0.2f;
|
||||
float thirdPersonDistance = 1.2f;
|
||||
float thirdPersonTightness = 8.0f;
|
||||
|
||||
|
@ -1692,6 +1682,10 @@ void idle(void) {
|
|||
handControl.stop();
|
||||
}
|
||||
|
||||
if (serialPort.active && USING_INVENSENSE_MPU9150) {
|
||||
serialPort.readData();
|
||||
}
|
||||
|
||||
// Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents
|
||||
updateAvatar(deltaTime);
|
||||
|
||||
|
@ -1711,6 +1705,7 @@ void idle(void) {
|
|||
}
|
||||
agentList->unlock();
|
||||
|
||||
myAvatar.setGravity(getGravity(myAvatar.getPosition()));
|
||||
myAvatar.simulate(deltaTime);
|
||||
|
||||
glutPostRedisplay();
|
||||
|
@ -1718,7 +1713,7 @@ void idle(void) {
|
|||
}
|
||||
|
||||
// Read serial data
|
||||
if (serialPort.active) {
|
||||
if (serialPort.active && !USING_INVENSENSE_MPU9150) {
|
||||
serialPort.readData();
|
||||
}
|
||||
}
|
||||
|
@ -1773,6 +1768,30 @@ void reshape(int width, int height) {
|
|||
glLoadIdentity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Find and return the gravity vector at this location
|
||||
glm::vec3 getGravity(glm::vec3 pos) {
|
||||
//
|
||||
// For now, we'll test this with a simple global lookup, but soon we will add getting this
|
||||
// from the domain/voxelserver (or something similar)
|
||||
//
|
||||
if ((pos.x > 0.f) &&
|
||||
(pos.x < 10.f) &&
|
||||
(pos.z > 0.f) &&
|
||||
(pos.z < 10.f) &&
|
||||
(pos.y > 0.f) &&
|
||||
(pos.y < 3.f)) {
|
||||
// If above ground plane, turn gravity on
|
||||
return glm::vec3(0.f, -1.f, 0.f);
|
||||
} else {
|
||||
// If flying in space, turn gravity OFF
|
||||
return glm::vec3(0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
void mouseFunc(int button, int state, int x, int y) {
|
||||
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) {
|
||||
if (state == GLUT_DOWN && !menu.mouseClick(x, y)) {
|
||||
|
|
|
@ -52,8 +52,8 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent
|
|||
type = agentType;
|
||||
agentId = thisAgentId;
|
||||
|
||||
firstRecvTimeUsecs = usecTimestampNow();
|
||||
lastRecvTimeUsecs = usecTimestampNow();
|
||||
_wakeMicrostamp = usecTimestampNow();
|
||||
_lastHeardMicrostamp = usecTimestampNow();
|
||||
|
||||
activeSocket = NULL;
|
||||
linkedData = NULL;
|
||||
|
@ -87,8 +87,8 @@ Agent::Agent(const Agent &otherAgent) {
|
|||
activeSocket = NULL;
|
||||
}
|
||||
|
||||
firstRecvTimeUsecs = otherAgent.firstRecvTimeUsecs;
|
||||
lastRecvTimeUsecs = otherAgent.lastRecvTimeUsecs;
|
||||
_wakeMicrostamp = otherAgent._wakeMicrostamp;
|
||||
_lastHeardMicrostamp = otherAgent._lastHeardMicrostamp;
|
||||
type = otherAgent.type;
|
||||
|
||||
if (otherAgent.linkedData != NULL) {
|
||||
|
@ -120,8 +120,8 @@ void Agent::swap(Agent &first, Agent &second) {
|
|||
swap(first.type, second.type);
|
||||
swap(first.linkedData, second.linkedData);
|
||||
swap(first.agentId, second.agentId);
|
||||
swap(first.firstRecvTimeUsecs, second.firstRecvTimeUsecs);
|
||||
swap(first.lastRecvTimeUsecs, second.lastRecvTimeUsecs);
|
||||
swap(first._wakeMicrostamp, second._wakeMicrostamp);
|
||||
swap(first._lastHeardMicrostamp, second._lastHeardMicrostamp);
|
||||
swap(first._bytesReceivedMovingAverage, second._bytesReceivedMovingAverage);
|
||||
}
|
||||
|
||||
|
@ -178,22 +178,6 @@ void Agent::setAgentId(uint16_t thisAgentId) {
|
|||
agentId = thisAgentId;
|
||||
}
|
||||
|
||||
double Agent::getFirstRecvTimeUsecs() {
|
||||
return firstRecvTimeUsecs;
|
||||
}
|
||||
|
||||
void Agent::setFirstRecvTimeUsecs(double newTimeUsecs) {
|
||||
firstRecvTimeUsecs = newTimeUsecs;
|
||||
}
|
||||
|
||||
double Agent::getLastRecvTimeUsecs() {
|
||||
return lastRecvTimeUsecs;
|
||||
}
|
||||
|
||||
void Agent::setLastRecvTimeUsecs(double newTimeUsecs) {
|
||||
lastRecvTimeUsecs = newTimeUsecs;
|
||||
}
|
||||
|
||||
sockaddr* Agent::getPublicSocket() {
|
||||
return publicSocket;
|
||||
}
|
||||
|
|
|
@ -38,11 +38,11 @@ public:
|
|||
uint16_t getAgentId();
|
||||
void setAgentId(uint16_t thisAgentId);
|
||||
|
||||
double getFirstRecvTimeUsecs();
|
||||
void setFirstRecvTimeUsecs(double newTimeUsecs);
|
||||
double getWakeMicrostamp() const { return _wakeMicrostamp; }
|
||||
void setWakeMicrostamp(double wakeMicrostamp) { _wakeMicrostamp = wakeMicrostamp; }
|
||||
|
||||
double getLastRecvTimeUsecs();
|
||||
void setLastRecvTimeUsecs(double newTimeUsecs);
|
||||
double getLastHeardMicrostamp() const { return _lastHeardMicrostamp; }
|
||||
void setLastHeardMicrostamp(double lastHeardMicrostamp) { _lastHeardMicrostamp = lastHeardMicrostamp; }
|
||||
|
||||
sockaddr* getPublicSocket();
|
||||
void setPublicSocket(sockaddr *newSocket);
|
||||
|
@ -70,8 +70,8 @@ private:
|
|||
sockaddr *publicSocket, *localSocket, *activeSocket;
|
||||
char type;
|
||||
uint16_t agentId;
|
||||
double firstRecvTimeUsecs;
|
||||
double lastRecvTimeUsecs;
|
||||
double _wakeMicrostamp;
|
||||
double _lastHeardMicrostamp;
|
||||
SimpleMovingAverage* _bytesReceivedMovingAverage;
|
||||
AgentData* linkedData;
|
||||
bool _isAlive;
|
||||
|
|
|
@ -64,8 +64,7 @@ AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) :
|
|||
agentSocket(newSocketListenPort),
|
||||
ownerType(newOwnerType),
|
||||
socketListenPort(newSocketListenPort),
|
||||
lastAgentId(0)
|
||||
{
|
||||
lastAgentId(0) {
|
||||
pthread_mutex_init(&mutex, 0);
|
||||
}
|
||||
|
||||
|
@ -114,7 +113,7 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac
|
|||
Agent* bulkSendAgent = agentWithAddress(senderAddress);
|
||||
|
||||
if (bulkSendAgent) {
|
||||
bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
bulkSendAgent->setLastHeardMicrostamp(usecTimestampNow());
|
||||
bulkSendAgent->recordBytesReceived(numTotalBytes);
|
||||
}
|
||||
|
||||
|
@ -161,7 +160,7 @@ int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packe
|
|||
}
|
||||
|
||||
int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes) {
|
||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
agent->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
||||
if (agent->getActiveSocket() != NULL) {
|
||||
agent->recordBytesReceived(dataBytes);
|
||||
|
@ -273,7 +272,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
|||
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());
|
||||
agent->setLastHeardMicrostamp(usecTimestampNow());
|
||||
}
|
||||
|
||||
// we had this agent already, do nothing for now
|
||||
|
@ -383,7 +382,7 @@ void *removeSilentAgents(void *args) {
|
|||
|
||||
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); ++agent) {
|
||||
|
||||
if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS
|
||||
if ((checkTimeUSecs - agent->getLastHeardMicrostamp()) > AGENT_SILENCE_THRESHOLD_USECS
|
||||
&& agent->getType() != AGENT_TYPE_VOXEL) {
|
||||
|
||||
printLog("Killing agent - ");
|
||||
|
@ -418,13 +417,6 @@ void *checkInWithDomainServer(void *args) {
|
|||
|
||||
const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
||||
|
||||
AgentList* parentAgentList = (AgentList*) args;
|
||||
|
||||
timeval lastSend;
|
||||
unsigned char output[7];
|
||||
|
||||
in_addr_t localAddress = getLocalAddress();
|
||||
|
||||
// Lookup the IP address of the domain server if we need to
|
||||
if (atoi(DOMAIN_IP) == 0) {
|
||||
struct hostent* pHostInfo;
|
||||
|
@ -439,14 +431,23 @@ void *checkInWithDomainServer(void *args) {
|
|||
}
|
||||
} else printLog("Using static domainserver IP: %s\n", DOMAIN_IP);
|
||||
|
||||
AgentList* parentAgentList = (AgentList*) args;
|
||||
|
||||
timeval lastSend;
|
||||
in_addr_t localAddress = getLocalAddress();
|
||||
unsigned char packet[8];
|
||||
|
||||
packet[0] = PACKET_HEADER_DOMAIN_RFD;
|
||||
packet[1] = parentAgentList->getOwnerType();
|
||||
|
||||
while (!domainServerCheckinStopFlag) {
|
||||
gettimeofday(&lastSend, NULL);
|
||||
|
||||
output[0] = parentAgentList->getOwnerType();
|
||||
packSocket(output + 1, localAddress, htons(parentAgentList->getSocketListenPort()));
|
||||
packSocket(packet + 2, localAddress, htons(parentAgentList->getSocketListenPort()));
|
||||
|
||||
parentAgentList->getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
|
||||
parentAgentList->getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, packet, sizeof(packet));
|
||||
|
||||
packet[0] = PACKET_HEADER_DOMAIN_LIST_REQUEST;
|
||||
|
||||
double usecToSleep = DOMAIN_SERVER_CHECK_IN_USECS - (usecTimestampNow() - usecTimestamp(&lastSend));
|
||||
|
||||
|
@ -481,7 +482,8 @@ AgentList::iterator AgentList::begin() const {
|
|||
}
|
||||
}
|
||||
|
||||
return AgentListIterator(this, 0);
|
||||
// there's no alive agent to start from - return the end
|
||||
return end();
|
||||
}
|
||||
|
||||
AgentList::iterator AgentList::end() const {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
//
|
||||
// PacketHeaders.h
|
||||
// hifi
|
||||
|
@ -23,5 +24,7 @@ const char PACKET_HEADER_ERASE_VOXEL = 'E';
|
|||
const char PACKET_HEADER_VOXEL_DATA = 'V';
|
||||
const char PACKET_HEADER_BULK_AVATAR_DATA = 'X';
|
||||
const char PACKET_HEADER_TRANSMITTER_DATA = 't';
|
||||
const char PACKET_HEADER_DOMAIN_LIST_REQUEST = 'L';
|
||||
const char PACKET_HEADER_DOMAIN_RFD = 'C';
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// Simple axis aligned box class.
|
||||
//
|
||||
|
||||
#include "SharedUtil.h"
|
||||
|
||||
#include "AABox.h"
|
||||
|
||||
|
||||
|
@ -68,3 +70,50 @@ glm::vec3 AABox::getVertexN(const glm::vec3 &normal) const {
|
|||
|
||||
return(res);
|
||||
}
|
||||
|
||||
// determines whether a value is within the extents
|
||||
static bool isWithin(float value, float corner, float size) {
|
||||
return value >= corner && value <= corner + size;
|
||||
}
|
||||
|
||||
bool AABox::contains(const glm::vec3& point) const {
|
||||
return isWithin(point.x, _corner.x, _size.x) &&
|
||||
isWithin(point.y, _corner.y, _size.y) &&
|
||||
isWithin(point.z, _corner.z, _size.z);
|
||||
}
|
||||
|
||||
// finds the intersection between a ray and the facing plane on one axis
|
||||
static bool findIntersection(float origin, float direction, float corner, float size, float& distance) {
|
||||
if (direction > EPSILON) {
|
||||
distance = (corner - origin) / direction;
|
||||
return true;
|
||||
|
||||
} else if (direction < -EPSILON) {
|
||||
distance = (corner + size - origin) / direction;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
// handle the trivial case where the box contains the origin
|
||||
if (contains(origin)) {
|
||||
distance = 0;
|
||||
return true;
|
||||
}
|
||||
// check each axis
|
||||
float axisDistance;
|
||||
if (findIntersection(origin.x, direction.x, _corner.x, _size.x, axisDistance) && axisDistance >= 0 &&
|
||||
isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) &&
|
||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z) ||
|
||||
findIntersection(origin.y, direction.y, _corner.y, _size.y, axisDistance) && axisDistance >= 0 &&
|
||||
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x) &&
|
||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z) ||
|
||||
findIntersection(origin.z, direction.z, _corner.z, _size.z, axisDistance) && axisDistance >= 0 &&
|
||||
isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) &&
|
||||
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x)) {
|
||||
distance = axisDistance;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ public:
|
|||
const glm::vec3& getSize() const { return _size; };
|
||||
const glm::vec3& getCenter() const { return _center; };
|
||||
|
||||
bool contains(const glm::vec3& point) const;
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
private:
|
||||
glm::vec3 _corner;
|
||||
glm::vec3 _center;
|
||||
|
|
|
@ -238,3 +238,7 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo) const {
|
|||
|
||||
|
||||
|
||||
void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const {
|
||||
origin = _nearTopLeft + x*(_nearTopRight - _nearTopLeft) + y*(_nearBottomLeft - _nearTopLeft);
|
||||
direction = glm::normalize(origin - _position);
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ public:
|
|||
// some frustum comparisons
|
||||
bool matches(const ViewFrustum& compareTo) const;
|
||||
bool matches(const ViewFrustum* compareTo) const { return matches(*compareTo); };
|
||||
|
||||
void computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -546,7 +546,41 @@ int VoxelTree::searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const
|
|||
return levelReached;
|
||||
}
|
||||
|
||||
// combines the ray cast arguments into a single object
|
||||
class RayArgs {
|
||||
public:
|
||||
glm::vec3 origin;
|
||||
glm::vec3 direction;
|
||||
VoxelNode*& node;
|
||||
float& distance;
|
||||
bool found;
|
||||
};
|
||||
|
||||
bool findRayOperation(VoxelNode* node, void* extraData) {
|
||||
RayArgs* args = static_cast<RayArgs*>(extraData);
|
||||
AABox box;
|
||||
node->getAABox(box);
|
||||
float distance;
|
||||
if (!box.findRayIntersection(args->origin, args->direction, distance)) {
|
||||
return false;
|
||||
}
|
||||
if (!node->isLeaf()) {
|
||||
return true; // recurse on children
|
||||
}
|
||||
if (!args->found || distance < args->distance) {
|
||||
args->node = node;
|
||||
args->distance = distance;
|
||||
args->found = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VoxelTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance)
|
||||
{
|
||||
RayArgs args = { origin / (float)TREE_SCALE, direction, node, distance };
|
||||
recurseTreeWithOperation(findRayOperation, &args);
|
||||
return args.found;
|
||||
}
|
||||
|
||||
int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
|
||||
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag) {
|
||||
|
|
|
@ -62,6 +62,8 @@ public:
|
|||
void clearDirtyBit() { _isDirty = false; };
|
||||
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance);
|
||||
|
||||
// Note: this assumes the fileFormat is the HIO individual voxels code files
|
||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||
|
||||
|
|
Loading…
Reference in a new issue