mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 09:33:36 +02:00
resolve conflicts on merge with upstream master
This commit is contained in:
commit
24c1ea5e7f
21 changed files with 1573 additions and 905 deletions
|
@ -8,5 +8,6 @@ add_subdirectory(domain-server)
|
|||
add_subdirectory(eve)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(injector)
|
||||
add_subdirectory(pairing-server)
|
||||
add_subdirectory(space-server)
|
||||
add_subdirectory(voxel-server)
|
|
@ -114,7 +114,7 @@ int main(int argc, const char* argv[]) {
|
|||
// pick a random point inside a 10x10 grid
|
||||
|
||||
eve.setPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION),
|
||||
0.32, // this is the same as the pelvis standing height (as of 4/26/13)
|
||||
1.33, // this should be the same as the avatar's pelvis standing height
|
||||
randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION)));
|
||||
|
||||
// face any instance of eve down the z-axis
|
||||
|
@ -122,7 +122,7 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
// put her hand out so somebody can shake it
|
||||
eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2,
|
||||
0.25,
|
||||
0.5,
|
||||
eve.getPosition()[2] + 0.1));
|
||||
// read eve's audio data
|
||||
AudioInjector eveAudioInjector("/etc/highfidelity/eve/resources/eve.raw");
|
||||
|
|
|
@ -80,10 +80,6 @@ timeval firstPlaybackTimer;
|
|||
int packetsReceivedThisPlayback = 0;
|
||||
float usecsAtStartup = 0;
|
||||
|
||||
#define LOG_SAMPLE_DELAY 0
|
||||
|
||||
std::ofstream logFile;
|
||||
|
||||
/**
|
||||
* Audio callback used by portaudio.
|
||||
* Communicates with Audio via a shared pointer to Audio::data.
|
||||
|
@ -315,34 +311,12 @@ void *receiveAudioViaUDP(void *args) {
|
|||
|
||||
stdev.reset();
|
||||
|
||||
if (LOG_SAMPLE_DELAY) {
|
||||
|
||||
char *directory = new char[50];
|
||||
char *filename = new char[50];
|
||||
|
||||
sprintf(directory, "%s/Desktop/echo_tests", getenv("HOME"));
|
||||
|
||||
mkdir(directory, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
sprintf(filename, "%s/%ld.csv", directory, previousReceiveTime.tv_sec);
|
||||
|
||||
logFile.open(filename, std::ios::out);
|
||||
|
||||
delete[] directory;
|
||||
delete[] filename;
|
||||
}
|
||||
|
||||
while (!stopAudioReceiveThread) {
|
||||
|
||||
if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) {
|
||||
|
||||
gettimeofday(¤tReceiveTime, NULL);
|
||||
totalPacketsReceived++;
|
||||
|
||||
if (LOG_SAMPLE_DELAY) {
|
||||
// write time difference (in microseconds) between packet receipts to file
|
||||
double timeDiff = diffclock(&previousReceiveTime, ¤tReceiveTime);
|
||||
logFile << timeDiff << std::endl;
|
||||
}
|
||||
|
||||
double tDiff = diffclock(&previousReceiveTime, ¤tReceiveTime);
|
||||
//printLog("tDiff %4.1f\n", tDiff);
|
||||
|
@ -562,8 +536,7 @@ void Audio::render(int screenWidth, int screenHeight)
|
|||
* @return Returns true if the initialization was successful, or false if an error occured.
|
||||
The error code may be retrieved by Audio::getError().
|
||||
*/
|
||||
bool Audio::terminate ()
|
||||
{
|
||||
bool Audio::terminate() {
|
||||
stopAudioReceiveThread = true;
|
||||
pthread_join(audioReceiveThread, NULL);
|
||||
|
||||
|
@ -577,7 +550,6 @@ bool Audio::terminate ()
|
|||
if (paError != paNoError) goto error;
|
||||
}
|
||||
|
||||
logFile.close();
|
||||
delete audioData;
|
||||
|
||||
return true;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,36 +42,38 @@ enum AvatarMode
|
|||
NUM_AVATAR_MODES
|
||||
};
|
||||
|
||||
enum AvatarBoneID
|
||||
enum AvatarJointID
|
||||
{
|
||||
AVATAR_BONE_NULL = -1,
|
||||
AVATAR_BONE_PELVIS_SPINE, // connects pelvis joint with torso joint (not supposed to be rotated)
|
||||
AVATAR_BONE_MID_SPINE, // connects torso joint with chest joint
|
||||
AVATAR_BONE_CHEST_SPINE, // connects chest joint with neckBase joint (not supposed to be rotated)
|
||||
AVATAR_BONE_NECK, // connects neckBase joint with headBase joint
|
||||
AVATAR_BONE_HEAD, // connects headBase joint with headTop joint
|
||||
AVATAR_BONE_LEFT_CHEST, // connects chest joint with left clavicle joint (not supposed to be rotated)
|
||||
AVATAR_BONE_LEFT_SHOULDER, // connects left clavicle joint with left shoulder joint
|
||||
AVATAR_BONE_LEFT_UPPER_ARM, // connects left shoulder joint with left elbow joint
|
||||
AVATAR_BONE_LEFT_FOREARM, // connects left elbow joint with left wrist joint
|
||||
AVATAR_BONE_LEFT_HAND, // connects left wrist joint with left fingertips joint
|
||||
AVATAR_BONE_RIGHT_CHEST, // connects chest joint with right clavicle joint (not supposed to be rotated)
|
||||
AVATAR_BONE_RIGHT_SHOULDER, // connects right clavicle joint with right shoulder joint
|
||||
AVATAR_BONE_RIGHT_UPPER_ARM, // connects right shoulder joint with right elbow joint
|
||||
AVATAR_BONE_RIGHT_FOREARM, // connects right elbow joint with right wrist joint
|
||||
AVATAR_BONE_RIGHT_HAND, // connects right wrist joint with right fingertips joint
|
||||
AVATAR_BONE_LEFT_PELVIS, // connects pelvis joint with left hip joint (not supposed to be rotated)
|
||||
AVATAR_BONE_LEFT_THIGH, // connects left hip joint with left knee joint
|
||||
AVATAR_BONE_LEFT_SHIN, // connects left knee joint with left heel joint
|
||||
AVATAR_BONE_LEFT_FOOT, // connects left heel joint with left toes joint
|
||||
AVATAR_BONE_RIGHT_PELVIS, // connects pelvis joint with right hip joint (not supposed to be rotated)
|
||||
AVATAR_BONE_RIGHT_THIGH, // connects right hip joint with right knee joint
|
||||
AVATAR_BONE_RIGHT_SHIN, // connects right knee joint with right heel joint
|
||||
AVATAR_BONE_RIGHT_FOOT, // connects right heel joint with right toes joint
|
||||
AVATAR_JOINT_NULL = -1,
|
||||
AVATAR_JOINT_PELVIS,
|
||||
AVATAR_JOINT_TORSO,
|
||||
AVATAR_JOINT_CHEST,
|
||||
AVATAR_JOINT_NECK_BASE,
|
||||
AVATAR_JOINT_HEAD_BASE,
|
||||
AVATAR_JOINT_HEAD_TOP,
|
||||
AVATAR_JOINT_LEFT_COLLAR,
|
||||
AVATAR_JOINT_LEFT_SHOULDER,
|
||||
AVATAR_JOINT_LEFT_ELBOW,
|
||||
AVATAR_JOINT_LEFT_WRIST,
|
||||
AVATAR_JOINT_LEFT_FINGERTIPS,
|
||||
AVATAR_JOINT_RIGHT_COLLAR,
|
||||
AVATAR_JOINT_RIGHT_SHOULDER,
|
||||
AVATAR_JOINT_RIGHT_ELBOW,
|
||||
AVATAR_JOINT_RIGHT_WRIST,
|
||||
AVATAR_JOINT_RIGHT_FINGERTIPS,
|
||||
AVATAR_JOINT_LEFT_HIP,
|
||||
AVATAR_JOINT_LEFT_KNEE,
|
||||
AVATAR_JOINT_LEFT_HEEL,
|
||||
AVATAR_JOINT_LEFT_TOES,
|
||||
AVATAR_JOINT_RIGHT_HIP,
|
||||
AVATAR_JOINT_RIGHT_KNEE,
|
||||
AVATAR_JOINT_RIGHT_HEEL,
|
||||
AVATAR_JOINT_RIGHT_TOES,
|
||||
|
||||
NUM_AVATAR_BONES
|
||||
NUM_AVATAR_JOINTS
|
||||
};
|
||||
|
||||
|
||||
class Avatar : public AvatarData {
|
||||
public:
|
||||
Avatar(bool isMine);
|
||||
|
@ -99,11 +101,14 @@ public:
|
|||
void setLeanSideways(float dist);
|
||||
void addLean(float x, float z);
|
||||
|
||||
const glm::vec3& getHeadLookatDirection() const { return _orientation.getFront(); };
|
||||
const glm::vec3& getHeadLookatDirectionUp() const { return _orientation.getUp(); };
|
||||
const glm::vec3& getHeadLookatDirectionRight() const { return _orientation.getRight(); };
|
||||
/*
|
||||
const glm::vec3& getHeadRightDirection() const { return _orientation.getRight(); };
|
||||
const glm::vec3& getHeadUpDirection () const { return _orientation.getUp (); };
|
||||
const glm::vec3& getHeadFrontDirection() const { return _orientation.getFront(); };
|
||||
*/
|
||||
|
||||
const glm::vec3& getHeadPosition() const ;
|
||||
const glm::vec3& getBonePosition(AvatarBoneID b) const { return _bone[b].position; };
|
||||
const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].position; };
|
||||
const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); };
|
||||
float getSpeed() const { return _speed; };
|
||||
float getGirth();
|
||||
|
@ -117,7 +122,6 @@ public:
|
|||
void renderHead(bool lookingInMirror);
|
||||
void simulate(float);
|
||||
void setHandMovementValues( glm::vec3 movement );
|
||||
void updateHandMovement( float deltaTime );
|
||||
void updateArmIKAndConstraints( float deltaTime );
|
||||
void setDisplayingHead( bool displayingHead );
|
||||
|
||||
|
@ -142,48 +146,31 @@ public:
|
|||
// Find out what the local gravity vector is at this location
|
||||
glm::vec3 getGravity(glm::vec3 pos);
|
||||
|
||||
private:
|
||||
void writeAvatarDataToFile();
|
||||
void readAvatarDataFromFile();
|
||||
|
||||
const bool BALLS_ON = false;
|
||||
const bool AVATAR_GRAVITY = true;
|
||||
const float DECAY = 0.1;
|
||||
const float THRUST_MAG = 1200.0;
|
||||
const float YAW_MAG = 500.0;
|
||||
const float BODY_PITCH_DECAY = 5.0;
|
||||
const float BODY_YAW_DECAY = 5.0;
|
||||
const float BODY_ROLL_DECAY = 5.0;
|
||||
const float LIN_VEL_DECAY = 5.0;
|
||||
const float MY_HAND_HOLDING_PULL = 0.2;
|
||||
const float YOUR_HAND_HOLDING_PULL = 1.0;
|
||||
const float BODY_SPRING_FORCE = 6.0f;
|
||||
const float BODY_SPRING_DECAY = 16.0f;
|
||||
const float BODY_SPRING_DEFAULT_TIGHTNESS = 10.0f;
|
||||
const float COLLISION_RADIUS_SCALAR = 1.8;
|
||||
const float COLLISION_BALL_FORCE = 1.0;
|
||||
const float COLLISION_BODY_FORCE = 6.0;
|
||||
const float COLLISION_BALL_FRICTION = 60.0;
|
||||
const float COLLISION_BODY_FRICTION = 0.5;
|
||||
private:
|
||||
|
||||
// Do you want head to try to return to center (depends on interface detected)
|
||||
void setHeadReturnToCenter(bool r) { _returnHeadToCenter = r; };
|
||||
const bool getHeadReturnToCenter() const { return _returnHeadToCenter; };
|
||||
|
||||
struct AvatarBone
|
||||
struct AvatarJoint
|
||||
{
|
||||
AvatarBoneID parent; // which bone is this bone connected to?
|
||||
glm::vec3 position; // the position at the "end" of the bone - in global space
|
||||
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::vec3 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
|
||||
bool isCollidable; // when false, the bone position will not register a collision
|
||||
AvatarJointID parent; // which joint is this joint connected to?
|
||||
glm::vec3 position; // the position at the "end" of the joint - in global space
|
||||
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::vec3 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 joint rotation off the parent
|
||||
float pitch; // the pitch Euler angle of the joint rotation off the parent
|
||||
float roll; // the roll Euler angle of the joint rotation off the parent
|
||||
Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll
|
||||
float length; // the length of vector connecting the joint and its parent
|
||||
float radius; // used for detecting collisions for certain physical effects
|
||||
bool isCollidable; // when false, the joint position will not register a collision
|
||||
};
|
||||
|
||||
struct AvatarHead
|
||||
|
@ -238,7 +225,7 @@ private:
|
|||
bool _usingBodySprings;
|
||||
glm::vec3 _movedHandOffset;
|
||||
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
|
||||
AvatarBone _bone[ NUM_AVATAR_BONES ];
|
||||
AvatarJoint _joint[ NUM_AVATAR_JOINTS ];
|
||||
AvatarMode _mode;
|
||||
glm::vec3 _handHoldingPosition;
|
||||
glm::vec3 _velocity;
|
||||
|
@ -263,6 +250,7 @@ private:
|
|||
AvatarTouch _avatarTouch;
|
||||
bool _displayingHead; // should be false if in first-person view
|
||||
bool _returnHeadToCenter;
|
||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||
|
||||
// private methods...
|
||||
void initializeSkeleton();
|
||||
|
@ -272,6 +260,7 @@ private:
|
|||
void calculateBoneLengths();
|
||||
void readSensors();
|
||||
void updateHead( float deltaTime );
|
||||
void updateHandMovementAndTouching(float deltaTime);
|
||||
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
||||
void updateCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||
void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime);
|
||||
|
|
32
interface/src/AvatarRenderer.cpp
Normal file
32
interface/src/AvatarRenderer.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// AvatarRenderer.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Jeffrey Ventrella
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <SharedUtil.h>
|
||||
#include "AvatarRenderer.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
|
||||
AvatarRenderer::AvatarRenderer() {
|
||||
}
|
||||
|
||||
// this method renders the avatar
|
||||
void AvatarRenderer::render(Avatar *avatar, bool lookingInMirror) {
|
||||
|
||||
/*
|
||||
// show avatar position
|
||||
glColor4f( 0.5f, 0.5f, 0.5f, 0.6 );
|
||||
glPushMatrix();
|
||||
glTranslatef(avatar->_position.x, avatar->_position.y, avatar->_position.z);
|
||||
glScalef( 0.03, 0.03, 0.03 );
|
||||
glutSolidSphere( 1, 10, 10 );
|
||||
glPopMatrix();
|
||||
*/
|
||||
}
|
||||
|
||||
|
25
interface/src/AvatarRenderer.h
Normal file
25
interface/src/AvatarRenderer.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// AvatarRenderer.h
|
||||
// interface
|
||||
//
|
||||
// Created by Jeffrey Ventrella
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__AvatarRenderer__
|
||||
#define __interface__AvatarRenderer__
|
||||
|
||||
#include "Avatar.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class AvatarRenderer {
|
||||
public:
|
||||
|
||||
AvatarRenderer();
|
||||
void render(Avatar *avatar, bool lookingInMirror);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -11,11 +11,11 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.1;
|
||||
|
||||
class AvatarTouch {
|
||||
public:
|
||||
|
||||
const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.1;
|
||||
|
||||
AvatarTouch();
|
||||
|
||||
void simulate(float deltaTime);
|
||||
|
|
|
@ -24,7 +24,6 @@ using namespace std;
|
|||
// no clue which versions are affected...
|
||||
#define WORKAROUND_BROKEN_GLUT_STROKES
|
||||
// see http://www.opengl.org/resources/libraries/glut/spec3/node78.html
|
||||
static float MONO_STROKE_WIDTH_GLUT = 104.76;
|
||||
|
||||
void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * front, glm::vec3 * right, glm::vec3 * up) {
|
||||
//
|
||||
|
@ -172,7 +171,6 @@ void drawtext(int x, int y, float scale, float rotate, float thick, int mono,
|
|||
//
|
||||
// Draws text on screen as stroked so it can be resized
|
||||
//
|
||||
int len, i;
|
||||
glPushMatrix();
|
||||
glTranslatef( static_cast<float>(x), static_cast<float>(y), 0.0f);
|
||||
glColor3f(r,g,b);
|
||||
|
@ -213,42 +211,28 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl
|
|||
|
||||
}
|
||||
|
||||
void drawGroundPlaneGrid( float size, int resolution )
|
||||
void drawGroundPlaneGrid(float size)
|
||||
{
|
||||
|
||||
glColor3f( 0.4f, 0.5f, 0.3f );
|
||||
glColor3f( 0.4f, 0.5f, 0.3f );
|
||||
glLineWidth(2.0);
|
||||
|
||||
float gridSize = 10.0;
|
||||
int gridResolution = 20;
|
||||
|
||||
for (int g=0; g<gridResolution; g++)
|
||||
{
|
||||
float fraction = (float)g / (float)( gridResolution - 1 );
|
||||
float inc = -gridSize * ONE_HALF + fraction * gridSize;
|
||||
glBegin( GL_LINE_STRIP );
|
||||
glVertex3f( inc, 0.0f, -gridSize * ONE_HALF );
|
||||
glVertex3f( inc, 0.0f, gridSize * ONE_HALF );
|
||||
glEnd();
|
||||
}
|
||||
|
||||
for (int g=0; g<gridResolution; g++)
|
||||
{
|
||||
float fraction = (float)g / (float)( gridResolution - 1 );
|
||||
float inc = -gridSize * ONE_HALF + fraction * gridSize;
|
||||
glBegin( GL_LINE_STRIP );
|
||||
glVertex3f( -gridSize * ONE_HALF, 0.0f, inc );
|
||||
glVertex3f( gridSize * ONE_HALF, 0.0f, inc );
|
||||
glEnd();
|
||||
}
|
||||
|
||||
for (float x = 0; x <= size; x++) {
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(x, 0.0f, 0);
|
||||
glVertex3f(x, 0.0f, size);
|
||||
glVertex3f(0, 0.0f, x);
|
||||
glVertex3f(size, 0.0f, x);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Draw a translucent quad just underneath the grid.
|
||||
glColor4f(0.5, 0.5, 0.5, 0.4);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(-gridSize * ONE_HALF, 0, -gridSize * ONE_HALF);
|
||||
glVertex3f(gridSize * ONE_HALF, 0, -gridSize * ONE_HALF);
|
||||
glVertex3f(gridSize * ONE_HALF, 0, gridSize * ONE_HALF);
|
||||
glVertex3f(-gridSize * ONE_HALF, 0, gridSize * ONE_HALF);
|
||||
glVertex3f(0, 0, 0);
|
||||
glVertex3f(size, 0, 0);
|
||||
glVertex3f(size, 0, size);
|
||||
glVertex3f(0, 0, size);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl
|
|||
float r=1.0, float g=1.0, float b=1.0);
|
||||
double diffclock(timeval *clock1,timeval *clock2);
|
||||
|
||||
void drawGroundPlaneGrid( float size, int resolution );
|
||||
void drawGroundPlaneGrid(float size);
|
||||
|
||||
void renderOrientationDirections( glm::vec3 position, Orientation orientation, float size );
|
||||
|
||||
|
|
|
@ -97,8 +97,26 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
|
||||
switch(command) {
|
||||
case PACKET_HEADER_VOXEL_DATA:
|
||||
{
|
||||
double start = usecTimestampNow();
|
||||
// ask the VoxelTree to read the bitstream into the tree
|
||||
_tree->readBitstreamToTree(voxelData, numBytes - 1);
|
||||
if (_renderWarningsOn && _tree->getNodesChangedFromBitstream()) {
|
||||
printLog("readBitstreamToTree()... getNodesChangedFromBitstream=%ld _tree->isDirty()=%s \n",
|
||||
_tree->getNodesChangedFromBitstream(), (_tree->isDirty() ? "yes" : "no") );
|
||||
}
|
||||
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec);
|
||||
} else {
|
||||
printLog("WARNING! readBitstreamToTree() took %lf milliseconds\n",elapsedmsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PACKET_HEADER_ERASE_VOXEL:
|
||||
// ask the tree to read the "remove" bitstream
|
||||
|
@ -135,17 +153,48 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
}
|
||||
|
||||
void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||
_voxelsUpdated = newTreeToArrays(_tree->rootNode);
|
||||
double start = usecTimestampNow();
|
||||
|
||||
double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished);
|
||||
|
||||
if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {
|
||||
return; // bail early, it hasn't been long enough since the last time we ran
|
||||
}
|
||||
|
||||
if (_tree->isDirty()) {
|
||||
_callsToTreesToArrays++;
|
||||
_voxelsUpdated = newTreeToArrays(_tree->rootNode);
|
||||
_tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean
|
||||
} else {
|
||||
_voxelsUpdated = 0;
|
||||
}
|
||||
if (_voxelsUpdated) {
|
||||
_voxelsDirty=true;
|
||||
}
|
||||
|
||||
// copy the newly written data to the arrays designated for reading
|
||||
copyWrittenDataToReadArrays();
|
||||
if (_voxelsDirty) {
|
||||
// copy the newly written data to the arrays designated for reading
|
||||
copyWrittenDataToReadArrays();
|
||||
}
|
||||
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! newTreeToArrays() took %lf seconds %ld voxels updated\n", elapsedsec, _voxelsUpdated);
|
||||
} else {
|
||||
printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
_setupNewVoxelsForDrawingLastFinished = end;
|
||||
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
|
||||
}
|
||||
|
||||
void VoxelSystem::copyWrittenDataToReadArrays() {
|
||||
if (_voxelsDirty) {
|
||||
double start = usecTimestampNow();
|
||||
if (_voxelsDirty && _voxelsUpdated) {
|
||||
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
|
||||
pthread_mutex_lock(&_bufferWriteLock);
|
||||
int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
|
||||
|
@ -154,6 +203,18 @@ void VoxelSystem::copyWrittenDataToReadArrays() {
|
|||
memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
|
||||
pthread_mutex_unlock(&_bufferWriteLock);
|
||||
}
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds for %ld voxels %ld updated\n",
|
||||
elapsedsec, _voxelsInArrays, _voxelsUpdated);
|
||||
} else {
|
||||
printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds for %ld voxels %ld updated\n",
|
||||
elapsedmsec, _voxelsInArrays, _voxelsUpdated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
||||
|
@ -164,7 +225,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
|||
float childBoundary = boundaryDistanceForRenderLevel(*node->octalCode + 2);
|
||||
bool inBoundary = (distanceToNode <= boundary);
|
||||
bool inChildBoundary = (distanceToNode <= childBoundary);
|
||||
bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary));
|
||||
bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary));
|
||||
|
||||
node->setShouldRender(shouldRender);
|
||||
// let children figure out their renderness
|
||||
|
@ -213,8 +274,8 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
|||
_voxelsInArrays++; // our know vertices in the arrays
|
||||
}
|
||||
voxelsUpdated++;
|
||||
node->clearDirtyBit();
|
||||
}
|
||||
node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered
|
||||
return voxelsUpdated;
|
||||
}
|
||||
|
||||
|
@ -225,6 +286,11 @@ VoxelSystem* VoxelSystem::clone() const {
|
|||
|
||||
void VoxelSystem::init() {
|
||||
|
||||
_renderWarningsOn = false;
|
||||
_callsToTreesToArrays = 0;
|
||||
_setupNewVoxelsForDrawingLastFinished = 0;
|
||||
_setupNewVoxelsForDrawingLastElapsed = 0;
|
||||
|
||||
// When we change voxels representations in the arrays, we'll update this
|
||||
_voxelsDirty = false;
|
||||
_voxelsInArrays = 0;
|
||||
|
@ -296,6 +362,7 @@ void VoxelSystem::init() {
|
|||
}
|
||||
|
||||
void VoxelSystem::updateVBOs() {
|
||||
double start = usecTimestampNow();
|
||||
if (_voxelsDirty) {
|
||||
glBufferIndex segmentStart = 0;
|
||||
glBufferIndex segmentEnd = 0;
|
||||
|
@ -327,9 +394,27 @@ void VoxelSystem::updateVBOs() {
|
|||
}
|
||||
_voxelsDirty = false;
|
||||
}
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! updateVBOs() took %lf seconds after %d calls to newTreeToArrays()\n",
|
||||
elapsedsec, _callsToTreesToArrays);
|
||||
} else {
|
||||
printLog("WARNING! updateVBOs() took %lf milliseconds after %d calls to newTreeToArrays()\n",
|
||||
elapsedmsec, _callsToTreesToArrays);
|
||||
}
|
||||
} else {
|
||||
printLog("WARNING! updateVBOs() called after %d calls to newTreeToArrays()\n",_callsToTreesToArrays);
|
||||
}
|
||||
}
|
||||
_callsToTreesToArrays = 0; // clear it
|
||||
}
|
||||
|
||||
void VoxelSystem::render() {
|
||||
double start = usecTimestampNow();
|
||||
glPushMatrix();
|
||||
updateVBOs();
|
||||
// tell OpenGL where to find vertex and color information
|
||||
|
@ -348,7 +433,7 @@ void VoxelSystem::render() {
|
|||
|
||||
// draw the number of voxels we have
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
||||
glScalef(10, 10, 10);
|
||||
glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);
|
||||
glDrawElements(GL_TRIANGLES, 36 * _voxelsInArrays, GL_UNSIGNED_INT, 0);
|
||||
|
||||
// deactivate vertex and color arrays after drawing
|
||||
|
@ -362,14 +447,31 @@ void VoxelSystem::render() {
|
|||
|
||||
// scale back down to 1 so heads aren't massive
|
||||
glPopMatrix();
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! render() took %lf seconds\n",elapsedsec);
|
||||
} else {
|
||||
printLog("WARNING! render() took %lf milliseconds\n",elapsedmsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int VoxelSystem::_nodeCount = 0;
|
||||
|
||||
void VoxelSystem::killLocalVoxels() {
|
||||
_tree->eraseAllVoxels();
|
||||
_voxelsInArrays = 0; // better way to do this??
|
||||
//setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
|
||||
bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {
|
||||
_nodeCount++;
|
||||
if (node->isColored()) {
|
||||
nodeColor newColor = { randomColorValue(150), randomColorValue(150), randomColorValue(150), 1 };
|
||||
nodeColor newColor = { 255, randomColorValue(150), randomColorValue(150), 1 };
|
||||
node->setColor(newColor);
|
||||
}
|
||||
return true;
|
||||
|
@ -385,7 +487,7 @@ void VoxelSystem::randomizeVoxelColors() {
|
|||
bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) {
|
||||
_nodeCount++;
|
||||
// always false colorize
|
||||
node->setFalseColor(randomColorValue(150), randomColorValue(150), randomColorValue(150));
|
||||
node->setFalseColor(255, randomColorValue(150), randomColorValue(150));
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,14 @@ public:
|
|||
void falseColorizeInView(ViewFrustum* viewFrustum);
|
||||
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
|
||||
|
||||
void killLocalVoxels();
|
||||
void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; };
|
||||
bool getRenderPipelineWarnings() const { return _renderWarningsOn; };
|
||||
|
||||
private:
|
||||
int _callsToTreesToArrays;
|
||||
|
||||
bool _renderWarningsOn;
|
||||
// Operation functions for tree recursion methods
|
||||
static int _nodeCount;
|
||||
static bool randomColorOperation(VoxelNode* node, void* extraData);
|
||||
|
@ -83,6 +90,10 @@ private:
|
|||
unsigned long _voxelsUpdated;
|
||||
unsigned long _voxelsInArrays;
|
||||
|
||||
|
||||
double _setupNewVoxelsForDrawingLastElapsed;
|
||||
double _setupNewVoxelsForDrawingLastFinished;
|
||||
|
||||
GLuint _vboVerticesID;
|
||||
GLuint _vboNormalsID;
|
||||
GLuint _vboColorsID;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// Welcome Aboard!
|
||||
//
|
||||
//
|
||||
// Keyboard Commands:
|
||||
// Keyboard Commands:
|
||||
//
|
||||
// / = toggle stats display
|
||||
// spacebar = reset gyros/head position
|
||||
|
@ -69,6 +69,7 @@
|
|||
|
||||
#include "Camera.h"
|
||||
#include "Avatar.h"
|
||||
#include "AvatarRenderer.h"
|
||||
#include "Texture.h"
|
||||
#include <AgentList.h>
|
||||
#include <AgentTypes.h>
|
||||
|
@ -119,6 +120,9 @@ Avatar myAvatar(true); // The rendered avatar of oneself
|
|||
Camera myCamera; // My view onto the world (sometimes on myself :)
|
||||
Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
||||
|
||||
|
||||
AvatarRenderer avatarRenderer;
|
||||
|
||||
// Starfield information
|
||||
char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
|
||||
char starCacheFile[] = "cachedStars.txt";
|
||||
|
@ -130,16 +134,21 @@ glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
|
|||
|
||||
VoxelSystem voxels;
|
||||
|
||||
bool wantToKillLocalVoxels = false;
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
Audio audio(&audioScope, &myAvatar);
|
||||
#endif
|
||||
|
||||
#define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff
|
||||
#define IDLE_SIMULATE_MSECS 16 // How often should call simulate and other stuff
|
||||
// in the idle loop?
|
||||
|
||||
// Where one's own agent begins in the world (needs to become a dynamic thing passed to the program)
|
||||
glm::vec3 start_location(6.1f, 0, 1.4f);
|
||||
|
||||
bool renderWarningsOn = false; // Whether to show render pipeline warnings
|
||||
|
||||
bool statsOn = false; // Whether to show onscreen text overlay with stats
|
||||
bool starsOn = false; // Whether to display the stars
|
||||
bool paintOn = false; // Whether to paint voxels as you fly around
|
||||
|
@ -174,7 +183,10 @@ int menuOn = 1; // Whether to show onscreen menu
|
|||
ChatEntry chatEntry; // chat entry field
|
||||
bool chatEntryOn = false; // Whether to show the chat entry
|
||||
|
||||
|
||||
bool oculusOn = false; // Whether to configure the display for the Oculus Rift
|
||||
GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion
|
||||
GLhandleARB oculusProgramID = 0; // The GLSL program containing the distortion shader
|
||||
float oculusDistortionScale = 1.25; // Controls the Oculus field of view
|
||||
|
||||
//
|
||||
// Serial USB Variables
|
||||
|
@ -221,37 +233,30 @@ void displayStats(void)
|
|||
if (::menuOn == 0) {
|
||||
statsVerticalOffset = 8;
|
||||
}
|
||||
// bitmap chars are about 10 pels high
|
||||
char legend[] = "/ - toggle this display, Q - exit, H - show head, M - show hand, T - test audio";
|
||||
drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, legend);
|
||||
|
||||
char legend2[] = "* - toggle stars, & - toggle paint mode, '-' - send erase all, '%' - send add scene";
|
||||
drawtext(10, statsVerticalOffset + 32, 0.10f, 0, 1.0, 0, legend2);
|
||||
|
||||
glm::vec3 avatarPos = myAvatar.getPosition();
|
||||
|
||||
char stats[200];
|
||||
sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)= %4.2f, %4.2f, %4.2f ",
|
||||
FPS, packetsPerSecond, bytesPerSecond, avatarPos.x,avatarPos.y,avatarPos.z);
|
||||
drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats);
|
||||
sprintf(stats, "%3.0f FPS, %d Pkts/sec, %3.2f Mbps",
|
||||
FPS, packetsPerSecond, (float)bytesPerSecond * 8.f / 1000000.f);
|
||||
drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, stats);
|
||||
|
||||
std::stringstream voxelStats;
|
||||
voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() << " Updated: " << voxels.getVoxelsUpdated();
|
||||
drawtext(10, statsVerticalOffset + 70, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||
voxelStats.precision(4);
|
||||
voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() / 1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K";
|
||||
drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() << " (" << voxels.getVoxelsCreatedPerSecondAverage()
|
||||
<< "/sec) ";
|
||||
voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() / 1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage() / 1000.f
|
||||
<< "Kps) ";
|
||||
drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() << " (" << voxels.getVoxelsColoredPerSecondAverage()
|
||||
<< "/sec) ";
|
||||
voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() / 1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage() / 1000.f
|
||||
<< "Kps) ";
|
||||
drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats << "Voxels Bytes Read: " << voxels.getVoxelsBytesRead()
|
||||
<< " (" << voxels.getVoxelsBytesReadPerSecondAverage() << " Bps)";
|
||||
voxelStats << "Voxel Bits Read: " << voxels.getVoxelsBytesRead() * 8.f / 1000000.f
|
||||
<< "M (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)";
|
||||
drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||
|
||||
voxelStats.str("");
|
||||
|
@ -259,13 +264,13 @@ void displayStats(void)
|
|||
? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored())
|
||||
: 0;
|
||||
|
||||
voxelStats << "Voxels Bytes per Colored: " << voxelsBytesPerColored;
|
||||
voxelStats << "Voxels Bits per Colored: " << voxelsBytesPerColored * 8;
|
||||
drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||
|
||||
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
char avatarMixerStats[200];
|
||||
if (avatarMixer) {
|
||||
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
||||
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||
} else {
|
||||
|
@ -339,7 +344,9 @@ void init(void)
|
|||
|
||||
void terminate () {
|
||||
// Close serial port
|
||||
//close(serial_fd);
|
||||
// close(serial_fd);
|
||||
|
||||
myAvatar.writeAvatarDataToFile();
|
||||
|
||||
#ifndef _WIN32
|
||||
audio.terminate();
|
||||
|
@ -676,6 +683,289 @@ void renderViewFrustum(ViewFrustum& viewFrustum) {
|
|||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
// displays a single side (left, right, or combined for non-Oculus)
|
||||
void displaySide(Camera& whichCamera) {
|
||||
glPushMatrix();
|
||||
|
||||
if (::starsOn) {
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
|
||||
// finally render the starfield
|
||||
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
|
||||
}
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// draw a red sphere
|
||||
float sphereRadius = 0.25f;
|
||||
glColor3f(1,0,0);
|
||||
glPushMatrix();
|
||||
glutSolidSphere( sphereRadius, 15, 15 );
|
||||
glPopMatrix();
|
||||
|
||||
//draw a grid ground plane....
|
||||
drawGroundPlaneGrid(10.f);
|
||||
|
||||
// Draw voxels
|
||||
if ( showingVoxels )
|
||||
{
|
||||
voxels.render();
|
||||
}
|
||||
|
||||
// Render avatars of other agents
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
agentList->lock();
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||
avatar->render(0);
|
||||
//avatarRenderer.render(avatar, 0); // this will replace the above call
|
||||
}
|
||||
}
|
||||
agentList->unlock();
|
||||
|
||||
// Render the world box
|
||||
if (!::lookingInMirror && ::statsOn) { render_world_box(); }
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||
|
||||
//Render my own avatar
|
||||
myAvatar.render(::lookingInMirror);
|
||||
//avatarRenderer.render(&myAvatar, lookingInMirror); // this will replace the above call
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample
|
||||
// code (Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp), which is under the Apache license
|
||||
// (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
const char* DISTORTION_FRAGMENT_SHADER =
|
||||
"#version 120\n"
|
||||
"uniform sampler2D texture;"
|
||||
"uniform vec2 lensCenter;"
|
||||
"uniform vec2 screenCenter;"
|
||||
"uniform vec2 scale;"
|
||||
"uniform vec2 scaleIn;"
|
||||
"uniform vec4 hmdWarpParam;"
|
||||
"vec2 hmdWarp(vec2 in01) {"
|
||||
" vec2 theta = (in01 - lensCenter) * scaleIn;"
|
||||
" float rSq = theta.x * theta.x + theta.y * theta.y;"
|
||||
" vec2 theta1 = theta * (hmdWarpParam.x + hmdWarpParam.y * rSq + "
|
||||
" hmdWarpParam.z * rSq * rSq + hmdWarpParam.w * rSq * rSq * rSq);"
|
||||
" return lensCenter + scale * theta1;"
|
||||
"}"
|
||||
"void main(void) {"
|
||||
" vec2 tc = hmdWarp(gl_TexCoord[0].st);"
|
||||
" vec2 below = step(screenCenter.st + vec2(-0.25, -0.5), tc.st);"
|
||||
" vec2 above = vec2(1.0, 1.0) - step(screenCenter.st + vec2(0.25, 0.5), tc.st);"
|
||||
" gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texture2D(texture, tc), "
|
||||
" above.s * above.t * below.s * below.t);"
|
||||
"}";
|
||||
|
||||
// the locations of the uniform variables
|
||||
int textureLocation;
|
||||
int lensCenterLocation;
|
||||
int screenCenterLocation;
|
||||
int scaleLocation;
|
||||
int scaleInLocation;
|
||||
int hmdWarpParamLocation;
|
||||
|
||||
// renders both sides into a texture, then renders the texture to the display with distortion
|
||||
void displayOculus(Camera& whichCamera) {
|
||||
// magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates
|
||||
// the rendering parameters from the hardware stats, i just folded their calculations into
|
||||
// constants using the stats for the current-model hardware as contained in the SDK file
|
||||
// LibOVR/Src/Util/Util_Render_Stereo.cpp
|
||||
|
||||
// eye
|
||||
|
||||
// render the left eye view to the left side of the screen
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.151976, 0, 0); // +h, see Oculus SDK docs p. 26
|
||||
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
|
||||
whichCamera.getNearClip(), whichCamera.getFarClip());
|
||||
glTranslatef(0.032, 0, 0); // dip/2, see p. 27
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glViewport(0, 0, WIDTH/2, HEIGHT);
|
||||
displaySide(whichCamera);
|
||||
|
||||
// and the right eye to the right side
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glTranslatef(-0.151976, 0, 0); // -h
|
||||
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
|
||||
whichCamera.getNearClip(), whichCamera.getFarClip());
|
||||
glTranslatef(-0.032, 0, 0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glViewport(WIDTH/2, 0, WIDTH/2, HEIGHT);
|
||||
displaySide(whichCamera);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
// restore our normal viewport
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
if (::oculusTextureID == 0) {
|
||||
glGenTextures(1, &::oculusTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
GLhandleARB shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
|
||||
glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0);
|
||||
glCompileShaderARB(shaderID);
|
||||
::oculusProgramID = glCreateProgramObjectARB();
|
||||
glAttachObjectARB(::oculusProgramID, shaderID);
|
||||
glLinkProgramARB(::oculusProgramID);
|
||||
textureLocation = glGetUniformLocationARB(::oculusProgramID, "texture");
|
||||
lensCenterLocation = glGetUniformLocationARB(::oculusProgramID, "lensCenter");
|
||||
screenCenterLocation = glGetUniformLocationARB(::oculusProgramID, "screenCenter");
|
||||
scaleLocation = glGetUniformLocationARB(::oculusProgramID, "scale");
|
||||
scaleInLocation = glGetUniformLocationARB(::oculusProgramID, "scaleIn");
|
||||
hmdWarpParamLocation = glGetUniformLocationARB(::oculusProgramID, "hmdWarpParam");
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
|
||||
}
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, WIDTH, 0, HEIGHT);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
|
||||
|
||||
float scaleFactor = 1.0 / ::oculusDistortionScale;
|
||||
float aspectRatio = (WIDTH * 0.5) / HEIGHT;
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glUseProgramObjectARB(::oculusProgramID);
|
||||
glUniform1fARB(textureLocation, 0);
|
||||
glUniform2fARB(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
|
||||
glUniform2fARB(screenCenterLocation, 0.25, 0.5);
|
||||
glUniform2fARB(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
|
||||
glUniform2fARB(scaleInLocation, 4, 2 / aspectRatio);
|
||||
glUniform4fARB(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
|
||||
|
||||
glColor3f(1, 0, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(0, 0);
|
||||
glTexCoord2f(0.5, 0);
|
||||
glVertex2f(WIDTH/2, 0);
|
||||
glTexCoord2f(0.5, 1);
|
||||
glVertex2f(WIDTH/2, HEIGHT);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex2f(0, HEIGHT);
|
||||
glEnd();
|
||||
|
||||
glUniform2fARB(lensCenterLocation, 0.787994, 0.5);
|
||||
glUniform2fARB(screenCenterLocation, 0.75, 0.5);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.5, 0);
|
||||
glVertex2f(WIDTH/2, 0);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(WIDTH, 0);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(WIDTH, HEIGHT);
|
||||
glTexCoord2f(0.5, 1);
|
||||
glVertex2f(WIDTH/2, HEIGHT);
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glUseProgramObjectARB(0);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void displayOverlay() {
|
||||
// Render 2D overlay: I/O level bar graphs and text
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, WIDTH, HEIGHT, 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
#ifndef _WIN32
|
||||
audio.render(WIDTH, HEIGHT);
|
||||
audioScope.render();
|
||||
#endif
|
||||
|
||||
if (displayHeadMouse && !::lookingInMirror && statsOn) {
|
||||
// Display small target box at center or head mouse target that can also be used to measure LOD
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
const int PIXEL_BOX = 20;
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glEnd();
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
// Show detected levels from the serial I/O ADC channel sensors
|
||||
if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT);
|
||||
|
||||
// Display stats and log text onscreen
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
|
||||
if (::statsOn) { displayStats(); }
|
||||
if (::logOn) { logger.render(WIDTH, HEIGHT); }
|
||||
|
||||
// Show menu
|
||||
if (::menuOn) {
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
menu.render(WIDTH,HEIGHT);
|
||||
}
|
||||
|
||||
// Show chat entry field
|
||||
if (::chatEntryOn) {
|
||||
chatEntry.render(WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
// Stats at upper right of screen about who domain server is telling us about
|
||||
glPointSize(1.0f);
|
||||
char agents[100];
|
||||
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
int totalAvatars = 0, totalServers = 0;
|
||||
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++;
|
||||
}
|
||||
|
||||
sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
|
||||
drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
|
||||
|
||||
if (::paintOn) {
|
||||
|
||||
char paintMessage[100];
|
||||
sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)",
|
||||
::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s,
|
||||
(unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue);
|
||||
drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void display(void)
|
||||
{
|
||||
|
@ -728,7 +1018,7 @@ void display(void)
|
|||
|
||||
float thirdPersonPitch = 0.0f;
|
||||
float thirdPersonUpShift = -0.1f;
|
||||
float thirdPersonDistance = 1.f;
|
||||
float thirdPersonDistance = 1.2f;
|
||||
float thirdPersonTightness = 8.0f;
|
||||
|
||||
if ( USING_FIRST_PERSON_EFFECT ) {
|
||||
|
@ -836,131 +1126,17 @@ void display(void)
|
|||
|
||||
glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z );
|
||||
|
||||
if (::starsOn) {
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
|
||||
// finally render the starfield
|
||||
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
|
||||
if (::oculusOn) {
|
||||
displayOculus(whichCamera);
|
||||
|
||||
} else {
|
||||
displaySide(whichCamera);
|
||||
glPopMatrix();
|
||||
|
||||
displayOverlay();
|
||||
}
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// draw a red sphere
|
||||
float sphereRadius = 0.25f;
|
||||
glColor3f(1,0,0);
|
||||
glPushMatrix();
|
||||
glutSolidSphere( sphereRadius, 15, 15 );
|
||||
glPopMatrix();
|
||||
|
||||
//draw a grid ground plane....
|
||||
drawGroundPlaneGrid( 5.0f, 9 );
|
||||
|
||||
// Draw voxels
|
||||
if ( showingVoxels )
|
||||
{
|
||||
voxels.render();
|
||||
}
|
||||
|
||||
// Render avatars of other agents
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
agentList->lock();
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||
avatar->render(0);
|
||||
}
|
||||
}
|
||||
agentList->unlock();
|
||||
|
||||
// Render the world box
|
||||
if (!::lookingInMirror && ::statsOn) { render_world_box(); }
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||
|
||||
//Render my own avatar
|
||||
myAvatar.render(::lookingInMirror);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
// Render 2D overlay: I/O level bar graphs and text
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, WIDTH, HEIGHT, 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
#ifndef _WIN32
|
||||
audio.render(WIDTH, HEIGHT);
|
||||
audioScope.render();
|
||||
#endif
|
||||
|
||||
if (displayHeadMouse && !::lookingInMirror && statsOn) {
|
||||
// Display small target box at center or head mouse target that can also be used to measure LOD
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
const int PIXEL_BOX = 20;
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glEnd();
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
// Show detected levels from the serial I/O ADC channel sensors
|
||||
if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT);
|
||||
|
||||
// Display stats and log text onscreen
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
|
||||
if (::statsOn) { displayStats(); }
|
||||
if (::logOn) { logger.render(WIDTH, HEIGHT); }
|
||||
|
||||
// Show menu
|
||||
if (::menuOn) {
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
menu.render(WIDTH,HEIGHT);
|
||||
}
|
||||
|
||||
// Show chat entry field
|
||||
if (::chatEntryOn) {
|
||||
chatEntry.render(WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
// Stats at upper right of screen about who domain server is telling us about
|
||||
glPointSize(1.0f);
|
||||
char agents[100];
|
||||
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
int totalAvatars = 0, totalServers = 0;
|
||||
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++;
|
||||
}
|
||||
|
||||
sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
|
||||
drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
|
||||
|
||||
if (::paintOn) {
|
||||
|
||||
char paintMessage[100];
|
||||
sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)",
|
||||
::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s,
|
||||
(unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue);
|
||||
drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
glutSwapBuffers();
|
||||
frameCount++;
|
||||
|
||||
|
@ -1022,6 +1198,20 @@ int setGyroLook(int state) {
|
|||
return iRet;
|
||||
}
|
||||
|
||||
int setFullscreen(int state) {
|
||||
bool wasFullscreen = ::fullscreen;
|
||||
int value = setValue(state, &::fullscreen);
|
||||
if (::fullscreen != wasFullscreen) {
|
||||
if (::fullscreen) {
|
||||
glutFullScreen();
|
||||
|
||||
} else {
|
||||
glutReshapeWindow(WIDTH, HEIGHT);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int setVoxels(int state) {
|
||||
return setValue(state, &::showingVoxels);
|
||||
}
|
||||
|
@ -1030,6 +1220,15 @@ int setStars(int state) {
|
|||
return setValue(state, &::starsOn);
|
||||
}
|
||||
|
||||
int setOculus(int state) {
|
||||
bool wasOn = ::oculusOn;
|
||||
int value = setValue(state, &::oculusOn);
|
||||
if (::oculusOn != wasOn) {
|
||||
reshape(WIDTH, HEIGHT);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int setStats(int state) {
|
||||
return setValue(state, &::statsOn);
|
||||
}
|
||||
|
@ -1038,6 +1237,14 @@ int setMenu(int state) {
|
|||
return setValue(state, &::menuOn);
|
||||
}
|
||||
|
||||
int setRenderWarnings(int state) {
|
||||
int value = setValue(state, &::renderWarningsOn);
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
::voxels.setRenderPipelineWarnings(::renderWarningsOn);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int setDisplayFrustum(int state) {
|
||||
return setValue(state, &::frustumOn);
|
||||
}
|
||||
|
@ -1071,6 +1278,13 @@ int setFrustumRenderMode(int state) {
|
|||
return ::frustumDrawingMode;
|
||||
}
|
||||
|
||||
int doKillLocalVoxels(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
::wantToKillLocalVoxels = true;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
int doRandomizeVoxelColors(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
::voxels.randomizeVoxelColors();
|
||||
|
@ -1078,7 +1292,6 @@ int doRandomizeVoxelColors(int state) {
|
|||
return state;
|
||||
}
|
||||
|
||||
|
||||
int doFalseRandomizeVoxelColors(int state) {
|
||||
if (state == MENU_ROW_PICKED) {
|
||||
::voxels.falseColorizeRandom();
|
||||
|
@ -1110,7 +1323,6 @@ int doFalseColorizeInView(int state) {
|
|||
return state;
|
||||
}
|
||||
|
||||
|
||||
const char* modeAll = " - All ";
|
||||
const char* modeVectors = " - Vectors ";
|
||||
const char* modePlanes = " - Planes ";
|
||||
|
@ -1146,12 +1358,14 @@ void initMenu() {
|
|||
menuColumnOptions->addRow("Mirror (h)", setHead);
|
||||
menuColumnOptions->addRow("Noise (n)", setNoise);
|
||||
menuColumnOptions->addRow("Gyro Look", setGyroLook);
|
||||
menuColumnOptions->addRow("Fullscreen (f)", setFullscreen);
|
||||
menuColumnOptions->addRow("Quit (q)", quitApp);
|
||||
|
||||
// Render
|
||||
menuColumnRender = menu.addColumn("Render");
|
||||
menuColumnRender->addRow("Voxels (V)", setVoxels);
|
||||
menuColumnRender->addRow("Stars (*)", setStars);
|
||||
menuColumnRender->addRow("Oculus (o)", setOculus);
|
||||
|
||||
// Tools
|
||||
menuColumnTools = menu.addColumn("Tools");
|
||||
|
@ -1168,6 +1382,8 @@ void initMenu() {
|
|||
|
||||
// Debug
|
||||
menuColumnDebug = menu.addColumn("Debug");
|
||||
menuColumnDebug->addRow("Show Render Pipeline Warnings", setRenderWarnings);
|
||||
menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels);
|
||||
menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors);
|
||||
menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors);
|
||||
menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance);
|
||||
|
@ -1180,8 +1396,7 @@ void testPointToVoxel()
|
|||
float y=0;
|
||||
float z=0;
|
||||
float s=0.1;
|
||||
for (float x=0; x<=1; x+= 0.05)
|
||||
{
|
||||
for (float x=0; x<=1; x+= 0.05) {
|
||||
printLog(" x=%f");
|
||||
|
||||
unsigned char red = 200; //randomColorValue(65);
|
||||
|
@ -1270,11 +1485,9 @@ void specialkeyUp(int k, int x, int y) {
|
|||
myAvatar.setDriveKeys(RIGHT, 0);
|
||||
myAvatar.setDriveKeys(ROT_RIGHT, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void specialkey(int k, int x, int y)
|
||||
{
|
||||
void specialkey(int k, int x, int y) {
|
||||
if (::chatEntryOn) {
|
||||
chatEntry.specialKey(k);
|
||||
return;
|
||||
|
@ -1316,7 +1529,6 @@ void keyUp(unsigned char k, int x, int y) {
|
|||
if (k == 's') myAvatar.setDriveKeys(BACK, 0);
|
||||
if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 0);
|
||||
if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 0);
|
||||
|
||||
}
|
||||
|
||||
void key(unsigned char k, int x, int y)
|
||||
|
@ -1343,6 +1555,8 @@ void key(unsigned char k, int x, int y)
|
|||
if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
|
||||
if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at
|
||||
if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging
|
||||
if (k == 'f') setFullscreen(!::fullscreen);
|
||||
if (k == 'o') setOculus(!::oculusOn);
|
||||
|
||||
if (k == '[') ::viewFrustumOffsetYaw -= 0.5;
|
||||
if (k == ']') ::viewFrustumOffsetYaw += 0.5;
|
||||
|
@ -1406,12 +1620,17 @@ void key(unsigned char k, int x, int y)
|
|||
}
|
||||
|
||||
// Receive packets from other agents/servers and decide what to do with them!
|
||||
void* networkReceive(void* args)
|
||||
{
|
||||
void* networkReceive(void* args) {
|
||||
sockaddr senderAddress;
|
||||
ssize_t bytesReceived;
|
||||
|
||||
while (!stopNetworkReceiveThread) {
|
||||
// check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that
|
||||
if (::wantToKillLocalVoxels) {
|
||||
::voxels.killLocalVoxels();
|
||||
::wantToKillLocalVoxels = false;
|
||||
}
|
||||
|
||||
if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||
packetCount++;
|
||||
bytesCount += bytesReceived;
|
||||
|
@ -1477,9 +1696,7 @@ void idle(void) {
|
|||
serialPort.readData();
|
||||
}
|
||||
|
||||
//
|
||||
// Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents
|
||||
//
|
||||
updateAvatar(deltaTime);
|
||||
|
||||
// read incoming packets from network
|
||||
|
@ -1510,39 +1727,38 @@ void idle(void) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void reshape(int width, int height)
|
||||
{
|
||||
void reshape(int width, int height) {
|
||||
WIDTH = width;
|
||||
HEIGHT = height;
|
||||
aspectRatio = ((float)width/(float)height); // based on screen resize
|
||||
|
||||
float fov;
|
||||
float nearClip;
|
||||
float farClip;
|
||||
|
||||
// get the lens details from the current camera
|
||||
if (::viewFrustumFromOffset) {
|
||||
fov = ::viewFrustumOffsetCamera.getFieldOfView();
|
||||
nearClip = ::viewFrustumOffsetCamera.getNearClip();
|
||||
farClip = ::viewFrustumOffsetCamera.getFarClip();
|
||||
Camera& camera = ::viewFrustumFromOffset ? (::viewFrustumOffsetCamera) : (::myCamera);
|
||||
float nearClip = camera.getNearClip();
|
||||
float farClip = camera.getFarClip();
|
||||
float fov;
|
||||
|
||||
if (::oculusOn) {
|
||||
// more magic numbers; see Oculus SDK docs, p. 32
|
||||
camera.setAspectRatio(aspectRatio *= 0.5);
|
||||
camera.setFieldOfView(fov = 2 * atan((0.0468 * ::oculusDistortionScale) / 0.041) * (180 / PI));
|
||||
|
||||
// resize the render texture
|
||||
if (::oculusTextureID != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
} else {
|
||||
fov = ::myCamera.getFieldOfView();
|
||||
nearClip = ::myCamera.getNearClip();
|
||||
farClip = ::myCamera.getFarClip();
|
||||
camera.setFieldOfView(fov = 60);
|
||||
}
|
||||
|
||||
//printLog("reshape() width=%d, height=%d, aspectRatio=%f fov=%f near=%f far=%f \n",
|
||||
// width,height,aspectRatio,fov,nearClip,farClip);
|
||||
|
||||
// Tell our viewFrustum about this change
|
||||
::viewFrustum.setAspectRatio(aspectRatio);
|
||||
|
||||
|
||||
glViewport(0, 0, width, height); // shouldn't this account for the menu???
|
||||
|
||||
glMatrixMode(GL_PROJECTION); //hello
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
// XXXBHG - If we're in view frustum mode, then we need to do this little bit of hackery so that
|
||||
|
@ -1559,46 +1775,34 @@ void reshape(int width, int height)
|
|||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void mouseFunc( int button, int state, int x, int y )
|
||||
{
|
||||
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
|
||||
{
|
||||
if (!menu.mouseClick(x, y)) {
|
||||
void mouseFunc(int button, int state, int x, int y) {
|
||||
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) {
|
||||
if (state == GLUT_DOWN && !menu.mouseClick(x, y)) {
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
mousePressed = 1;
|
||||
} else if (state == GLUT_UP) {
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
mousePressed = 0;
|
||||
}
|
||||
}
|
||||
if( button == GLUT_LEFT_BUTTON && state == GLUT_UP ) {
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
mousePressed = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void motionFunc( int x, int y)
|
||||
{
|
||||
void motionFunc(int x, int y) {
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
}
|
||||
|
||||
void mouseoverFunc( 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 Avatar(false));
|
||||
|
@ -1642,7 +1846,7 @@ int main(int argc, const char * argv[])
|
|||
int ip = getLocalAddress();
|
||||
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
|
||||
// the callback for our instance of AgentList is attachNewHeadToAgent
|
||||
AgentList::getInstance()->linkedDataCreateCallback = &attachNewHeadToAgent;
|
||||
|
||||
|
@ -1679,7 +1883,7 @@ int main(int argc, const char * argv[])
|
|||
// field of view and near and far clip to make it interesting.
|
||||
//viewFrustumOffsetCamera.setFieldOfView(90.0);
|
||||
viewFrustumOffsetCamera.setNearClip(0.1);
|
||||
viewFrustumOffsetCamera.setFarClip(500.0);
|
||||
viewFrustumOffsetCamera.setFarClip(500.0*TREE_SCALE);
|
||||
|
||||
printLog( "Created Display Window.\n" );
|
||||
|
||||
|
@ -1720,6 +1924,8 @@ int main(int argc, const char * argv[])
|
|||
printLog("Network receive thread created.\n");
|
||||
}
|
||||
|
||||
myAvatar.readAvatarDataFromFile();
|
||||
|
||||
glutTimerFunc(1000, Timer, 0);
|
||||
glutMainLoop();
|
||||
|
||||
|
|
|
@ -24,4 +24,5 @@ const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
|||
typedef unsigned long int glBufferIndex;
|
||||
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
||||
|
||||
const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60;
|
||||
#endif
|
||||
|
|
|
@ -125,7 +125,9 @@ void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) {
|
|||
_currentColor[1] = green;
|
||||
_currentColor[2] = blue;
|
||||
_currentColor[3] = 1; // XXXBHG - False colors are always considered set
|
||||
_isDirty = true;
|
||||
//if (_shouldRender) {
|
||||
_isDirty = true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,18 +138,24 @@ void VoxelNode::setFalseColored(bool isFalseColored) {
|
|||
memcpy(&_currentColor,&_trueColor,sizeof(nodeColor));
|
||||
}
|
||||
_falseColored = isFalseColored;
|
||||
_isDirty = true;
|
||||
//if (_shouldRender) {
|
||||
_isDirty = true;
|
||||
//}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void VoxelNode::setColor(const nodeColor& color) {
|
||||
if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) {
|
||||
//printLog("VoxelNode::setColor() was: (%d,%d,%d) is: (%d,%d,%d)\n",
|
||||
// _trueColor[0],_trueColor[1],_trueColor[2],color[0],color[1],color[2]);
|
||||
memcpy(&_trueColor,&color,sizeof(nodeColor));
|
||||
if (!_falseColored) {
|
||||
memcpy(&_currentColor,&color,sizeof(nodeColor));
|
||||
}
|
||||
_isDirty = true;
|
||||
//if (_shouldRender) {
|
||||
_isDirty = true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -234,6 +242,7 @@ bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const {
|
|||
float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const {
|
||||
AABox box;
|
||||
getAABox(box);
|
||||
box.scale(TREE_SCALE);
|
||||
float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - (box.getCorner().x + box.getSize().x), 2) +
|
||||
powf(viewFrustum.getPosition().y - (box.getCorner().y + box.getSize().y), 2) +
|
||||
powf(viewFrustum.getPosition().z - (box.getCorner().z + box.getSize().z), 2));
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
typedef unsigned char colorPart;
|
||||
typedef unsigned char nodeColor[4];
|
||||
typedef unsigned char rgbColor[3];
|
||||
|
||||
class VoxelNode {
|
||||
private:
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
using voxels_lib::printLog;
|
||||
|
||||
int boundaryDistanceForRenderLevel(unsigned int renderLevel) {
|
||||
float voxelSizeScale = 5000.0;
|
||||
float voxelSizeScale = 500.0*TREE_SCALE;
|
||||
return voxelSizeScale / powf(2, renderLevel);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,8 @@ VoxelTree::VoxelTree() :
|
|||
voxelsBytesRead(0),
|
||||
voxelsCreatedStats(100),
|
||||
voxelsColoredStats(100),
|
||||
voxelsBytesReadStats(100) {
|
||||
voxelsBytesReadStats(100),
|
||||
_isDirty(true) {
|
||||
|
||||
rootNode = new VoxelNode();
|
||||
rootNode->octalCode = new unsigned char[1];
|
||||
|
@ -127,17 +128,29 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
|||
// check the colors mask to see if we have a child to color in
|
||||
if (oneAtBit(*nodeData, i)) {
|
||||
// create the child if it doesn't exist
|
||||
if (destinationNode->children[i] == NULL) {
|
||||
if (!destinationNode->children[i]) {
|
||||
destinationNode->addChildAtIndex(i);
|
||||
this->voxelsCreated++;
|
||||
this->voxelsCreatedStats.updateAverage(1);
|
||||
if (destinationNode->isDirty()) {
|
||||
_isDirty = true;
|
||||
_nodesChangedFromBitstream++;
|
||||
}
|
||||
voxelsCreated++;
|
||||
voxelsCreatedStats.updateAverage(1);
|
||||
}
|
||||
|
||||
// pull the color for this child
|
||||
nodeColor newColor;
|
||||
memcpy(newColor, nodeData + bytesRead, 3);
|
||||
newColor[3] = 1;
|
||||
bool nodeWasDirty = destinationNode->children[i]->isDirty();
|
||||
destinationNode->children[i]->setColor(newColor);
|
||||
bool nodeIsDirty = destinationNode->children[i]->isDirty();
|
||||
if (nodeIsDirty) {
|
||||
_isDirty = true;
|
||||
}
|
||||
if (!nodeWasDirty && nodeIsDirty) {
|
||||
_nodesChangedFromBitstream++;
|
||||
}
|
||||
this->voxelsColored++;
|
||||
this->voxelsColoredStats.updateAverage(1);
|
||||
|
||||
|
@ -145,7 +158,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
|||
}
|
||||
}
|
||||
// average node's color based on color of children
|
||||
bool nodeWasDirty = destinationNode->isDirty();
|
||||
destinationNode->setColorFromAverageOfChildren();
|
||||
bool nodeIsDirty = destinationNode->isDirty();
|
||||
if (nodeIsDirty) {
|
||||
_isDirty = true;
|
||||
}
|
||||
if (!nodeWasDirty && nodeIsDirty) {
|
||||
_nodesChangedFromBitstream++;
|
||||
}
|
||||
|
||||
// give this destination node the child mask from the packet
|
||||
unsigned char childMask = *(nodeData + bytesRead);
|
||||
|
@ -157,9 +178,17 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
|||
// check the exists mask to see if we have a child to traverse into
|
||||
|
||||
if (oneAtBit(childMask, childIndex)) {
|
||||
if (destinationNode->children[childIndex] == NULL) {
|
||||
if (!destinationNode->children[childIndex]) {
|
||||
// add a child at that index, if it doesn't exist
|
||||
bool nodeWasDirty = destinationNode->isDirty();
|
||||
destinationNode->addChildAtIndex(childIndex);
|
||||
bool nodeIsDirty = destinationNode->isDirty();
|
||||
if (nodeIsDirty) {
|
||||
_isDirty = true;
|
||||
}
|
||||
if (!nodeWasDirty && nodeIsDirty) {
|
||||
_nodesChangedFromBitstream++;
|
||||
}
|
||||
this->voxelsCreated++;
|
||||
this->voxelsCreatedStats.updateAverage(this->voxelsCreated);
|
||||
}
|
||||
|
@ -179,6 +208,8 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
|||
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes) {
|
||||
int bytesRead = 0;
|
||||
unsigned char* bitstreamAt = bitstream;
|
||||
|
||||
_nodesChangedFromBitstream = 0;
|
||||
|
||||
// Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes
|
||||
// into a single network packet. readNodeData() basically goes down a tree from the root, and fills things in from there
|
||||
|
@ -193,6 +224,10 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt
|
|||
// Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial
|
||||
// octal code is always relative to root!
|
||||
bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt);
|
||||
if (bitstreamRootNode->isDirty()) {
|
||||
_isDirty = true;
|
||||
_nodesChangedFromBitstream++;
|
||||
}
|
||||
}
|
||||
|
||||
int octalCodeBytes = bytesRequiredForCodeLength(*bitstreamAt);
|
||||
|
@ -403,6 +438,27 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
|||
}
|
||||
}
|
||||
|
||||
void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue) {
|
||||
unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue);
|
||||
this->readCodeColorBufferToTree(voxelData);
|
||||
delete voxelData;
|
||||
}
|
||||
|
||||
|
||||
void VoxelTree::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color) {
|
||||
glm::vec3 distance = point2 - point1;
|
||||
glm::vec3 items = distance / unitSize;
|
||||
int maxItems = std::max(items.x, std::max(items.y, items.z));
|
||||
glm::vec3 increment = distance * (1.0f/ maxItems);
|
||||
glm::vec3 pointAt = point1;
|
||||
for (int i = 0; i <= maxItems; i++ ) {
|
||||
pointAt += increment;
|
||||
unsigned char* voxelData = pointToVoxel(pointAt.x,pointAt.y,pointAt.z,unitSize,color[0],color[1],color[2]);
|
||||
readCodeColorBufferToTree(voxelData);
|
||||
delete voxelData;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) {
|
||||
// About the color of the sphere... we're going to make this sphere be a gradient
|
||||
// between two RGB colors. We will do the gradient along the phi spectrum
|
||||
|
@ -498,10 +554,10 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
|
|||
// Keep track of how deep we've searched.
|
||||
currentSearchLevel++;
|
||||
|
||||
// If we've reached our max Search Level, then stop searching.
|
||||
if (currentSearchLevel >= maxSearchLevel) {
|
||||
return currentSearchLevel;
|
||||
}
|
||||
// If we've passed our max Search Level, then stop searching. return last level searched
|
||||
if (currentSearchLevel > maxSearchLevel) {
|
||||
return currentSearchLevel-1;
|
||||
}
|
||||
|
||||
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
|
||||
if (!node->isInView(viewFrustum)) {
|
||||
|
|
|
@ -46,6 +46,9 @@ public:
|
|||
void reaverageVoxelColors(VoxelNode *startNode);
|
||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
||||
void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue);
|
||||
|
||||
void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color);
|
||||
|
||||
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
||||
|
||||
|
@ -54,6 +57,10 @@ public:
|
|||
VoxelNodeBag& bag);
|
||||
|
||||
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
|
||||
|
||||
bool isDirty() const { return _isDirty; };
|
||||
void clearDirtyBit() { _isDirty = false; };
|
||||
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
|
||||
|
||||
private:
|
||||
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||
|
@ -68,6 +75,9 @@ private:
|
|||
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);
|
||||
|
||||
bool _isDirty;
|
||||
unsigned long int _nodesChangedFromBitstream;
|
||||
};
|
||||
|
||||
int boundaryDistanceForRenderLevel(unsigned int renderLevel);
|
||||
|
|
13
pairing-server/CMakeLists.txt
Normal file
13
pairing-server/CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
|
||||
set(TARGET_NAME pairing-server)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
|
||||
# link the shared hifi library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
106
pairing-server/src/main.cpp
Normal file
106
pairing-server/src/main.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// main.cpp
|
||||
// pairing-server
|
||||
//
|
||||
// Created by Stephen Birarda on 5/1/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <UDPSocket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
const int PAIRING_SERVER_LISTEN_PORT = 7247;
|
||||
const int MAX_PACKET_SIZE_BYTES = 1400;
|
||||
|
||||
struct PairableDevice {
|
||||
char identifier[64];
|
||||
char name[64];
|
||||
sockaddr_in sendingSocket;
|
||||
sockaddr_in localSocket;
|
||||
};
|
||||
|
||||
int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) {
|
||||
int currentIndex = 0;
|
||||
|
||||
while (haystack[currentIndex] != '\0' && haystack[currentIndex] != needle) {
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT);
|
||||
|
||||
sockaddr_in senderSocket;
|
||||
char senderData[MAX_PACKET_SIZE_BYTES] = {};
|
||||
ssize_t receivedBytes = 0;
|
||||
|
||||
std::vector<PairableDevice> devices;
|
||||
|
||||
while (true) {
|
||||
if (serverSocket.receive((sockaddr *)&senderSocket, &senderData, &receivedBytes)) {
|
||||
|
||||
if (senderData[0] == 'A') {
|
||||
// this is a device reporting itself as available
|
||||
|
||||
// create a new PairableDevice
|
||||
PairableDevice newDevice = {};
|
||||
|
||||
int addressBytes[4];
|
||||
int socketPort = 0;
|
||||
|
||||
int numMatches = sscanf(senderData, "Available %s %d.%d.%d.%d:%d %s",
|
||||
newDevice.identifier,
|
||||
&addressBytes[3],
|
||||
&addressBytes[2],
|
||||
&addressBytes[1],
|
||||
&addressBytes[0],
|
||||
&socketPort,
|
||||
newDevice.name);
|
||||
|
||||
if (numMatches >= 6) {
|
||||
// if we have fewer than 6 matches the packet wasn't properly formatted
|
||||
|
||||
// setup the localSocket for the pairing device
|
||||
newDevice.localSocket.sin_family = AF_INET;
|
||||
newDevice.localSocket.sin_addr.s_addr = (addressBytes[3] |
|
||||
addressBytes[2] << 8 |
|
||||
addressBytes[1] << 16 |
|
||||
addressBytes[0] << 24);
|
||||
newDevice.localSocket.sin_port = socketPort;
|
||||
|
||||
// store this device's sending socket so we can talk back to it
|
||||
newDevice.sendingSocket = senderSocket;
|
||||
|
||||
// push this new device into the vector
|
||||
printf("Adding device %s (%s) to list\n", newDevice.identifier, newDevice.name);
|
||||
devices.push_back(newDevice);
|
||||
}
|
||||
} else if (senderData[0] == 'F') {
|
||||
// this is a client looking to pair with a device
|
||||
// send the most recent device this address so it can attempt to pair
|
||||
|
||||
char requestorAddress[INET_ADDRSTRLEN] = {};
|
||||
int requestorPort = 0;
|
||||
|
||||
int requestorMatches = sscanf(senderData, "Find %[^:]:%d", requestorAddress, &requestorPort);
|
||||
|
||||
if (requestorMatches == 2) {
|
||||
PairableDevice lastDevice = devices[devices.size() - 1];
|
||||
|
||||
char pairData[INET_ADDRSTRLEN + 6] = {};
|
||||
sprintf(pairData, "%s:%d", requestorAddress, requestorPort);
|
||||
|
||||
serverSocket.send((sockaddr*) &lastDevice.sendingSocket, pairData, strlen(pairData));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -38,15 +38,14 @@ const float DEATH_STAR_RADIUS = 4.0;
|
|||
const float MAX_CUBE = 0.05f;
|
||||
|
||||
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
|
||||
const int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
|
||||
int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
|
||||
|
||||
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
||||
|
||||
VoxelTree randomTree;
|
||||
|
||||
bool wantColorRandomizer = false;
|
||||
bool debugViewFrustum = false;
|
||||
bool viewFrustumCulling = true; // for now
|
||||
bool debugVoxelSending = false;
|
||||
|
||||
void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
|
||||
float r = random ? randFloatInRange(0.05,0.1) : 0.25;
|
||||
|
@ -76,43 +75,71 @@ bool countVoxelsOperation(VoxelNode* node, void* extraData) {
|
|||
}
|
||||
|
||||
void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
|
||||
printf("adding scene of spheres...\n");
|
||||
|
||||
int sphereBaseSize = 512;
|
||||
|
||||
tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer);
|
||||
printf("one sphere added...\n");
|
||||
tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
printf("adding scene...\n");
|
||||
|
||||
float voxelSize = 1.f/32;
|
||||
printf("creating corner points...\n");
|
||||
tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255);
|
||||
tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 );
|
||||
tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 );
|
||||
tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255);
|
||||
|
||||
|
||||
printf("two spheres added...\n");
|
||||
tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
printf("three spheres added...\n");
|
||||
tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
printf("four spheres added...\n");
|
||||
tree->createSphere(0.030625, (1.0 - 0.030625), 0.06125, (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
printf("five spheres added...\n");
|
||||
tree->createSphere(0.06125, 0.125, 0.125, (1.0 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255);
|
||||
tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255);
|
||||
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 );
|
||||
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255);
|
||||
printf("DONE creating corner points...\n");
|
||||
|
||||
printf("creating voxel lines...\n");
|
||||
float lineVoxelSize = 0.99f/256;
|
||||
rgbColor red = {255,0,0};
|
||||
rgbColor green = {0,255,0};
|
||||
rgbColor blue = {0,0,255};
|
||||
|
||||
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), lineVoxelSize, blue);
|
||||
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), lineVoxelSize, red);
|
||||
tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), lineVoxelSize, green);
|
||||
|
||||
printf("DONE creating lines...\n");
|
||||
|
||||
int sphereBaseSize = 512;
|
||||
printf("creating spheres...\n");
|
||||
tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer);
|
||||
printf("one sphere added...\n");
|
||||
tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
|
||||
|
||||
printf("two spheres added...\n");
|
||||
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
printf("three spheres added...\n");
|
||||
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
printf("four spheres added...\n");
|
||||
tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
printf("five spheres added...\n");
|
||||
tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||
|
||||
float radius = 0.0125f;
|
||||
printf("6 spheres added...\n");
|
||||
tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("7 spheres added...\n");
|
||||
tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("8 spheres added...\n");
|
||||
tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("9 spheres added...\n");
|
||||
tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("10 spheres added...\n");
|
||||
tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("11 spheres added...\n");
|
||||
printf("6 spheres added...\n");
|
||||
tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("7 spheres added...\n");
|
||||
tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("8 spheres added...\n");
|
||||
tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("9 spheres added...\n");
|
||||
tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("10 spheres added...\n");
|
||||
tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||
printf("11 spheres added...\n");
|
||||
|
||||
printf("DONE creating spheres...\n");
|
||||
|
||||
_nodeCount=0;
|
||||
tree->recurseTreeWithOperation(countVoxelsOperation);
|
||||
printf("Nodes after adding scene %d nodes\n", _nodeCount);
|
||||
|
||||
|
||||
printf("DONE adding scene of spheres...\n");
|
||||
printf("DONE adding scene of spheres...\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,8 +194,14 @@ void eraseVoxelTreeAndCleanupAgentVisitData() {
|
|||
|
||||
|
||||
void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) {
|
||||
// If the bag is empty, fill it...
|
||||
if (agentData->nodeBag.isEmpty()) {
|
||||
bool searchReset = false;
|
||||
int searchLoops = 0;
|
||||
int searchLevelWas = agentData->getMaxSearchLevel();
|
||||
double start = usecTimestampNow();
|
||||
while (!searchReset && agentData->nodeBag.isEmpty()) {
|
||||
searchLoops++;
|
||||
|
||||
searchLevelWas = agentData->getMaxSearchLevel();
|
||||
int maxLevelReached = randomTree.searchForColoredNodes(agentData->getMaxSearchLevel(), randomTree.rootNode,
|
||||
viewFrustum, agentData->nodeBag);
|
||||
agentData->setMaxLevelReached(maxLevelReached);
|
||||
|
@ -177,17 +210,38 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
|
|||
if (agentData->nodeBag.isEmpty()) {
|
||||
if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) {
|
||||
agentData->resetMaxSearchLevel();
|
||||
searchReset = true;
|
||||
} else {
|
||||
agentData->incrementMaxSearchLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (elapsedmsec > 100) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printf("WARNING! searchForColoredNodes() took %lf seconds to identify %d nodes at level %d in %d loops\n",
|
||||
elapsedsec, agentData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||
} else {
|
||||
printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n",
|
||||
elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||
}
|
||||
} else if (::debugVoxelSending) {
|
||||
printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n",
|
||||
elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||
}
|
||||
|
||||
|
||||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||
if (!agentData->nodeBag.isEmpty()) {
|
||||
static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static
|
||||
int bytesWritten = 0;
|
||||
int packetsSentThisInterval = 0;
|
||||
int truePacketsSent = 0;
|
||||
int trueBytesSent = 0;
|
||||
double start = usecTimestampNow();
|
||||
|
||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) {
|
||||
if (!agentData->nodeBag.isEmpty()) {
|
||||
VoxelNode* subTree = agentData->nodeBag.extract();
|
||||
|
@ -200,6 +254,8 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
|
|||
} else {
|
||||
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
||||
agentData->getPacket(), agentData->getPacketLength());
|
||||
trueBytesSent += agentData->getPacketLength();
|
||||
truePacketsSent++;
|
||||
packetsSentThisInterval++;
|
||||
agentData->resetVoxelPacket();
|
||||
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||
|
@ -208,12 +264,30 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
|
|||
if (agentData->isPacketWaiting()) {
|
||||
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
||||
agentData->getPacket(), agentData->getPacketLength());
|
||||
trueBytesSent += agentData->getPacketLength();
|
||||
truePacketsSent++;
|
||||
agentData->resetVoxelPacket();
|
||||
|
||||
}
|
||||
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
|
||||
}
|
||||
}
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (elapsedmsec > 100) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printf("WARNING! packetLoop() took %lf seconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||
elapsedsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count());
|
||||
} else {
|
||||
printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||
elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count());
|
||||
}
|
||||
} else if (::debugVoxelSending) {
|
||||
printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||
elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count());
|
||||
}
|
||||
|
||||
// if during this last pass, we emptied our bag, then we want to move to the next level.
|
||||
if (agentData->nodeBag.isEmpty()) {
|
||||
if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) {
|
||||
|
@ -296,13 +370,9 @@ int main(int argc, const char * argv[])
|
|||
|
||||
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* DEBUG_VOXEL_SENDING = "--debugVoxelSending";
|
||||
::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING);
|
||||
printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no"));
|
||||
|
||||
const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer";
|
||||
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
||||
|
@ -315,6 +385,17 @@ int main(int argc, const char * argv[])
|
|||
if (voxelsFilename) {
|
||||
randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
||||
}
|
||||
|
||||
// Check to see if the user passed in a command line option for setting packet send rate
|
||||
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
||||
const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND);
|
||||
if (packetsPerSecond) {
|
||||
PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10;
|
||||
if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) {
|
||||
PACKETS_PER_CLIENT_PER_INTERVAL = 1;
|
||||
}
|
||||
printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL);
|
||||
}
|
||||
|
||||
const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels";
|
||||
if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) {
|
||||
|
@ -380,8 +461,6 @@ int main(int argc, const char * argv[])
|
|||
delete []vertices;
|
||||
|
||||
randomTree.readCodeColorBufferToTree(pVoxelData);
|
||||
//printf("readCodeColorBufferToTree() of size=%d atByte=%d receivedBytes=%ld\n",
|
||||
// voxelDataSize,atByte,receivedBytes);
|
||||
// skip to next
|
||||
pVoxelData+=voxelDataSize;
|
||||
atByte+=voxelDataSize;
|
||||
|
|
Loading…
Reference in a new issue