mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 03:03:35 +02:00
Merge branch 'master' of git://github.com/worklist/hifi into 19188
This commit is contained in:
commit
723d49d78c
38 changed files with 2104 additions and 1086 deletions
|
@ -5,6 +5,7 @@ project(hifi)
|
|||
add_subdirectory(avatar-mixer)
|
||||
add_subdirectory(audio-mixer)
|
||||
add_subdirectory(domain-server)
|
||||
add_subdirectory(eve)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(injector)
|
||||
add_subdirectory(space-server)
|
||||
|
|
|
@ -135,7 +135,11 @@ int main(int argc, const char * argv[])
|
|||
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
||||
if (memchr(SOLO_AGENT_TYPES_STRING, agent->getType(), 1) == NULL) {
|
||||
// this is an agent of which there can be multiple, just add them to the packet
|
||||
currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent));
|
||||
// don't send avatar agents to other avatars, that will come from avatar mixer
|
||||
if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) {
|
||||
currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent));
|
||||
}
|
||||
|
||||
} else {
|
||||
// solo agent, we need to only send newest
|
||||
if (newestSoloAgents[agent->getType()] == NULL ||
|
||||
|
|
20
eve/CMakeLists.txt
Normal file
20
eve/CMakeLists.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
|
||||
set(TARGET_NAME eve)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# link the required hifi libraries
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
128
eve/src/main.cpp
Normal file
128
eve/src/main.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
//
|
||||
// main.cpp
|
||||
// eve
|
||||
//
|
||||
// Created by Stephen Birarda on 4/22/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <AgentTypes.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <AgentList.h>
|
||||
#include <AvatarData.h>
|
||||
|
||||
const int EVE_AGENT_LIST_PORT = 55441;
|
||||
const float DATA_SEND_INTERVAL_MSECS = 10;
|
||||
|
||||
bool stopReceiveAgentDataThread;
|
||||
|
||||
void *receiveAgentData(void *args)
|
||||
{
|
||||
sockaddr senderAddress;
|
||||
ssize_t bytesReceived;
|
||||
unsigned char incomingPacket[MAX_PACKET_SIZE];
|
||||
|
||||
AgentList *agentList = AgentList::getInstance();
|
||||
Agent *avatarMixer = NULL;
|
||||
|
||||
while (!::stopReceiveAgentDataThread) {
|
||||
if (agentList->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||
switch (incomingPacket[0]) {
|
||||
case PACKET_HEADER_BULK_AVATAR_DATA:
|
||||
// this is the positional data for other agents
|
||||
// eve doesn't care about this for now, so let's just update the receive time for the
|
||||
// avatar mixer - this makes sure it won't be killed during silent agent removal
|
||||
avatarMixer = agentList->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
|
||||
if (avatarMixer != NULL) {
|
||||
avatarMixer->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// have the agentList handle list of agents from DS, replies from other agents, etc.
|
||||
agentList->processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// create an AgentList instance to handle communication with other agents
|
||||
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT);
|
||||
|
||||
// start telling the domain server that we are alive
|
||||
agentList->startDomainServerCheckInThread();
|
||||
|
||||
// start the agent list thread that will kill off agents when they stop talking
|
||||
agentList->startSilentAgentRemovalThread();
|
||||
|
||||
// start the ping thread that hole punches to create an active connection to other agents
|
||||
agentList->startPingUnknownAgentsThread();
|
||||
|
||||
pthread_t receiveAgentDataThread;
|
||||
pthread_create(&receiveAgentDataThread, NULL, receiveAgentData, NULL);
|
||||
|
||||
// create an AvatarData object, "eve"
|
||||
AvatarData eve = AvatarData();
|
||||
|
||||
// move eve away from the origin
|
||||
eve.setBodyPosition(glm::vec3(3, 0, -3));
|
||||
|
||||
// turn her back towards the origin
|
||||
eve.setBodyYaw(-45);
|
||||
|
||||
// put her hand out so somebody can shake it
|
||||
eve.setHandPosition(glm::vec3(eve.getBodyPosition()[0] - 0.2,
|
||||
0.25,
|
||||
eve.getBodyPosition()[2] + 0.1));
|
||||
|
||||
unsigned char broadcastPacket[MAX_PACKET_SIZE];
|
||||
broadcastPacket[0] = PACKET_HEADER_HEAD_DATA;
|
||||
|
||||
int numBytesToSend = 0;
|
||||
|
||||
timeval thisSend;
|
||||
double numMicrosecondsSleep = 0;
|
||||
|
||||
while (true) {
|
||||
// update the thisSend timeval to the current time
|
||||
gettimeofday(&thisSend, NULL);
|
||||
|
||||
// find the current avatar mixer
|
||||
Agent *avatarMixer = agentList->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
|
||||
// make sure we actually have an avatar mixer with an active socket
|
||||
if (avatarMixer != NULL && avatarMixer->getActiveSocket() != NULL) {
|
||||
// use the getBroadcastData method in the AvatarData class to populate the broadcastPacket buffer
|
||||
numBytesToSend = eve.getBroadcastData((broadcastPacket + 1));
|
||||
|
||||
|
||||
// use the UDPSocket instance attached to our agent list to send avatar data to mixer
|
||||
agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, numBytesToSend);
|
||||
}
|
||||
|
||||
// sleep for the correct amount of time to have data send be consistently timed
|
||||
if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
|
||||
usleep(numMicrosecondsSleep);
|
||||
}
|
||||
}
|
||||
|
||||
// stop the receive agent data thread
|
||||
stopReceiveAgentDataThread = true;
|
||||
pthread_join(receiveAgentDataThread, NULL);
|
||||
|
||||
// stop the agent list's threads
|
||||
agentList->stopDomainServerCheckInThread();
|
||||
agentList->stopPingUnknownAgentsThread();
|
||||
agentList->stopSilentAgentRemovalThread();
|
||||
}
|
||||
|
||||
|
|
@ -8,7 +8,6 @@ project(${TARGET_NAME})
|
|||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
set(GLM_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external)
|
||||
set(LODEPNG_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LodePNG)
|
||||
set(PORTAUDIO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,6 +22,13 @@
|
|||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp> //looks like we might not need this
|
||||
|
||||
const bool AVATAR_GRAVITY = true;
|
||||
const float DECAY = 0.1;
|
||||
const float THRUST_MAG = 10.0;
|
||||
const float YAW_MAG = 300.0;
|
||||
const float TEST_YAW_DECAY = 5.0;
|
||||
const float LIN_VEL_DECAY = 5.0;
|
||||
|
||||
enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
||||
|
||||
#define FWD 0
|
||||
|
@ -34,17 +41,17 @@ enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
|||
#define ROT_RIGHT 7
|
||||
#define MAX_DRIVE_KEYS 8
|
||||
|
||||
#define NUM_OTHER_AVATARS 5 // temporary - for testing purposes!
|
||||
#define MAX_OTHER_AVATARS 50 // temporary - for testing purposes!
|
||||
|
||||
enum AvatarMode
|
||||
{
|
||||
AVATAR_MODE_STANDING = 0,
|
||||
AVATAR_MODE_WALKING,
|
||||
AVATAR_MODE_COMMUNICATING,
|
||||
AVATAR_MODE_INTERACTING,
|
||||
NUM_AVATAR_MODES
|
||||
};
|
||||
|
||||
enum AvatarBones
|
||||
enum AvatarBoneID
|
||||
{
|
||||
AVATAR_BONE_NULL = -1,
|
||||
AVATAR_BONE_PELVIS_SPINE, // connects pelvis joint with torso joint (not supposed to be rotated)
|
||||
|
@ -76,29 +83,63 @@ enum AvatarBones
|
|||
|
||||
struct AvatarBone
|
||||
{
|
||||
AvatarBones parent; // which bone is this bone connected to?
|
||||
glm::vec3 position; // the position at the "end" of the bone
|
||||
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
||||
glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position)
|
||||
glm::dvec3 springyVelocity; // used for special effects ( the velocity of the springy position)
|
||||
float springBodyTightness; // how tightly the springy position tries to stay on the position
|
||||
glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation)
|
||||
float yaw; // the yaw Euler angle of the bone rotation off the parent
|
||||
float pitch; // the pitch Euler angle of the bone rotation off the parent
|
||||
float roll; // the roll Euler angle of the bone rotation off the parent
|
||||
Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll
|
||||
float length; // the length of the bone
|
||||
float radius; // used for detecting collisions for certain physical effects
|
||||
AvatarBoneID parent; // which bone is this bone connected to?
|
||||
glm::vec3 position; // the position at the "end" of the bone
|
||||
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
||||
glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position)
|
||||
glm::dvec3 springyVelocity; // used for special effects ( the velocity of the springy position)
|
||||
float springBodyTightness; // how tightly the springy position tries to stay on the position
|
||||
glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation)
|
||||
float yaw; // the yaw Euler angle of the bone rotation off the parent
|
||||
float pitch; // the pitch Euler angle of the bone rotation off the parent
|
||||
float roll; // the roll Euler angle of the bone rotation off the parent
|
||||
Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll
|
||||
float length; // the length of the bone
|
||||
float radius; // used for detecting collisions for certain physical effects
|
||||
};
|
||||
|
||||
struct Avatar
|
||||
struct AvatarHead
|
||||
{
|
||||
glm::dvec3 velocity;
|
||||
glm::vec3 thrust;
|
||||
float maxArmLength;
|
||||
Orientation orientation;
|
||||
float pitch;
|
||||
float yaw;
|
||||
float roll;
|
||||
float pitchRate;
|
||||
float yawRate;
|
||||
float rollRate;
|
||||
float noise;
|
||||
float eyeballPitch[2];
|
||||
float eyeballYaw [2];
|
||||
float eyebrowPitch[2];
|
||||
float eyebrowRoll [2];
|
||||
float eyeballScaleX;
|
||||
float eyeballScaleY;
|
||||
float eyeballScaleZ;
|
||||
float interPupilDistance;
|
||||
float interBrowDistance;
|
||||
float nominalPupilSize;
|
||||
float pupilSize;
|
||||
float mouthPitch;
|
||||
float mouthYaw;
|
||||
float mouthWidth;
|
||||
float mouthHeight;
|
||||
float leanForward;
|
||||
float leanSideways;
|
||||
float pitchTarget;
|
||||
float yawTarget;
|
||||
float noiseEnvelope;
|
||||
float pupilConverge;
|
||||
float scale;
|
||||
int eyeContact;
|
||||
float browAudioLift;
|
||||
eyeContactTargets eyeContactTarget;
|
||||
|
||||
// Sound loudness information
|
||||
float loudness, lastLoudness;
|
||||
float averageLoudness;
|
||||
float audioAttack;
|
||||
};
|
||||
|
||||
|
||||
class Head : public AvatarData {
|
||||
public:
|
||||
Head(bool isMine);
|
||||
|
@ -106,56 +147,52 @@ class Head : public AvatarData {
|
|||
Head(const Head &otherHead);
|
||||
Head* clone() const;
|
||||
|
||||
void reset();
|
||||
void UpdateGyros(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity);
|
||||
void setNoise (float mag) { _noise = mag; }
|
||||
void setPitch(float p) {_headPitch = p; }
|
||||
void setYaw(float y) {_headYaw = y; }
|
||||
void setRoll(float r) {_headRoll = r; };
|
||||
void setScale(float s) {_scale = s; };
|
||||
void setRenderYaw(float y) {_renderYaw = y;}
|
||||
void setRenderPitch(float p) {_renderPitch = p;}
|
||||
void reset();
|
||||
void UpdateGyros(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity);
|
||||
void setNoise (float mag) { _head.noise = mag; }
|
||||
void setPitch(float p) {_head.pitch = p; }
|
||||
void setYaw(float y) {_head.yaw = y; }
|
||||
void setRoll(float r) {_head.roll = r; };
|
||||
void setScale(float s) {_head.scale = s; };
|
||||
void setRenderYaw(float y) {_renderYaw = y;}
|
||||
void setRenderPitch(float p) {_renderPitch = p;}
|
||||
float getRenderYaw() {return _renderYaw;}
|
||||
float getRenderPitch() {return _renderPitch;}
|
||||
void setLeanForward(float dist);
|
||||
void setLeanSideways(float dist);
|
||||
void addPitch(float p) {_headPitch -= p; }
|
||||
void addYaw(float y){_headYaw -= y; }
|
||||
void addRoll(float r){_headRoll += r; }
|
||||
void addLean(float x, float z);
|
||||
float getPitch() {return _headPitch;}
|
||||
float getRoll() {return _headRoll;}
|
||||
float getYaw() {return _headYaw;}
|
||||
float getLastMeasuredYaw() {return _headYawRate;}
|
||||
|
||||
void setLeanForward(float dist);
|
||||
void setLeanSideways(float dist);
|
||||
void addPitch(float p) {_head.pitch -= p; }
|
||||
void addYaw(float y){_head.yaw -= y; }
|
||||
void addRoll(float r){_head.roll += r; }
|
||||
void addLean(float x, float z);
|
||||
float getPitch() {return _head.pitch;}
|
||||
float getRoll() {return _head.roll;}
|
||||
float getYaw() {return _head.yaw;}
|
||||
float getLastMeasuredYaw() {return _head.yawRate;}
|
||||
float getBodyYaw() {return _bodyYaw;};
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
|
||||
glm::vec3 getHeadLookatDirection();
|
||||
glm::vec3 getHeadLookatDirectionUp();
|
||||
glm::vec3 getHeadLookatDirectionRight();
|
||||
glm::vec3 getHeadPosition();
|
||||
glm::vec3 getBonePosition( AvatarBones b );
|
||||
glm::vec3 getBonePosition( AvatarBoneID b );
|
||||
|
||||
AvatarMode getMode();
|
||||
|
||||
void setTriggeringAction( bool trigger );
|
||||
|
||||
void setMousePressed( bool pressed );
|
||||
void render(int faceToFace);
|
||||
|
||||
void renderBody();
|
||||
void renderHead( int faceToFace);
|
||||
//void renderOrientationDirections( glm::vec3 position, Orientation orientation, float size );
|
||||
|
||||
void simulate(float);
|
||||
|
||||
void setHandMovement( glm::vec3 movement );
|
||||
void startHandMovement();
|
||||
void stopHandMovement();
|
||||
void setHandMovementValues( glm::vec3 movement );
|
||||
void updateHandMovement();
|
||||
|
||||
float getLoudness() {return _loudness;};
|
||||
float getAverageLoudness() {return _averageLoudness;};
|
||||
void setAverageLoudness(float al) {_averageLoudness = al;};
|
||||
void setLoudness(float l) {_loudness = l;};
|
||||
float getLoudness() {return _head.loudness;};
|
||||
float getAverageLoudness() {return _head.averageLoudness;};
|
||||
void setAverageLoudness(float al) {_head.averageLoudness = al;};
|
||||
void setLoudness(float l) {_head.loudness = l;};
|
||||
|
||||
void SetNewHeadTarget(float, float);
|
||||
|
||||
|
@ -164,9 +201,9 @@ class Head : public AvatarData {
|
|||
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
||||
|
||||
// Set/Get update the thrust that will move the avatar around
|
||||
void setThrust(glm::vec3 newThrust) { _avatar.thrust = newThrust; };
|
||||
void addThrust(glm::vec3 newThrust) { _avatar.thrust += newThrust; };
|
||||
glm::vec3 getThrust() { return _avatar.thrust; };
|
||||
void setThrust(glm::vec3 newThrust) { _thrust = newThrust; };
|
||||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||
glm::vec3 getThrust() { return _thrust; };
|
||||
|
||||
//
|
||||
// Related to getting transmitter UDP data used to animate the avatar hand
|
||||
|
@ -176,67 +213,30 @@ class Head : public AvatarData {
|
|||
float getTransmitterHz() { return _transmitterHz; };
|
||||
|
||||
private:
|
||||
bool _isMine;
|
||||
float _noise;
|
||||
float _headPitch;
|
||||
float _headYaw;
|
||||
float _headRoll;
|
||||
float _headPitchRate;
|
||||
float _headYawRate;
|
||||
float _headRollRate;
|
||||
float _eyeballPitch[2];
|
||||
float _eyeballYaw[2];
|
||||
float _eyebrowPitch[2];
|
||||
float _eyebrowRoll[2];
|
||||
float _eyeballScaleX, _eyeballScaleY, _eyeballScaleZ;
|
||||
float _interPupilDistance;
|
||||
float _interBrowDistance;
|
||||
float _nominalPupilSize;
|
||||
float _pupilSize;
|
||||
float _mouthPitch;
|
||||
float _mouthYaw;
|
||||
float _mouthWidth;
|
||||
float _mouthHeight;
|
||||
float _leanForward;
|
||||
float _leanSideways;
|
||||
float _pitchTarget;
|
||||
float _yawTarget;
|
||||
float _noiseEnvelope;
|
||||
float _pupilConverge;
|
||||
float _scale;
|
||||
|
||||
// Sound loudness information
|
||||
float _loudness, _lastLoudness;
|
||||
float _averageLoudness;
|
||||
float _audioAttack;
|
||||
float _browAudioLift;
|
||||
|
||||
AvatarHead _head;
|
||||
bool _isMine;
|
||||
glm::vec3 _TEST_bigSpherePosition;
|
||||
float _TEST_bigSphereRadius;
|
||||
glm::vec3 _DEBUG_otherAvatarListPosition[ NUM_OTHER_AVATARS ];
|
||||
float _DEBUG_otherAvatarListTimer [ NUM_OTHER_AVATARS ];
|
||||
bool _triggeringAction;
|
||||
glm::vec3 _otherAvatarHandPosition[ MAX_OTHER_AVATARS ];
|
||||
bool _mousePressed;
|
||||
float _bodyYawDelta;
|
||||
float _closeEnoughToInteract;
|
||||
int _closestOtherAvatar;
|
||||
bool _usingSprings;
|
||||
bool _handBeingMoved;
|
||||
bool _previousHandBeingMoved;
|
||||
bool _usingBodySprings;
|
||||
glm::vec3 _movedHandOffset;
|
||||
float _springVelocityDecay;
|
||||
float _springForce;
|
||||
glm::quat _rotation; // the rotation of the avatar body as a whole
|
||||
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
|
||||
AvatarBone _bone[ NUM_AVATAR_BONES ];
|
||||
AvatarMode _mode;
|
||||
Avatar _avatar;
|
||||
glm::dvec3 _velocity;
|
||||
glm::vec3 _thrust;
|
||||
float _maxArmLength;
|
||||
Orientation _orientation;
|
||||
int _numOtherAvatarsInView;
|
||||
int _driveKeys[MAX_DRIVE_KEYS];
|
||||
int _eyeContact;
|
||||
eyeContactTargets _eyeContactTarget;
|
||||
|
||||
GLUquadric *_sphere;
|
||||
|
||||
float _renderYaw;
|
||||
float _renderPitch; // Pitch from view frustum when this is own head.
|
||||
GLUquadric* _sphere;
|
||||
float _renderYaw;
|
||||
float _renderPitch; // Pitch from view frustum when this is own head.
|
||||
|
||||
//
|
||||
// Related to getting transmitter UDP data used to animate the avatar hand
|
||||
|
@ -255,6 +255,8 @@ class Head : public AvatarData {
|
|||
void calculateBoneLengths();
|
||||
void updateBigSphereCollisionTest( float deltaTime );
|
||||
void readSensors();
|
||||
void renderBoneAsBlock( AvatarBoneID b );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -114,7 +114,7 @@ float VoxelSystem::getVoxelsBytesReadPerSecondAverage() {
|
|||
}
|
||||
|
||||
|
||||
void VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||
int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||
|
||||
unsigned char command = *sourceBuffer;
|
||||
unsigned char *voxelData = sourceBuffer + 1;
|
||||
|
@ -154,6 +154,7 @@ void VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
}
|
||||
|
||||
setupNewVoxelsForDrawing();
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||
|
@ -161,9 +162,8 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
|||
writeVerticesEndPointer = writeVerticesArray;
|
||||
// call recursive function to populate in memory arrays
|
||||
// it will return the number of voxels added
|
||||
float treeRoot[3] = {0,0,0};
|
||||
glm::vec3 treeRoot = glm::vec3(0,0,0);
|
||||
voxelsRendered = treeToArrays(tree->rootNode, treeRoot);
|
||||
|
||||
// copy the newly written data to the arrays designated for reading
|
||||
copyWrittenDataToReadArrays();
|
||||
}
|
||||
|
@ -176,42 +176,35 @@ void VoxelSystem::copyWrittenDataToReadArrays() {
|
|||
// copy the vertices and colors
|
||||
memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat));
|
||||
memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte));
|
||||
|
||||
// set the read vertices end pointer to the correct spot so the GPU knows how much to pull
|
||||
readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray);
|
||||
pthread_mutex_unlock(&bufferWriteLock);
|
||||
}
|
||||
|
||||
int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) {
|
||||
int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosition) {
|
||||
int voxelsAdded = 0;
|
||||
|
||||
float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE);
|
||||
glm::vec3 viewerPosition = viewerHead->getBodyPosition();
|
||||
|
||||
// XXXBHG - Note: It appears as if the X and Z coordinates of Head or Agent are flip-flopped relative to the
|
||||
// coords of the voxel space. This flip flop causes LOD behavior to be extremely odd. This is my temporary hack
|
||||
// to fix this behavior. To disable this swap, set swapXandZ to false.
|
||||
bool swapXandZ=true;
|
||||
float viewerX = swapXandZ ? viewerPosition[2] : viewerPosition[0];
|
||||
float viewerZ = swapXandZ ? viewerPosition[0] : viewerPosition[2];
|
||||
// debug LOD code
|
||||
glm::vec3 debugNodePosition;
|
||||
copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition);
|
||||
|
||||
// debugging code.
|
||||
//printLog("treeToArrays() halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
||||
//printLog("treeToArrays() viewerPosition {x,y,z or [0],[1],[2]} ={%f,%f,%f}\n",
|
||||
// viewerPosition[0],viewerPosition[1],viewerPosition[2]);
|
||||
//printLog("treeToArrays() nodePosition {x,y,z or [0],[1],[2]} = {%f,%f,%f}\n",
|
||||
// nodePosition[0],nodePosition[1],nodePosition[2]);
|
||||
//float* vertices = firstVertexForCode(currentNode->octalCode);
|
||||
//printLog("treeToArrays() firstVerticesForCode(currentNode->octalCode)={x,y,z or [0],[1],[2]} = {%f,%f,%f}\n",
|
||||
// vertices[0],vertices[1],vertices[2]);
|
||||
//delete []vertices;
|
||||
|
||||
float distanceToVoxelCenter = sqrtf(powf(viewerX - nodePosition[0] - halfUnitForVoxel, 2) +
|
||||
powf(viewerPosition[1] - nodePosition[1] - halfUnitForVoxel, 2) +
|
||||
powf(viewerZ - nodePosition[2] - halfUnitForVoxel, 2));
|
||||
//printf("-----------------\n");
|
||||
//printf("halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
||||
//printf("viewer.x=%f y=%f z=%f \n", viewerPosition.x, viewerPosition.y, viewerPosition.z);
|
||||
//printf("node.x=%f y=%f z=%f \n", nodePosition[0], nodePosition[1], nodePosition[2]);
|
||||
//printf("debugNodePosition.x=%f y=%f z=%f \n", debugNodePosition[0], debugNodePosition[1], debugNodePosition[2]);
|
||||
|
||||
int boundaryPosition = boundaryDistanceForRenderLevel(*currentNode->octalCode + 1);
|
||||
//printLog("treeToArrays() distanceToVoxelCenter=%f boundaryPosition=%d\n",distanceToVoxelCenter,boundaryPosition);
|
||||
float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) +
|
||||
powf(viewerPosition.y - nodePosition[1] - halfUnitForVoxel, 2) +
|
||||
powf(viewerPosition.z - nodePosition[2] - halfUnitForVoxel, 2));
|
||||
|
||||
int renderLevel = *currentNode->octalCode + 1;
|
||||
int boundaryPosition = boundaryDistanceForRenderLevel(renderLevel);
|
||||
//printLog("treeToArrays() renderLevel=%d distanceToVoxelCenter=%f boundaryPosition=%d\n",
|
||||
// renderLevel,distanceToVoxelCenter,boundaryPosition);
|
||||
|
||||
bool alwaysDraw = false; // XXXBHG - temporary debug code. Flip this to true to disable LOD blurring
|
||||
|
||||
|
@ -220,43 +213,46 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) {
|
|||
// check if there is a child here
|
||||
if (currentNode->children[i] != NULL) {
|
||||
|
||||
// calculate the child's position based on the parent position
|
||||
float childNodePosition[3];
|
||||
glm::vec3 childNodePosition;
|
||||
copyFirstVertexForCode(currentNode->children[i]->octalCode,(float*)&childNodePosition);
|
||||
childNodePosition *= (float)TREE_SCALE; // scale it up
|
||||
|
||||
/**** disabled ************************************************************************************************
|
||||
// Note: Stephen, I intentionally left this in so you would talk to me about it. Here's the deal, this code
|
||||
// doesn't seem to work correctly. It returns X and Z flipped and the values are negative. Since we use the
|
||||
// firstVertexForCode() function below to calculate the child vertex and that DOES work, I've decided to use
|
||||
// that function to calculate our position for LOD handling.
|
||||
//
|
||||
// calculate the child's position based on the parent position
|
||||
for (int j = 0; j < 3; j++) {
|
||||
childNodePosition[j] = nodePosition[j];
|
||||
|
||||
if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,
|
||||
currentNode->children[i]->octalCode),
|
||||
(7 - j))) {
|
||||
if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,currentNode->children[i]->octalCode),(7 - j))) {
|
||||
childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE);
|
||||
}
|
||||
}
|
||||
**** disabled ************************************************************************************************/
|
||||
voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// if we didn't get any voxels added then we're a leaf
|
||||
// add our vertex and color information to the interleaved array
|
||||
if (voxelsAdded == 0 && currentNode->color[3] == 1) {
|
||||
float * startVertex = firstVertexForCode(currentNode->octalCode);
|
||||
if (voxelsAdded == 0 && currentNode->isColored()) {
|
||||
float startVertex[3];
|
||||
copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex);
|
||||
float voxelScale = 1 / powf(2, *currentNode->octalCode);
|
||||
|
||||
// populate the array with points for the 8 vertices
|
||||
// and RGB color for each added vertex
|
||||
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
||||
*writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale);
|
||||
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->color[j % 3];
|
||||
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3];
|
||||
|
||||
writeVerticesEndPointer++;
|
||||
}
|
||||
|
||||
voxelsAdded++;
|
||||
|
||||
delete [] startVertex;
|
||||
}
|
||||
|
||||
return voxelsAdded;
|
||||
|
@ -363,4 +359,263 @@ void VoxelSystem::simulate(float deltaTime) {
|
|||
|
||||
}
|
||||
|
||||
int VoxelSystem::_nodeCount = 0;
|
||||
|
||||
bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraData) {
|
||||
|
||||
// we do our operations on the way up!
|
||||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_nodeCount++;
|
||||
if (node->isColored()) {
|
||||
nodeColor newColor = { 0,0,0,1 };
|
||||
newColor[0] = randomColorValue(150);
|
||||
newColor[1] = randomColorValue(150);
|
||||
newColor[1] = randomColorValue(150);
|
||||
|
||||
//printf("randomize color node %d was %x,%x,%x NOW %x,%x,%x\n",
|
||||
// _nodeCount,node->getTrueColor()[0],node->getTrueColor()[1],node->getTrueColor()[2],
|
||||
// newColor[0],newColor[1],newColor[2]);
|
||||
node->setColor(newColor);
|
||||
} else {
|
||||
//printf("not randomizing color node of %d since it has no color\n",_nodeCount);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void VoxelSystem::randomizeVoxelColors() {
|
||||
_nodeCount = 0;
|
||||
tree->recurseTreeWithOperation(randomColorOperation);
|
||||
printf("setting randomized true color for %d nodes\n",_nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData) {
|
||||
|
||||
// we do our operations on the way up!
|
||||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_nodeCount++;
|
||||
|
||||
// always false colorize
|
||||
unsigned char newR = randomColorValue(150);
|
||||
unsigned char newG = randomColorValue(150);
|
||||
unsigned char newB = randomColorValue(150);
|
||||
|
||||
printf("randomize FALSE color node %d was %x,%x,%x NOW %x,%x,%x\n",
|
||||
_nodeCount,node->getTrueColor()[0],node->getTrueColor()[1],node->getTrueColor()[2],
|
||||
newR,newG,newB);
|
||||
node->setFalseColor(newR,newG,newB);
|
||||
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
void VoxelSystem::falseColorizeRandom() {
|
||||
_nodeCount = 0;
|
||||
tree->recurseTreeWithOperation(falseColorizeRandomOperation);
|
||||
printf("setting randomized false color for %d nodes\n",_nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraData) {
|
||||
|
||||
// we do our operations on the way up!
|
||||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_nodeCount++;
|
||||
node->setFalseColored(false);
|
||||
//printf("setting true color for node %d\n",_nodeCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VoxelSystem::trueColorize() {
|
||||
_nodeCount = 0;
|
||||
tree->recurseTreeWithOperation(trueColorizeOperation);
|
||||
printf("setting true color for %d nodes\n",_nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
// Will false colorize voxels that are not in view
|
||||
bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData) {
|
||||
|
||||
// we do our operations on the way up!
|
||||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||
|
||||
_nodeCount++;
|
||||
|
||||
// only do this for truely colored voxels...
|
||||
if (node->isColored()) {
|
||||
// first calculate the AAbox for the voxel
|
||||
AABox voxelBox;
|
||||
node->getAABox(voxelBox);
|
||||
|
||||
voxelBox.scale(TREE_SCALE);
|
||||
|
||||
printf("voxelBox corner=(%f,%f,%f) x=%f\n",
|
||||
voxelBox.getCorner().x, voxelBox.getCorner().y, voxelBox.getCorner().z,
|
||||
voxelBox.getSize().x);
|
||||
|
||||
// If the voxel is outside of the view frustum, then false color it red
|
||||
if (ViewFrustum::OUTSIDE == viewFrustum->boxInFrustum(voxelBox)) {
|
||||
// Out of view voxels are colored RED
|
||||
unsigned char newR = 255;
|
||||
unsigned char newG = 0;
|
||||
unsigned char newB = 0;
|
||||
|
||||
//printf("voxel OUTSIDE view - FALSE colorizing node %d TRUE color is %x,%x,%x \n",
|
||||
// _nodeCount,node->getTrueColor()[0],node->getTrueColor()[1],node->getTrueColor()[2]);
|
||||
node->setFalseColor(newR,newG,newB);
|
||||
} else {
|
||||
printf("voxel NOT OUTSIDE view\n");
|
||||
}
|
||||
} else {
|
||||
printf("voxel not colored, don't consider it\n");
|
||||
}
|
||||
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) {
|
||||
_nodeCount = 0;
|
||||
tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum);
|
||||
printf("setting in view false color for %d nodes\n",_nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
// Will false colorize voxels based on distance from view
|
||||
bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData) {
|
||||
|
||||
//printf("falseColorizeDistanceFromViewOperation() down=%s\n",(down ? "TRUE" : "FALSE"));
|
||||
|
||||
// we do our operations on the way up!
|
||||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||
|
||||
// only do this for truly colored voxels...
|
||||
if (node->isColored()) {
|
||||
|
||||
// We need our distance for both up and down
|
||||
glm::vec3 nodePosition;
|
||||
float* startVertex = firstVertexForCode(node->octalCode);
|
||||
nodePosition.x = startVertex[0];
|
||||
nodePosition.y = startVertex[1];
|
||||
nodePosition.z = startVertex[2];
|
||||
delete startVertex;
|
||||
|
||||
// scale up the node position
|
||||
nodePosition = nodePosition*(float)TREE_SCALE;
|
||||
|
||||
float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE);
|
||||
glm::vec3 viewerPosition = viewFrustum->getPosition();
|
||||
|
||||
//printf("halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
||||
//printf("viewer.x=%f y=%f z=%f \n", viewerPosition.x, viewerPosition.y, viewerPosition.z);
|
||||
//printf("node.x=%f y=%f z=%f \n", nodePosition.x, nodePosition.y, nodePosition.z);
|
||||
|
||||
float distance = sqrtf(powf(viewerPosition.x - nodePosition.x - halfUnitForVoxel, 2) +
|
||||
powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) +
|
||||
powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2));
|
||||
|
||||
// actually colorize
|
||||
_nodeCount++;
|
||||
|
||||
float distanceRatio = (_minDistance==_maxDistance) ? 1 : (distance - _minDistance)/(_maxDistance - _minDistance);
|
||||
|
||||
// We want to colorize this in 16 bug chunks of color
|
||||
const unsigned char maxColor = 255;
|
||||
const unsigned char colorBands = 16;
|
||||
const unsigned char gradientOver = 128;
|
||||
unsigned char colorBand = (colorBands*distanceRatio);
|
||||
unsigned char newR = (colorBand*(gradientOver/colorBands))+(maxColor-gradientOver);
|
||||
unsigned char newG = 0;
|
||||
unsigned char newB = 0;
|
||||
//printf("Setting color down=%s distance=%f min=%f max=%f distanceRatio=%f color=%d \n",
|
||||
// (down ? "TRUE" : "FALSE"), distance, _minDistance, _maxDistance, distanceRatio, (int)newR);
|
||||
|
||||
node->setFalseColor(newR,newG,newB);
|
||||
} else {
|
||||
//printf("voxel not colored, don't consider it - down=%s\n",(down ? "TRUE" : "FALSE"));
|
||||
}
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
float VoxelSystem::_maxDistance = 0.0;
|
||||
float VoxelSystem::_minDistance = FLT_MAX;
|
||||
|
||||
// Helper function will get the distance from view range, would be nice if you could just keep track
|
||||
// of this as voxels are created and/or colored... seems like some transform math could do that so
|
||||
// we wouldn't need to do two passes of the tree
|
||||
bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData) {
|
||||
|
||||
// we do our operations on the way up!
|
||||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//printf("getDistanceFromViewRangeOperation() down=%s\n",(down ? "TRUE" : "FALSE"));
|
||||
|
||||
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||
|
||||
// only do this for truly colored voxels...
|
||||
if (node->isColored()) {
|
||||
|
||||
// We need our distance for both up and down
|
||||
glm::vec3 nodePosition;
|
||||
float* startVertex = firstVertexForCode(node->octalCode);
|
||||
nodePosition.x = startVertex[0];
|
||||
nodePosition.y = startVertex[1];
|
||||
nodePosition.z = startVertex[2];
|
||||
delete startVertex;
|
||||
|
||||
// scale up the node position
|
||||
nodePosition = nodePosition*(float)TREE_SCALE;
|
||||
|
||||
float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE);
|
||||
glm::vec3 viewerPosition = viewFrustum->getPosition();
|
||||
|
||||
float distance = sqrtf(powf(viewerPosition.x - nodePosition.x - halfUnitForVoxel, 2) +
|
||||
powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) +
|
||||
powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2));
|
||||
|
||||
// on way down, calculate the range of distances
|
||||
if (distance > _maxDistance) {
|
||||
_maxDistance = distance;
|
||||
//printf("new maxDistance=%f down=%s\n",_maxDistance, (down ? "TRUE" : "FALSE"));
|
||||
}
|
||||
if (distance < _minDistance) {
|
||||
_minDistance = distance;
|
||||
//printf("new minDistance=%f down=%s\n",_minDistance, (down ? "TRUE" : "FALSE"));
|
||||
}
|
||||
|
||||
_nodeCount++;
|
||||
}
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
|
||||
_nodeCount = 0;
|
||||
|
||||
_maxDistance = 0.0;
|
||||
_minDistance = FLT_MAX;
|
||||
tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum);
|
||||
printf("determining distance range for %d nodes\n",_nodeCount);
|
||||
|
||||
_nodeCount = 0;
|
||||
|
||||
tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum);
|
||||
printf("setting in distance false color for %d nodes\n",_nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <UDPSocket.h>
|
||||
#include <AgentData.h>
|
||||
#include <VoxelTree.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include "Head.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
@ -25,7 +26,7 @@ public:
|
|||
VoxelSystem();
|
||||
~VoxelSystem();
|
||||
|
||||
void parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
VoxelSystem* clone() const;
|
||||
|
||||
void init();
|
||||
|
@ -44,7 +45,27 @@ public:
|
|||
float getVoxelsColoredPerSecondAverage();
|
||||
float getVoxelsBytesReadPerSecondAverage();
|
||||
|
||||
// Methods that recurse tree
|
||||
void randomizeVoxelColors();
|
||||
void falseColorizeRandom();
|
||||
void trueColorize();
|
||||
void falseColorizeInView(ViewFrustum* viewFrustum);
|
||||
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
|
||||
|
||||
private:
|
||||
// Operation functions for tree recursion methods
|
||||
static int _nodeCount;
|
||||
static bool randomColorOperation(VoxelNode* node, bool down, void* extraData);
|
||||
static bool falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData);
|
||||
static bool trueColorizeOperation(VoxelNode* node, bool down, void* extraData);
|
||||
static bool falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData);
|
||||
static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData);
|
||||
static bool getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData);
|
||||
|
||||
// these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here
|
||||
static float _maxDistance;
|
||||
static float _minDistance;
|
||||
|
||||
int voxelsRendered;
|
||||
Head *viewerHead;
|
||||
VoxelTree *tree;
|
||||
|
@ -59,7 +80,7 @@ private:
|
|||
GLuint vboIndicesID;
|
||||
pthread_mutex_t bufferWriteLock;
|
||||
|
||||
int treeToArrays(VoxelNode *currentNode, float nodePosition[3]);
|
||||
int treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosition);
|
||||
void setupNewVoxelsForDrawing();
|
||||
void copyWrittenDataToReadArrays();
|
||||
};
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
using namespace std;
|
||||
|
||||
void reshape(int width, int height); // will be defined below
|
||||
void loadViewFrustum(ViewFrustum& viewFrustum); // will be defined below
|
||||
|
||||
|
||||
pthread_t networkReceiveThread;
|
||||
|
@ -168,15 +169,90 @@ int displayField = 0;
|
|||
int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement
|
||||
int headMouseX, headMouseY;
|
||||
|
||||
int mouseX, mouseY; // Where is the mouse
|
||||
int mouseX = 0;
|
||||
int mouseY = 0;
|
||||
|
||||
// Mouse location at start of last down click
|
||||
int mouseStartX = WIDTH / 2;
|
||||
int mouseStartY = HEIGHT / 2;
|
||||
int mousePressed = 0; // true if mouse has been pressed (clear when finished)
|
||||
|
||||
Menu menu; // main menu
|
||||
int menuOn = 1; // Whether to show onscreen menu
|
||||
Menu menu; // main menu
|
||||
int menuOn = 1; // Whether to show onscreen menu
|
||||
|
||||
struct HandController
|
||||
{
|
||||
bool enabled;
|
||||
int startX;
|
||||
int startY;
|
||||
int x;
|
||||
int y;
|
||||
int lastX;
|
||||
int lastY;
|
||||
int velocityX;
|
||||
int velocityY;
|
||||
float rampUpRate;
|
||||
float rampDownRate;
|
||||
float envelope;
|
||||
};
|
||||
|
||||
HandController handController;
|
||||
|
||||
void initializeHandController() {
|
||||
handController.enabled = false;
|
||||
handController.startX = WIDTH / 2;
|
||||
handController.startY = HEIGHT / 2;
|
||||
handController.x = 0;
|
||||
handController.y = 0;
|
||||
handController.lastX = 0;
|
||||
handController.lastY = 0;
|
||||
handController.velocityX = 0;
|
||||
handController.velocityY = 0;
|
||||
handController.rampUpRate = 0.05;
|
||||
handController.rampDownRate = 0.02;
|
||||
handController.envelope = 0.0f;
|
||||
}
|
||||
|
||||
void updateHandController( int x, int y ) {
|
||||
handController.lastX = handController.x;
|
||||
handController.lastY = handController.y;
|
||||
handController.x = x;
|
||||
handController.y = y;
|
||||
handController.velocityX = handController.x - handController.lastX;
|
||||
handController.velocityY = handController.y - handController.lastY;
|
||||
|
||||
if (( handController.velocityX != 0 )
|
||||
|| ( handController.velocityY != 0 )) {
|
||||
handController.enabled = true;
|
||||
myAvatar.startHandMovement();
|
||||
if ( handController.envelope < 1.0 ) {
|
||||
handController.envelope += handController.rampUpRate;
|
||||
if ( handController.envelope >= 1.0 ) {
|
||||
handController.envelope = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! handController.enabled ) {
|
||||
if ( handController.envelope > 0.0 ) {
|
||||
handController.envelope -= handController.rampDownRate;
|
||||
if ( handController.envelope <= 0.0 ) {
|
||||
handController.startX = WIDTH / 2;
|
||||
handController.startY = HEIGHT / 2;
|
||||
handController.envelope = 0.0;
|
||||
//prototype
|
||||
//myAvatar.stopHandMovement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( handController.envelope > 0.0 ) {
|
||||
float leftRight = ( ( handController.x - handController.startX ) / (float)WIDTH ) * handController.envelope;
|
||||
float downUp = ( ( handController.y - handController.startY ) / (float)HEIGHT ) * handController.envelope;
|
||||
float backFront = 0.0;
|
||||
myAvatar.setHandMovementValues( glm::vec3( leftRight, downUp, backFront ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Serial USB Variables
|
||||
|
@ -266,11 +342,15 @@ void displayStats(void)
|
|||
|
||||
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
char avatarMixerStats[200];
|
||||
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||
if (avatarMixer) {
|
||||
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||
} else {
|
||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||
}
|
||||
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
||||
|
||||
|
||||
if (::perfStatsOn) {
|
||||
// Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups
|
||||
char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1];
|
||||
|
@ -304,6 +384,8 @@ void init(void)
|
|||
voxels.init();
|
||||
voxels.setViewerHead(&myAvatar);
|
||||
myAvatar.setRenderYaw(startYaw);
|
||||
|
||||
initializeHandController();
|
||||
|
||||
headMouseX = WIDTH/2;
|
||||
headMouseY = HEIGHT/2;
|
||||
|
@ -369,22 +451,6 @@ void reset_sensors()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void updateAvatarHand(float deltaTime) {
|
||||
// If mouse is being dragged, send current force to the hand controller
|
||||
if (mousePressed == 1)
|
||||
{
|
||||
// NOTE--PER: Need to re-implement when ready for new avatar hand movements
|
||||
|
||||
const float MOUSE_HAND_FORCE = 1.5;
|
||||
float dx = mouseX - mouseStartX;
|
||||
float dy = mouseY - mouseStartY;
|
||||
glm::vec3 vel(dx*MOUSE_HAND_FORCE, -dy*MOUSE_HAND_FORCE*(WIDTH/HEIGHT), 0);
|
||||
//myAvatar.hand->addVelocity(vel*deltaTime);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// Using gyro data, update both view frustum and avatar head position
|
||||
//
|
||||
|
@ -457,6 +523,22 @@ void updateAvatar(float frametime)
|
|||
myAvatar.setAverageLoudness(averageLoudness);
|
||||
#endif
|
||||
|
||||
// Update Avatar with latest camera and view frustum data...
|
||||
// NOTE: we get this from the view frustum, to make it simpler, since the
|
||||
// loadViewFrumstum() method will get the correct details from the camera
|
||||
// We could optimize this to not actually load the viewFrustum, since we don't
|
||||
// actually need to calculate the view frustum planes to send these details
|
||||
// to the server.
|
||||
loadViewFrustum(::viewFrustum);
|
||||
myAvatar.setCameraPosition(::viewFrustum.getPosition());
|
||||
myAvatar.setCameraDirection(::viewFrustum.getDirection());
|
||||
myAvatar.setCameraUp(::viewFrustum.getUp());
|
||||
myAvatar.setCameraRight(::viewFrustum.getRight());
|
||||
myAvatar.setCameraFov(::viewFrustum.getFieldOfView());
|
||||
myAvatar.setCameraAspectRatio(::viewFrustum.getAspectRatio());
|
||||
myAvatar.setCameraNearClip(::viewFrustum.getNearClip());
|
||||
myAvatar.setCameraFarClip(::viewFrustum.getFarClip());
|
||||
|
||||
// Send my stream of head/hand data to the avatar mixer and voxel server
|
||||
unsigned char broadcastString[200];
|
||||
*broadcastString = PACKET_HEADER_HEAD_DATA;
|
||||
|
@ -494,34 +576,14 @@ void updateAvatar(float frametime)
|
|||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// render_view_frustum()
|
||||
// loadViewFrustum()
|
||||
//
|
||||
// Description: this will render the view frustum bounds for EITHER the head
|
||||
// Description: this will load the view frustum bounds for EITHER the head
|
||||
// or the "myCamera".
|
||||
//
|
||||
// Frustum rendering mode. For debug purposes, we allow drawing the frustum in a couple of different ways.
|
||||
// We can draw it with each of these parts:
|
||||
// * Origin Direction/Up/Right vectors - these will be drawn at the point of the camera
|
||||
// * Near plane - this plane is drawn very close to the origin point.
|
||||
// * Right/Left planes - these two planes are drawn between the near and far planes.
|
||||
// * Far plane - the plane is drawn in the distance.
|
||||
// Modes - the following modes, will draw the following parts.
|
||||
// * All - draws all the parts listed above
|
||||
// * Planes - draws the planes but not the origin vectors
|
||||
// * Origin Vectors - draws the origin vectors ONLY
|
||||
// * Near Plane - draws only the near plane
|
||||
// * Far Plane - draws only the far plane
|
||||
#define FRUSTUM_DRAW_MODE_ALL 0
|
||||
#define FRUSTUM_DRAW_MODE_VECTORS 1
|
||||
#define FRUSTUM_DRAW_MODE_PLANES 2
|
||||
#define FRUSTUM_DRAW_MODE_NEAR_PLANE 3
|
||||
#define FRUSTUM_DRAW_MODE_FAR_PLANE 4
|
||||
#define FRUSTUM_DRAW_MODE_COUNT 5
|
||||
|
||||
// These global scoped variables are used by our render_view_frustum() function below, but are also available as globals
|
||||
// so that the keyboard and menu can manipulate them.
|
||||
|
||||
int frustumDrawingMode = FRUSTUM_DRAW_MODE_ALL; // the mode we're drawing the frustum in, see notes above
|
||||
// These global scoped variables are used by our loadViewFrustum() and renderViewFrustum functions below, but are also
|
||||
// available as globals so that the keyboard and menu can manipulate them.
|
||||
|
||||
bool frustumOn = false; // Whether or not to display the debug view frustum
|
||||
bool cameraFrustum = true; // which frustum to look at
|
||||
|
@ -533,8 +595,7 @@ float viewFrustumOffsetRoll = 0.0;
|
|||
float viewFrustumOffsetDistance = 25.0;
|
||||
float viewFrustumOffsetUp = 0.0;
|
||||
|
||||
void render_view_frustum() {
|
||||
|
||||
void loadViewFrustum(ViewFrustum& viewFrustum) {
|
||||
// We will use these below, from either the camera or head vectors calculated above
|
||||
glm::vec3 position;
|
||||
glm::vec3 direction;
|
||||
|
@ -593,8 +654,44 @@ void render_view_frustum() {
|
|||
|
||||
// Ask the ViewFrustum class to calculate our corners
|
||||
viewFrustum.calculate();
|
||||
|
||||
//viewFrustum.dump();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// renderViewFrustum()
|
||||
//
|
||||
// Description: this will render the view frustum bounds for EITHER the head
|
||||
// or the "myCamera".
|
||||
//
|
||||
// Frustum rendering mode. For debug purposes, we allow drawing the frustum in a couple of different ways.
|
||||
// We can draw it with each of these parts:
|
||||
// * Origin Direction/Up/Right vectors - these will be drawn at the point of the camera
|
||||
// * Near plane - this plane is drawn very close to the origin point.
|
||||
// * Right/Left planes - these two planes are drawn between the near and far planes.
|
||||
// * Far plane - the plane is drawn in the distance.
|
||||
// Modes - the following modes, will draw the following parts.
|
||||
// * All - draws all the parts listed above
|
||||
// * Planes - draws the planes but not the origin vectors
|
||||
// * Origin Vectors - draws the origin vectors ONLY
|
||||
// * Near Plane - draws only the near plane
|
||||
// * Far Plane - draws only the far plane
|
||||
#define FRUSTUM_DRAW_MODE_ALL 0
|
||||
#define FRUSTUM_DRAW_MODE_VECTORS 1
|
||||
#define FRUSTUM_DRAW_MODE_PLANES 2
|
||||
#define FRUSTUM_DRAW_MODE_NEAR_PLANE 3
|
||||
#define FRUSTUM_DRAW_MODE_FAR_PLANE 4
|
||||
#define FRUSTUM_DRAW_MODE_COUNT 5
|
||||
|
||||
int frustumDrawingMode = FRUSTUM_DRAW_MODE_ALL; // the mode we're drawing the frustum in, see notes above
|
||||
|
||||
void renderViewFrustum(ViewFrustum& viewFrustum) {
|
||||
|
||||
// Load it with the latest details!
|
||||
loadViewFrustum(viewFrustum);
|
||||
|
||||
glm::vec3 position = viewFrustum.getPosition();
|
||||
glm::vec3 direction = viewFrustum.getDirection();
|
||||
glm::vec3 up = viewFrustum.getUp();
|
||||
glm::vec3 right = viewFrustum.getRight();
|
||||
|
||||
// Get ready to draw some lines
|
||||
glDisable(GL_LIGHTING);
|
||||
|
@ -722,18 +819,16 @@ void display(void)
|
|||
//--------------------------------------------------------
|
||||
// camera settings
|
||||
//--------------------------------------------------------
|
||||
myCamera.setTargetPosition( myAvatar.getBodyPosition() );
|
||||
|
||||
if ( displayHead ) {
|
||||
//-----------------------------------------------
|
||||
// set the camera to looking at my own face
|
||||
//-----------------------------------------------
|
||||
myCamera.setTargetPosition ( myAvatar.getBodyPosition() ); // XXXBHG - Shouldn't we use Head position here?
|
||||
myCamera.setTargetPosition ( myAvatar.getHeadPosition() );
|
||||
myCamera.setYaw ( - myAvatar.getBodyYaw() );
|
||||
myCamera.setPitch ( 0.0 );
|
||||
myCamera.setRoll ( 0.0 );
|
||||
myCamera.setUp ( 0.6 );
|
||||
myCamera.setDistance ( 0.3 );
|
||||
myCamera.setPitch ( 0.0 );
|
||||
myCamera.setRoll ( 0.0 );
|
||||
myCamera.setUp ( 0.0 );
|
||||
myCamera.setDistance ( 0.2 );
|
||||
myCamera.setTightness ( 100.0f );
|
||||
myCamera.update ( 1.f/FPS );
|
||||
} else {
|
||||
|
@ -742,12 +837,12 @@ void display(void)
|
|||
//----------------------------------------------------
|
||||
myCamera.setTargetPosition ( myAvatar.getBodyPosition() );
|
||||
myCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() );
|
||||
myCamera.setPitch ( 0.0 ); // temporarily, this must be 0.0 or else bad juju
|
||||
myCamera.setRoll ( 0.0 );
|
||||
myCamera.setUp ( 0.45);
|
||||
myCamera.setDistance ( 1.0 );
|
||||
myCamera.setTightness ( 10.0f );
|
||||
myCamera.update ( 1.f/FPS );
|
||||
myCamera.setPitch ( 0.0 ); // temporarily, this must be 0.0 or else bad juju
|
||||
myCamera.setRoll ( 0.0 );
|
||||
myCamera.setUp ( 0.45 );
|
||||
myCamera.setDistance ( 1.0 );
|
||||
myCamera.setTightness ( 8.0f );
|
||||
myCamera.update ( 1.f/FPS);
|
||||
}
|
||||
|
||||
// Note: whichCamera is used to pick between the normal camera myCamera for our
|
||||
|
@ -755,7 +850,7 @@ void display(void)
|
|||
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
||||
// to add other cameras.
|
||||
//
|
||||
// Why have two cameras? Well, one reason is that because in the case of the render_view_frustum()
|
||||
// Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum()
|
||||
// code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of
|
||||
// myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
|
||||
Camera whichCamera = myCamera;
|
||||
|
@ -811,14 +906,12 @@ void display(void)
|
|||
float sphereRadius = 0.25f;
|
||||
glColor3f(1,0,0);
|
||||
glPushMatrix();
|
||||
//glTranslatef( 0.0f, sphereRadius, 0.0f );
|
||||
glutSolidSphere( sphereRadius, 15, 15 );
|
||||
glPopMatrix();
|
||||
|
||||
//draw a grid gound plane....
|
||||
drawGroundPlaneGrid( 5.0f, 9 );
|
||||
|
||||
|
||||
// Draw cloud of dots
|
||||
if (!displayHead) cloud.render();
|
||||
|
||||
|
@ -836,11 +929,9 @@ void display(void)
|
|||
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
|
||||
agent != agentList->getAgents().end();
|
||||
agent++) {
|
||||
if (agent->getLinkedData() != NULL) {
|
||||
Head *agentHead = (Head *)agent->getLinkedData();
|
||||
glPushMatrix();
|
||||
agentHead->render(0);
|
||||
glPopMatrix();
|
||||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||
Head *avatar = (Head *)agent->getLinkedData();
|
||||
avatar->render(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -850,7 +941,7 @@ void display(void)
|
|||
if (!displayHead && statsOn) render_world_box();
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (::frustumOn) render_view_frustum();
|
||||
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||
|
||||
//Render my own avatar
|
||||
myAvatar.render(true);
|
||||
|
@ -904,11 +995,18 @@ void display(void)
|
|||
menu.render(WIDTH,HEIGHT);
|
||||
}
|
||||
|
||||
// Draw number of nearby people always
|
||||
// Stats at upper right of screen about who domain server is telling us about
|
||||
glPointSize(1.0f);
|
||||
char agents[100];
|
||||
sprintf(agents, "Agents: %ld\n", AgentList::getInstance()->getAgents().size());
|
||||
drawtext(WIDTH-100,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
|
||||
|
||||
int totalAgents = AgentList::getInstance()->getAgents().size();
|
||||
int totalAvatars = 0, totalServers = 0;
|
||||
for (int i = 0; i < totalAgents; i++) {
|
||||
(AgentList::getInstance()->getAgents()[i].getType() == AGENT_TYPE_AVATAR)
|
||||
? totalAvatars++ : totalServers++;
|
||||
}
|
||||
sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
|
||||
drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
|
||||
|
||||
if (::paintOn) {
|
||||
|
||||
|
@ -1030,6 +1128,46 @@ int setFrustumRenderMode(int state) {
|
|||
return ::frustumDrawingMode;
|
||||
}
|
||||
|
||||
int doRandomizeVoxelColors(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
::voxels.randomizeVoxelColors();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
int doFalseRandomizeVoxelColors(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
::voxels.falseColorizeRandom();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
int doTrueVoxelColors(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
::voxels.trueColorize();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
int doFalseColorizeByDistance(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
loadViewFrustum(::viewFrustum);
|
||||
voxels.falseColorizeDistanceFromView(&::viewFrustum);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
int doFalseColorizeInView(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
loadViewFrustum(::viewFrustum);
|
||||
// we probably want to make sure the viewFrustum is initialized first
|
||||
voxels.falseColorizeInView(&::viewFrustum);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
const char* modeAll = " - All ";
|
||||
const char* modeVectors = " - Vectors ";
|
||||
const char* modePlanes = " - Planes ";
|
||||
|
@ -1084,7 +1222,11 @@ void initMenu() {
|
|||
|
||||
// Debug
|
||||
menuColumnDebug = menu.addColumn("Debug");
|
||||
|
||||
menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors);
|
||||
menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors);
|
||||
menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance);
|
||||
menuColumnDebug->addRow("FALSE Color Voxel Out of View", doFalseColorizeInView);
|
||||
menuColumnDebug->addRow("Show TRUE Colors", doTrueVoxelColors);
|
||||
}
|
||||
|
||||
void testPointToVoxel()
|
||||
|
@ -1248,7 +1390,7 @@ void key(unsigned char k, int x, int y)
|
|||
// if (k == '\\') ViewFrustum::fovAngleAdust += 0.05;
|
||||
|
||||
if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED);
|
||||
|
||||
|
||||
if (k == '&') {
|
||||
::paintOn = !::paintOn; // toggle paint
|
||||
::setupPaintingVoxel(); // also randomizes colors
|
||||
|
@ -1267,7 +1409,6 @@ void key(unsigned char k, int x, int y)
|
|||
{
|
||||
myAvatar.setNoise(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (k == 'h') {
|
||||
|
@ -1316,8 +1457,7 @@ void *networkReceive(void *args)
|
|||
case PACKET_HEADER_BULK_AVATAR_DATA:
|
||||
AgentList::getInstance()->processBulkAgentData(&senderAddress,
|
||||
incomingPacket,
|
||||
bytesReceived,
|
||||
BYTES_PER_AVATAR);
|
||||
bytesReceived);
|
||||
break;
|
||||
default:
|
||||
AgentList::getInstance()->processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
|
@ -1339,40 +1479,29 @@ void idle(void) {
|
|||
|
||||
if (diffclock(&lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
|
||||
|
||||
//if ( myAvatar.getMode() == AVATAR_MODE_COMMUNICATING ) {
|
||||
float leftRight = ( mouseX - mouseStartX ) / (float)WIDTH;
|
||||
float downUp = ( mouseY - mouseStartY ) / (float)HEIGHT;
|
||||
float backFront = 0.0;
|
||||
glm::vec3 handMovement( leftRight, downUp, backFront );
|
||||
myAvatar.setHandMovement( handMovement );
|
||||
/*}
|
||||
else {
|
||||
mouseStartX = mouseX;
|
||||
mouseStartY = mouseY;
|
||||
//mouseStartX = (float)WIDTH / 2.0f;
|
||||
//mouseStartY = (float)HEIGHT / 2.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------
|
||||
// when the mouse is being pressed, an 'action' is being
|
||||
// triggered in the avatar. The action is context-based.
|
||||
//--------------------------------------------------------
|
||||
float deltaTime = 1.f/FPS;
|
||||
|
||||
// update behaviors for avatar hand movement
|
||||
updateHandController( mouseX, mouseY );
|
||||
|
||||
// tell my avatar if the mouse is being pressed...
|
||||
if ( mousePressed == 1 ) {
|
||||
myAvatar.setTriggeringAction( true );
|
||||
myAvatar.setMousePressed( true );
|
||||
}
|
||||
else {
|
||||
myAvatar.setTriggeringAction( false );
|
||||
myAvatar.setMousePressed( false );
|
||||
}
|
||||
|
||||
// walking triggers the handController to stop
|
||||
if ( myAvatar.getMode() == AVATAR_MODE_WALKING ) {
|
||||
handController.enabled = false;
|
||||
}
|
||||
|
||||
float deltaTime = 1.f/FPS;
|
||||
|
||||
//
|
||||
// Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents
|
||||
//
|
||||
updateAvatar( 1.f/FPS );
|
||||
updateAvatar(deltaTime);
|
||||
|
||||
|
||||
//loop through all the other avatars and simulate them.
|
||||
AgentList * agentList = AgentList::getInstance();
|
||||
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++)
|
||||
|
@ -1383,9 +1512,6 @@ void idle(void) {
|
|||
avatar->simulate(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//updateAvatarHand(1.f/FPS);
|
||||
|
||||
field.simulate (deltaTime);
|
||||
myAvatar.simulate(deltaTime);
|
||||
|
@ -1464,8 +1590,6 @@ void mouseFunc( int button, int state, int x, int y )
|
|||
mouseX = x;
|
||||
mouseY = y;
|
||||
mousePressed = 1;
|
||||
//mouseStartX = x;
|
||||
//mouseStartY = y;
|
||||
}
|
||||
}
|
||||
if( button == GLUT_LEFT_BUTTON && state == GLUT_UP ) {
|
||||
|
@ -1485,12 +1609,15 @@ void motionFunc( int x, int y)
|
|||
void mouseoverFunc( int x, int y)
|
||||
{
|
||||
menu.mouseOver(x, y);
|
||||
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
if (mousePressed == 0)
|
||||
{}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void attachNewHeadToAgent(Agent *newAgent) {
|
||||
if (newAgent->getLinkedData() == NULL) {
|
||||
newAgent->setLinkedData(new Head(false));
|
||||
|
@ -1515,7 +1642,7 @@ int main(int argc, const char * argv[])
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AgentList::createInstance(AGENT_TYPE_INTERFACE);
|
||||
AgentList::createInstance(AGENT_TYPE_AVATAR);
|
||||
|
||||
gettimeofday(&applicationStartupTime, NULL);
|
||||
const char* domainIP = getCmdOption(argc, argv, "--domain");
|
||||
|
|
|
@ -36,7 +36,15 @@ int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPo
|
|||
AvatarData::AvatarData() :
|
||||
_bodyYaw(-90.0),
|
||||
_bodyPitch(0.0),
|
||||
_bodyRoll(0.0) {
|
||||
_bodyRoll(0.0),
|
||||
_cameraPosition(0,0,0),
|
||||
_cameraDirection(0,0,0),
|
||||
_cameraUp(0,0,0),
|
||||
_cameraRight(0,0,0),
|
||||
_cameraFov(0.0f),
|
||||
_cameraAspectRatio(0.0f),
|
||||
_cameraNearClip(0.0f),
|
||||
_cameraFarClip(0.0f) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -64,17 +72,36 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
|
||||
memcpy(destinationBuffer, &_handPosition, sizeof(float) * 3);
|
||||
destinationBuffer += sizeof(float) * 3;
|
||||
|
||||
//printLog("%f, %f, %f\n", _handPosition.x, _handPosition.y, _handPosition.z);
|
||||
|
||||
|
||||
// camera details
|
||||
memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition));
|
||||
destinationBuffer += sizeof(_cameraPosition);
|
||||
memcpy(destinationBuffer, &_cameraDirection, sizeof(_cameraDirection));
|
||||
destinationBuffer += sizeof(_cameraDirection);
|
||||
memcpy(destinationBuffer, &_cameraRight, sizeof(_cameraRight));
|
||||
destinationBuffer += sizeof(_cameraRight);
|
||||
memcpy(destinationBuffer, &_cameraUp, sizeof(_cameraUp));
|
||||
destinationBuffer += sizeof(_cameraUp);
|
||||
memcpy(destinationBuffer, &_cameraFov, sizeof(_cameraFov));
|
||||
destinationBuffer += sizeof(_cameraFov);
|
||||
memcpy(destinationBuffer, &_cameraAspectRatio, sizeof(_cameraAspectRatio));
|
||||
destinationBuffer += sizeof(_cameraAspectRatio);
|
||||
memcpy(destinationBuffer, &_cameraNearClip, sizeof(_cameraNearClip));
|
||||
destinationBuffer += sizeof(_cameraNearClip);
|
||||
memcpy(destinationBuffer, &_cameraFarClip, sizeof(_cameraFarClip));
|
||||
destinationBuffer += sizeof(_cameraFarClip);
|
||||
|
||||
return destinationBuffer - bufferStart;
|
||||
}
|
||||
|
||||
// called on the other agents - assigns it to my views of the others
|
||||
void AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||
int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||
|
||||
// increment to push past the packet header
|
||||
sourceBuffer++;
|
||||
|
||||
unsigned char* startPosition = sourceBuffer;
|
||||
|
||||
memcpy(&_bodyPosition, sourceBuffer, sizeof(float) * 3);
|
||||
sourceBuffer += sizeof(float) * 3;
|
||||
|
||||
|
@ -85,10 +112,25 @@ void AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
memcpy(&_handPosition, sourceBuffer, sizeof(float) * 3);
|
||||
sourceBuffer += sizeof(float) * 3;
|
||||
|
||||
//printLog( "_bodyYaw = %f", _bodyYaw );
|
||||
|
||||
//printLog("%f, %f, %f\n", _handPosition.x, _handPosition.y, _handPosition.z);
|
||||
//printLog("%f, %f, %f\n", _bodyPosition.x, _bodyPosition.y, _bodyPosition.z);
|
||||
// camera details
|
||||
memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition));
|
||||
sourceBuffer += sizeof(_cameraPosition);
|
||||
memcpy(&_cameraDirection, sourceBuffer, sizeof(_cameraDirection));
|
||||
sourceBuffer += sizeof(_cameraDirection);
|
||||
memcpy(&_cameraRight, sourceBuffer, sizeof(_cameraRight));
|
||||
sourceBuffer += sizeof(_cameraRight);
|
||||
memcpy(&_cameraUp, sourceBuffer, sizeof(_cameraUp));
|
||||
sourceBuffer += sizeof(_cameraUp);
|
||||
memcpy(&_cameraFov, sourceBuffer, sizeof(_cameraFov));
|
||||
sourceBuffer += sizeof(_cameraFov);
|
||||
memcpy(&_cameraAspectRatio, sourceBuffer, sizeof(_cameraAspectRatio));
|
||||
sourceBuffer += sizeof(_cameraAspectRatio);
|
||||
memcpy(&_cameraNearClip, sourceBuffer, sizeof(_cameraNearClip));
|
||||
sourceBuffer += sizeof(_cameraNearClip);
|
||||
memcpy(&_cameraFarClip, sourceBuffer, sizeof(_cameraFarClip));
|
||||
sourceBuffer += sizeof(_cameraFarClip);
|
||||
|
||||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
glm::vec3 AvatarData::getBodyPosition() {
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
#include <AgentData.h>
|
||||
|
||||
const int BYTES_PER_AVATAR = 30;
|
||||
|
||||
class AvatarData : public AgentData {
|
||||
public:
|
||||
AvatarData();
|
||||
|
@ -27,7 +25,7 @@ public:
|
|||
void setHandPosition(glm::vec3 handPosition);
|
||||
|
||||
int getBroadcastData(unsigned char* destinationBuffer);
|
||||
void parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
|
||||
float getBodyYaw();
|
||||
void setBodyYaw(float bodyYaw);
|
||||
|
@ -37,6 +35,26 @@ public:
|
|||
|
||||
float getBodyRoll();
|
||||
void setBodyRoll(float bodyRoll);
|
||||
|
||||
// getters for camera details
|
||||
const glm::vec3& getCameraPosition() const { return _cameraPosition; };
|
||||
const glm::vec3& getCameraDirection() const { return _cameraDirection; }
|
||||
const glm::vec3& getCameraUp() const { return _cameraUp; }
|
||||
const glm::vec3& getCameraRight() const { return _cameraRight; }
|
||||
float getCameraFov() const { return _cameraFov; }
|
||||
float getCameraAspectRatio() const { return _cameraAspectRatio; }
|
||||
float getCameraNearClip() const { return _cameraNearClip; }
|
||||
float getCameraFarClip() const { return _cameraFarClip; }
|
||||
|
||||
// setters for camera details
|
||||
void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; };
|
||||
void setCameraDirection(const glm::vec3& direction) { _cameraDirection = direction; }
|
||||
void setCameraUp(const glm::vec3& up) { _cameraUp = up; }
|
||||
void setCameraRight(const glm::vec3& right) { _cameraRight = right; }
|
||||
void setCameraFov(float fov) { _cameraFov = fov; }
|
||||
void setCameraAspectRatio(float aspectRatio) { _cameraAspectRatio = aspectRatio; }
|
||||
void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; }
|
||||
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
|
||||
|
||||
protected:
|
||||
glm::vec3 _bodyPosition;
|
||||
|
@ -45,6 +63,18 @@ protected:
|
|||
float _bodyYaw;
|
||||
float _bodyPitch;
|
||||
float _bodyRoll;
|
||||
|
||||
// camera details for the avatar
|
||||
glm::vec3 _cameraPosition;
|
||||
|
||||
// can we describe this in less space? For example, a Quaternion? or Euler angles?
|
||||
glm::vec3 _cameraDirection;
|
||||
glm::vec3 _cameraUp;
|
||||
glm::vec3 _cameraRight;
|
||||
float _cameraFov;
|
||||
float _cameraAspectRatio;
|
||||
float _cameraNearClip;
|
||||
float _cameraFarClip;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AvatarData__) */
|
||||
|
|
|
@ -20,8 +20,7 @@ using avatars_lib::printLog;
|
|||
//
|
||||
// tosh - yep, I noticed... :-)
|
||||
//
|
||||
// JJV - I noticed too :-)
|
||||
//
|
||||
|
||||
static bool testingForNormalizationAndOrthogonality = false;
|
||||
|
||||
Orientation::Orientation() {
|
||||
|
|
|
@ -23,11 +23,19 @@
|
|||
using shared_lib::printLog;
|
||||
|
||||
Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType, uint16_t thisAgentId) {
|
||||
publicSocket = new sockaddr;
|
||||
memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr));
|
||||
if (agentPublicSocket != NULL) {
|
||||
publicSocket = new sockaddr;
|
||||
memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr));
|
||||
} else {
|
||||
publicSocket = NULL;
|
||||
}
|
||||
|
||||
localSocket = new sockaddr;
|
||||
memcpy(localSocket, agentLocalSocket, sizeof(sockaddr));
|
||||
if (agentLocalSocket != NULL) {
|
||||
localSocket = new sockaddr;
|
||||
memcpy(localSocket, agentLocalSocket, sizeof(sockaddr));
|
||||
} else {
|
||||
localSocket = NULL;
|
||||
}
|
||||
|
||||
type = agentType;
|
||||
agentId = thisAgentId;
|
||||
|
@ -44,11 +52,19 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent
|
|||
}
|
||||
|
||||
Agent::Agent(const Agent &otherAgent) {
|
||||
publicSocket = new sockaddr;
|
||||
memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr));
|
||||
if (otherAgent.publicSocket != NULL) {
|
||||
publicSocket = new sockaddr;
|
||||
memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr));
|
||||
} else {
|
||||
publicSocket = NULL;
|
||||
}
|
||||
|
||||
localSocket = new sockaddr;
|
||||
memcpy(localSocket, otherAgent.localSocket, sizeof(sockaddr));
|
||||
if (otherAgent.localSocket != NULL) {
|
||||
localSocket = new sockaddr;
|
||||
memcpy(localSocket, otherAgent.localSocket, sizeof(sockaddr));
|
||||
} else {
|
||||
localSocket = NULL;
|
||||
}
|
||||
|
||||
agentId = otherAgent.agentId;
|
||||
|
||||
|
@ -132,7 +148,7 @@ const char* Agent::getTypeName() const {
|
|||
case AGENT_TYPE_VOXEL:
|
||||
name = AGENT_TYPE_NAME_VOXEL;
|
||||
break;
|
||||
case AGENT_TYPE_INTERFACE:
|
||||
case AGENT_TYPE_AVATAR:
|
||||
name = AGENT_TYPE_NAME_INTERFACE;
|
||||
break;
|
||||
case AGENT_TYPE_AUDIO_MIXER:
|
||||
|
@ -248,18 +264,27 @@ void Agent::printLog(Agent const& agent) {
|
|||
|
||||
sockaddr_in *agentPublicSocket = (sockaddr_in *) agent.publicSocket;
|
||||
sockaddr_in *agentLocalSocket = (sockaddr_in *) agent.localSocket;
|
||||
|
||||
::printLog("T: %s (%c) PA: %s:%d LA: %s:%d\n", agent.getTypeName(), agent.type,
|
||||
inet_ntoa(agentPublicSocket->sin_addr), ntohs(agentPublicSocket->sin_port),
|
||||
inet_ntoa(agentLocalSocket->sin_addr), ntohs(agentLocalSocket->sin_port));
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Agent* agent) {
|
||||
sockaddr_in *agentPublicSocket = (sockaddr_in *)agent->publicSocket;
|
||||
sockaddr_in *agentLocalSocket = (sockaddr_in *)agent->localSocket;
|
||||
|
||||
os << "T: " << agent->getTypeName() << " (" << agent->type << ") PA: " << inet_ntoa(agentPublicSocket->sin_addr) <<
|
||||
":" << ntohs(agentPublicSocket->sin_port) << " LA: " << inet_ntoa(agentLocalSocket->sin_addr) <<
|
||||
":" << ntohs(agentLocalSocket->sin_port);
|
||||
return os;
|
||||
const char* publicAddressString = (agentPublicSocket == NULL)
|
||||
? "Unknown"
|
||||
: inet_ntoa(agentPublicSocket->sin_addr);
|
||||
unsigned short publicAddressPort = (agentPublicSocket == NULL)
|
||||
? 0
|
||||
: ntohs(agentPublicSocket->sin_port);
|
||||
|
||||
const char* localAddressString = (agentLocalSocket == NULL)
|
||||
? "Unknown"
|
||||
: inet_ntoa(agentLocalSocket->sin_addr);
|
||||
unsigned short localAddressPort = (agentLocalSocket == NULL)
|
||||
? 0
|
||||
: ntohs(agentPublicSocket->sin_port);
|
||||
|
||||
::printLog("ID: %d T: %s (%c) PA: %s:%d LA: %s:%d\n",
|
||||
agent.agentId,
|
||||
agent.getTypeName(),
|
||||
agent.type,
|
||||
publicAddressString,
|
||||
publicAddressPort,
|
||||
localAddressString,
|
||||
localAddressPort);
|
||||
}
|
|
@ -63,7 +63,6 @@ public:
|
|||
float getAveragePacketsPerSecond();
|
||||
|
||||
static void printLog(Agent const&);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Agent* agent);
|
||||
private:
|
||||
void swap(Agent &first, Agent &second);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
class AgentData {
|
||||
public:
|
||||
virtual ~AgentData() = 0;
|
||||
virtual void parseData(unsigned char* sourceBuffer, int numBytes) = 0;
|
||||
virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0;
|
||||
virtual AgentData* clone() const = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD
|
|||
}
|
||||
}
|
||||
|
||||
void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes, int numBytesPerAgent) {
|
||||
void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) {
|
||||
// find the avatar mixer in our agent list and update the lastRecvTime from it
|
||||
int bulkSendAgentIndex = indexOfMatchingAgent(senderAddress);
|
||||
|
||||
|
@ -118,7 +118,7 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac
|
|||
|
||||
unsigned char *startPosition = packetData;
|
||||
unsigned char *currentPosition = startPosition + 1;
|
||||
unsigned char packetHolder[numBytesPerAgent + 1];
|
||||
unsigned char packetHolder[numTotalBytes];
|
||||
|
||||
packetHolder[0] = PACKET_HEADER_HEAD_DATA;
|
||||
|
||||
|
@ -126,39 +126,49 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac
|
|||
|
||||
while ((currentPosition - startPosition) < numTotalBytes) {
|
||||
currentPosition += unpackAgentId(currentPosition, &agentID);
|
||||
memcpy(packetHolder + 1, currentPosition, numBytesPerAgent);
|
||||
memcpy(packetHolder + 1, currentPosition, numTotalBytes - (currentPosition - startPosition));
|
||||
|
||||
int matchingAgentIndex = indexOfMatchingAgent(agentID);
|
||||
|
||||
if (matchingAgentIndex >= 0) {
|
||||
if (matchingAgentIndex < 0) {
|
||||
// we're missing this agent, we need to add it to the list
|
||||
addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID);
|
||||
|
||||
updateAgentWithData(&agents[matchingAgentIndex], packetHolder, numBytesPerAgent + 1);
|
||||
// theoretically if we can lock the vector we could assume this is size - 1
|
||||
matchingAgentIndex = indexOfMatchingAgent(agentID);
|
||||
}
|
||||
|
||||
currentPosition += numBytesPerAgent;
|
||||
currentPosition += updateAgentWithData(&agents[matchingAgentIndex],
|
||||
packetHolder,
|
||||
numTotalBytes - (currentPosition - startPosition));
|
||||
}
|
||||
}
|
||||
|
||||
void AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
|
||||
int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
|
||||
// find the agent by the sockaddr
|
||||
int agentIndex = indexOfMatchingAgent(senderAddress);
|
||||
|
||||
if (agentIndex != -1) {
|
||||
updateAgentWithData(&agents[agentIndex], packetData, dataBytes);
|
||||
return updateAgentWithData(&agents[agentIndex], packetData, dataBytes);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes) {
|
||||
int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes) {
|
||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
agent->recordBytesReceived(dataBytes);
|
||||
|
||||
if (agent->getActiveSocket() != NULL) {
|
||||
agent->recordBytesReceived(dataBytes);
|
||||
}
|
||||
|
||||
if (agent->getLinkedData() == NULL) {
|
||||
if (linkedDataCreateCallback != NULL) {
|
||||
linkedDataCreateCallback(agent);
|
||||
}
|
||||
}
|
||||
|
||||
agent->getLinkedData()->parseData(packetData, dataBytes);
|
||||
|
||||
return agent->getLinkedData()->parseData(packetData, dataBytes);
|
||||
}
|
||||
|
||||
int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
|
||||
|
@ -173,7 +183,7 @@ int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
|
|||
|
||||
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) {
|
||||
if (agent->getAgentId() == agentID) {
|
||||
return agent - agents.begin();
|
||||
}
|
||||
}
|
||||
|
@ -219,16 +229,19 @@ int AgentList::updateList(unsigned char *packetData, size_t dataBytes) {
|
|||
bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId) {
|
||||
std::vector<Agent>::iterator agent;
|
||||
|
||||
for (agent = agents.begin(); agent != agents.end(); agent++) {
|
||||
if (agent->matches(publicSocket, localSocket, agentType)) {
|
||||
// we already have this agent, stop checking
|
||||
break;
|
||||
if (publicSocket != NULL) {
|
||||
for (agent = agents.begin(); agent != agents.end(); agent++) {
|
||||
if (agent->matches(publicSocket, localSocket, agentType)) {
|
||||
// we already have this agent, stop checking
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
agent = agents.end();
|
||||
}
|
||||
|
||||
if (agent == agents.end()) {
|
||||
// we didn't have this agent, so add them
|
||||
|
||||
Agent newAgent = Agent(publicSocket, localSocket, agentType, agentId);
|
||||
|
||||
if (socketMatch(publicSocket, localSocket)) {
|
||||
|
@ -281,7 +294,7 @@ void AgentList::broadcastToAgents(unsigned char *broadcastData, size_t dataBytes
|
|||
void AgentList::handlePingReply(sockaddr *agentAddress) {
|
||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||
// 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
|
||||
// prioritize the private address so that we prune erroneous local matches
|
||||
if (socketMatch(agent->getPublicSocket(), agentAddress)) {
|
||||
agent->activatePublicSocket();
|
||||
break;
|
||||
|
@ -317,7 +330,8 @@ void *pingUnknownAgents(void *args) {
|
|||
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
|
||||
agent != agentList->getAgents().end();
|
||||
agent++) {
|
||||
if (agent->getActiveSocket() == NULL) {
|
||||
if (agent->getActiveSocket() == NULL
|
||||
&& (agent->getPublicSocket() != NULL && agent->getLocalSocket() != 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);
|
||||
|
|
|
@ -50,10 +50,10 @@ public:
|
|||
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId);
|
||||
|
||||
void processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes);
|
||||
void processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes, int numBytesPerAgent);
|
||||
void processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes);
|
||||
|
||||
void updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes);
|
||||
void updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes);
|
||||
int updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes);
|
||||
int updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes);
|
||||
|
||||
void broadcastToAgents(unsigned char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes);
|
||||
char getOwnerType();
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
// Agent Type Codes
|
||||
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_AVATAR = 'I'; // could also be injector???
|
||||
const char AGENT_TYPE_AUDIO_MIXER = 'M';
|
||||
const char AGENT_TYPE_AVATAR_MIXER = 'W';
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ void AudioRingBuffer::setBearing(float newBearing) {
|
|||
bearing = newBearing;
|
||||
}
|
||||
|
||||
void AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||
int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||
if (numBytes > (bufferLengthSamples * sizeof(int16_t))) {
|
||||
|
||||
unsigned char *dataPtr = sourceBuffer + 1;
|
||||
|
@ -140,7 +140,9 @@ void AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
|
||||
if (endOfLastWrite >= buffer + ringBufferLengthSamples) {
|
||||
endOfLastWrite = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
short AudioRingBuffer::diffLastWriteNextOutput()
|
||||
|
|
|
@ -18,7 +18,7 @@ class AudioRingBuffer : public AgentData {
|
|||
~AudioRingBuffer();
|
||||
AudioRingBuffer(const AudioRingBuffer &otherRingBuffer);
|
||||
|
||||
void parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
AudioRingBuffer* clone() const;
|
||||
|
||||
int16_t* getNextOutput();
|
||||
|
|
|
@ -104,9 +104,8 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber
|
|||
return newCode;
|
||||
}
|
||||
|
||||
float * firstVertexForCode(unsigned char * octalCode) {
|
||||
float * firstVertex = new float[3];
|
||||
memset(firstVertex, 0, 3 * sizeof(float));
|
||||
void copyFirstVertexForCode(unsigned char * octalCode, float* output) {
|
||||
memset(output, 0, 3 * sizeof(float));
|
||||
|
||||
float currentScale = 0.5;
|
||||
|
||||
|
@ -114,11 +113,16 @@ float * firstVertexForCode(unsigned char * octalCode) {
|
|||
int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
firstVertex[j] += currentScale * (int)oneAtBit(sectionIndex, 5 + j);
|
||||
output[j] += currentScale * (int)oneAtBit(sectionIndex, 5 + j);
|
||||
}
|
||||
|
||||
currentScale *= 0.5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float * firstVertexForCode(unsigned char * octalCode) {
|
||||
float * firstVertex = new float[3];
|
||||
copyFirstVertexForCode(octalCode, firstVertex);
|
||||
return firstVertex;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,11 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes);
|
|||
bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode);
|
||||
int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode);
|
||||
unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber);
|
||||
|
||||
|
||||
// Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return
|
||||
// but other than that these do the same thing.
|
||||
float * firstVertexForCode(unsigned char * octalCode);
|
||||
void copyFirstVertexForCode(unsigned char * octalCode, float* output);
|
||||
|
||||
#endif /* defined(__hifi__OctalCode__) */
|
||||
|
|
|
@ -28,20 +28,24 @@ using shared_lib::printLog;
|
|||
sockaddr_in destSockaddr, senderAddress;
|
||||
|
||||
bool socketMatch(sockaddr *first, sockaddr *second) {
|
||||
// utility function that indicates if two sockets are equivalent
|
||||
|
||||
// currently only compares two IPv4 addresses
|
||||
// expandable to IPv6 by adding else if for AF_INET6
|
||||
|
||||
if (first->sa_family != second->sa_family) {
|
||||
// not the same family, can't be equal
|
||||
return false;
|
||||
} else if (first->sa_family == AF_INET) {
|
||||
sockaddr_in *firstIn = (sockaddr_in *) first;
|
||||
sockaddr_in *secondIn = (sockaddr_in *) second;
|
||||
if (first != NULL && second != NULL) {
|
||||
// utility function that indicates if two sockets are equivalent
|
||||
|
||||
return firstIn->sin_addr.s_addr == secondIn->sin_addr.s_addr
|
||||
// currently only compares two IPv4 addresses
|
||||
// expandable to IPv6 by adding else if for AF_INET6
|
||||
|
||||
if (first->sa_family != second->sa_family) {
|
||||
// not the same family, can't be equal
|
||||
return false;
|
||||
} else if (first->sa_family == AF_INET) {
|
||||
sockaddr_in *firstIn = (sockaddr_in *) first;
|
||||
sockaddr_in *secondIn = (sockaddr_in *) second;
|
||||
|
||||
return firstIn->sin_addr.s_addr == secondIn->sin_addr.s_addr
|
||||
&& firstIn->sin_port == secondIn->sin_port;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,76 +1,68 @@
|
|||
/* ------------------------------------------------------
|
||||
|
||||
Axis Aligned Boxes - Lighthouse3D
|
||||
|
||||
-----------------------------------------------------*/
|
||||
//
|
||||
// AABox.h - Axis Aligned Boxes
|
||||
// hifi
|
||||
//
|
||||
// Added by Brad Hefta-Gaub on 04/11/13.
|
||||
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||
//
|
||||
// Simple axis aligned box class.
|
||||
//
|
||||
|
||||
#include "AABox.h"
|
||||
|
||||
|
||||
AABox::AABox(const glm::vec3& corner, float x, float y, float z) {
|
||||
setBox(corner,x,y,z);
|
||||
void AABox::scale(float scale) {
|
||||
_corner = _corner*scale;
|
||||
_size = _size*scale;
|
||||
}
|
||||
|
||||
AABox::AABox(void) {
|
||||
corner.x = 0; corner.y = 0; corner.z = 0;
|
||||
x = 1.0f;
|
||||
y = 1.0f;
|
||||
z = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
AABox::~AABox() {}
|
||||
|
||||
|
||||
|
||||
void AABox::setBox(const glm::vec3& corner, float x, float y, float z) {
|
||||
this->corner = corner;
|
||||
if (x < 0.0) {
|
||||
x = -x;
|
||||
this->corner.x -= x;
|
||||
void AABox::setBox(const glm::vec3& corner, const glm::vec3& size) {
|
||||
_corner = corner;
|
||||
_size = size;
|
||||
|
||||
// In the event that the caller gave us negative sizes, fix things up to be reasonable
|
||||
if (_size.x < 0.0) {
|
||||
_size.x = -size.x;
|
||||
_corner.x -= _size.x;
|
||||
}
|
||||
if (y < 0.0) {
|
||||
y = -y;
|
||||
this->corner.y -= y;
|
||||
if (_size.y < 0.0) {
|
||||
_size.y = -size.y;
|
||||
_corner.y -= _size.y;
|
||||
}
|
||||
if (z < 0.0) {
|
||||
z = -z;
|
||||
this->corner.z -= z;
|
||||
if (_size.z < 0.0) {
|
||||
_size.z = -size.z;
|
||||
_corner.z -= _size.z;
|
||||
}
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::vec3 AABox::getVertexP(const glm::vec3 &normal) {
|
||||
glm::vec3 res = corner;
|
||||
glm::vec3 AABox::getVertexP(const glm::vec3 &normal) const {
|
||||
glm::vec3 res = _corner;
|
||||
if (normal.x > 0)
|
||||
res.x += x;
|
||||
res.x += _size.x;
|
||||
|
||||
if (normal.y > 0)
|
||||
res.y += y;
|
||||
res.y += _size.y;
|
||||
|
||||
if (normal.z > 0)
|
||||
res.z += z;
|
||||
res.z += _size.z;
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::vec3 AABox::getVertexN(const glm::vec3 &normal) {
|
||||
glm::vec3 res = corner;
|
||||
glm::vec3 AABox::getVertexN(const glm::vec3 &normal) const {
|
||||
glm::vec3 res = _corner;
|
||||
|
||||
if (normal.x < 0)
|
||||
res.x += x;
|
||||
res.x += _size.x;
|
||||
|
||||
if (normal.y < 0)
|
||||
res.y += y;
|
||||
res.y += _size.y;
|
||||
|
||||
if (normal.z < 0)
|
||||
res.z += z;
|
||||
res.z += _size.z;
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
/* ------------------------------------------------------
|
||||
|
||||
Axis Aligned Boxes - Lighthouse3D
|
||||
|
||||
-----------------------------------------------------*/
|
||||
|
||||
//
|
||||
// AABox.h - Axis Aligned Boxes
|
||||
// hifi
|
||||
//
|
||||
// Added by Brad Hefta-Gaub on 04/11/13.
|
||||
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||
//
|
||||
// Simple axis aligned box class.
|
||||
//
|
||||
|
||||
#ifndef _AABOX_
|
||||
#define _AABOX_
|
||||
|
@ -15,18 +18,26 @@ class AABox
|
|||
|
||||
public:
|
||||
|
||||
glm::vec3 corner;
|
||||
float x,y,z;
|
||||
AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x,y,z) { };
|
||||
AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { };
|
||||
AABox() : _corner(0,0,0), _size(0,0,0) { }
|
||||
~AABox() { }
|
||||
|
||||
AABox(const glm::vec3 &corner, float x, float y, float z);
|
||||
AABox(void);
|
||||
~AABox();
|
||||
|
||||
void setBox(const glm::vec3& corner, float x, float y, float z);
|
||||
void setBox(const glm::vec3& corner, float x, float y, float z) { setBox(corner,glm::vec3(x,y,z)); };
|
||||
void setBox(const glm::vec3& corner, const glm::vec3& size);
|
||||
|
||||
// for use in frustum computations
|
||||
glm::vec3 getVertexP(const glm::vec3& normal);
|
||||
glm::vec3 getVertexN(const glm::vec3& normal);
|
||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||
|
||||
void scale(float scale);
|
||||
|
||||
const glm::vec3& getCorner() const { return _corner; };
|
||||
const glm::vec3& getSize() const { return _size; };
|
||||
|
||||
private:
|
||||
glm::vec3 _corner;
|
||||
glm::vec3 _size;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
// Plane.cpp
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Plane.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||
//
|
||||
// Simple plane class.
|
||||
//
|
||||
|
||||
#include "Plane.h"
|
||||
#include <stdio.h>
|
||||
|
@ -10,78 +16,55 @@
|
|||
using voxels_lib::printLog;
|
||||
|
||||
// These are some useful utilities that vec3 is missing
|
||||
float vec3_length(const glm::vec3& v) {
|
||||
return((float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z));
|
||||
void printVec3(const char* name, const glm::vec3& v) {
|
||||
printf("%s x=%f y=%f z=%f\n", name, v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
void vec3_normalize(glm::vec3& v) {
|
||||
|
||||
float len;
|
||||
|
||||
len = vec3_length(v);
|
||||
if (len) {
|
||||
v.x /= len;;
|
||||
v.y /= len;
|
||||
v.z /= len;
|
||||
}
|
||||
}
|
||||
|
||||
float vec3_innerProduct(const glm::vec3& v1,const glm::vec3& v2) {
|
||||
|
||||
return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Plane::Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
|
||||
|
||||
set3Points(v1,v2,v3);
|
||||
}
|
||||
|
||||
|
||||
Plane::Plane() {}
|
||||
|
||||
Plane::~Plane() {}
|
||||
|
||||
|
||||
void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
|
||||
glm::vec3 linev1v2, linev1v3;
|
||||
|
||||
linev1v2 = v2 - v1;
|
||||
linev1v3 = v3 - v1;
|
||||
|
||||
glm::vec3 aux1, aux2;
|
||||
// this will be perpendicular to both lines
|
||||
_normal = glm::cross(linev1v2,linev1v3);
|
||||
glm::normalize(_normal);
|
||||
|
||||
aux1 = v1 - v2;
|
||||
aux2 = v3 - v2;
|
||||
// this is a point on the plane
|
||||
_point = v2;
|
||||
|
||||
normal = aux2 * aux1;
|
||||
|
||||
vec3_normalize(normal);
|
||||
point = v2;
|
||||
d = -(vec3_innerProduct(normal,point));
|
||||
// the D coefficient from the form Ax+By+Cz=D
|
||||
_dCoefficient = -(glm::dot(_normal,_point));
|
||||
}
|
||||
|
||||
void Plane::setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point) {
|
||||
_point = point;
|
||||
_normal = normal;
|
||||
glm::normalize(_normal);
|
||||
|
||||
this->normal = normal;
|
||||
vec3_normalize(this->normal);
|
||||
d = -(vec3_innerProduct(this->normal,point));
|
||||
// the D coefficient from the form Ax+By+Cz=D
|
||||
_dCoefficient = -(glm::dot(_normal,_point));
|
||||
}
|
||||
|
||||
void Plane::setCoefficients(float a, float b, float c, float d) {
|
||||
// set the normal vector
|
||||
_normal = glm::vec3(a,b,c);
|
||||
|
||||
// set the normal vector
|
||||
normal = glm::vec3(a,b,c);
|
||||
//compute the lenght of the vector
|
||||
float l = normal.length();
|
||||
// normalize the vector
|
||||
normal = glm::vec3(a/l,b/l,c/l);
|
||||
// and divide d by th length as well
|
||||
this->d = d/l;
|
||||
//compute the lenght of the vector
|
||||
float l = glm::length(_normal);
|
||||
|
||||
// normalize the vector
|
||||
_normal = glm::vec3(a/l,b/l,c/l);
|
||||
|
||||
// and divide d by th length as well
|
||||
_dCoefficient = d/l;
|
||||
}
|
||||
|
||||
float Plane::distance(const glm::vec3 &p) {
|
||||
return (d + vec3_innerProduct(normal,p));
|
||||
float Plane::distance(const glm::vec3 &point) const {
|
||||
return (_dCoefficient + glm::dot(_normal,point));
|
||||
}
|
||||
|
||||
void Plane::print() {
|
||||
//printLog("Plane(");normal.print();printLog("# %f)",d);
|
||||
void Plane::print() const {
|
||||
printf("Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f\n",
|
||||
_point.x, _point.y, _point.z, _normal.x, _normal.y, _normal.z, _dCoefficient);
|
||||
}
|
||||
|
|
|
@ -1,34 +1,43 @@
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
// Plane.h - inspired and modified from lighthouse3d.com
|
||||
//
|
||||
|
||||
// Plane.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||
//
|
||||
// Simple plane class.
|
||||
//
|
||||
|
||||
#ifndef _PLANE_
|
||||
#define _PLANE_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
||||
class Plane
|
||||
{
|
||||
|
||||
public:
|
||||
Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); }
|
||||
Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {};
|
||||
~Plane() {} ;
|
||||
|
||||
glm::vec3 normal,point;
|
||||
float d;
|
||||
|
||||
|
||||
Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3);
|
||||
Plane(void);
|
||||
~Plane();
|
||||
|
||||
// methods for defining the plane
|
||||
void set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3);
|
||||
void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point);
|
||||
void setCoefficients(float a, float b, float c, float d);
|
||||
float distance(const glm::vec3 &p);
|
||||
|
||||
void print();
|
||||
// getters
|
||||
const glm::vec3& getNormal() const { return _normal; };
|
||||
const glm::vec3& getPoint() const { return _point; };
|
||||
float getDCoefficient() const { return _dCoefficient; };
|
||||
|
||||
// utilities
|
||||
float distance(const glm::vec3 &point) const;
|
||||
void print() const;
|
||||
|
||||
private:
|
||||
glm::vec3 _normal;
|
||||
glm::vec3 _point;
|
||||
float _dCoefficient;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -53,102 +53,134 @@ void ViewFrustum::calculate() {
|
|||
glm::vec3 front = _direction;
|
||||
|
||||
// Calculating field of view.
|
||||
float fovInRadians = this->_fieldOfView * PI_OVER_180;
|
||||
float fovInRadians = _fieldOfView * PI_OVER_180;
|
||||
|
||||
float twoTimesTanHalfFOV = 2.0f * tan(fovInRadians/2.0f);
|
||||
|
||||
// Do we need this?
|
||||
//tang = (float)tan(ANG2RAD * angle * 0.5) ;
|
||||
|
||||
float nearClip = this->_nearClip;
|
||||
float farClip = this->_farClip;
|
||||
float nearClip = _nearClip;
|
||||
float farClip = _farClip;
|
||||
|
||||
this->_nearHeight = (twoTimesTanHalfFOV * nearClip);
|
||||
this->_nearWidth = this->_nearHeight * this->_aspectRatio;
|
||||
this->_farHeight = (twoTimesTanHalfFOV * farClip);
|
||||
this->_farWidth = this->_farHeight * this->_aspectRatio;
|
||||
_nearHeight = (twoTimesTanHalfFOV * nearClip);
|
||||
_nearWidth = _nearHeight * _aspectRatio;
|
||||
_farHeight = (twoTimesTanHalfFOV * farClip);
|
||||
_farWidth = _farHeight * _aspectRatio;
|
||||
|
||||
float farHalfHeight = (this->_farHeight * 0.5f);
|
||||
float farHalfWidth = (this->_farWidth * 0.5f);
|
||||
this->_farCenter = this->_position+front * farClip;
|
||||
this->_farTopLeft = this->_farCenter + (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
|
||||
this->_farTopRight = this->_farCenter + (this->_up * farHalfHeight) + (this->_right * farHalfWidth);
|
||||
this->_farBottomLeft = this->_farCenter - (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
|
||||
this->_farBottomRight = this->_farCenter - (this->_up * farHalfHeight) + (this->_right * farHalfWidth);
|
||||
float farHalfHeight = (_farHeight * 0.5f);
|
||||
float farHalfWidth = (_farWidth * 0.5f);
|
||||
_farCenter = _position+front * farClip;
|
||||
_farTopLeft = _farCenter + (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||
_farTopRight = _farCenter + (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||
_farBottomLeft = _farCenter - (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||
_farBottomRight = _farCenter - (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||
|
||||
float nearHalfHeight = (this->_nearHeight * 0.5f);
|
||||
float nearHalfWidth = (this->_nearWidth * 0.5f);
|
||||
this->_nearCenter = this->_position+front * nearClip;
|
||||
this->_nearTopLeft = this->_nearCenter + (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth);
|
||||
this->_nearTopRight = this->_nearCenter + (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth);
|
||||
this->_nearBottomLeft = this->_nearCenter - (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth);
|
||||
this->_nearBottomRight = this->_nearCenter - (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth);
|
||||
float nearHalfHeight = (_nearHeight * 0.5f);
|
||||
float nearHalfWidth = (_nearWidth * 0.5f);
|
||||
_nearCenter = _position+front * nearClip;
|
||||
_nearTopLeft = _nearCenter + (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||
_nearTopRight = _nearCenter + (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||
_nearBottomLeft = _nearCenter - (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||
_nearBottomRight = _nearCenter - (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||
|
||||
// compute the six planes
|
||||
// the function set3Points assumes that the points
|
||||
// are given in counter clockwise order
|
||||
this->_planes[TOPP].set3Points(this->_nearTopRight,this->_nearTopLeft,this->_farTopLeft);
|
||||
this->_planes[BOTTOMP].set3Points(this->_nearBottomLeft,this->_nearBottomRight,this->_farBottomRight);
|
||||
this->_planes[LEFTP].set3Points(this->_nearTopLeft,this->_nearBottomLeft,this->_farBottomLeft);
|
||||
this->_planes[RIGHTP].set3Points(this->_nearBottomRight,this->_nearTopRight,this->_farBottomRight);
|
||||
this->_planes[NEARP].set3Points(this->_nearTopLeft,this->_nearTopRight,this->_nearBottomRight);
|
||||
this->_planes[FARP].set3Points(this->_farTopRight,this->_farTopLeft,this->_farBottomLeft);
|
||||
// The planes are defined such that the normal points towards the inside of the view frustum.
|
||||
// Testing if an object is inside the view frustum is performed by computing on which side of
|
||||
// the plane the object resides. This can be done computing the signed distance from the point
|
||||
// to the plane. If it is on the side that the normal is pointing, i.e. the signed distance
|
||||
// is positive, then it is on the right side of the respective plane. If an object is on the
|
||||
// right side of all six planes then the object is inside the frustum.
|
||||
|
||||
// the function set3Points assumes that the points are given in counter clockwise order, assume you
|
||||
// are inside the frustum, facing the plane. Start with any point, and go counter clockwise for
|
||||
// three consecutive points
|
||||
|
||||
_planes[TOP_PLANE ].set3Points(_nearTopRight,_nearTopLeft,_farTopLeft);
|
||||
_planes[BOTTOM_PLANE].set3Points(_nearBottomLeft,_nearBottomRight,_farBottomRight);
|
||||
_planes[LEFT_PLANE ].set3Points(_nearBottomLeft,_farBottomLeft,_farTopLeft);
|
||||
_planes[RIGHT_PLANE ].set3Points(_farBottomRight,_nearBottomRight,_nearTopRight);
|
||||
_planes[NEAR_PLANE ].set3Points(_nearBottomRight,_nearBottomLeft,_nearTopLeft);
|
||||
_planes[FAR_PLANE ].set3Points(_farBottomLeft,_farBottomRight,_farTopRight);
|
||||
|
||||
}
|
||||
|
||||
void ViewFrustum::dump() {
|
||||
void ViewFrustum::dump() const {
|
||||
|
||||
printLog("position.x=%f, position.y=%f, position.z=%f\n", this->_position.x, this->_position.y, this->_position.z);
|
||||
printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", this->_direction.x, this->_direction.y, this->_direction.z);
|
||||
printLog("up.x=%f, up.y=%f, up.z=%f\n", this->_up.x, this->_up.y, this->_up.z);
|
||||
printLog("right.x=%f, right.y=%f, right.z=%f\n", this->_right.x, this->_right.y, this->_right.z);
|
||||
printLog("position.x=%f, position.y=%f, position.z=%f\n", _position.x, _position.y, _position.z);
|
||||
printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", _direction.x, _direction.y, _direction.z);
|
||||
printLog("up.x=%f, up.y=%f, up.z=%f\n", _up.x, _up.y, _up.z);
|
||||
printLog("right.x=%f, right.y=%f, right.z=%f\n", _right.x, _right.y, _right.z);
|
||||
|
||||
printLog("farDist=%f\n", this->_farClip);
|
||||
printLog("farHeight=%f\n", this->_farHeight);
|
||||
printLog("farWidth=%f\n", this->_farWidth);
|
||||
printLog("farDist=%f\n", _farClip);
|
||||
printLog("farHeight=%f\n", _farHeight);
|
||||
printLog("farWidth=%f\n", _farWidth);
|
||||
|
||||
printLog("nearDist=%f\n", this->_nearClip);
|
||||
printLog("nearHeight=%f\n", this->_nearHeight);
|
||||
printLog("nearWidth=%f\n", this->_nearWidth);
|
||||
printLog("nearDist=%f\n", _nearClip);
|
||||
printLog("nearHeight=%f\n", _nearHeight);
|
||||
printLog("nearWidth=%f\n", _nearWidth);
|
||||
|
||||
printLog("farCenter.x=%f, farCenter.y=%f, farCenter.z=%f\n",
|
||||
this->_farCenter.x, this->_farCenter.y, this->_farCenter.z);
|
||||
_farCenter.x, _farCenter.y, _farCenter.z);
|
||||
printLog("farTopLeft.x=%f, farTopLeft.y=%f, farTopLeft.z=%f\n",
|
||||
this->_farTopLeft.x, this->_farTopLeft.y, this->_farTopLeft.z);
|
||||
_farTopLeft.x, _farTopLeft.y, _farTopLeft.z);
|
||||
printLog("farTopRight.x=%f, farTopRight.y=%f, farTopRight.z=%f\n",
|
||||
this->_farTopRight.x, this->_farTopRight.y, this->_farTopRight.z);
|
||||
_farTopRight.x, _farTopRight.y, _farTopRight.z);
|
||||
printLog("farBottomLeft.x=%f, farBottomLeft.y=%f, farBottomLeft.z=%f\n",
|
||||
this->_farBottomLeft.x, this->_farBottomLeft.y, this->_farBottomLeft.z);
|
||||
_farBottomLeft.x, _farBottomLeft.y, _farBottomLeft.z);
|
||||
printLog("farBottomRight.x=%f, farBottomRight.y=%f, farBottomRight.z=%f\n",
|
||||
this->_farBottomRight.x, this->_farBottomRight.y, this->_farBottomRight.z);
|
||||
_farBottomRight.x, _farBottomRight.y, _farBottomRight.z);
|
||||
|
||||
printLog("nearCenter.x=%f, nearCenter.y=%f, nearCenter.z=%f\n",
|
||||
this->_nearCenter.x, this->_nearCenter.y, this->_nearCenter.z);
|
||||
_nearCenter.x, _nearCenter.y, _nearCenter.z);
|
||||
printLog("nearTopLeft.x=%f, nearTopLeft.y=%f, nearTopLeft.z=%f\n",
|
||||
this->_nearTopLeft.x, this->_nearTopLeft.y, this->_nearTopLeft.z);
|
||||
_nearTopLeft.x, _nearTopLeft.y, _nearTopLeft.z);
|
||||
printLog("nearTopRight.x=%f, nearTopRight.y=%f, nearTopRight.z=%f\n",
|
||||
this->_nearTopRight.x, this->_nearTopRight.y, this->_nearTopRight.z);
|
||||
_nearTopRight.x, _nearTopRight.y, _nearTopRight.z);
|
||||
printLog("nearBottomLeft.x=%f, nearBottomLeft.y=%f, nearBottomLeft.z=%f\n",
|
||||
this->_nearBottomLeft.x, this->_nearBottomLeft.y, this->_nearBottomLeft.z);
|
||||
_nearBottomLeft.x, _nearBottomLeft.y, _nearBottomLeft.z);
|
||||
printLog("nearBottomRight.x=%f, nearBottomRight.y=%f, nearBottomRight.z=%f\n",
|
||||
this->_nearBottomRight.x, this->_nearBottomRight.y, this->_nearBottomRight.z);
|
||||
_nearBottomRight.x, _nearBottomRight.y, _nearBottomRight.z);
|
||||
}
|
||||
|
||||
|
||||
int ViewFrustum::pointInFrustum(glm::vec3 &p) {
|
||||
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||
const char* ViewFrustum::debugPlaneName (int plane) const {
|
||||
switch (plane) {
|
||||
case TOP_PLANE: return "Top Plane";
|
||||
case BOTTOM_PLANE: return "Bottom Plane";
|
||||
case LEFT_PLANE: return "Left Plane";
|
||||
case RIGHT_PLANE: return "Right Plane";
|
||||
case NEAR_PLANE: return "Near Plane";
|
||||
case FAR_PLANE: return "Far Plane";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
||||
int ViewFrustum::pointInFrustum(const glm::vec3& point) const {
|
||||
|
||||
//printf("ViewFrustum::pointInFrustum() point=%f,%f,%f\n",point.x,point.y,point.z);
|
||||
//dump();
|
||||
|
||||
int result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
if (this->_planes[i].distance(p) < 0)
|
||||
float distance = _planes[i].distance(point);
|
||||
|
||||
//printf("plane[%d] %s -- distance=%f \n",i,debugPlaneName(i),distance);
|
||||
|
||||
if (distance < 0) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
int ViewFrustum::sphereInFrustum(glm::vec3 ¢er, float radius) {
|
||||
int ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
|
||||
int result = INSIDE;
|
||||
float distance;
|
||||
for(int i=0; i < 6; i++) {
|
||||
distance = this->_planes[i].distance(center);
|
||||
distance = _planes[i].distance(center);
|
||||
if (distance < -radius)
|
||||
return OUTSIDE;
|
||||
else if (distance < radius)
|
||||
|
@ -158,13 +190,37 @@ int ViewFrustum::sphereInFrustum(glm::vec3 ¢er, float radius) {
|
|||
}
|
||||
|
||||
|
||||
int ViewFrustum::boxInFrustum(AABox &b) {
|
||||
int ViewFrustum::boxInFrustum(const AABox& box) const {
|
||||
|
||||
//printf("ViewFrustum::boxInFrustum() box.corner=%f,%f,%f x=%f\n",
|
||||
// box.getCorner().x,box.getCorner().y,box.getCorner().z,box.getSize().x);
|
||||
int result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
if (this->_planes[i].distance(b.getVertexP(this->_planes[i].normal)) < 0)
|
||||
|
||||
//printf("plane[%d] -- point(%f,%f,%f) normal(%f,%f,%f) d=%f \n",i,
|
||||
// _planes[i].getPoint().x, _planes[i].getPoint().y, _planes[i].getPoint().z,
|
||||
// _planes[i].getNormal().x, _planes[i].getNormal().y, _planes[i].getNormal().z,
|
||||
// _planes[i].getDCoefficient()
|
||||
//);
|
||||
|
||||
glm::vec3 normal = _planes[i].getNormal();
|
||||
glm::vec3 boxVertexP = box.getVertexP(normal);
|
||||
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||
|
||||
glm::vec3 boxVertexN = box.getVertexN(normal);
|
||||
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||
|
||||
//printf("plane[%d] normal=(%f,%f,%f) bVertexP=(%f,%f,%f) planeToBoxVertexPDistance=%f boxVertexN=(%f,%f,%f) planeToBoxVertexNDistance=%f\n",i,
|
||||
// normal.x,normal.y,normal.z,
|
||||
// boxVertexP.x,boxVertexP.y,boxVertexP.z,planeToBoxVertexPDistance,
|
||||
// boxVertexN.x,boxVertexN.y,boxVertexN.z,planeToBoxVertexNDistance
|
||||
// );
|
||||
|
||||
if (planeToBoxVertexPDistance < 0) {
|
||||
return OUTSIDE;
|
||||
else if (this->_planes[i].distance(b.getVertexN(this->_planes[i].normal)) < 0)
|
||||
} else if (planeToBoxVertexNDistance < 0) {
|
||||
result = INTERSECT;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
|
|
@ -45,15 +45,23 @@ private:
|
|||
glm::vec3 _nearTopRight;
|
||||
glm::vec3 _nearBottomLeft;
|
||||
glm::vec3 _nearBottomRight;
|
||||
enum { TOPP = 0, BOTTOMP, LEFTP, RIGHTP, NEARP, FARP };
|
||||
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||
Plane _planes[6]; // How will this be used?
|
||||
|
||||
const char* debugPlaneName (int plane) const;
|
||||
|
||||
public:
|
||||
// setters for camera attributes
|
||||
void setPosition (const glm::vec3& p) { _position = p; }
|
||||
void setOrientation (const glm::vec3& d, const glm::vec3& u, const glm::vec3& r )
|
||||
{ _direction = d; _up = u; _right = r; }
|
||||
|
||||
// getters for camera attributes
|
||||
const glm::vec3& getPosition() const { return _position; };
|
||||
const glm::vec3& getDirection() const { return _direction; };
|
||||
const glm::vec3& getUp() const { return _up; };
|
||||
const glm::vec3& getRight() const { return _right; };
|
||||
|
||||
// setters for lens attributes
|
||||
void setFieldOfView ( float f ) { _fieldOfView = f; }
|
||||
void setAspectRatio ( float a ) { _aspectRatio = a; }
|
||||
|
@ -82,13 +90,13 @@ public:
|
|||
|
||||
ViewFrustum();
|
||||
|
||||
void dump();
|
||||
void dump() const;
|
||||
|
||||
enum {OUTSIDE, INTERSECT, INSIDE};
|
||||
|
||||
int pointInFrustum(glm::vec3 &p);
|
||||
int sphereInFrustum(glm::vec3 ¢er, float radius);
|
||||
int boxInFrustum(AABox &b);
|
||||
int pointInFrustum(const glm::vec3& point) const;
|
||||
int sphereInFrustum(const glm::vec3& center, float radius) const;
|
||||
int boxInFrustum(const AABox& box) const;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -6,17 +6,23 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstring>
|
||||
#include "SharedUtil.h"
|
||||
//#include "voxels_Log.h"
|
||||
#include "VoxelNode.h"
|
||||
#include "OctalCode.h"
|
||||
#include "AABox.h"
|
||||
|
||||
// using voxels_lib::printLog;
|
||||
|
||||
VoxelNode::VoxelNode() {
|
||||
octalCode = NULL;
|
||||
|
||||
#ifdef HAS_FALSE_COLOR
|
||||
_falseColored = false; // assume true color
|
||||
#endif
|
||||
|
||||
// default pointers to child nodes to NULL
|
||||
for (int i = 0; i < 8; i++) {
|
||||
children[i] = NULL;
|
||||
|
@ -28,13 +34,36 @@ VoxelNode::~VoxelNode() {
|
|||
|
||||
// delete all of this node's children
|
||||
for (int i = 0; i < 8; i++) {
|
||||
delete children[i];
|
||||
if (children[i]) {
|
||||
delete children[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelNode::getAABox(AABox& box) const {
|
||||
|
||||
glm::vec3 corner;
|
||||
glm::vec3 size;
|
||||
|
||||
// copy corner into box
|
||||
copyFirstVertexForCode(octalCode,(float*)&corner);
|
||||
|
||||
// this tells you the "size" of the voxel
|
||||
float voxelScale = 1 / powf(2, *octalCode);
|
||||
size = glm::vec3(voxelScale,voxelScale,voxelScale);
|
||||
|
||||
box.setBox(corner,size);
|
||||
}
|
||||
|
||||
void VoxelNode::addChildAtIndex(int childIndex) {
|
||||
children[childIndex] = new VoxelNode();
|
||||
|
||||
// XXXBHG - When the node is constructed, it should be cleanly set up as
|
||||
// true colored, but for some reason, not so much. I've added a a basecamp
|
||||
// to-do to research this. But for now we'll use belt and suspenders and set
|
||||
// it to not-false-colored here!
|
||||
children[childIndex]->setFalseColored(false);
|
||||
|
||||
// give this child its octal code
|
||||
children[childIndex]->octalCode = childOctalCode(octalCode, childIndex);
|
||||
}
|
||||
|
@ -43,30 +72,60 @@ void VoxelNode::addChildAtIndex(int childIndex) {
|
|||
void VoxelNode::setColorFromAverageOfChildren() {
|
||||
int colorArray[4] = {0,0,0,0};
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (children[i] != NULL && children[i]->color[3] == 1) {
|
||||
if (children[i] != NULL && children[i]->isColored()) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
colorArray[j] += children[i]->color[j];
|
||||
colorArray[j] += children[i]->getTrueColor()[j]; // color averaging should always be based on true colors
|
||||
}
|
||||
colorArray[3]++;
|
||||
}
|
||||
}
|
||||
|
||||
nodeColor newColor = { 0, 0, 0, 0};
|
||||
if (colorArray[3] > 4) {
|
||||
// we need at least 4 colored children to have an average color value
|
||||
// or if we have none we generate random values
|
||||
for (int c = 0; c < 3; c++) {
|
||||
// set the average color value
|
||||
color[c] = colorArray[c] / colorArray[3];
|
||||
newColor[c] = colorArray[c] / colorArray[3];
|
||||
}
|
||||
// set the alpha to 1 to indicate that this isn't transparent
|
||||
color[3] = 1;
|
||||
} else {
|
||||
// some children, but not enough
|
||||
// set this node's alpha to 0
|
||||
color[3] = 0;
|
||||
}
|
||||
newColor[3] = 1;
|
||||
}
|
||||
// actually set our color, note, if we didn't have enough children
|
||||
// this will be the default value all zeros, and therefore be marked as
|
||||
// transparent with a 4th element of 0
|
||||
setColor(newColor);
|
||||
}
|
||||
|
||||
// Note: !NO_FALSE_COLOR implementations of setFalseColor(), setFalseColored(), and setColor() here.
|
||||
// the actual NO_FALSE_COLOR version are inline in the VoxelNode.h
|
||||
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||
void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) {
|
||||
_falseColored=true;
|
||||
_currentColor[0] = red;
|
||||
_currentColor[1] = green;
|
||||
_currentColor[2] = blue;
|
||||
_currentColor[3] = 1; // XXXBHG - False colors are always considered set
|
||||
}
|
||||
|
||||
void VoxelNode::setFalseColored(bool isFalseColored) {
|
||||
// if we were false colored, and are no longer false colored, then swap back
|
||||
if (_falseColored && !isFalseColored) {
|
||||
memcpy(&_currentColor,&_trueColor,sizeof(nodeColor));
|
||||
}
|
||||
_falseColored = isFalseColored;
|
||||
};
|
||||
|
||||
|
||||
void VoxelNode::setColor(const nodeColor& color) {
|
||||
//printf("VoxelNode::setColor() isFalseColored=%s\n",_falseColored ? "Yes" : "No");
|
||||
memcpy(&_trueColor,&color,sizeof(nodeColor));
|
||||
if (!_falseColored) {
|
||||
memcpy(&_currentColor,&color,sizeof(nodeColor));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// will detect if children are leaves AND the same color
|
||||
// and in that case will delete the children and make this node
|
||||
// a leaf, returns TRUE if all the leaves are collapsed into a
|
||||
|
@ -77,16 +136,17 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
|||
int red,green,blue;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// if no child, or child doesn't have a color
|
||||
if (children[i] == NULL || children[i]->color[3] != 1) {
|
||||
if (children[i] == NULL || !children[i]->isColored()) {
|
||||
allChildrenMatch=false;
|
||||
//printLog("SADNESS child missing or not colored! i=%d\n",i);
|
||||
break;
|
||||
} else {
|
||||
if (i==0) {
|
||||
red = children[i]->color[0];
|
||||
green = children[i]->color[1];
|
||||
blue = children[i]->color[2];
|
||||
} else if (red != children[i]->color[0] || green != children[i]->color[1] || blue != children[i]->color[2]) {
|
||||
red = children[i]->getColor()[0];
|
||||
green = children[i]->getColor()[1];
|
||||
blue = children[i]->getColor()[2];
|
||||
} else if (red != children[i]->getColor()[0] ||
|
||||
green != children[i]->getColor()[1] || blue != children[i]->getColor()[2]) {
|
||||
allChildrenMatch=false;
|
||||
break;
|
||||
}
|
||||
|
@ -100,18 +160,22 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
|||
delete children[i]; // delete all the child nodes
|
||||
children[i]=NULL; // set it to NULL
|
||||
}
|
||||
color[0]=red;
|
||||
color[1]=green;
|
||||
color[2]=blue;
|
||||
color[3]=1; // color is set
|
||||
nodeColor collapsedColor;
|
||||
collapsedColor[0]=red;
|
||||
collapsedColor[1]=green;
|
||||
collapsedColor[2]=blue;
|
||||
collapsedColor[3]=1; // color is set
|
||||
setColor(collapsedColor);
|
||||
}
|
||||
return allChildrenMatch;
|
||||
}
|
||||
|
||||
void VoxelNode::setRandomColor(int minimumBrightness) {
|
||||
nodeColor newColor;
|
||||
for (int c = 0; c < 3; c++) {
|
||||
color[c] = randomColorValue(minimumBrightness);
|
||||
newColor[c] = randomColorValue(minimumBrightness);
|
||||
}
|
||||
|
||||
color[3] = 1;
|
||||
newColor[3] = 1;
|
||||
setColor(newColor);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,18 @@
|
|||
#ifndef __hifi__VoxelNode__
|
||||
#define __hifi__VoxelNode__
|
||||
|
||||
#include "AABox.h"
|
||||
|
||||
typedef unsigned char colorPart;
|
||||
typedef unsigned char nodeColor[4];
|
||||
|
||||
class VoxelNode {
|
||||
private:
|
||||
nodeColor _trueColor;
|
||||
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||
nodeColor _currentColor;
|
||||
bool _falseColored;
|
||||
#endif
|
||||
public:
|
||||
VoxelNode();
|
||||
~VoxelNode();
|
||||
|
@ -20,8 +31,27 @@ public:
|
|||
bool collapseIdenticalLeaves();
|
||||
|
||||
unsigned char *octalCode;
|
||||
unsigned char color[4];
|
||||
VoxelNode *children[8];
|
||||
|
||||
bool isColored() const { return (_trueColor[3]==1); };
|
||||
|
||||
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||
void setFalseColor(colorPart red, colorPart green, colorPart blue);
|
||||
void setFalseColored(bool isFalseColored);
|
||||
bool getFalseColored() { return _falseColored; };
|
||||
void setColor(const nodeColor& color);
|
||||
const nodeColor& getTrueColor() const { return _trueColor; };
|
||||
const nodeColor& getColor() const { return _currentColor; };
|
||||
#else
|
||||
void setFalseColor(colorPart red, colorPart green, colorPart blue) { /* no op */ };
|
||||
void setFalseColored(bool isFalseColored) { /* no op */ };
|
||||
bool getFalseColored() { return false; };
|
||||
void setColor(const nodeColor& color) { memcpy(_trueColor,color,sizeof(nodeColor)); };
|
||||
const nodeColor& getTrueColor() const { return _trueColor; };
|
||||
const nodeColor& getColor() const { return _trueColor; };
|
||||
#endif
|
||||
|
||||
void getAABox(AABox& box) const;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__VoxelNode__) */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "PacketHeaders.h"
|
||||
#include "OctalCode.h"
|
||||
#include "VoxelTree.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include <fstream> // to load voxels from file
|
||||
|
||||
using voxels_lib::printLog;
|
||||
|
@ -66,6 +67,27 @@ VoxelTree::~VoxelTree() {
|
|||
}
|
||||
}
|
||||
|
||||
// Recurses voxel tree calling the RecurseVoxelTreeOperation function for each node.
|
||||
// stops recursion if operation function returns false.
|
||||
void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData) {
|
||||
recurseNodeWithOperation(rootNode, operation,extraData);
|
||||
}
|
||||
|
||||
// Recurses voxel node with an operation function
|
||||
void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData) {
|
||||
// call the operation function going "down" first, stop deeper recursion if function returns false
|
||||
if (operation(node,true,extraData)) {
|
||||
for (int i = 0; i < sizeof(node->children)/sizeof(node->children[0]); i++) {
|
||||
VoxelNode* child = node->children[i];
|
||||
if (child) {
|
||||
recurseNodeWithOperation(child,operation,extraData);
|
||||
}
|
||||
}
|
||||
// call operation on way back up
|
||||
operation(node,false,extraData);
|
||||
}
|
||||
}
|
||||
|
||||
VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode) {
|
||||
// find the appropriate branch index based on this ancestorNode
|
||||
if (*needleCode > 0) {
|
||||
|
@ -127,8 +149,10 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode,
|
|||
}
|
||||
|
||||
// pull the color for this child
|
||||
memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3);
|
||||
destinationNode->children[i]->color[3] = 1;
|
||||
nodeColor newColor;
|
||||
memcpy(newColor, nodeData + bytesRead, 3);
|
||||
newColor[3] = 1;
|
||||
destinationNode->children[i]->setColor(newColor);
|
||||
this->voxelsColored++;
|
||||
this->voxelsColoredStats.updateAverage(1);
|
||||
|
||||
|
@ -233,15 +257,20 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
|
|||
|
||||
// give this node its color
|
||||
int octalCodeBytes = bytesRequiredForCodeLength(*codeColorBuffer);
|
||||
memcpy(lastCreatedNode->color, codeColorBuffer + octalCodeBytes, 3);
|
||||
lastCreatedNode->color[3] = 1;
|
||||
|
||||
nodeColor newColor;
|
||||
memcpy(newColor, codeColorBuffer + octalCodeBytes, 3);
|
||||
newColor[3] = 1;
|
||||
lastCreatedNode->setColor(newColor);
|
||||
}
|
||||
|
||||
unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||
VoxelNode *currentVoxelNode,
|
||||
MarkerNode *currentMarkerNode,
|
||||
float * agentPosition,
|
||||
const glm::vec3& agentPosition,
|
||||
float thisNodePosition[3],
|
||||
const ViewFrustum& viewFrustum,
|
||||
bool viewFrustumCulling,
|
||||
unsigned char * stopOctalCode)
|
||||
{
|
||||
static unsigned char *initialBitstreamPos = bitstreamBuffer;
|
||||
|
@ -268,22 +297,38 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
unsigned char * childMaskPointer = NULL;
|
||||
|
||||
float halfUnitForVoxel = powf(0.5, *currentVoxelNode->octalCode) * (0.5 * TREE_SCALE);
|
||||
|
||||
// XXXBHG - Note: It appears as if the X and Z coordinates of Head or Agent are flip-flopped relative to the
|
||||
// coords of the voxel space. This flip flop causes LOD behavior to be extremely odd. This is my temporary hack
|
||||
// to fix this behavior. To disable this swap, set swapXandZ to false.
|
||||
// XXXBHG - 2013/04/11 - adding a note to my branch, I think this code is now broken.
|
||||
bool swapXandZ=true;
|
||||
float agentX = swapXandZ ? agentPosition[2] : agentPosition[0];
|
||||
float agentZ = swapXandZ ? agentPosition[0] : agentPosition[2];
|
||||
|
||||
float distanceToVoxelCenter = sqrtf(powf(agentX - thisNodePosition[0] - halfUnitForVoxel, 2) +
|
||||
float distanceToVoxelCenter = sqrtf(powf(agentPosition[0] - thisNodePosition[0] - halfUnitForVoxel, 2) +
|
||||
powf(agentPosition[1] - thisNodePosition[1] - halfUnitForVoxel, 2) +
|
||||
powf(agentZ - thisNodePosition[2] - halfUnitForVoxel, 2));
|
||||
powf(agentPosition[2] - thisNodePosition[2] - halfUnitForVoxel, 2));
|
||||
|
||||
// If the voxel is outside of the view frustum, then don't bother sending or recursing
|
||||
bool voxelInView = true;
|
||||
|
||||
/**** not yet working properly at this level! **************************************************************************
|
||||
if (viewFrustumCulling) {
|
||||
float fullUnitForVoxel = halfUnitForVoxel * 2.0f;
|
||||
AABox voxelBox;
|
||||
voxelBox.setBox(glm::vec3(thisNodePosition[0],thisNodePosition[1],thisNodePosition[2]),
|
||||
fullUnitForVoxel,fullUnitForVoxel,fullUnitForVoxel);
|
||||
|
||||
//printf("VoxelTree::loadBitstreamBuffer() voxelBox.corner=(%f,%f,%f) x=%f \n",
|
||||
// voxelBox.getCorner().x,voxelBox.getCorner().y,voxelBox.getCorner().z, voxelBox.getSize().x);
|
||||
|
||||
voxelInView = (ViewFrustum::OUTSIDE != viewFrustum.pointInFrustum(voxelBox.getCorner()));
|
||||
} else {
|
||||
voxelInView = true;
|
||||
}
|
||||
**********************************************************************************************************************/
|
||||
|
||||
// if the distance to this voxel's center is less than the threshold
|
||||
// distance for its children, we should send the children
|
||||
if (distanceToVoxelCenter < boundaryDistanceForRenderLevel(*currentVoxelNode->octalCode + 1)) {
|
||||
bool voxelIsClose = (distanceToVoxelCenter < boundaryDistanceForRenderLevel(*currentVoxelNode->octalCode + 1));
|
||||
bool sendVoxel = voxelIsClose && voxelInView;
|
||||
|
||||
//printf("VoxelTree::loadBitstreamBuffer() sendVoxel=%d, voxelIsClose=%d, voxelInView=%d, viewFrustumCulling=%d\n",
|
||||
// sendVoxel, voxelIsClose, voxelInView, viewFrustumCulling);
|
||||
|
||||
if (sendVoxel) {
|
||||
|
||||
// write this voxel's data if we're below or at
|
||||
// or at the same level as the stopOctalCode
|
||||
|
@ -315,16 +360,78 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
||||
// check if the child exists and is not transparent
|
||||
if (currentVoxelNode->children[i] != NULL
|
||||
&& currentVoxelNode->children[i]->color[3] != 0) {
|
||||
// Rules for including a child:
|
||||
// 1) child must exists
|
||||
if ((currentVoxelNode->children[i] != NULL)) {
|
||||
// 2) child must have a color...
|
||||
if (currentVoxelNode->children[i]->isColored()) {
|
||||
|
||||
// copy in the childs color to bitstreamBuffer
|
||||
memcpy(colorPointer, currentVoxelNode->children[i]->color, 3);
|
||||
colorPointer += 3;
|
||||
unsigned char* childOctalCode = currentVoxelNode->children[i]->octalCode;
|
||||
|
||||
float childPosition[3];
|
||||
copyFirstVertexForCode(childOctalCode,(float*)&childPosition);
|
||||
childPosition[0] *= TREE_SCALE; // scale it up
|
||||
childPosition[1] *= TREE_SCALE; // scale it up
|
||||
childPosition[2] *= TREE_SCALE; // scale it up
|
||||
|
||||
// set the colorMask by bitshifting the value of childExists
|
||||
*bitstreamBuffer += (1 << (7 - i));
|
||||
float halfChildVoxel = powf(0.5, *childOctalCode) * (0.5 * TREE_SCALE);
|
||||
float distanceToChildCenter = sqrtf(powf(agentPosition[0] - childPosition[0] - halfChildVoxel, 2) +
|
||||
powf(agentPosition[1] - childPosition[1] - halfChildVoxel, 2) +
|
||||
powf(agentPosition[2] - childPosition[2] - halfChildVoxel, 2));
|
||||
|
||||
float fullChildVoxel = halfChildVoxel * 2.0f;
|
||||
AABox childBox;
|
||||
childBox.setBox(glm::vec3(childPosition[0], childPosition[1], childPosition[2]),
|
||||
fullChildVoxel, fullChildVoxel, fullChildVoxel);
|
||||
|
||||
//printf("VoxelTree::loadBitstreamBuffer() childBox.corner=(%f,%f,%f) x=%f \n",
|
||||
// childBox.getCorner().x,childBox.getCorner().y,childBox.getCorner().z, childBox.getSize().x);
|
||||
|
||||
// XXXBHG - not sure we want to do this "distance/LOD culling" at this level.
|
||||
//bool childIsClose = (distanceToChildCenter < boundaryDistanceForRenderLevel(*childOctalCode + 1));
|
||||
|
||||
bool childIsClose = true; // for now, assume we're close enough
|
||||
bool childInView = !viewFrustumCulling ||
|
||||
(ViewFrustum::OUTSIDE != viewFrustum.boxInFrustum(childBox));
|
||||
|
||||
/// XXXBHG - debug code, switch this to true, and we'll send everything but include false coloring
|
||||
// on voxels based on whether or not they match these rules.
|
||||
bool falseColorInsteadOfCulling = false;
|
||||
|
||||
// removed childIsClose - until we determine if we want to include that
|
||||
bool sendChild = (childInView) || falseColorInsteadOfCulling;
|
||||
|
||||
//printf("VoxelTree::loadBitstreamBuffer() childIsClose=%d, childInView=%d\n",
|
||||
// childIsClose, childInView);
|
||||
|
||||
// if we sendAnyway, we'll do false coloring of the voxels based on childIsClose && childInView
|
||||
if (sendChild) {
|
||||
|
||||
// copy in the childs color to bitstreamBuffer
|
||||
if (childIsClose && childInView) {
|
||||
// true color
|
||||
memcpy(colorPointer, currentVoxelNode->children[i]->getTrueColor(), 3);
|
||||
} else {
|
||||
unsigned char red[3] = {255,0,0};
|
||||
unsigned char green[3] = {0,255,0};
|
||||
unsigned char blue[3] = {0,0,255};
|
||||
if (!childIsClose && !childInView) {
|
||||
// If both too far, and not in view, color them red
|
||||
memcpy(colorPointer, red, 3);
|
||||
} else if (!childIsClose) {
|
||||
// If too far, but in view, color them blue
|
||||
memcpy(colorPointer, blue, 3);
|
||||
} else {
|
||||
// If close, but out of view, color them green
|
||||
memcpy(colorPointer, green, 3);
|
||||
}
|
||||
}
|
||||
colorPointer += 3;
|
||||
|
||||
// set the colorMask by bitshifting the value of childExists
|
||||
*bitstreamBuffer += (1 << (7 - i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,9 +465,19 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
currentMarkerNode->children[i] = new MarkerNode();
|
||||
}
|
||||
|
||||
// calculate the child's position based on the parent position
|
||||
float childNodePosition[3];
|
||||
|
||||
copyFirstVertexForCode(currentVoxelNode->children[i]->octalCode,(float*)&childNodePosition);
|
||||
childNodePosition[0] *= TREE_SCALE; // scale it up
|
||||
childNodePosition[1] *= TREE_SCALE; // scale it up
|
||||
childNodePosition[2] *= TREE_SCALE; // scale it up
|
||||
|
||||
/**** disabled *****************************************************************************************
|
||||
// Note: Stephen, I intentionally left this in so you would talk to me about it. Here's the deal, this
|
||||
// code doesn't seem to work correctly. It returns X and Z flipped and the values are negative. Since
|
||||
// we use the firstVertexForCode() function in VoxelSystem to calculate the child vertex and that DOES
|
||||
// work, I've decided to use that function to calculate our position for LOD handling.
|
||||
//
|
||||
// calculate the child's position based on the parent position
|
||||
for (int j = 0; j < 3; j++) {
|
||||
childNodePosition[j] = thisNodePosition[j];
|
||||
|
||||
|
@ -370,6 +487,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
childNodePosition[j] -= (powf(0.5, *currentVoxelNode->children[i]->octalCode) * TREE_SCALE);
|
||||
}
|
||||
}
|
||||
**** disabled *****************************************************************************************/
|
||||
|
||||
// ask the child to load the bitstream buffer with their data
|
||||
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer,
|
||||
|
@ -377,6 +495,8 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
|||
currentMarkerNode->children[i],
|
||||
agentPosition,
|
||||
childNodePosition,
|
||||
viewFrustum,
|
||||
viewFrustumCulling,
|
||||
stopOctalCode);
|
||||
|
||||
if (bitstreamBuffer - arrBufferBeforeChild > 0) {
|
||||
|
@ -437,7 +557,7 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
|||
|
||||
// create the color mask
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (startNode->children[i] != NULL && startNode->children[i]->color[3] != 0) {
|
||||
if (startNode->children[i] != NULL && startNode->children[i]->isColored()) {
|
||||
colorMask += (1 << (7 - i));
|
||||
}
|
||||
}
|
||||
|
@ -446,9 +566,9 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
|||
|
||||
// output the colors we have
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (startNode->children[j] != NULL && startNode->children[j]->color[3] != 0) {
|
||||
if (startNode->children[j] != NULL && startNode->children[j]->isColored()) {
|
||||
for (int c = 0; c < 3; c++) {
|
||||
outputBits(startNode->children[j]->color[c]);
|
||||
outputBits(startNode->children[j]->getTrueColor()[c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "SimpleMovingAverage.h"
|
||||
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelNode.h"
|
||||
#include "MarkerNode.h"
|
||||
|
||||
|
@ -18,6 +19,9 @@ const int MAX_VOXEL_PACKET_SIZE = 1492;
|
|||
const int MAX_TREE_SLICE_BYTES = 26;
|
||||
const int TREE_SCALE = 10;
|
||||
|
||||
// Callback function, for recuseTreeWithOperation
|
||||
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData);
|
||||
|
||||
class VoxelTree {
|
||||
public:
|
||||
// when a voxel is created in the tree (object new'd)
|
||||
|
@ -47,13 +51,19 @@ public:
|
|||
unsigned char * loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||
VoxelNode *currentVoxelNode,
|
||||
MarkerNode *currentMarkerNode,
|
||||
float * agentPosition,
|
||||
const glm::vec3& agentPosition,
|
||||
float thisNodePosition[3],
|
||||
const ViewFrustum& viewFrustum,
|
||||
bool viewFrustumCulling,
|
||||
unsigned char * octalCode = NULL);
|
||||
|
||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
||||
|
||||
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
||||
|
||||
private:
|
||||
void recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData);
|
||||
VoxelNode * nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode);
|
||||
VoxelNode * createMissingNode(VoxelNode *lastParentNode, unsigned char *deepestCodeToCreate);
|
||||
int readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bufferSizeBytes);
|
||||
|
|
|
@ -5,6 +5,13 @@ set(TARGET_NAME voxel-server)
|
|||
set(ROOT_DIR ..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
|
||||
# set up the external glm library
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
|
@ -14,4 +21,8 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
|||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# link in the hifi voxels library
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# link in the hifi avatars library
|
||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
|
|
|
@ -19,18 +19,10 @@ VoxelAgentData::~VoxelAgentData() {
|
|||
}
|
||||
|
||||
VoxelAgentData::VoxelAgentData(const VoxelAgentData &otherAgentData) {
|
||||
memcpy(position, otherAgentData.position, sizeof(float) * 3);
|
||||
memcpy(&_bodyPosition, &otherAgentData._bodyPosition, sizeof(_bodyPosition));
|
||||
rootMarkerNode = new MarkerNode();
|
||||
}
|
||||
|
||||
VoxelAgentData* VoxelAgentData::clone() const {
|
||||
return new VoxelAgentData(*this);
|
||||
}
|
||||
|
||||
void VoxelAgentData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||
// push past the packet header
|
||||
sourceBuffer++;
|
||||
|
||||
// pull the position from the interface agent data packet
|
||||
memcpy(&position, sourceBuffer, sizeof(float) * 3);
|
||||
}
|
||||
|
|
|
@ -11,18 +11,17 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <AgentData.h>
|
||||
#include <AvatarData.h>
|
||||
#include "MarkerNode.h"
|
||||
|
||||
class VoxelAgentData : public AgentData {
|
||||
class VoxelAgentData : public AvatarData {
|
||||
public:
|
||||
float position[3];
|
||||
MarkerNode *rootMarkerNode;
|
||||
|
||||
VoxelAgentData();
|
||||
~VoxelAgentData();
|
||||
VoxelAgentData(const VoxelAgentData &otherAgentData);
|
||||
|
||||
void parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
VoxelAgentData* clone() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
|||
VoxelTree randomTree;
|
||||
|
||||
bool wantColorRandomizer = false;
|
||||
bool debugViewFrustum = false;
|
||||
bool viewFrustumCulling = true; // for now
|
||||
|
||||
void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
|
||||
float r = random ? randFloatInRange(0.05,0.1) : 0.25;
|
||||
|
@ -165,6 +167,24 @@ void *distributeVoxelsToListeners(void *args) {
|
|||
Agent *thisAgent = (Agent *)&agentList->getAgents()[i];
|
||||
VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData());
|
||||
|
||||
ViewFrustum viewFrustum;
|
||||
// get position and orientation details from the camera
|
||||
viewFrustum.setPosition(agentData->getCameraPosition());
|
||||
viewFrustum.setOrientation(agentData->getCameraDirection(), agentData->getCameraUp(), agentData->getCameraRight());
|
||||
|
||||
// Also make sure it's got the correct lens details from the camera
|
||||
viewFrustum.setFieldOfView(agentData->getCameraFov());
|
||||
viewFrustum.setAspectRatio(agentData->getCameraAspectRatio());
|
||||
viewFrustum.setNearClip(agentData->getCameraNearClip());
|
||||
viewFrustum.setFarClip(agentData->getCameraFarClip());
|
||||
|
||||
viewFrustum.calculate();
|
||||
|
||||
// debug for fun!!
|
||||
if (::debugViewFrustum) {
|
||||
viewFrustum.dump();
|
||||
}
|
||||
|
||||
// lock this agent's delete mutex so that the delete thread doesn't
|
||||
// kill the agent while we are working with it
|
||||
pthread_mutex_lock(thisAgent->deleteMutex);
|
||||
|
@ -179,8 +199,10 @@ void *distributeVoxelsToListeners(void *args) {
|
|||
stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd,
|
||||
randomTree.rootNode,
|
||||
agentData->rootMarkerNode,
|
||||
agentData->position,
|
||||
agentData->getBodyPosition(),
|
||||
treeRoot,
|
||||
viewFrustum,
|
||||
::viewFrustumCulling,
|
||||
stopOctal);
|
||||
|
||||
agentList->getAgentSocket().send(thisAgent->getActiveSocket(), voxelPacket, voxelPacketEnd - voxelPacket);
|
||||
|
@ -249,37 +271,43 @@ int main(int argc, const char * argv[])
|
|||
agentList->startDomainServerCheckInThread();
|
||||
|
||||
srand((unsigned)time(0));
|
||||
|
||||
const char* DEBUG_VIEW_FRUSTUM = "--DebugViewFrustum";
|
||||
::debugViewFrustum = cmdOptionExists(argc, argv, DEBUG_VIEW_FRUSTUM);
|
||||
printf("debugViewFrustum=%s\n", (::debugViewFrustum ? "yes" : "no"));
|
||||
|
||||
const char* NO_VIEW_FRUSTUM_CULLING = "--NoViewFrustumCulling";
|
||||
::viewFrustumCulling = !cmdOptionExists(argc, argv, NO_VIEW_FRUSTUM_CULLING);
|
||||
printf("viewFrustumCulling=%s\n", (::viewFrustumCulling ? "yes" : "no"));
|
||||
|
||||
const char* WANT_COLOR_RANDOMIZER = "--WantColorRandomizer";
|
||||
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
||||
printf("wantColorRandomizer=%s\n", (::wantColorRandomizer ? "yes" : "no"));
|
||||
|
||||
// Check to see if the user passed in a command line option for loading a local
|
||||
// Voxel File. If so, load it now.
|
||||
const char* WANT_COLOR_RANDOMIZER="--WantColorRandomizer";
|
||||
const char* INPUT_FILE="-i";
|
||||
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
||||
|
||||
printf("wantColorRandomizer=%s\n",(wantColorRandomizer?"yes":"no"));
|
||||
const char* INPUT_FILE = "-i";
|
||||
const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE);
|
||||
|
||||
if (voxelsFilename) {
|
||||
randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
||||
}
|
||||
|
||||
const char* ADD_RANDOM_VOXELS="--AddRandomVoxels";
|
||||
const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels";
|
||||
if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) {
|
||||
// create an octal code buffer and load it with 0 so that the recursive tree fill can give
|
||||
// octal codes to the tree nodes that it is creating
|
||||
randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode);
|
||||
}
|
||||
|
||||
|
||||
const char* ADD_SPHERE="--AddSphere";
|
||||
const char* ADD_RANDOM_SPHERE="--AddRandomSphere";
|
||||
const char* ADD_SPHERE = "--AddSphere";
|
||||
const char* ADD_RANDOM_SPHERE = "--AddRandomSphere";
|
||||
if (cmdOptionExists(argc, argv, ADD_SPHERE)) {
|
||||
addSphere(&randomTree,false,wantColorRandomizer);
|
||||
} else if (cmdOptionExists(argc, argv, ADD_RANDOM_SPHERE)) {
|
||||
addSphere(&randomTree,true,wantColorRandomizer);
|
||||
}
|
||||
|
||||
const char* NO_ADD_SCENE="--NoAddScene";
|
||||
const char* NO_ADD_SCENE = "--NoAddScene";
|
||||
if (!cmdOptionExists(argc, argv, NO_ADD_SCENE)) {
|
||||
addSphereScene(&randomTree,wantColorRandomizer);
|
||||
}
|
||||
|
@ -345,7 +373,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, &AGENT_TYPE_INTERFACE, 1);
|
||||
agentList->broadcastToAgents(packetData,receivedBytes, &AGENT_TYPE_AVATAR, 1);
|
||||
|
||||
}
|
||||
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
|
||||
|
@ -373,14 +401,14 @@ 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, &AGENT_TYPE_INTERFACE, 1);
|
||||
agentList->broadcastToAgents(packetData,receivedBytes, &AGENT_TYPE_AVATAR, 1);
|
||||
}
|
||||
// If we got a PACKET_HEADER_HEAD_DATA, then we're talking to an AGENT_TYPE_INTERFACE, and we
|
||||
// If we got a PACKET_HEADER_HEAD_DATA, then we're talking to an AGENT_TYPE_AVATAR, and we
|
||||
// need to make sure we have it in our agentList.
|
||||
if (packetData[0] == PACKET_HEADER_HEAD_DATA) {
|
||||
if (agentList->addOrUpdateAgent(&agentPublicAddress,
|
||||
&agentPublicAddress,
|
||||
AGENT_TYPE_INTERFACE,
|
||||
AGENT_TYPE_AVATAR,
|
||||
agentList->getLastAgentId())) {
|
||||
agentList->increaseAgentId();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue