mirror of
https://github.com/lubosz/overte.git
synced 2025-04-17 00:57:44 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into pointy
Conflicts: interface/src/Application.h interface/src/Audio.h interface/src/Webcam.cpp
This commit is contained in:
commit
b5a8c2710c
77 changed files with 1659 additions and 827 deletions
|
@ -14,7 +14,7 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
|
|||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# link in the shared library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
|
|
|
@ -9,7 +9,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake
|
|||
set(TARGET_NAME audio-mixer)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# set up the external glm library
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
|
|
|
@ -10,7 +10,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake
|
|||
|
||||
# setup the project
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# include glm
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
MACRO(SETUP_HIFI_LIBRARY TARGET)
|
||||
project(${TARGET_NAME})
|
||||
project(${TARGET})
|
||||
|
||||
# grab the implemenation and header files
|
||||
file(GLOB LIB_SRCS src/*.h src/*.cpp)
|
||||
|
||||
# create a library and set the property so it can be referenced later
|
||||
add_library(${TARGET_NAME} ${LIB_SRCS})
|
||||
add_library(${TARGET} ${LIB_SRCS})
|
||||
|
||||
find_package(Qt4 REQUIRED QtCore)
|
||||
include(${QT_USE_FILE})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
||||
|
||||
target_link_libraries(${TARGET} ${QT_LIBRARIES})
|
||||
ENDMACRO(SETUP_HIFI_LIBRARY _target)
|
|
@ -1,4 +1,4 @@
|
|||
MACRO(SETUP_HIFI_PROJECT TARGET)
|
||||
MACRO(SETUP_HIFI_PROJECT TARGET INCLUDE_QT)
|
||||
project(${TARGET})
|
||||
|
||||
# grab the implemenation and header files
|
||||
|
@ -6,4 +6,12 @@ MACRO(SETUP_HIFI_PROJECT TARGET)
|
|||
|
||||
# add the executable
|
||||
add_executable(${TARGET} ${TARGET_SRCS})
|
||||
ENDMACRO(SETUP_HIFI_PROJECT _target)
|
||||
|
||||
IF (${INCLUDE_QT})
|
||||
find_package(Qt4 REQUIRED QtCore)
|
||||
include(${QT_USE_FILE})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
||||
ENDIF()
|
||||
|
||||
target_link_libraries(${TARGET} ${QT_LIBRARIES})
|
||||
ENDMACRO(SETUP_HIFI_PROJECT _target _include_qt)
|
|
@ -6,7 +6,7 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
|||
set(TARGET_NAME domain-server)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# link the shared hifi library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
|
|
|
@ -9,7 +9,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake
|
|||
set(TARGET_NAME eve)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
|
|
|
@ -9,7 +9,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake
|
|||
set(TARGET_NAME injector)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# set up the external glm library
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
|
|
|
@ -70,10 +70,10 @@
|
|||
using namespace std;
|
||||
|
||||
// Starfield information
|
||||
static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
|
||||
static char STAR_FILE[] = "http://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
|
||||
static char STAR_CACHE_FILE[] = "cachedStars.txt";
|
||||
|
||||
static const bool TESTING_PARTICLE_SYSTEM = false;
|
||||
static const bool TESTING_PARTICLE_SYSTEM = true;
|
||||
|
||||
static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored
|
||||
|
||||
|
@ -164,6 +164,11 @@ void GLCanvas::wheelEvent(QWheelEvent* event) {
|
|||
Application::getInstance()->wheelEvent(event);
|
||||
}
|
||||
|
||||
void messageHandler(QtMsgType type, const char* message) {
|
||||
fprintf(stdout, "%s", message);
|
||||
LogDisplay::instance.addMessage(message);
|
||||
}
|
||||
|
||||
Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||
QApplication(argc, argv),
|
||||
_window(new QMainWindow(desktop())),
|
||||
|
@ -173,6 +178,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_frameCount(0),
|
||||
_fps(120.0f),
|
||||
_justStarted(true),
|
||||
_particleSystemInitialized(false),
|
||||
_coolDemoParticleEmitter(-1),
|
||||
_wantToKillLocalVoxels(false),
|
||||
_frustumDrawingMode(FRUSTUM_DRAW_MODE_ALL),
|
||||
_viewFrustumOffsetYaw(-135.0),
|
||||
|
@ -188,6 +195,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_isTouchPressed(false),
|
||||
_yawFromTouch(0.0f),
|
||||
_pitchFromTouch(0.0f),
|
||||
_groundPlaneImpact(0.0f),
|
||||
_mousePressed(false),
|
||||
_mouseVoxelScale(1.0f / 1024.0f),
|
||||
_justEditedVoxel(false),
|
||||
|
@ -210,7 +218,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
{
|
||||
_applicationStartupTime = startup_time;
|
||||
_window->setWindowTitle("Interface");
|
||||
printLog("Interface Startup:\n");
|
||||
|
||||
qInstallMsgHandler(messageHandler);
|
||||
|
||||
unsigned int listenPort = 0; // bind to an ephemeral port by default
|
||||
const char** constArgv = const_cast<const char**>(argv);
|
||||
|
@ -233,7 +242,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
|
||||
// Handle Local Domain testing with the --local command line
|
||||
if (cmdOptionExists(argc, constArgv, "--local")) {
|
||||
printLog("Local Domain MODE!\n");
|
||||
qDebug("Local Domain MODE!\n");
|
||||
|
||||
NodeList::getInstance()->setDomainIPToLocalhost();
|
||||
}
|
||||
|
@ -297,7 +306,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
}
|
||||
|
||||
void Application::initializeGL() {
|
||||
printLog( "Created Display Window.\n" );
|
||||
qDebug( "Created Display Window.\n" );
|
||||
|
||||
// initialize glut for shape drawing; Qt apparently initializes it on OS X
|
||||
#ifndef __APPLE__
|
||||
|
@ -312,10 +321,10 @@ void Application::initializeGL() {
|
|||
_viewFrustumOffsetCamera.setFarClip(500.0 * TREE_SCALE);
|
||||
|
||||
initDisplay();
|
||||
printLog( "Initialized Display.\n" );
|
||||
qDebug( "Initialized Display.\n" );
|
||||
|
||||
init();
|
||||
printLog( "Init() complete.\n" );
|
||||
qDebug( "Init() complete.\n" );
|
||||
|
||||
// Check to see if the user passed in a command line option for randomizing colors
|
||||
bool wantColorRandomizer = !arguments().contains("--NoColorRandomizer");
|
||||
|
@ -324,13 +333,13 @@ void Application::initializeGL() {
|
|||
// Voxel File. If so, load it now.
|
||||
if (!_voxelsFilename.isEmpty()) {
|
||||
_voxels.loadVoxelsFile(_voxelsFilename.constData(), wantColorRandomizer);
|
||||
printLog("Local Voxel File loaded.\n");
|
||||
qDebug("Local Voxel File loaded.\n");
|
||||
}
|
||||
|
||||
// create thread for receipt of data via UDP
|
||||
if (_enableNetworkThread) {
|
||||
pthread_create(&_networkReceiveThread, NULL, networkReceive, NULL);
|
||||
printLog("Network receive thread created.\n");
|
||||
qDebug("Network receive thread created.\n");
|
||||
}
|
||||
|
||||
// call terminate before exiting
|
||||
|
@ -352,7 +361,7 @@ void Application::initializeGL() {
|
|||
_justStarted = false;
|
||||
char title[50];
|
||||
sprintf(title, "Interface: %4.2f seconds\n", startupTime);
|
||||
printLog("%s", title);
|
||||
qDebug("%s", title);
|
||||
_window->setWindowTitle(title);
|
||||
|
||||
const char LOGSTASH_INTERFACE_START_TIME_KEY[] = "interface-start-time";
|
||||
|
@ -1177,25 +1186,20 @@ void Application::editPreferences() {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
const char* newHostname = domainServerHostname->text().toLocal8Bit().data();
|
||||
|
||||
char newHostname[MAX_HOSTNAME_BYTES] = {};
|
||||
memcpy(newHostname, domainServerHostname->text().toAscii().data(), domainServerHostname->text().size());
|
||||
|
||||
// check if the domain server hostname is new
|
||||
if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname, sizeof(&newHostname)) != 0) {
|
||||
// if so we need to clear the nodelist and delete the local voxels
|
||||
Node *voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
|
||||
|
||||
if (voxelServer) {
|
||||
voxelServer->lock();
|
||||
}
|
||||
|
||||
_voxels.killLocalVoxels();
|
||||
|
||||
if (voxelServer) {
|
||||
voxelServer->unlock();
|
||||
}
|
||||
if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname, strlen(newHostname)) != 0) {
|
||||
|
||||
NodeList::getInstance()->clear();
|
||||
|
||||
// kill the local voxels
|
||||
_voxels.killLocalVoxels();
|
||||
|
||||
// reset the environment to default
|
||||
_environment.resetToDefault();
|
||||
|
||||
NodeList::getInstance()->setDomainHostname(newHostname);
|
||||
}
|
||||
|
||||
|
@ -1456,12 +1460,12 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
|||
uint64_t elapsed = now - args->lastSendTime;
|
||||
int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed;
|
||||
if (usecToSleep > 0) {
|
||||
printLog("sendVoxelsOperation: packet: %d bytes:%ld elapsed %ld usecs, sleeping for %d usecs!\n",
|
||||
args->packetsSent, args->bytesSent, elapsed, usecToSleep);
|
||||
qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, sleeping for %d usecs!\n",
|
||||
args->packetsSent, args->bytesSent, elapsed, usecToSleep);
|
||||
usleep(usecToSleep);
|
||||
} else {
|
||||
printLog("sendVoxelsOperation: packet: %d bytes:%ld elapsed %ld usecs, no need to sleep!\n",
|
||||
args->packetsSent, args->bytesSent, elapsed);
|
||||
qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, no need to sleep!\n",
|
||||
args->packetsSent, args->bytesSent, elapsed);
|
||||
}
|
||||
args->lastSendTime = now;
|
||||
}
|
||||
|
@ -1505,7 +1509,7 @@ void Application::importVoxelsToClipboard() {
|
|||
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
|
||||
QImage pngImage = QImage(fileName);
|
||||
if (pngImage.height() != pngImage.width()) {
|
||||
printLog("ERROR: Bad PNG size: height != width.\n");
|
||||
qDebug("ERROR: Bad PNG size: height != width.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1539,7 +1543,7 @@ void Application::importVoxels() {
|
|||
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
|
||||
QImage pngImage = QImage(fileName);
|
||||
if (pngImage.height() != pngImage.width()) {
|
||||
printLog("ERROR: Bad PNG size: height != width.\n");
|
||||
qDebug("ERROR: Bad PNG size: height != width.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1644,9 +1648,9 @@ void Application::pasteVoxels() {
|
|||
// If we have voxels left in the packet, then send the packet
|
||||
if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) {
|
||||
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||
printLog("sending packet: %d\n", ++args.packetsSent);
|
||||
qDebug("sending packet: %d\n", ++args.packetsSent);
|
||||
args.bytesSent += args.bufferInUse;
|
||||
printLog("total bytes sent: %ld\n", args.bytesSent);
|
||||
qDebug("total bytes sent: %lld\n", args.bytesSent);
|
||||
}
|
||||
|
||||
if (calculatedOctCode) {
|
||||
|
@ -1713,8 +1717,8 @@ void Application::initMenu() {
|
|||
"First Person", this, SLOT(setRenderFirstPerson(bool)), Qt::Key_P))->setCheckable(true);
|
||||
(_manualThirdPerson = renderMenu->addAction(
|
||||
"Third Person", this, SLOT(setRenderThirdPerson(bool))))->setCheckable(true);
|
||||
renderMenu->addAction("Increase Avatar Size", this, SLOT(increaseAvatarSize()), Qt::SHIFT | Qt::Key_Plus);
|
||||
renderMenu->addAction("Decrease Avatar Size", this, SLOT(decreaseAvatarSize()), Qt::SHIFT | Qt::Key_Minus);
|
||||
renderMenu->addAction("Increase Avatar Size", this, SLOT(increaseAvatarSize()), Qt::ALT | Qt::Key_Plus);
|
||||
renderMenu->addAction("Decrease Avatar Size", this, SLOT(decreaseAvatarSize()), Qt::ALT | Qt::Key_Minus);
|
||||
|
||||
|
||||
QMenu* toolsMenu = menuBar->addMenu("Tools");
|
||||
|
@ -1894,7 +1898,7 @@ void Application::init() {
|
|||
_audio.setJitterBufferSamples(_audioJitterBufferSamples);
|
||||
}
|
||||
|
||||
printLog("Loaded settings.\n");
|
||||
qDebug("Loaded settings.\n");
|
||||
|
||||
sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL());
|
||||
|
||||
|
@ -1904,9 +1908,10 @@ void Application::init() {
|
|||
_palette.addTool(&_swatch);
|
||||
_palette.addAction(_colorVoxelMode, 0, 2);
|
||||
_palette.addAction(_eyedropperMode, 0, 3);
|
||||
_palette.addAction(_selectVoxelMode, 0, 4);
|
||||
_palette.addAction(_selectVoxelMode, 0, 4);
|
||||
}
|
||||
|
||||
|
||||
const float MAX_AVATAR_EDIT_VELOCITY = 1.0f;
|
||||
const float MAX_VOXEL_EDIT_DISTANCE = 20.0f;
|
||||
const float HEAD_SPHERE_RADIUS = 0.07;
|
||||
|
@ -2071,6 +2076,7 @@ void Application::update(float deltaTime) {
|
|||
// Leap finger-sensing device
|
||||
LeapManager::enableFakeFingers(_simulateLeapHand->isChecked() || _testRaveGlove->isChecked());
|
||||
LeapManager::nextFrame();
|
||||
_myAvatar.getHand().setRaveGloveActive(_testRaveGlove->isChecked());
|
||||
_myAvatar.getHand().setLeapFingers(LeapManager::getFingerTips(), LeapManager::getFingerRoots());
|
||||
_myAvatar.getHand().setLeapHands(LeapManager::getHandPositions(), LeapManager::getHandNormals());
|
||||
|
||||
|
@ -2118,6 +2124,8 @@ void Application::update(float deltaTime) {
|
|||
_myAvatar.simulate(deltaTime, NULL);
|
||||
}
|
||||
|
||||
_myAvatar.getHand().simulate(deltaTime, true);
|
||||
|
||||
if (!OculusManager::isConnected()) {
|
||||
if (_lookingInMirror->isChecked()) {
|
||||
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
||||
|
@ -2166,8 +2174,8 @@ void Application::update(float deltaTime) {
|
|||
#endif
|
||||
|
||||
if (TESTING_PARTICLE_SYSTEM) {
|
||||
_particleSystem.simulate(deltaTime);
|
||||
}
|
||||
updateParticleSystem(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateAvatar(float deltaTime) {
|
||||
|
@ -2560,7 +2568,7 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
|
||||
//draw a grid ground plane....
|
||||
if (_renderGroundPlaneOn->isChecked()) {
|
||||
drawGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE);
|
||||
renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude());
|
||||
}
|
||||
// Draw voxels
|
||||
if (_renderVoxels->isChecked()) {
|
||||
|
@ -2616,7 +2624,9 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
}
|
||||
|
||||
if (TESTING_PARTICLE_SYSTEM) {
|
||||
_particleSystem.render();
|
||||
if (_particleSystemInitialized) {
|
||||
_particleSystem.render();
|
||||
}
|
||||
}
|
||||
|
||||
// Render the world box
|
||||
|
@ -2636,6 +2646,9 @@ void Application::displayOverlay() {
|
|||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// Display a single screen-size quad to
|
||||
renderCollisionOverlay(_glWidget->width(), _glWidget->height(), _audio.getCollisionSoundMagnitude());
|
||||
|
||||
#ifndef _WIN32
|
||||
_audio.render(_glWidget->width(), _glWidget->height());
|
||||
if (_oscilloscopeOn->isChecked()) {
|
||||
|
@ -2907,7 +2920,7 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
|
|||
// render the coverage map on screen
|
||||
void Application::renderCoverageMapV2() {
|
||||
|
||||
//printLog("renderCoverageMap()\n");
|
||||
//qDebug("renderCoverageMap()\n");
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2.0);
|
||||
|
@ -2952,7 +2965,7 @@ void Application::renderCoverageMapsV2Recursively(CoverageMapV2* map) {
|
|||
// render the coverage map on screen
|
||||
void Application::renderCoverageMap() {
|
||||
|
||||
//printLog("renderCoverageMap()\n");
|
||||
//qDebug("renderCoverageMap()\n");
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2.0);
|
||||
|
@ -3283,7 +3296,7 @@ void Application::eyedropperVoxelUnderCursor() {
|
|||
}
|
||||
|
||||
void Application::goHome() {
|
||||
printLog("Going Home!\n");
|
||||
qDebug("Going Home!\n");
|
||||
_myAvatar.setPosition(START_LOCATION);
|
||||
}
|
||||
|
||||
|
@ -3378,7 +3391,7 @@ void* Application::networkReceive(void* args) {
|
|||
case PACKET_TYPE_ENVIRONMENT_DATA: {
|
||||
if (app->_renderVoxels->isChecked()) {
|
||||
Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
|
||||
if (voxelServer) {
|
||||
if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) {
|
||||
voxelServer->lock();
|
||||
|
||||
if (app->_incomingPacket[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
|
||||
|
@ -3528,3 +3541,68 @@ void Application::exportSettings() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
void Application::updateParticleSystem(float deltaTime) {
|
||||
|
||||
if (!_particleSystemInitialized) {
|
||||
// create a stable test emitter and spit out a bunch of particles
|
||||
_coolDemoParticleEmitter = _particleSystem.addEmitter();
|
||||
|
||||
if (_coolDemoParticleEmitter != -1) {
|
||||
_particleSystem.setShowingEmitter(_coolDemoParticleEmitter, true);
|
||||
glm::vec3 particleEmitterPosition = glm::vec3(5.0f, 1.0f, 5.0f);
|
||||
_particleSystem.setEmitterPosition(_coolDemoParticleEmitter, particleEmitterPosition);
|
||||
glm::vec3 velocity(0.0f, 0.1f, 0.0f);
|
||||
float lifespan = 100000.0f;
|
||||
_particleSystem.emitParticlesNow(_coolDemoParticleEmitter, 1500, velocity, lifespan);
|
||||
}
|
||||
|
||||
// signal that the particle system has been initialized
|
||||
_particleSystemInitialized = true;
|
||||
} else {
|
||||
// update the particle system
|
||||
|
||||
static float t = 0.0f;
|
||||
t += deltaTime;
|
||||
|
||||
if (_coolDemoParticleEmitter != -1) {
|
||||
|
||||
glm::vec3 tilt = glm::vec3
|
||||
(
|
||||
30.0f * sinf( t * 0.55f ),
|
||||
0.0f,
|
||||
30.0f * cosf( t * 0.75f )
|
||||
);
|
||||
|
||||
_particleSystem.setEmitterRotation(_coolDemoParticleEmitter, glm::quat(glm::radians(tilt)));
|
||||
|
||||
ParticleSystem::ParticleAttributes attributes;
|
||||
|
||||
attributes.radius = 0.01f;
|
||||
attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
attributes.gravity = 0.0f + 0.05f * sinf( t * 0.52f );
|
||||
attributes.airFriction = 2.5 + 2.0f * sinf( t * 0.32f );
|
||||
attributes.jitter = 0.05f + 0.05f * sinf( t * 0.42f );
|
||||
attributes.emitterAttraction = 0.015f + 0.015f * cosf( t * 0.6f );
|
||||
attributes.tornadoForce = 0.0f + 0.03f * sinf( t * 0.7f );
|
||||
attributes.neighborAttraction = 0.1f + 0.1f * cosf( t * 0.8f );
|
||||
attributes.neighborRepulsion = 0.2f + 0.2f * sinf( t * 0.4f );
|
||||
attributes.bounce = 1.0f;
|
||||
attributes.usingCollisionSphere = true;
|
||||
attributes.collisionSpherePosition = glm::vec3( 5.0f, 0.5f, 5.0f );
|
||||
attributes.collisionSphereRadius = 0.5f;
|
||||
|
||||
if (attributes.gravity < 0.0f) {
|
||||
attributes.gravity = 0.0f;
|
||||
}
|
||||
|
||||
_particleSystem.setParticleAttributes(_coolDemoParticleEmitter, attributes);
|
||||
}
|
||||
|
||||
_particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
_particleSystem.simulate(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "Audio.h"
|
||||
#endif
|
||||
|
@ -31,15 +29,18 @@
|
|||
#include "BandwidthMeter.h"
|
||||
#include "Camera.h"
|
||||
#include "Environment.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "ParticleSystem.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
#include "SerialInterface.h"
|
||||
#include "Stars.h"
|
||||
#include "Swatch.h"
|
||||
#include "ToolsPalette.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelSystem.h"
|
||||
#include "Webcam.h"
|
||||
#include "avatar/Avatar.h"
|
||||
#include "avatar/HandControl.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
#include "ui/BandwidthDialog.h"
|
||||
#include "ui/ChatEntry.h"
|
||||
|
||||
|
@ -83,7 +84,10 @@ public:
|
|||
|
||||
const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel);
|
||||
|
||||
void updateParticleSystem(float deltaTime);
|
||||
|
||||
Avatar* getAvatar() { return &_myAvatar; }
|
||||
Audio* getAudio() { return &_audio; }
|
||||
Camera* getCamera() { return &_myCamera; }
|
||||
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
||||
VoxelSystem* getVoxels() { return &_voxels; }
|
||||
|
@ -104,6 +108,9 @@ public slots:
|
|||
|
||||
void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data);
|
||||
|
||||
void setGroundPlaneImpact(float groundPlaneImpact) { _groundPlaneImpact = groundPlaneImpact; }
|
||||
|
||||
|
||||
private slots:
|
||||
|
||||
void timer();
|
||||
|
@ -210,7 +217,7 @@ private:
|
|||
void deleteVoxelUnderCursor();
|
||||
void eyedropperVoxelUnderCursor();
|
||||
void resetSensors();
|
||||
|
||||
|
||||
void setMenuShortcutsEnabled(bool enabled);
|
||||
|
||||
void updateCursor();
|
||||
|
@ -290,6 +297,8 @@ private:
|
|||
timeval _timerStart, _timerEnd;
|
||||
timeval _lastTimeUpdated;
|
||||
bool _justStarted;
|
||||
bool _particleSystemInitialized;
|
||||
int _coolDemoParticleEmitter;
|
||||
|
||||
Stars _stars;
|
||||
|
||||
|
@ -348,6 +357,8 @@ private:
|
|||
float _yawFromTouch;
|
||||
float _pitchFromTouch;
|
||||
|
||||
float _groundPlaneImpact;
|
||||
|
||||
VoxelDetail _mouseVoxelDragging;
|
||||
glm::vec3 _voxelThrust;
|
||||
bool _mousePressed; // true if mouse has been pressed (clear when finished)
|
||||
|
|
|
@ -7,24 +7,25 @@
|
|||
//
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <StdDev.h>
|
||||
#include <UDPSocket.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include <AngleUtil.h>
|
||||
#include <NodeList.h>
|
||||
#include <NodeTypes.h>
|
||||
#include <AngleUtil.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StdDev.h>
|
||||
#include <UDPSocket.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Audio.h"
|
||||
#include "Util.h"
|
||||
#include "Log.h"
|
||||
|
||||
// Uncomment the following definition to test audio device latency by copying output to input
|
||||
//#define TEST_AUDIO_LOOPBACK
|
||||
|
@ -75,9 +76,12 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
|||
NodeList* nodeList = NodeList::getInstance();
|
||||
Application* interface = Application::getInstance();
|
||||
Avatar* interfaceAvatar = interface->getAvatar();
|
||||
|
||||
|
||||
memset(outputLeft, 0, PACKET_LENGTH_BYTES_PER_CHANNEL);
|
||||
memset(outputRight, 0, PACKET_LENGTH_BYTES_PER_CHANNEL);
|
||||
|
||||
// Add Procedural effects to input samples
|
||||
addProceduralSounds(inputLeft, BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
addProceduralSounds(inputLeft, outputLeft, outputRight, BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
|
||||
if (nodeList && inputLeft) {
|
||||
|
||||
|
@ -134,12 +138,8 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
|||
+ leadingBytes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
memset(outputLeft, 0, PACKET_LENGTH_BYTES_PER_CHANNEL);
|
||||
memset(outputRight, 0, PACKET_LENGTH_BYTES_PER_CHANNEL);
|
||||
|
||||
|
||||
AudioRingBuffer* ringBuffer = &_ringBuffer;
|
||||
|
||||
// if there is anything in the ring buffer, decide what to do:
|
||||
|
@ -151,7 +151,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
|||
// If not enough audio has arrived to start playback, keep waiting
|
||||
//
|
||||
#ifdef SHOW_AUDIO_DEBUG
|
||||
printLog("%i,%i,%i,%i\n",
|
||||
qDebug("%i,%i,%i,%i\n",
|
||||
_packetsReceivedThisPlayback,
|
||||
ringBuffer->diffLastWriteNextOutput(),
|
||||
PACKET_LENGTH_SAMPLES,
|
||||
|
@ -168,7 +168,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
|||
_packetsReceivedThisPlayback = 0;
|
||||
_wasStarved = 10; // Frames for which to render the indication that the system was starved.
|
||||
#ifdef SHOW_AUDIO_DEBUG
|
||||
printLog("Starved, remaining samples = %d\n",
|
||||
qDebug("Starved, remaining samples = %d\n",
|
||||
ringBuffer->diffLastWriteNextOutput());
|
||||
#endif
|
||||
|
||||
|
@ -179,7 +179,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
|||
if (!ringBuffer->isStarted()) {
|
||||
ringBuffer->setStarted(true);
|
||||
#ifdef SHOW_AUDIO_DEBUG
|
||||
printLog("starting playback %0.1f msecs delayed, jitter = %d, pkts recvd: %d \n",
|
||||
qDebug("starting playback %0.1f msecs delayed, jitter = %d, pkts recvd: %d \n",
|
||||
(usecTimestampNow() - usecTimestamp(&_firstPacketReceivedTime))/1000.0,
|
||||
_jitterBufferSamples,
|
||||
_packetsReceivedThisPlayback);
|
||||
|
@ -250,11 +250,11 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
|||
}
|
||||
}
|
||||
#ifndef TEST_AUDIO_LOOPBACK
|
||||
outputLeft[s] = leftSample;
|
||||
outputRight[s] = rightSample;
|
||||
outputLeft[s] += leftSample;
|
||||
outputRight[s] += rightSample;
|
||||
#else
|
||||
outputLeft[s] = inputLeft[s];
|
||||
outputRight[s] = inputLeft[s];
|
||||
outputLeft[s] += inputLeft[s];
|
||||
outputRight[s] += inputLeft[s];
|
||||
#endif
|
||||
}
|
||||
ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES);
|
||||
|
@ -299,8 +299,8 @@ int Audio::audioCallback (const void* inputBuffer,
|
|||
|
||||
static void outputPortAudioError(PaError error) {
|
||||
if (error != paNoError) {
|
||||
printLog("-- portaudio termination error --\n");
|
||||
printLog("PortAudio error (%d): %s\n", error, Pa_GetErrorText(error));
|
||||
qDebug("-- portaudio termination error --\n");
|
||||
qDebug("PortAudio error (%d): %s\n", error, Pa_GetErrorText(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,13 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) :
|
|||
_lastYawMeasuredMaximum(0),
|
||||
_flangeIntensity(0.0f),
|
||||
_flangeRate(0.0f),
|
||||
_flangeWeight(0.0f)
|
||||
_flangeWeight(0.0f),
|
||||
_collisionSoundMagnitude(0.0f),
|
||||
_collisionSoundFrequency(0.0f),
|
||||
_collisionSoundNoise(0.0f),
|
||||
_collisionSoundDuration(0.0f),
|
||||
_proceduralEffectSample(0),
|
||||
_heartbeatMagnitude(0.0f)
|
||||
{
|
||||
outputPortAudioError(Pa_Initialize());
|
||||
|
||||
|
@ -349,7 +355,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) :
|
|||
outputParameters.device = Pa_GetDefaultOutputDevice();
|
||||
|
||||
if (inputParameters.device == -1 || outputParameters.device == -1) {
|
||||
printLog("Audio: Missing device.\n");
|
||||
qDebug("Audio: Missing device.\n");
|
||||
outputPortAudioError(Pa_Terminate());
|
||||
return;
|
||||
}
|
||||
|
@ -384,12 +390,12 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) :
|
|||
outputPortAudioError(Pa_StartStream(_stream));
|
||||
|
||||
// Uncomment these lines to see the system-reported latency
|
||||
//printLog("Default low input, output latency (secs): %0.4f, %0.4f\n",
|
||||
//qDebug("Default low input, output latency (secs): %0.4f, %0.4f\n",
|
||||
// Pa_GetDeviceInfo(Pa_GetDefaultInputDevice())->defaultLowInputLatency,
|
||||
// Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice())->defaultLowOutputLatency);
|
||||
|
||||
const PaStreamInfo* streamInfo = Pa_GetStreamInfo(_stream);
|
||||
printLog("Started audio with reported latency msecs In/Out: %.0f, %.0f\n", streamInfo->inputLatency * 1000.f,
|
||||
qDebug("Started audio with reported latency msecs In/Out: %.0f, %.0f\n", streamInfo->inputLatency * 1000.f,
|
||||
streamInfo->outputLatency * 1000.f);
|
||||
|
||||
gettimeofday(&_lastReceiveTime, NULL);
|
||||
|
@ -588,7 +594,10 @@ void Audio::lowPassFilter(int16_t* inputBuffer) {
|
|||
}
|
||||
|
||||
// Take a pointer to the acquired microphone input samples and add procedural sounds
|
||||
void Audio::addProceduralSounds(int16_t* inputBuffer, int numSamples) {
|
||||
void Audio::addProceduralSounds(int16_t* inputBuffer,
|
||||
int16_t* outputLeft,
|
||||
int16_t* outputRight,
|
||||
int numSamples) {
|
||||
const float MAX_AUDIBLE_VELOCITY = 6.0;
|
||||
const float MIN_AUDIBLE_VELOCITY = 0.1;
|
||||
const int VOLUME_BASELINE = 400;
|
||||
|
@ -597,14 +606,48 @@ void Audio::addProceduralSounds(int16_t* inputBuffer, int numSamples) {
|
|||
float speed = glm::length(_lastVelocity);
|
||||
float volume = VOLUME_BASELINE * (1.f - speed / MAX_AUDIBLE_VELOCITY);
|
||||
|
||||
int sample;
|
||||
|
||||
//
|
||||
// Travelling noise
|
||||
//
|
||||
// Add a noise-modulated sinewave with volume that tapers off with speed increasing
|
||||
if ((speed > MIN_AUDIBLE_VELOCITY) && (speed < MAX_AUDIBLE_VELOCITY)) {
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
inputBuffer[i] += (int16_t)((sinf((float) i / SOUND_PITCH * speed) * randFloat()) * volume * speed);
|
||||
inputBuffer[i] += (int16_t)(sinf((float) (_proceduralEffectSample + i) / SOUND_PITCH ) * volume * (1.f + randFloat() * 0.25f) * speed);
|
||||
}
|
||||
}
|
||||
const float COLLISION_SOUND_CUTOFF_LEVEL = 0.01f;
|
||||
const float COLLISION_SOUND_MAX_VOLUME = 1000.f;
|
||||
const float UP_MAJOR_FIFTH = powf(1.5f, 4.0f);
|
||||
const float DOWN_TWO_OCTAVES = 4.f;
|
||||
const float DOWN_FOUR_OCTAVES = 16.f;
|
||||
float t;
|
||||
if (_collisionSoundMagnitude > COLLISION_SOUND_CUTOFF_LEVEL) {
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
t = (float) _proceduralEffectSample + (float) i;
|
||||
sample = sinf(t * _collisionSoundFrequency) +
|
||||
sinf(t * _collisionSoundFrequency / DOWN_TWO_OCTAVES) +
|
||||
sinf(t * _collisionSoundFrequency / DOWN_FOUR_OCTAVES * UP_MAJOR_FIFTH);
|
||||
sample *= _collisionSoundMagnitude * COLLISION_SOUND_MAX_VOLUME;
|
||||
inputBuffer[i] += sample;
|
||||
outputLeft[i] += sample;
|
||||
outputRight[i] += sample;
|
||||
_collisionSoundMagnitude *= _collisionSoundDuration;
|
||||
}
|
||||
}
|
||||
_proceduralEffectSample += numSamples;
|
||||
}
|
||||
|
||||
//
|
||||
// Starts a collision sound. magnitude is 0-1, with 1 the loudest possible sound.
|
||||
//
|
||||
void Audio::startCollisionSound(float magnitude, float frequency, float noise, float duration) {
|
||||
_collisionSoundMagnitude = magnitude;
|
||||
_collisionSoundFrequency = frequency;
|
||||
_collisionSoundNoise = noise;
|
||||
_collisionSoundDuration = duration;
|
||||
}
|
||||
// -----------------------------------------------------------
|
||||
// Accoustic ping (audio system round trip time determination)
|
||||
// -----------------------------------------------------------
|
||||
|
@ -650,7 +693,7 @@ inline void Audio::eventuallySendRecvPing(int16_t* inputLeft, int16_t* outputLef
|
|||
// As of the next frame, we'll be recoding PING_FRAMES_TO_RECORD from
|
||||
// the mic (pointless to start now as we can't record unsent audio).
|
||||
_isSendingEchoPing = false;
|
||||
printLog("Send audio ping\n");
|
||||
qDebug("Send audio ping\n");
|
||||
|
||||
} else if (_pingFramesToRecord > 0) {
|
||||
|
||||
|
@ -664,7 +707,7 @@ inline void Audio::eventuallySendRecvPing(int16_t* inputLeft, int16_t* outputLef
|
|||
|
||||
if (_pingFramesToRecord == 0) {
|
||||
_pingAnalysisPending = true;
|
||||
printLog("Received ping echo\n");
|
||||
qDebug("Received ping echo\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -688,25 +731,25 @@ inline void Audio::analyzePing() {
|
|||
// Determine extrema
|
||||
int botAt = findExtremum(_echoSamplesLeft, PING_SAMPLES_TO_ANALYZE, -1);
|
||||
if (botAt == -1) {
|
||||
printLog("Audio Ping: Minimum not found.\n");
|
||||
qDebug("Audio Ping: Minimum not found.\n");
|
||||
return;
|
||||
}
|
||||
int topAt = findExtremum(_echoSamplesLeft, PING_SAMPLES_TO_ANALYZE, 1);
|
||||
if (topAt == -1) {
|
||||
printLog("Audio Ping: Maximum not found.\n");
|
||||
qDebug("Audio Ping: Maximum not found.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine peak amplitude - warn if low
|
||||
int ampli = (_echoSamplesLeft[topAt] - _echoSamplesLeft[botAt]) / 2;
|
||||
if (ampli < PING_MIN_AMPLI) {
|
||||
printLog("Audio Ping unreliable - low amplitude %d.\n", ampli);
|
||||
qDebug("Audio Ping unreliable - low amplitude %d.\n", ampli);
|
||||
}
|
||||
|
||||
// Determine period - warn if doesn't look like our signal
|
||||
int halfPeriod = abs(topAt - botAt);
|
||||
if (abs(halfPeriod-PING_HALF_PERIOD) > PING_MAX_PERIOD_DIFFERENCE) {
|
||||
printLog("Audio Ping unreliable - peak distance %d vs. %d\n", halfPeriod, PING_HALF_PERIOD);
|
||||
qDebug("Audio Ping unreliable - peak distance %d vs. %d\n", halfPeriod, PING_HALF_PERIOD);
|
||||
}
|
||||
|
||||
// Ping is sent:
|
||||
|
@ -747,7 +790,7 @@ inline void Audio::analyzePing() {
|
|||
|
||||
int delay = (botAt + topAt) / 2 + PING_PERIOD;
|
||||
|
||||
printLog("\n| Audio Ping results:\n+----- ---- --- - - - - -\n\n"
|
||||
qDebug("\n| Audio Ping results:\n+----- ---- --- - - - - -\n\n"
|
||||
"Delay = %d samples (%d ms)\nPeak amplitude = %d\n\n",
|
||||
delay, (delay * 1000) / int(SAMPLE_RATE), ampli);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <StdDev.h>
|
||||
|
||||
#include "Oscilloscope.h"
|
||||
#include "avatar/Avatar.h"
|
||||
|
||||
static const int NUM_AUDIO_CHANNELS = 2;
|
||||
|
||||
|
@ -43,7 +42,11 @@ public:
|
|||
int getJitterBufferSamples() { return _jitterBufferSamples; };
|
||||
|
||||
void lowPassFilter(int16_t* inputBuffer);
|
||||
|
||||
|
||||
void startCollisionSound(float magnitude, float frequency, float noise, float duration);
|
||||
float getCollisionSoundMagnitude() { return _collisionSoundMagnitude; };
|
||||
|
||||
|
||||
void ping();
|
||||
|
||||
// Call periodically to eventually perform round trip time analysis,
|
||||
|
@ -81,7 +84,13 @@ private:
|
|||
float _flangeIntensity;
|
||||
float _flangeRate;
|
||||
float _flangeWeight;
|
||||
|
||||
float _collisionSoundMagnitude;
|
||||
float _collisionSoundFrequency;
|
||||
float _collisionSoundNoise;
|
||||
float _collisionSoundDuration;
|
||||
int _proceduralEffectSample;
|
||||
float _heartbeatMagnitude;
|
||||
|
||||
// Audio callback in class context.
|
||||
inline void performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* outputRight);
|
||||
|
||||
|
@ -93,7 +102,7 @@ private:
|
|||
inline void analyzePing();
|
||||
|
||||
// Add sounds that we want the user to not hear themselves, by adding on top of mic input signal
|
||||
void addProceduralSounds(int16_t* inputBuffer, int numSamples);
|
||||
void addProceduralSounds(int16_t* inputBuffer, int16_t* outputLeft, int16_t* outputRight, int numSamples);
|
||||
|
||||
|
||||
// Audio callback called by portaudio. Calls 'performIO'.
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "BandwidthMeter.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace { // .cpp-local
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include "Log.h"
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
|
|
@ -47,6 +47,11 @@ void Environment::init() {
|
|||
_data[getZeroAddress()][0];
|
||||
}
|
||||
|
||||
void Environment::resetToDefault() {
|
||||
_data.clear();
|
||||
_data[getZeroAddress()][0];
|
||||
}
|
||||
|
||||
void Environment::renderAtmospheres(Camera& camera) {
|
||||
// get the lock for the duration of the call
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
|
|
@ -24,6 +24,7 @@ class Environment {
|
|||
public:
|
||||
|
||||
void init();
|
||||
void resetToDefault();
|
||||
void renderAtmospheres(Camera& camera);
|
||||
|
||||
glm::vec3 getGravity (const glm::vec3& position);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
FILE* const LogDisplay::DEFAULT_STREAM = stdout;
|
||||
FILE* const LogDisplay::DEFAULT_STREAM = 0l;
|
||||
|
||||
//
|
||||
// Singleton constructor
|
||||
|
@ -26,9 +26,7 @@ LogDisplay LogDisplay::instance;
|
|||
// State management
|
||||
//
|
||||
|
||||
LogDisplay::LogDisplay() :
|
||||
|
||||
|
||||
LogDisplay::LogDisplay() :
|
||||
_textRenderer(SANS_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT),
|
||||
_stream(DEFAULT_STREAM),
|
||||
_chars(0l),
|
||||
|
@ -53,8 +51,6 @@ LogDisplay::LogDisplay() :
|
|||
memset(_lines, 0, LINE_BUFFER_SIZE * sizeof(char*));
|
||||
|
||||
setCharacterSize(DEFAULT_CHAR_WIDTH, DEFAULT_CHAR_HEIGHT);
|
||||
|
||||
printLog = & printLogHandler;
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,32 +88,7 @@ void LogDisplay::setCharacterSize(unsigned width, unsigned height) {
|
|||
// Logging
|
||||
//
|
||||
|
||||
int LogDisplay::printLogHandler(char const* fmt, ...) {
|
||||
|
||||
va_list args;
|
||||
int n;
|
||||
char buf[MAX_MESSAGE_LENGTH];
|
||||
va_start(args,fmt);
|
||||
|
||||
// print to buffer
|
||||
n = vsnprintf(buf, MAX_MESSAGE_LENGTH, fmt, args);
|
||||
if (n > 0) {
|
||||
|
||||
// all fine? log the message
|
||||
instance.addMessage(buf);
|
||||
|
||||
} else {
|
||||
|
||||
// error? -> mutter on stream or stderr
|
||||
fprintf(instance._stream != 0l ? instance._stream : stderr,
|
||||
"Log: Failed to log message with format string = \"%s\".\n", fmt);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
inline void LogDisplay::addMessage(char const* ptr) {
|
||||
void LogDisplay::addMessage(const char* ptr) {
|
||||
|
||||
pthread_mutex_lock(& _mutex);
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "Log.h"
|
||||
#include "ui/TextRenderer.h"
|
||||
|
||||
class LogDisplay {
|
||||
|
@ -21,6 +20,9 @@ public:
|
|||
static LogDisplay instance;
|
||||
|
||||
void render(unsigned screenWidth, unsigned screenHeight);
|
||||
|
||||
// log formatted message
|
||||
void addMessage(const char* message);
|
||||
|
||||
// settings
|
||||
|
||||
|
@ -50,12 +52,6 @@ private:
|
|||
LogDisplay(LogDisplay const&); // = delete;
|
||||
LogDisplay& operator=(LogDisplay const&); // = delete;
|
||||
|
||||
// format and log message - entrypoint used to replace global 'printLog'
|
||||
static int printLogHandler(char const* fmt, ...);
|
||||
|
||||
// log formatted message (called by printLogHandler)
|
||||
inline void addMessage(char const*);
|
||||
|
||||
TextRenderer _textRenderer;
|
||||
FILE* _stream; // FILE as secondary destination for log messages
|
||||
char* _chars; // character buffer base address
|
||||
|
|
|
@ -8,116 +8,217 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include "InterfaceConfig.h"
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "ParticleSystem.h"
|
||||
#include "Application.h"
|
||||
|
||||
const float DEFAULT_PARTICLE_RADIUS = 0.01f;
|
||||
const float DEFAULT_PARTICLE_BOUNCE = 1.0f;
|
||||
const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f;
|
||||
|
||||
ParticleSystem::ParticleSystem() {
|
||||
|
||||
_numberOfParticles = 1500;
|
||||
assert(_numberOfParticles <= MAX_PARTICLES);
|
||||
|
||||
_bounce = 0.9f;
|
||||
_timer = 0.0f;
|
||||
_airFriction = 6.0f;
|
||||
_jitter = 0.1f;
|
||||
_homeAttraction = 0.0f;
|
||||
_tornadoForce = 0.0f;
|
||||
_neighborAttraction = 0.02f;
|
||||
_neighborRepulsion = 0.9f;
|
||||
_tornadoAxis = glm::normalize(glm::vec3(0.1f, 1.0f, 0.1f));
|
||||
_home = glm::vec3(5.0f, 1.0f, 5.0f);
|
||||
|
||||
_TEST_bigSphereRadius = 0.5f;
|
||||
_TEST_bigSpherePosition = glm::vec3( 5.0f, _TEST_bigSphereRadius, 5.0f);
|
||||
_numEmitters = 0;
|
||||
_numParticles = 0;
|
||||
_upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
|
||||
|
||||
for (unsigned int emitterIndex = 0; emitterIndex < MAX_EMITTERS; emitterIndex++) {
|
||||
_emitter[emitterIndex].position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
_emitter[emitterIndex].rotation = glm::quat();
|
||||
_emitter[emitterIndex].visible = false;
|
||||
_emitter[emitterIndex].baseParticle.alive = false;
|
||||
_emitter[emitterIndex].baseParticle.age = 0.0f;
|
||||
_emitter[emitterIndex].baseParticle.lifespan = 0.0f;
|
||||
_emitter[emitterIndex].baseParticle.radius = 0.0f;
|
||||
_emitter[emitterIndex].baseParticle.emitterIndex = 0;
|
||||
_emitter[emitterIndex].baseParticle.position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
_emitter[emitterIndex].baseParticle.velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
for (int lifeStage = 0; lifeStage<NUM_PARTICLE_LIFE_STAGES; lifeStage++) {
|
||||
|
||||
for (unsigned int p = 0; p < _numberOfParticles; p++) {
|
||||
_particle[p].position = _home;
|
||||
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float radian = ((float)p / (float)_numberOfParticles) * PI_TIMES_TWO;
|
||||
float wave = sinf(radian);
|
||||
|
||||
float red = 0.5f + 0.5f * wave;
|
||||
float green = 0.3f + 0.3f * wave;
|
||||
float blue = 0.2f - 0.2f * wave;
|
||||
|
||||
_particle[p].color = glm::vec3(red, green, blue);
|
||||
_particle[p].age = 0.0f;
|
||||
_particle[p].radius = 0.01f;
|
||||
}
|
||||
ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage];
|
||||
|
||||
a->radius = DEFAULT_PARTICLE_RADIUS;
|
||||
a->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
a->bounce = DEFAULT_PARTICLE_BOUNCE;
|
||||
a->airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
|
||||
a->gravity = 0.0f;
|
||||
a->jitter = 0.0f;
|
||||
a->emitterAttraction = 0.0f;
|
||||
a->tornadoForce = 0.0f;
|
||||
a->neighborAttraction = 0.0f;
|
||||
a->neighborRepulsion = 0.0f;
|
||||
a->collisionSphereRadius = 0.0f;
|
||||
a->collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
a->usingCollisionSphere = false;
|
||||
}
|
||||
};
|
||||
|
||||
for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
|
||||
_particle[p].alive = false;
|
||||
_particle[p].age = 0.0f;
|
||||
_particle[p].lifespan = 0.0f;
|
||||
_particle[p].radius = 0.0f;
|
||||
_particle[p].emitterIndex = 0;
|
||||
_particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int ParticleSystem::addEmitter() {
|
||||
|
||||
_numEmitters ++;
|
||||
|
||||
if (_numEmitters > MAX_EMITTERS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _numEmitters - 1;
|
||||
}
|
||||
|
||||
|
||||
void ParticleSystem::simulate(float deltaTime) {
|
||||
|
||||
runSpecialEffectsTest(deltaTime);
|
||||
|
||||
for (unsigned int p = 0; p < _numberOfParticles; p++) {
|
||||
updateParticle(p, deltaTime);
|
||||
// update particles
|
||||
for (unsigned int p = 0; p < _numParticles; p++) {
|
||||
if (_particle[p].alive) {
|
||||
if (_particle[p].age > _particle[p].lifespan) {
|
||||
killParticle(p);
|
||||
} else {
|
||||
updateParticle(p, deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::emitParticlesNow(int e, int num, glm::vec3 velocity, float lifespan) {
|
||||
|
||||
|
||||
void ParticleSystem::runSpecialEffectsTest(float deltaTime) {
|
||||
|
||||
_timer += deltaTime;
|
||||
|
||||
_gravity = 0.01f + 0.01f * sinf( _timer * 0.52f );
|
||||
_airFriction = 3.0f + 2.0f * sinf( _timer * 0.32f );
|
||||
_jitter = 0.05f + 0.05f * sinf( _timer * 0.42f );
|
||||
_homeAttraction = 0.01f + 0.01f * cosf( _timer * 0.6f );
|
||||
_tornadoForce = 0.0f + 0.03f * sinf( _timer * 0.7f );
|
||||
_neighborAttraction = 0.1f + 0.1f * cosf( _timer * 0.8f );
|
||||
_neighborRepulsion = 0.4f + 0.3f * sinf( _timer * 0.4f );
|
||||
|
||||
_tornadoAxis = glm::vec3
|
||||
(
|
||||
0.0f + 0.5f * sinf( _timer * 0.55f ),
|
||||
1.0f,
|
||||
0.0f + 0.5f * cosf( _timer * 0.75f )
|
||||
);
|
||||
for (unsigned int p = 0; p < num; p++) {
|
||||
createParticle(e, velocity, lifespan);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::createParticle(int e, glm::vec3 velocity, float lifespan) {
|
||||
|
||||
for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
|
||||
if (!_particle[p].alive) {
|
||||
|
||||
_particle[p].emitterIndex = e;
|
||||
_particle[p].lifespan = lifespan;
|
||||
_particle[p].alive = true;
|
||||
_particle[p].age = 0.0f;
|
||||
_particle[p].velocity = velocity;
|
||||
_particle[p].position = _emitter[e].position;
|
||||
_particle[p].radius = _emitter[e].particleAttributes[0].radius;
|
||||
_particle[p].color = _emitter[e].particleAttributes[0].color;
|
||||
|
||||
_numParticles ++;
|
||||
|
||||
assert(_numParticles <= MAX_PARTICLES);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::killParticle(int p) {
|
||||
|
||||
assert( p >= 0);
|
||||
assert( p < MAX_PARTICLES);
|
||||
assert( _numParticles > 0);
|
||||
|
||||
_particle[p].alive = false;
|
||||
_numParticles --;
|
||||
}
|
||||
|
||||
|
||||
void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) {
|
||||
|
||||
for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++ ) {
|
||||
setParticleAttributes(emitterIndex, lifeStage, attributes);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, ParticleAttributes attributes) {
|
||||
|
||||
ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage];
|
||||
|
||||
a->radius = attributes.radius;
|
||||
a->color = attributes.color;
|
||||
a->bounce = attributes.bounce;
|
||||
a->gravity = attributes.gravity;
|
||||
a->airFriction = attributes.airFriction;
|
||||
a->jitter = attributes.jitter;
|
||||
a->emitterAttraction = attributes.emitterAttraction;
|
||||
a->tornadoForce = attributes.tornadoForce;
|
||||
a->neighborAttraction = attributes.neighborAttraction;
|
||||
a->neighborRepulsion = attributes.neighborRepulsion;
|
||||
a->usingCollisionSphere = attributes.usingCollisionSphere;
|
||||
a->collisionSpherePosition = attributes.collisionSpherePosition;
|
||||
a->collisionSphereRadius = attributes.collisionSphereRadius;
|
||||
}
|
||||
|
||||
|
||||
void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||
|
||||
_particle[p].age += deltaTime;
|
||||
assert(_particle[p].age <= _particle[p].lifespan);
|
||||
|
||||
float ageFraction = _particle[p].age / _particle[p].lifespan;
|
||||
|
||||
int lifeStage = (int)( ageFraction * (NUM_PARTICLE_LIFE_STAGES-1) );
|
||||
|
||||
float lifeStageFraction = ageFraction * ( NUM_PARTICLE_LIFE_STAGES - 1 ) - lifeStage;
|
||||
|
||||
_particle[p].radius
|
||||
= _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage ].radius * (1.0f - lifeStageFraction)
|
||||
+ _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage+1].radius * lifeStageFraction;
|
||||
|
||||
_particle[p].color
|
||||
= _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage ].color * (1.0f - lifeStageFraction)
|
||||
+ _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage+1].color * lifeStageFraction;
|
||||
|
||||
Emitter myEmitter = _emitter[_particle[p].emitterIndex];
|
||||
|
||||
// apply random jitter
|
||||
float j = myEmitter.particleAttributes[lifeStage].jitter;
|
||||
_particle[p].velocity +=
|
||||
glm::vec3
|
||||
(
|
||||
-_jitter * ONE_HALF + _jitter * randFloat(),
|
||||
-_jitter * ONE_HALF + _jitter * randFloat(),
|
||||
-_jitter * ONE_HALF + _jitter * randFloat()
|
||||
-j * ONE_HALF + j * randFloat(),
|
||||
-j * ONE_HALF + j * randFloat(),
|
||||
-j * ONE_HALF + j * randFloat()
|
||||
) * deltaTime;
|
||||
|
||||
|
||||
// apply attraction to home position
|
||||
glm::vec3 vectorToHome = _home - _particle[p].position;
|
||||
_particle[p].velocity += vectorToHome * _homeAttraction * deltaTime;
|
||||
glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;
|
||||
_particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime;
|
||||
|
||||
// apply neighbor attraction
|
||||
int neighbor = p + 1;
|
||||
if (neighbor == _numberOfParticles ) {
|
||||
if (neighbor == _numParticles ) {
|
||||
neighbor = 0;
|
||||
}
|
||||
glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
|
||||
|
||||
_particle[p].velocity -= vectorToNeighbor * _neighborAttraction * deltaTime;
|
||||
if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
|
||||
glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
|
||||
|
||||
_particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
|
||||
|
||||
float distanceToNeighbor = glm::length(vectorToNeighbor);
|
||||
if (distanceToNeighbor > 0.0f) {
|
||||
_particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * _neighborRepulsion * deltaTime;
|
||||
float distanceToNeighbor = glm::length(vectorToNeighbor);
|
||||
if (distanceToNeighbor > 0.0f) {
|
||||
_particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
// apply tornado force
|
||||
glm::vec3 tornadoDirection = glm::cross(vectorToHome, _tornadoAxis);
|
||||
_particle[p].velocity += tornadoDirection * _tornadoForce * deltaTime;
|
||||
|
||||
|
||||
glm::vec3 emitterUp = myEmitter.rotation * IDENTITY_UP;
|
||||
|
||||
glm::vec3 tornadoDirection = glm::cross(vectorToHome, emitterUp);
|
||||
_particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
|
||||
|
||||
// apply air friction
|
||||
float drag = 1.0 - _airFriction * deltaTime;
|
||||
float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
|
||||
if (drag < 0.0f) {
|
||||
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
} else {
|
||||
|
@ -125,7 +226,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
|||
}
|
||||
|
||||
// apply gravity
|
||||
_particle[p].velocity.y -= _gravity * deltaTime;
|
||||
_particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
|
||||
|
||||
// update position by velocity
|
||||
_particle[p].position += _particle[p].velocity;
|
||||
|
@ -135,49 +236,149 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
|||
_particle[p].position.y = _particle[p].radius;
|
||||
|
||||
if (_particle[p].velocity.y < 0.0f) {
|
||||
_particle[p].velocity.y *= -_bounce;
|
||||
_particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;
|
||||
}
|
||||
}
|
||||
|
||||
// collision with sphere
|
||||
glm::vec3 vectorToSphereCenter = _TEST_bigSpherePosition - _particle[p].position;
|
||||
float distanceToSphereCenter = glm::length(vectorToSphereCenter);
|
||||
float combinedRadius = _TEST_bigSphereRadius + _particle[p].radius;
|
||||
if (distanceToSphereCenter < combinedRadius) {
|
||||
|
||||
if (distanceToSphereCenter > 0.0f){
|
||||
glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
|
||||
_particle[p].position = _TEST_bigSpherePosition - directionToSphereCenter * combinedRadius;
|
||||
if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
|
||||
glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
|
||||
float distanceToSphereCenter = glm::length(vectorToSphereCenter);
|
||||
float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
|
||||
if (distanceToSphereCenter < combinedRadius) {
|
||||
|
||||
if (distanceToSphereCenter > 0.0f){
|
||||
glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
|
||||
_particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do this at the end...
|
||||
_particle[p].age += deltaTime;
|
||||
}
|
||||
|
||||
void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing ) {
|
||||
|
||||
_emitter[emitterIndex].baseParticle.alive = true;
|
||||
_emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
|
||||
}
|
||||
|
||||
void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing, float radius, glm::vec4 color ) {
|
||||
|
||||
_emitter[emitterIndex].baseParticle.alive = true;
|
||||
_emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
|
||||
_emitter[emitterIndex].baseParticle.radius = radius;
|
||||
_emitter[emitterIndex].baseParticle.color = color;
|
||||
}
|
||||
|
||||
|
||||
void ParticleSystem::render() {
|
||||
|
||||
for (unsigned int p = 0; p < _numberOfParticles; p++) {
|
||||
glColor3f(_particle[p].color.x, _particle[p].color.y, _particle[p].color.z);
|
||||
// render the emitters
|
||||
for (int e = 0; e < _numEmitters; e++) {
|
||||
|
||||
if (_emitter[e].baseParticle.alive) {
|
||||
glColor4f(_emitter[e].baseParticle.color.r, _emitter[e].baseParticle.color.g, _emitter[e].baseParticle.color.b, _emitter[e].baseParticle.color.a );
|
||||
glPushMatrix();
|
||||
glTranslatef(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
|
||||
glutSolidSphere(_emitter[e].baseParticle.radius, 6, 6);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
if (_emitter[e].visible) {
|
||||
renderEmitter(e, 0.2f);
|
||||
}
|
||||
};
|
||||
|
||||
// render the particles
|
||||
for (unsigned int p = 0; p < _numParticles; p++) {
|
||||
if (_particle[p].alive) {
|
||||
renderParticle(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::renderParticle(int p) {
|
||||
|
||||
glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );
|
||||
|
||||
if (USE_BILLBOARD_RENDERING) {
|
||||
glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
|
||||
glm::vec3 viewVector = _particle[p].position - cameraPosition;
|
||||
float distance = glm::length(viewVector);
|
||||
|
||||
if (distance >= 0.0f) {
|
||||
viewVector /= distance;
|
||||
glm::vec3 up = glm::vec3(viewVector.y, viewVector.z, viewVector.x);
|
||||
glm::vec3 right = glm::vec3(viewVector.z, viewVector.x, viewVector.y);
|
||||
|
||||
glm::vec3 p0 = _particle[p].position - right * _particle[p].radius - up * _particle[p].radius;
|
||||
glm::vec3 p1 = _particle[p].position + right * _particle[p].radius - up * _particle[p].radius;
|
||||
glm::vec3 p2 = _particle[p].position + right * _particle[p].radius + up * _particle[p].radius;
|
||||
glm::vec3 p3 = _particle[p].position - right * _particle[p].radius + up * _particle[p].radius;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex3f(p0.x, p0.y, p0.z);
|
||||
glVertex3f(p1.x, p1.y, p1.z);
|
||||
glVertex3f(p2.x, p2.y, p2.z);
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex3f(p0.x, p0.y, p0.z);
|
||||
glVertex3f(p2.x, p2.y, p2.z);
|
||||
glVertex3f(p3.x, p3.y, p3.z);
|
||||
glEnd();
|
||||
}
|
||||
} else {
|
||||
glPushMatrix();
|
||||
glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
||||
glutSolidSphere(_particle[p].radius, 6, 6);
|
||||
glPopMatrix();
|
||||
|
||||
// render velocity lines
|
||||
glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);
|
||||
glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
||||
glVertex3f(end.x, end.y, end.z);
|
||||
|
||||
glEnd();
|
||||
|
||||
|
||||
if (SHOW_VELOCITY_TAILS) {
|
||||
glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);
|
||||
glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
||||
glVertex3f(end.x, end.y, end.z);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ParticleSystem::renderEmitter(int e, float size) {
|
||||
|
||||
glm::vec3 r = _emitter[e].rotation * IDENTITY_FRONT * size;
|
||||
glm::vec3 u = _emitter[e].rotation * IDENTITY_RIGHT * size;
|
||||
glm::vec3 f = _emitter[e].rotation * IDENTITY_UP * size;
|
||||
|
||||
glLineWidth(2.0f);
|
||||
|
||||
glColor3f(0.8f, 0.4, 0.4);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
|
||||
glVertex3f(_emitter[e].position.x + r.x, _emitter[e].position.y + r.y, _emitter[e].position.z + r.z);
|
||||
glEnd();
|
||||
|
||||
glColor3f(0.4f, 0.8, 0.4);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
|
||||
glVertex3f(_emitter[e].position.x + u.x, _emitter[e].position.y + u.y, _emitter[e].position.z + u.z);
|
||||
glEnd();
|
||||
|
||||
glColor3f(0.4f, 0.4, 0.8);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
|
||||
glVertex3f(_emitter[e].position.x + f.x, _emitter[e].position.y + f.y, _emitter[e].position.z + f.z);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,56 +4,86 @@
|
|||
//
|
||||
// Created by Jeffrey on July 10, 2013
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef hifi_ParticleSystem_h
|
||||
#define hifi_ParticleSystem_h
|
||||
|
||||
const int MAX_PARTICLES = 5000;
|
||||
const int MAX_EMITTERS = 10;
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
const int MAX_PARTICLES = 5000;
|
||||
const int MAX_EMITTERS = 20;
|
||||
const int NUM_PARTICLE_LIFE_STAGES = 4;
|
||||
const bool USE_BILLBOARD_RENDERING = false;
|
||||
const bool SHOW_VELOCITY_TAILS = false;
|
||||
|
||||
class ParticleSystem {
|
||||
public:
|
||||
|
||||
struct ParticleAttributes {
|
||||
float radius;
|
||||
glm::vec4 color;
|
||||
float bounce;
|
||||
float gravity;
|
||||
float airFriction;
|
||||
float jitter;
|
||||
float emitterAttraction;
|
||||
float tornadoForce;
|
||||
float neighborAttraction;
|
||||
float neighborRepulsion;
|
||||
bool usingCollisionSphere;
|
||||
glm::vec3 collisionSpherePosition;
|
||||
float collisionSphereRadius;
|
||||
};
|
||||
|
||||
ParticleSystem();
|
||||
|
||||
int addEmitter(); // add (create new) emitter and get its unique id
|
||||
void emitParticlesNow(int emitterIndex, int numParticles, glm::vec3 velocity, float lifespan);
|
||||
void simulate(float deltaTime);
|
||||
void render();
|
||||
|
||||
void setUpDirection(glm::vec3 upDirection) {_upDirection = upDirection;} // tell particle system which direction is up
|
||||
void setEmitterBaseParticle(int emitterIndex, bool showing );
|
||||
void setEmitterBaseParticle(int emitterIndex, bool showing, float radius, glm::vec4 color );
|
||||
void setParticleAttributes (int emitterIndex, ParticleAttributes attributes);
|
||||
void setParticleAttributes (int emitterIndex, int lifeStage, ParticleAttributes attributes);
|
||||
void setEmitterPosition (int emitterIndex, glm::vec3 position) { _emitter[emitterIndex].position = position; } // set position of emitter
|
||||
void setEmitterRotation (int emitterIndex, glm::quat rotation) { _emitter[emitterIndex].rotation = rotation; } // set rotation of emitter
|
||||
void setShowingEmitter (int emitterIndex, bool showing ) { _emitter[emitterIndex].visible = showing; } // set its visibiity
|
||||
|
||||
private:
|
||||
|
||||
struct Particle {
|
||||
glm::vec3 position;
|
||||
glm::vec3 velocity;
|
||||
glm::vec3 color;
|
||||
float age;
|
||||
float radius;
|
||||
};
|
||||
|
||||
struct Emitter {
|
||||
glm::vec3 position;
|
||||
glm::vec3 direction;
|
||||
};
|
||||
|
||||
float _bounce;
|
||||
float _gravity;
|
||||
float _timer;
|
||||
Emitter _emitter[MAX_EMITTERS];
|
||||
Particle _particle[MAX_PARTICLES];
|
||||
int _numberOfParticles;
|
||||
glm::vec3 _home;
|
||||
glm::vec3 _tornadoAxis;
|
||||
float _airFriction;
|
||||
float _jitter;
|
||||
float _homeAttraction;
|
||||
float _tornadoForce;
|
||||
float _neighborAttraction;
|
||||
float _neighborRepulsion;
|
||||
float _TEST_bigSphereRadius;
|
||||
glm::vec3 _TEST_bigSpherePosition;
|
||||
struct Particle {
|
||||
bool alive; // is the particle active?
|
||||
glm::vec3 position; // position
|
||||
glm::vec3 velocity; // velocity
|
||||
glm::vec4 color; // color (rgba)
|
||||
float age; // age in seconds
|
||||
float radius; // radius
|
||||
float lifespan; // how long this particle stays alive (in seconds)
|
||||
int emitterIndex; // which emitter created this particle?
|
||||
};
|
||||
|
||||
struct Emitter {
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
bool visible;
|
||||
Particle baseParticle; // a non-physical particle at the emitter position
|
||||
ParticleAttributes particleAttributes[NUM_PARTICLE_LIFE_STAGES]; // the attributes of particles emitted from this emitter
|
||||
};
|
||||
|
||||
glm::vec3 _upDirection;
|
||||
Emitter _emitter[MAX_EMITTERS];
|
||||
Particle _particle[MAX_PARTICLES];
|
||||
int _numParticles;
|
||||
int _numEmitters;
|
||||
|
||||
// private methods
|
||||
void updateParticle(int index, float deltaTime);
|
||||
void runSpecialEffectsTest(float deltaTime);
|
||||
void createParticle(int e, glm::vec3 velocity, float lifespan);
|
||||
void killParticle(int p);
|
||||
void renderEmitter(int emitterIndex, float size);
|
||||
void renderParticle(int p);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,28 @@ const int LONG_TERM_RATE_SAMPLES = 1000;
|
|||
|
||||
const bool USING_INVENSENSE_MPU9150 = 1;
|
||||
|
||||
SerialInterface::SerialInterface() :
|
||||
_active(false),
|
||||
_gravity(0, 0, 0),
|
||||
_averageRotationRates(0, 0, 0),
|
||||
_averageAcceleration(0, 0, 0),
|
||||
_estimatedRotation(0, 0, 0),
|
||||
_estimatedPosition(0, 0, 0),
|
||||
_estimatedVelocity(0, 0, 0),
|
||||
_lastAcceleration(0, 0, 0),
|
||||
_lastRotationRates(0, 0, 0),
|
||||
_compassMinima(-211, -132, -186),
|
||||
_compassMaxima(89, 95, 98),
|
||||
_angularVelocityToLinearAccel(0.003f, -0.001f, -0.006f,
|
||||
-0.005f, -0.001f, -0.006f,
|
||||
0.010f, 0.004f, 0.007f),
|
||||
_angularAccelToLinearAccel(0.0f, 0.0f, 0.002f,
|
||||
0.0f, 0.0f, 0.001f,
|
||||
-0.002f, -0.002f, 0.0f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SerialInterface::pair() {
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -75,10 +97,10 @@ void SerialInterface::initializePort(char* portname) {
|
|||
#ifndef _WIN32
|
||||
_serialDescriptor = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
printLog("Opening SerialUSB %s: ", portname);
|
||||
qDebug("Opening SerialUSB %s: ", portname);
|
||||
|
||||
if (_serialDescriptor == -1) {
|
||||
printLog("Failed.\n");
|
||||
qDebug("Failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -112,7 +134,7 @@ void SerialInterface::initializePort(char* portname) {
|
|||
mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL | INV_XYZ_COMPASS);
|
||||
}
|
||||
|
||||
printLog("Connected.\n");
|
||||
qDebug("Connected.\n");
|
||||
resetSerial();
|
||||
|
||||
_active = true;
|
||||
|
@ -351,7 +373,7 @@ void SerialInterface::readData(float deltaTime) {
|
|||
gettimeofday(&now, NULL);
|
||||
|
||||
if (diffclock(&lastGoodRead, &now) > NO_READ_MAXIMUM_MSECS) {
|
||||
printLog("No data - Shutting down SerialInterface.\n");
|
||||
qDebug("No data - Shutting down SerialInterface.\n");
|
||||
resetSerial();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
//
|
||||
// SerialInterface.h
|
||||
//
|
||||
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 2/15/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__SerialInterface__
|
||||
#define __interface__SerialInterface__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Log.h"
|
||||
|
||||
// These includes are for serial port reading/writing
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
|
@ -20,30 +17,16 @@
|
|||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Util.h"
|
||||
|
||||
extern const bool USING_INVENSENSE_MPU9150;
|
||||
|
||||
class SerialInterface {
|
||||
public:
|
||||
SerialInterface() : _active(false),
|
||||
_gravity(0, 0, 0),
|
||||
_averageRotationRates(0, 0, 0),
|
||||
_averageAcceleration(0, 0, 0),
|
||||
_estimatedRotation(0, 0, 0),
|
||||
_estimatedPosition(0, 0, 0),
|
||||
_estimatedVelocity(0, 0, 0),
|
||||
_lastAcceleration(0, 0, 0),
|
||||
_lastRotationRates(0, 0, 0),
|
||||
_compassMinima(-211, -132, -186),
|
||||
_compassMaxima(89, 95, 98),
|
||||
_angularVelocityToLinearAccel(
|
||||
0.003f, -0.001f, -0.006f,
|
||||
-0.005f, -0.001f, -0.006f,
|
||||
0.010f, 0.004f, 0.007f),
|
||||
_angularAccelToLinearAccel(
|
||||
0.0f, 0.0f, 0.002f,
|
||||
0.0f, 0.0f, 0.001f,
|
||||
-0.002f, -0.002f, 0.0f)
|
||||
{}
|
||||
SerialInterface();
|
||||
|
||||
void pair();
|
||||
void readData(float deltaTime);
|
||||
|
|
|
@ -13,11 +13,9 @@
|
|||
#include <PacketHeaders.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Log.h"
|
||||
#include "Transmitter.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
const float DELTA_TIME = 1.f / 60.f;
|
||||
const float DECAY_RATE = 0.15f;
|
||||
|
||||
|
@ -40,7 +38,7 @@ void Transmitter::checkForLostTransmitter() {
|
|||
int msecsSinceLast = diffclock(_lastReceivedPacket, &now);
|
||||
if (msecsSinceLast > TIME_TO_ASSUME_LOST_MSECS) {
|
||||
resetLevels();
|
||||
printLog("Transmitter signal lost.\n");
|
||||
qDebug("Transmitter signal lost.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,12 +93,12 @@ void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) {
|
|||
_estimatedRotation.y *= (1.f - DECAY_RATE * DELTA_TIME);
|
||||
|
||||
if (!_isConnected) {
|
||||
printLog("Transmitter Connected.\n");
|
||||
qDebug("Transmitter Connected.\n");
|
||||
_isConnected = true;
|
||||
_estimatedRotation *= 0.0;
|
||||
}
|
||||
} else {
|
||||
printLog("Transmitter packet read error, %d bytes.\n", numBytes);
|
||||
qDebug("Transmitter packet read error, %d bytes.\n", numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <time.h>
|
||||
|
@ -15,16 +14,16 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/noise.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Log.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "ui/TextRenderer.h"
|
||||
#include "world.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
#include "VoxelConstants.h"
|
||||
#include "world.h"
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -326,22 +325,38 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
void renderCollisionOverlay(int width, int height, float magnitude) {
|
||||
const float MIN_VISIBLE_COLLISION = 0.01f;
|
||||
if (magnitude > MIN_VISIBLE_COLLISION) {
|
||||
glColor4f(0, 0, 0, magnitude);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2d(width, 0);
|
||||
glVertex2d(width, height);
|
||||
glVertex2d(0, height);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void drawGroundPlaneGrid(float size) {
|
||||
glColor3f(0.4f, 0.5f, 0.3f);
|
||||
void renderGroundPlaneGrid(float size, float impact) {
|
||||
glLineWidth(2.0);
|
||||
|
||||
glm::vec4 impactColor(1, 0, 0, 1);
|
||||
glm::vec3 lineColor(0.4, 0.5, 0.3);
|
||||
glm::vec4 surfaceColor(0.5, 0.5, 0.5, 0.4);
|
||||
|
||||
glColor3fv(&lineColor.x);
|
||||
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);
|
||||
glVertex3f(x, 0, 0);
|
||||
glVertex3f(x, 0, size);
|
||||
glVertex3f(0, 0, x);
|
||||
glVertex3f(size, 0, x);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Draw a translucent quad just underneath the grid.
|
||||
glColor4f(0.5, 0.5, 0.5, 0.4);
|
||||
// Draw the floor, colored for recent impact
|
||||
glm::vec4 floorColor = impact * impactColor + (1.f - impact) * surfaceColor;
|
||||
glColor4fv(&floorColor.x);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(0, 0, 0);
|
||||
glVertex3f(size, 0, 0);
|
||||
|
@ -452,7 +467,7 @@ void renderOrientationDirections(glm::vec3 position, const glm::quat& orientatio
|
|||
|
||||
bool closeEnoughForGovernmentWork(float a, float b) {
|
||||
float distance = std::abs(a-b);
|
||||
//printLog("closeEnoughForGovernmentWork() a=%1.10f b=%1.10f distance=%1.10f\n",a,b,distance);
|
||||
//qDebug("closeEnoughForGovernmentWork() a=%1.10f b=%1.10f distance=%1.10f\n",a,b,distance);
|
||||
return (distance < 0.00001f);
|
||||
}
|
||||
|
||||
|
@ -470,7 +485,7 @@ void runTimingTests() {
|
|||
gettimeofday(&endTime, NULL);
|
||||
}
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("gettimeofday() usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
qDebug("gettimeofday() usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
// Random number generation
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
@ -479,7 +494,7 @@ void runTimingTests() {
|
|||
}
|
||||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("rand() stored in array usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
qDebug("rand() stored in array usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
// Random number generation using randFloat()
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
@ -488,7 +503,7 @@ void runTimingTests() {
|
|||
}
|
||||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("randFloat() stored in array usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
qDebug("randFloat() stored in array usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
// PowF function
|
||||
fTest = 1145323.2342f;
|
||||
|
@ -498,7 +513,7 @@ void runTimingTests() {
|
|||
}
|
||||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("powf(f, 0.5) usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
qDebug("powf(f, 0.5) usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
// Vector Math
|
||||
float distance;
|
||||
|
@ -511,7 +526,7 @@ void runTimingTests() {
|
|||
}
|
||||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("vector math usecs: %f [%f msecs total for %d tests]\n",
|
||||
qDebug("vector math usecs: %f [%f msecs total for %d tests]\n",
|
||||
1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests);
|
||||
|
||||
// Vec3 test
|
||||
|
@ -525,7 +540,7 @@ void runTimingTests() {
|
|||
}
|
||||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
printLog("vec3 assign and dot() usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
qDebug("vec3 assign and dot() usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -57,7 +57,10 @@ glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha);
|
|||
|
||||
double diffclock(timeval *clock1,timeval *clock2);
|
||||
|
||||
void drawGroundPlaneGrid(float size);
|
||||
void renderGroundPlaneGrid(float size, float impact);
|
||||
|
||||
void renderCollisionOverlay(int width, int height, float magnitude);
|
||||
|
||||
|
||||
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness);
|
||||
|
||||
|
|
|
@ -5,28 +5,31 @@
|
|||
// Created by Philip on 12/31/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _timeval_
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <iostream> // to load voxels from file
|
||||
#include <fstream> // to load voxels from file
|
||||
#include <pthread.h>
|
||||
|
||||
#include <glm/gtc/random.hpp>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include <OctalCode.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PerfStat.h>
|
||||
#include <OctalCode.h>
|
||||
#include <pthread.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Log.h"
|
||||
#include "VoxelConstants.h"
|
||||
#include "CoverageMap.h"
|
||||
#include "CoverageMapV2.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
|
||||
#include "VoxelConstants.h"
|
||||
#include "VoxelSystem.h"
|
||||
|
||||
float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1,
|
||||
|
@ -141,16 +144,16 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
int commandLength = strlen(command); // commands are null terminated strings
|
||||
int totalLength = 1+commandLength+1;
|
||||
|
||||
printLog("got Z message len(%d)= %s\n", numBytes, command);
|
||||
qDebug("got Z message len(%d)= %s\n", numBytes, command);
|
||||
|
||||
while (totalLength <= numBytes) {
|
||||
if (0==strcmp(command,(char*)"erase all")) {
|
||||
printLog("got Z message == erase all\n");
|
||||
qDebug("got Z message == erase all\n");
|
||||
_tree->eraseAllVoxels();
|
||||
_voxelsInReadArrays = _voxelsInWriteArrays = 0; // better way to do this??
|
||||
}
|
||||
if (0==strcmp(command,(char*)"add scene")) {
|
||||
printLog("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n");
|
||||
qDebug("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n");
|
||||
}
|
||||
totalLength += commandLength+1;
|
||||
}
|
||||
|
@ -705,7 +708,7 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {
|
|||
void VoxelSystem::randomizeVoxelColors() {
|
||||
_nodeCount = 0;
|
||||
_tree->recurseTreeWithOperation(randomColorOperation);
|
||||
printLog("setting randomized true color for %d nodes\n", _nodeCount);
|
||||
qDebug("setting randomized true color for %d nodes\n", _nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
|
@ -719,7 +722,7 @@ bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData)
|
|||
void VoxelSystem::falseColorizeRandom() {
|
||||
_nodeCount = 0;
|
||||
_tree->recurseTreeWithOperation(falseColorizeRandomOperation);
|
||||
printLog("setting randomized false color for %d nodes\n", _nodeCount);
|
||||
qDebug("setting randomized false color for %d nodes\n", _nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
|
@ -733,7 +736,7 @@ void VoxelSystem::trueColorize() {
|
|||
PerformanceWarning warn(true, "trueColorize()",true);
|
||||
_nodeCount = 0;
|
||||
_tree->recurseTreeWithOperation(trueColorizeOperation);
|
||||
printLog("setting true color for %d nodes\n", _nodeCount);
|
||||
qDebug("setting true color for %d nodes\n", _nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
|
@ -753,7 +756,7 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData)
|
|||
void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) {
|
||||
_nodeCount = 0;
|
||||
_tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum);
|
||||
printLog("setting in view false color for %d nodes\n", _nodeCount);
|
||||
qDebug("setting in view false color for %d nodes\n", _nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
|
@ -803,10 +806,10 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
|
|||
_maxDistance = 0.0;
|
||||
_minDistance = FLT_MAX;
|
||||
_tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum);
|
||||
printLog("determining distance range for %d nodes\n", _nodeCount);
|
||||
qDebug("determining distance range for %d nodes\n", _nodeCount);
|
||||
_nodeCount = 0;
|
||||
_tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum);
|
||||
printLog("setting in distance false color for %d nodes\n", _nodeCount);
|
||||
qDebug("setting in distance false color for %d nodes\n", _nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
|
@ -918,7 +921,7 @@ void VoxelSystem::removeOutOfView() {
|
|||
}
|
||||
bool showRemoveDebugDetails = false;
|
||||
if (showRemoveDebugDetails) {
|
||||
printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n",
|
||||
qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n",
|
||||
args.nodesScanned, args.nodesRemoved, args.nodesInside,
|
||||
args.nodesIntersect, args.nodesOutside, _removedVoxels.count()
|
||||
);
|
||||
|
@ -984,7 +987,7 @@ bool VoxelSystem::falseColorizeRandomEveryOtherOperation(VoxelNode* node, void*
|
|||
void VoxelSystem::falseColorizeRandomEveryOther() {
|
||||
falseColorizeRandomEveryOtherArgs args;
|
||||
_tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args);
|
||||
printLog("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n",
|
||||
qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n",
|
||||
args.totalNodes, args.colorableNodes, args.coloredNodes);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
@ -1045,7 +1048,7 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* ex
|
|||
unsigned long nodeIndex = node->getBufferIndex();
|
||||
if (args->hasIndexFound[nodeIndex]) {
|
||||
args->duplicateVBOIndex++;
|
||||
printLog("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,
|
||||
qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,
|
||||
debug::valueOf(node->isDirty()), debug::valueOf(node->getShouldRender()));
|
||||
} else {
|
||||
args->hasIndexFound[nodeIndex] = true;
|
||||
|
@ -1080,13 +1083,13 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
|||
args.expectedMax = _voxelsInWriteArrays;
|
||||
_tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);
|
||||
|
||||
printLog("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n",
|
||||
qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n",
|
||||
args.totalNodes, args.leafNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes);
|
||||
|
||||
printLog(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld \n", debug::valueOf(_voxelsDirty),
|
||||
qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld \n", debug::valueOf(_voxelsDirty),
|
||||
_voxelsInWriteArrays, minDirty, maxDirty);
|
||||
|
||||
printLog(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n",
|
||||
qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n",
|
||||
args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender);
|
||||
|
||||
glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN;
|
||||
|
@ -1099,7 +1102,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
|||
}
|
||||
}
|
||||
|
||||
printLog(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n",
|
||||
qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n",
|
||||
minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays);
|
||||
|
||||
}
|
||||
|
@ -1124,7 +1127,7 @@ void VoxelSystem::createVoxel(float x, float y, float z, float s,
|
|||
unsigned char red, unsigned char green, unsigned char blue, bool destructive) {
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
|
||||
//printLog("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s);
|
||||
//qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s);
|
||||
_tree->createVoxel(x, y, z, s, red, green, blue, destructive);
|
||||
setupNewVoxelsForDrawing();
|
||||
|
||||
|
@ -1250,9 +1253,9 @@ bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraDat
|
|||
args->occludedVoxels++;
|
||||
} else if (result == STORED) {
|
||||
args->notOccludedVoxels++;
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE is STORED *****\n");
|
||||
//qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n");
|
||||
} else if (result == DOESNT_FIT) {
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n");
|
||||
//qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n");
|
||||
}
|
||||
}
|
||||
return true; // keep going!
|
||||
|
@ -1285,7 +1288,7 @@ void VoxelSystem::falseColorizeOccluded() {
|
|||
|
||||
_tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args);
|
||||
|
||||
printLog("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n stagedForDeletion=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
|
||||
qDebug("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n stagedForDeletion=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
|
||||
position.x, position.y,
|
||||
args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
|
||||
args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
|
||||
|
@ -1371,9 +1374,9 @@ bool VoxelSystem::falseColorizeOccludedV2Operation(VoxelNode* node, void* extraD
|
|||
args->occludedVoxels++;
|
||||
} else if (result == V2_STORED) {
|
||||
args->notOccludedVoxels++;
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE is STORED *****\n");
|
||||
//qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n");
|
||||
} else if (result == V2_DOESNT_FIT) {
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n");
|
||||
//qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n");
|
||||
}
|
||||
delete voxelPolygon; // V2 maps don't store polygons, so we're always in charge of freeing
|
||||
}
|
||||
|
@ -1410,7 +1413,7 @@ void VoxelSystem::falseColorizeOccludedV2() {
|
|||
|
||||
_tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedV2Operation, position, (void*)&args);
|
||||
|
||||
printLog("falseColorizeOccludedV2()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n stagedForDeletion=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
|
||||
qDebug("falseColorizeOccludedV2()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n stagedForDeletion=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
|
||||
position.x, position.y,
|
||||
args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
|
||||
args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <UVCCameraControl.hpp>
|
||||
#endif
|
||||
|
||||
#include <Log.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
@ -158,7 +157,7 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, const Rota
|
|||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureSize.width = colorImage.width, _textureSize.height = colorImage.height,
|
||||
0, format, GL_UNSIGNED_BYTE, colorImage.imageData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
printLog("Capturing video at %gx%g.\n", _textureSize.width, _textureSize.height);
|
||||
qDebug("Capturing video at %gx%g.\n", _textureSize.width, _textureSize.height);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
|
@ -327,26 +326,26 @@ static glm::quat xnToGLM(const XnMatrix3X3& matrix) {
|
|||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE newUser(UserGenerator& generator, XnUserID id, void* cookie) {
|
||||
printLog("Found user %d.\n", id);
|
||||
qDebug("Found user %d.\n", id);
|
||||
generator.GetSkeletonCap().RequestCalibration(id, false);
|
||||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE lostUser(UserGenerator& generator, XnUserID id, void* cookie) {
|
||||
printLog("Lost user %d.\n", id);
|
||||
qDebug("Lost user %d.\n", id);
|
||||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE calibrationStarted(SkeletonCapability& capability, XnUserID id, void* cookie) {
|
||||
printLog("Calibration started for user %d.\n", id);
|
||||
qDebug("Calibration started for user %d.\n", id);
|
||||
}
|
||||
|
||||
static void XN_CALLBACK_TYPE calibrationCompleted(SkeletonCapability& capability,
|
||||
XnUserID id, XnCalibrationStatus status, void* cookie) {
|
||||
if (status == XN_CALIBRATION_STATUS_OK) {
|
||||
printLog("Calibration completed for user %d.\n", id);
|
||||
qDebug("Calibration completed for user %d.\n", id);
|
||||
capability.StartTracking(id);
|
||||
|
||||
} else {
|
||||
printLog("Calibration failed to user %d.\n", id);
|
||||
qDebug("Calibration failed to user %d.\n", id);
|
||||
capability.RequestCalibration(id, true);
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +440,7 @@ void FrameGrabber::grabFrame() {
|
|||
// make sure it's in the format we expect
|
||||
if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U || image->dataOrder != IPL_DATA_ORDER_PIXEL ||
|
||||
image->origin != 0) {
|
||||
printLog("Invalid webcam image format.\n");
|
||||
qDebug("Invalid webcam image format.\n");
|
||||
return;
|
||||
}
|
||||
color = image;
|
||||
|
@ -629,7 +628,7 @@ bool FrameGrabber::init() {
|
|||
// load our face cascade
|
||||
switchToResourcesParentIfRequired();
|
||||
if (_faceCascade.empty() && !_faceCascade.load("resources/haarcascades/haarcascade_frontalface_alt.xml")) {
|
||||
printLog("Failed to load Haar cascade for face tracking.\n");
|
||||
qDebug("Failed to load Haar cascade for face tracking.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -662,7 +661,7 @@ bool FrameGrabber::init() {
|
|||
|
||||
// next, an ordinary webcam
|
||||
if ((_capture = cvCaptureFromCAM(-1)) == 0) {
|
||||
printLog("Failed to open webcam.\n");
|
||||
qDebug("Failed to open webcam.\n");
|
||||
return false;
|
||||
}
|
||||
const int IDEAL_FRAME_WIDTH = 320;
|
||||
|
|
|
@ -5,24 +5,25 @@
|
|||
// Created by Philip Rosedale on 9/11/12.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include <NodeList.h>
|
||||
#include <NodeTypes.h>
|
||||
#include <OculusManager.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
#include "world.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "Log.h"
|
||||
#include "Physics.h"
|
||||
#include "world.h"
|
||||
#include "ui/TextRenderer.h"
|
||||
#include <NodeList.h>
|
||||
#include <NodeTypes.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <OculusManager.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -97,6 +98,7 @@ Avatar::Avatar(Node* owningNode) :
|
|||
_elapsedTimeMoving(0.0f),
|
||||
_elapsedTimeStopped(0.0f),
|
||||
_elapsedTimeSinceCollision(0.0f),
|
||||
_lastCollisionPosition(0, 0, 0),
|
||||
_speedBrakes(false),
|
||||
_isThrustOn(false),
|
||||
_voxels(this)
|
||||
|
@ -548,13 +550,13 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
|||
// For gravity, always move the avatar by the amount driven by gravity, so that the collision
|
||||
// routines will detect it and collide every frame when pulled by gravity to a surface
|
||||
//
|
||||
|
||||
_velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime);
|
||||
_position += _scale * _gravity * (GRAVITY_EARTH * deltaTime) * deltaTime;
|
||||
const float MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY = 0.02f;
|
||||
if (glm::length(_position - _lastCollisionPosition) > MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY) {
|
||||
_velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
updateCollisionWithEnvironment();
|
||||
updateCollisionWithVoxels();
|
||||
updateCollisionWithEnvironment(deltaTime);
|
||||
updateCollisionWithVoxels(deltaTime);
|
||||
updateAvatarCollisions(deltaTime);
|
||||
}
|
||||
|
||||
|
@ -826,6 +828,15 @@ void Avatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovem
|
|||
} else {
|
||||
_avatarTouch.setHasInteractingOther(false);
|
||||
}
|
||||
|
||||
// If there's a leap-interaction hand visible, use that as the endpoint
|
||||
for (size_t i = 0; i < getHand().getPalms().size(); ++i) {
|
||||
PalmData& palm = getHand().getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = palm.getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
}//if (_isMine)
|
||||
|
||||
//constrain right arm length and re-adjust elbow position as it bends
|
||||
|
@ -875,29 +886,40 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::updateCollisionWithEnvironment() {
|
||||
void Avatar::updateCollisionWithEnvironment(float deltaTime) {
|
||||
|
||||
glm::vec3 up = getBodyUpDirection();
|
||||
float radius = _height * 0.125f;
|
||||
const float ENVIRONMENT_SURFACE_ELASTICITY = 1.0f;
|
||||
const float ENVIRONMENT_SURFACE_DAMPING = 0.01;
|
||||
const float ENVIRONMENT_COLLISION_FREQUENCY = 0.05f;
|
||||
const float VISIBLE_GROUND_COLLISION_VELOCITY = 0.2f;
|
||||
glm::vec3 penetration;
|
||||
if (Application::getInstance()->getEnvironment()->findCapsulePenetration(
|
||||
_position - up * (_pelvisFloatingHeight - radius),
|
||||
_position + up * (_height - _pelvisFloatingHeight - radius), radius, penetration)) {
|
||||
float velocityTowardCollision = glm::dot(_velocity, glm::normalize(penetration));
|
||||
if (velocityTowardCollision > VISIBLE_GROUND_COLLISION_VELOCITY) {
|
||||
Application::getInstance()->setGroundPlaneImpact(1.0f);
|
||||
}
|
||||
_lastCollisionPosition = _position;
|
||||
updateCollisionSound(penetration, deltaTime, ENVIRONMENT_COLLISION_FREQUENCY);
|
||||
applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Avatar::updateCollisionWithVoxels() {
|
||||
void Avatar::updateCollisionWithVoxels(float deltaTime) {
|
||||
float radius = _height * 0.125f;
|
||||
const float VOXEL_ELASTICITY = 1.4f;
|
||||
const float VOXEL_DAMPING = 0.0;
|
||||
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
||||
glm::vec3 penetration;
|
||||
if (Application::getInstance()->getVoxels()->findCapsulePenetration(
|
||||
_position - glm::vec3(0.0f, _pelvisFloatingHeight - radius, 0.0f),
|
||||
_position + glm::vec3(0.0f, _height - _pelvisFloatingHeight - radius, 0.0f), radius, penetration)) {
|
||||
_lastCollisionPosition = _position;
|
||||
updateCollisionSound(penetration, deltaTime, VOXEL_COLLISION_FREQUENCY);
|
||||
applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
|
||||
}
|
||||
}
|
||||
|
@ -926,6 +948,36 @@ void Avatar::applyHardCollision(const glm::vec3& penetration, float elasticity,
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) {
|
||||
// consider whether to have the collision make a sound
|
||||
const float AUDIBLE_COLLISION_THRESHOLD = 0.02f;
|
||||
const float COLLISION_LOUDNESS = 1.f;
|
||||
const float DURATION_SCALING = 0.004f;
|
||||
const float NOISE_SCALING = 0.1f;
|
||||
glm::vec3 velocity = _velocity;
|
||||
glm::vec3 gravity = getGravity();
|
||||
|
||||
if (glm::length(gravity) > EPSILON) {
|
||||
// If gravity is on, remove the effect of gravity on velocity for this
|
||||
// frame, so that we are not constantly colliding with the surface
|
||||
velocity -= _scale * glm::length(gravity) * GRAVITY_EARTH * deltaTime * glm::normalize(gravity);
|
||||
}
|
||||
float velocityTowardCollision = glm::dot(velocity, glm::normalize(penetration));
|
||||
float velocityTangentToCollision = glm::length(velocity) - velocityTowardCollision;
|
||||
|
||||
if (velocityTowardCollision > AUDIBLE_COLLISION_THRESHOLD) {
|
||||
// Volume is proportional to collision velocity
|
||||
// Base frequency is modified upward by the angle of the collision
|
||||
// Noise is a function of the angle of collision
|
||||
// Duration of the sound is a function of both base frequency and velocity of impact
|
||||
Application::getInstance()->getAudio()->startCollisionSound(
|
||||
fmin(COLLISION_LOUDNESS * velocityTowardCollision, 1.f),
|
||||
frequency * (1.f + velocityTangentToCollision / velocityTowardCollision),
|
||||
fmin(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.f),
|
||||
1.f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision);
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::updateAvatarCollisions(float deltaTime) {
|
||||
|
||||
// Reset detector for nearest avatar
|
||||
|
@ -1055,7 +1107,7 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) {
|
|||
}
|
||||
glPushMatrix();
|
||||
|
||||
glm::vec3 chatPosition = _bodyBall[BODY_BALL_HEAD_BASE].position + getBodyUpDirection() * chatMessageHeight;
|
||||
glm::vec3 chatPosition = _bodyBall[BODY_BALL_HEAD_BASE].position + getBodyUpDirection() * chatMessageHeight * _scale;
|
||||
glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z);
|
||||
glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation();
|
||||
glm::vec3 chatAxis = glm::axis(chatRotation);
|
||||
|
@ -1065,7 +1117,7 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) {
|
|||
glColor3f(0, 0.8, 0);
|
||||
glRotatef(180, 0, 1, 0);
|
||||
glRotatef(180, 0, 0, 1);
|
||||
glScalef(chatMessageScale, chatMessageScale, 1.0f);
|
||||
glScalef(_scale * chatMessageScale, _scale * chatMessageScale, 1.0f);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDepthMask(false);
|
||||
|
|
|
@ -10,18 +10,21 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <AvatarData.h>
|
||||
|
||||
#include <QSettings>
|
||||
#include "world.h"
|
||||
|
||||
#include <AvatarData.h>
|
||||
|
||||
#include "AvatarTouch.h"
|
||||
#include "AvatarVoxelSystem.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "SerialInterface.h"
|
||||
#include "Balls.h"
|
||||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Skeleton.h"
|
||||
#include "SerialInterface.h"
|
||||
#include "Transmitter.h"
|
||||
#include "world.h"
|
||||
|
||||
const float BODY_BALL_RADIUS_PELVIS = 0.07;
|
||||
const float BODY_BALL_RADIUS_TORSO = 0.065;
|
||||
|
@ -115,7 +118,8 @@ public:
|
|||
const glm::vec3& amplifyAngle,
|
||||
float yawFromTouch,
|
||||
float pitchFromTouch);
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
void addBodyYaw(float bodyYaw) {_bodyYaw += bodyYaw;};
|
||||
void addBodyYawDelta(float bodyYawDelta) {_bodyYawDelta += bodyYawDelta;}
|
||||
void render(bool lookingInMirror, bool renderAvatarBalls);
|
||||
|
||||
//setters
|
||||
|
@ -152,6 +156,7 @@ public:
|
|||
float getElapsedTimeStopped () const { return _elapsedTimeStopped;}
|
||||
float getElapsedTimeMoving () const { return _elapsedTimeMoving;}
|
||||
float getElapsedTimeSinceCollision() const { return _elapsedTimeSinceCollision;}
|
||||
const glm::vec3& getLastCollisionPosition () const { return _lastCollisionPosition;}
|
||||
float getAbsoluteHeadYaw () const;
|
||||
float getAbsoluteHeadPitch () const;
|
||||
Head& getHead () {return _head; }
|
||||
|
@ -159,6 +164,8 @@ public:
|
|||
glm::quat getOrientation () const;
|
||||
glm::quat getWorldAlignedOrientation() const;
|
||||
|
||||
glm::vec3 getGravity () const { return _gravity; }
|
||||
|
||||
glm::vec3 getUprightHeadPosition() const;
|
||||
|
||||
AvatarVoxelSystem* getVoxels() { return &_voxels; }
|
||||
|
@ -240,6 +247,7 @@ private:
|
|||
float _elapsedTimeMoving; // Timers to drive camera transitions when moving
|
||||
float _elapsedTimeStopped;
|
||||
float _elapsedTimeSinceCollision;
|
||||
glm::vec3 _lastCollisionPosition;
|
||||
bool _speedBrakes;
|
||||
bool _isThrustOn;
|
||||
|
||||
|
@ -259,9 +267,10 @@ private:
|
|||
void updateAvatarCollisions(float deltaTime);
|
||||
void updateArmIKAndConstraints( float deltaTime );
|
||||
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
||||
void updateCollisionWithEnvironment();
|
||||
void updateCollisionWithVoxels();
|
||||
void updateCollisionWithEnvironment(float deltaTime);
|
||||
void updateCollisionWithVoxels(float deltaTime);
|
||||
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
|
||||
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
|
||||
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||
void checkForMouseRayTouching();
|
||||
};
|
||||
|
|
|
@ -93,7 +93,7 @@ const Mode MODES[] = {
|
|||
|
||||
void AvatarVoxelSystem::cycleMode() {
|
||||
_mode = (_mode + 1) % (sizeof(MODES) / sizeof(MODES[0]));
|
||||
printLog("Voxeltar bind mode %d.\n", _mode);
|
||||
qDebug("Voxeltar bind mode %d.\n", _mode);
|
||||
|
||||
// rebind
|
||||
QUrl url = _voxelURL;
|
||||
|
@ -255,7 +255,7 @@ void AvatarVoxelSystem::handleVoxelDownloadProgress(qint64 bytesReceived, qint64
|
|||
}
|
||||
|
||||
void AvatarVoxelSystem::handleVoxelReplyError() {
|
||||
printLog("%s\n", _voxelReply->errorString().toAscii().constData());
|
||||
qDebug("%s\n", _voxelReply->errorString().toAscii().constData());
|
||||
|
||||
_voxelReply->disconnect(this);
|
||||
_voxelReply->deleteLater();
|
||||
|
|
|
@ -22,9 +22,12 @@ Hand::Hand(Avatar* owningAvatar) :
|
|||
_renderAlpha(1.0),
|
||||
_lookingInMirror(false),
|
||||
_ballColor(0.0, 0.0, 0.4),
|
||||
_position(0.0, 0.4, 0.0),
|
||||
_orientation(0.0, 0.0, 0.0, 1.0)
|
||||
_particleSystemInitialized(false)
|
||||
{
|
||||
// initialize all finger particle emitters with an invalid id as default
|
||||
for (int f = 0; f< NUM_FINGERS_PER_HAND; f ++ ) {
|
||||
_fingerParticleEmitter[f] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::init() {
|
||||
|
@ -40,46 +43,89 @@ void Hand::reset() {
|
|||
}
|
||||
|
||||
void Hand::simulate(float deltaTime, bool isMine) {
|
||||
}
|
||||
|
||||
glm::vec3 Hand::leapPositionToWorldPosition(const glm::vec3& leapPosition) {
|
||||
float unitScale = 0.001; // convert mm to meters
|
||||
return _position + _orientation * (leapPosition * unitScale);
|
||||
if (_isRaveGloveActive) {
|
||||
updateFingerParticles(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::calculateGeometry() {
|
||||
glm::vec3 offset(0.2, -0.2, -0.3); // place the hand in front of the face where we can see it
|
||||
|
||||
Head& head = _owningAvatar->getHead();
|
||||
_position = head.getPosition() + head.getOrientation() * offset;
|
||||
_orientation = head.getOrientation();
|
||||
_basePosition = head.getPosition() + head.getOrientation() * offset;
|
||||
_baseOrientation = head.getOrientation();
|
||||
|
||||
int numLeapBalls = _fingerTips.size();
|
||||
_leapBalls.resize(numLeapBalls);
|
||||
|
||||
for (int i = 0; i < _fingerTips.size(); ++i) {
|
||||
_leapBalls[i].rotation = _orientation;
|
||||
_leapBalls[i].position = leapPositionToWorldPosition(_fingerTips[i]);
|
||||
_leapBalls[i].radius = 0.01;
|
||||
_leapBalls[i].touchForce = 0.0;
|
||||
_leapBalls[i].isCollidable = true;
|
||||
_leapBalls.clear();
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
if (finger.isActive()) {
|
||||
const float standardBallRadius = 0.01f;
|
||||
_leapBalls.resize(_leapBalls.size() + 1);
|
||||
HandBall& ball = _leapBalls.back();
|
||||
ball.rotation = _baseOrientation;
|
||||
ball.position = finger.getTipPosition();
|
||||
ball.radius = standardBallRadius;
|
||||
ball.touchForce = 0.0;
|
||||
ball.isCollidable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Hand::render(bool lookingInMirror) {
|
||||
|
||||
|
||||
_renderAlpha = 1.0;
|
||||
_lookingInMirror = lookingInMirror;
|
||||
|
||||
calculateGeometry();
|
||||
|
||||
if (_isRaveGloveActive) {
|
||||
renderRaveGloveStage();
|
||||
|
||||
if (_particleSystemInitialized) {
|
||||
_particleSystem.render();
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
|
||||
renderHandSpheres();
|
||||
}
|
||||
|
||||
void Hand::renderRaveGloveStage() {
|
||||
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
||||
Head& head = _owningAvatar->getHead();
|
||||
glm::quat headOrientation = head.getOrientation();
|
||||
glm::vec3 headPosition = head.getPosition();
|
||||
float scale = 100.0f;
|
||||
glm::vec3 vc = headOrientation * glm::vec3( 0.0f, 0.0f, -30.0f) + headPosition;
|
||||
glm::vec3 v0 = headOrientation * (glm::vec3(-1.0f, -1.0f, 0.0f) * scale) + vc;
|
||||
glm::vec3 v1 = headOrientation * (glm::vec3( 1.0f, -1.0f, 0.0f) * scale) + vc;
|
||||
glm::vec3 v2 = headOrientation * (glm::vec3( 1.0f, 1.0f, 0.0f) * scale) + vc;
|
||||
glm::vec3 v3 = headOrientation * (glm::vec3(-1.0f, 1.0f, 0.0f) * scale) + vc;
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glVertex3fv((float*)&vc);
|
||||
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
glVertex3fv((float*)&v0);
|
||||
glVertex3fv((float*)&v1);
|
||||
glVertex3fv((float*)&v2);
|
||||
glVertex3fv((float*)&v3);
|
||||
glVertex3fv((float*)&v0);
|
||||
glEnd();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::renderHandSpheres() {
|
||||
glPushMatrix();
|
||||
// Draw the leap balls
|
||||
|
@ -97,21 +143,29 @@ void Hand::renderHandSpheres() {
|
|||
}
|
||||
|
||||
// Draw the finger root cones
|
||||
if (_fingerTips.size() == _fingerRoots.size()) {
|
||||
for (size_t i = 0; i < _fingerTips.size(); ++i) {
|
||||
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, 0.5);
|
||||
glm::vec3 tip = leapPositionToWorldPosition(_fingerTips[i]);
|
||||
glm::vec3 root = leapPositionToWorldPosition(_fingerRoots[i]);
|
||||
Avatar::renderJointConnectingCone(root, tip, 0.001, 0.003);
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
if (finger.isActive()) {
|
||||
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, 0.5);
|
||||
glm::vec3 tip = finger.getTipPosition();
|
||||
glm::vec3 root = finger.getRootPosition();
|
||||
Avatar::renderJointConnectingCone(root, tip, 0.001, 0.003);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the palms
|
||||
if (_handPositions.size() == _handNormals.size()) {
|
||||
for (size_t i = 0; i < _handPositions.size(); ++i) {
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
const float palmThickness = 0.002f;
|
||||
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, 0.25);
|
||||
glm::vec3 tip = leapPositionToWorldPosition(_handPositions[i]);
|
||||
glm::vec3 root = leapPositionToWorldPosition(_handPositions[i] + (_handNormals[i] * 2.0f));
|
||||
glm::vec3 tip = palm.getPosition();
|
||||
glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness;
|
||||
Avatar::renderJointConnectingCone(root, tip, 0.05, 0.03);
|
||||
}
|
||||
}
|
||||
|
@ -121,14 +175,133 @@ void Hand::renderHandSpheres() {
|
|||
|
||||
void Hand::setLeapFingers(const std::vector<glm::vec3>& fingerTips,
|
||||
const std::vector<glm::vec3>& fingerRoots) {
|
||||
_fingerTips = fingerTips;
|
||||
_fingerRoots = fingerRoots;
|
||||
// TODO: add id-checking here to increase finger stability
|
||||
|
||||
size_t fingerIndex = 0;
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
if (fingerIndex < fingerTips.size()) {
|
||||
finger.setActive(true);
|
||||
finger.setRawTipPosition(fingerTips[fingerIndex]);
|
||||
finger.setRawRootPosition(fingerRoots[fingerIndex]);
|
||||
fingerIndex++;
|
||||
}
|
||||
else {
|
||||
finger.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||
const std::vector<glm::vec3>& handNormals) {
|
||||
_handPositions = handPositions;
|
||||
_handNormals = handNormals;
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (i < handPositions.size()) {
|
||||
palm.setActive(true);
|
||||
palm.setRawPosition(handPositions[i]);
|
||||
palm.setRawNormal(handNormals[i]);
|
||||
}
|
||||
else {
|
||||
palm.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Hand::updateFingerParticles(float deltaTime) {
|
||||
|
||||
if (!_particleSystemInitialized) {
|
||||
|
||||
for ( int f = 0; f< NUM_FINGERS_PER_HAND; f ++ ) {
|
||||
|
||||
_particleSystem.setShowingEmitter(f, true );
|
||||
|
||||
_fingerParticleEmitter[f] = _particleSystem.addEmitter();
|
||||
|
||||
assert( _fingerParticleEmitter[f] != -1 );
|
||||
|
||||
ParticleSystem::ParticleAttributes attributes;
|
||||
|
||||
// set attributes for each life stage of the particle:
|
||||
attributes.radius = 0.0f;
|
||||
attributes.color = glm::vec4( 1.0f, 1.0f, 0.5f, 0.5f);
|
||||
attributes.gravity = 0.0f;
|
||||
attributes.airFriction = 0.0f;
|
||||
attributes.jitter = 0.002f;
|
||||
attributes.emitterAttraction = 0.0f;
|
||||
attributes.tornadoForce = 0.0f;
|
||||
attributes.neighborAttraction = 0.0f;
|
||||
attributes.neighborRepulsion = 0.0f;
|
||||
attributes.bounce = 1.0f;
|
||||
attributes.usingCollisionSphere = false;
|
||||
_particleSystem.setParticleAttributes(_fingerParticleEmitter[f], 0, attributes);
|
||||
|
||||
attributes.radius = 0.01f;
|
||||
attributes.jitter = 0.0f;
|
||||
attributes.gravity = -0.005f;
|
||||
attributes.color = glm::vec4( 1.0f, 0.2f, 0.0f, 0.4f);
|
||||
_particleSystem.setParticleAttributes(_fingerParticleEmitter[f], 1, attributes);
|
||||
|
||||
attributes.radius = 0.01f;
|
||||
attributes.gravity = 0.0f;
|
||||
attributes.color = glm::vec4( 0.0f, 0.0f, 0.0f, 0.2f);
|
||||
_particleSystem.setParticleAttributes(_fingerParticleEmitter[f], 2, attributes);
|
||||
|
||||
attributes.radius = 0.02f;
|
||||
attributes.color = glm::vec4( 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
_particleSystem.setParticleAttributes(_fingerParticleEmitter[f], 3, attributes);
|
||||
}
|
||||
|
||||
_particleSystemInitialized = true;
|
||||
} else {
|
||||
// update the particles
|
||||
|
||||
static float t = 0.0f;
|
||||
t += deltaTime;
|
||||
|
||||
int fingerIndex = 0;
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
if (finger.isActive()) {
|
||||
if (_fingerParticleEmitter[fingerIndex] != -1) {
|
||||
|
||||
glm::vec3 particleEmitterPosition = finger.getTipPosition();
|
||||
|
||||
glm::vec3 fingerDirection = particleEmitterPosition - leapPositionToWorldPosition(finger.getRootPosition());
|
||||
float fingerLength = glm::length(fingerDirection);
|
||||
|
||||
if (fingerLength > 0.0f) {
|
||||
fingerDirection /= fingerLength;
|
||||
} else {
|
||||
fingerDirection = IDENTITY_UP;
|
||||
}
|
||||
|
||||
glm::quat particleEmitterRotation = rotationBetween(palm.getNormal(), fingerDirection);
|
||||
|
||||
//glm::quat particleEmitterRotation = glm::angleAxis(0.0f, fingerDirection);
|
||||
|
||||
_particleSystem.setEmitterPosition(_fingerParticleEmitter[f], particleEmitterPosition);
|
||||
_particleSystem.setEmitterRotation(_fingerParticleEmitter[f], particleEmitterRotation);
|
||||
|
||||
const glm::vec3 velocity = fingerDirection * 0.002f;
|
||||
const float lifespan = 1.0f;
|
||||
_particleSystem.emitParticlesNow(_fingerParticleEmitter[f], 1, velocity, lifespan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
_particleSystem.simulate(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "SerialInterface.h"
|
||||
#include "ParticleSystem.h"
|
||||
#include <SharedUtil.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class Avatar;
|
||||
class ProgramObject;
|
||||
|
||||
|
@ -46,27 +46,33 @@ public:
|
|||
const std::vector<glm::vec3>& fingerRoots);
|
||||
void setLeapHands (const std::vector<glm::vec3>& handPositions,
|
||||
const std::vector<glm::vec3>& handNormals);
|
||||
void updateFingerParticles(float deltaTime);
|
||||
void setRaveGloveActive(bool active) { _isRaveGloveActive = active; }
|
||||
|
||||
|
||||
// getters
|
||||
const glm::vec3& getLeapBallPosition (int ball) const { return _leapBalls[ball].position;}
|
||||
|
||||
// position conversion
|
||||
glm::vec3 leapPositionToWorldPosition(const glm::vec3& leapPosition);
|
||||
bool isRaveGloveActive () const { return _isRaveGloveActive; }
|
||||
|
||||
private:
|
||||
// disallow copies of the Hand, copy of owning Avatar is disallowed too
|
||||
Hand(const Hand&);
|
||||
Hand& operator= (const Hand&);
|
||||
|
||||
ParticleSystem _particleSystem;
|
||||
|
||||
Avatar* _owningAvatar;
|
||||
float _renderAlpha;
|
||||
bool _lookingInMirror;
|
||||
bool _isRaveGloveActive;
|
||||
glm::vec3 _ballColor;
|
||||
glm::vec3 _position;
|
||||
glm::quat _orientation;
|
||||
std::vector<HandBall> _leapBalls;
|
||||
|
||||
bool _particleSystemInitialized;
|
||||
int _fingerParticleEmitter[NUM_FINGERS_PER_HAND];
|
||||
|
||||
// private methods
|
||||
void renderRaveGloveStage();
|
||||
void renderHandSpheres();
|
||||
void calculateGeometry();
|
||||
};
|
||||
|
|
|
@ -227,8 +227,9 @@ void Head::simulate(float deltaTime, bool isMine) {
|
|||
const float CAMERA_FOLLOW_HEAD_RATE_START = 0.01f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_MAX = 0.5f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE = 1.05f;
|
||||
const float CAMERA_STOP_TOLERANCE_DEGREES = 0.1f;
|
||||
const float CAMERA_START_TOLERANCE_DEGREES = 2.0f;
|
||||
const float CAMERA_STOP_TOLERANCE_DEGREES = 0.5f;
|
||||
const float CAMERA_PITCH_START_TOLERANCE_DEGREES = 20.0f;
|
||||
const float CAMERA_YAW_START_TOLERANCE_DEGREES = 10.0f;
|
||||
float cameraHeadAngleDifference = glm::length(glm::vec2(_pitch - _cameraPitch, _yaw - _cameraYaw));
|
||||
if (_isCameraMoving) {
|
||||
_cameraFollowHeadRate = glm::clamp(_cameraFollowHeadRate * CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE,
|
||||
|
@ -241,7 +242,8 @@ void Head::simulate(float deltaTime, bool isMine) {
|
|||
_isCameraMoving = false;
|
||||
}
|
||||
} else {
|
||||
if (cameraHeadAngleDifference > CAMERA_START_TOLERANCE_DEGREES) {
|
||||
if ((fabs(_pitch - _cameraPitch) > CAMERA_PITCH_START_TOLERANCE_DEGREES) ||
|
||||
(fabs(_yaw - _cameraYaw) > CAMERA_YAW_START_TOLERANCE_DEGREES)) {
|
||||
_isCameraMoving = true;
|
||||
_cameraFollowHeadRate = CAMERA_FOLLOW_HEAD_RATE_START;
|
||||
}
|
||||
|
|
|
@ -16,15 +16,16 @@
|
|||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
timeval startup_time;
|
||||
gettimeofday(&startup_time, NULL);
|
||||
|
||||
Application app(argc, const_cast<char**>(argv), startup_time);
|
||||
printLog( "Created QT Application.\n" );
|
||||
qDebug( "Created QT Application.\n" );
|
||||
int exitCode = app.exec();
|
||||
printLog("Normal exit.\n");
|
||||
qDebug("Normal exit.\n");
|
||||
return exitCode;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cfloat>
|
||||
|
|
|
@ -38,12 +38,12 @@ namespace starfield {
|
|||
|
||||
if (! UrlReader::readUrl(url, *this, cacheFile))
|
||||
{
|
||||
printLog("%s:%d: %s\n",
|
||||
qDebug("%s:%d: %s\n",
|
||||
_urlStr, _lineNo, getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
printLog("Loaded %u stars.\n", _recordsRead);
|
||||
qDebug("Loaded %u stars.\n", _recordsRead);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ namespace starfield {
|
|||
|
||||
_vertices->clear();
|
||||
_vertices->reserve(_limit);
|
||||
// printLog("Stars.cpp: loader begin %s\n", url);
|
||||
// qDebug("Stars.cpp: loader begin %s\n", url);
|
||||
}
|
||||
|
||||
size_t transfer(char* input, size_t bytes) {
|
||||
|
@ -103,7 +103,7 @@ namespace starfield {
|
|||
|
||||
} else {
|
||||
|
||||
printLog("Stars.cpp:%d: Bad input from %s\n",
|
||||
qDebug("Stars.cpp:%d: Bad input from %s\n",
|
||||
_lineNo, _urlStr);
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ namespace starfield {
|
|||
// remember the brightness at its top
|
||||
if (_recordsRead == _limit) {
|
||||
|
||||
// printLog("Stars.cpp: vertex limit reached -> heap mode\n");
|
||||
// qDebug("Stars.cpp: vertex limit reached -> heap mode\n");
|
||||
|
||||
make_heap(
|
||||
_vertices->begin(), _vertices->end(),
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
#include <QPalette>
|
||||
#include <QColor>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
BandwidthDialog::BandwidthDialog(QWidget* parent, BandwidthMeter* model) :
|
||||
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint),
|
||||
_model(model) {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed
|
||||
|
||||
AvatarData::AvatarData(Node* owningNode) :
|
||||
NodeData(owningNode),
|
||||
_handPosition(0,0,0),
|
||||
|
@ -127,36 +129,22 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
*destinationBuffer++ = bitItems;
|
||||
|
||||
// leap hand data
|
||||
// In order to make the hand data version-robust, hand data packing is just a series of vec3's,
|
||||
// with conventions. If a client doesn't know the conventions, they can just get the vec3's
|
||||
// and render them as balls, or ignore them, without crashing or disrupting anyone.
|
||||
// Current convention:
|
||||
// Zero or more fingetTip positions, followed by the same number of fingerRoot positions
|
||||
|
||||
const std::vector<glm::vec3>& fingerTips = _handData->getFingerTips();
|
||||
const std::vector<glm::vec3>& fingerRoots = _handData->getFingerRoots();
|
||||
size_t numFingerVectors = fingerTips.size() + fingerRoots.size();
|
||||
if (numFingerVectors > 255)
|
||||
numFingerVectors = 0; // safety. We shouldn't ever get over 255, so consider that invalid.
|
||||
std::vector<glm::vec3> fingerVectors;
|
||||
_handData->encodeRemoteData(fingerVectors);
|
||||
|
||||
/////////////////////////////////
|
||||
// Temporarily disable Leap finger sending, as it's causing a crash whenever someone's got a Leap connected
|
||||
numFingerVectors = 0;
|
||||
fingerVectors.clear();
|
||||
/////////////////////////////////
|
||||
|
||||
*destinationBuffer++ = (unsigned char)numFingerVectors;
|
||||
|
||||
if (numFingerVectors > 0) {
|
||||
for (size_t i = 0; i < fingerTips.size(); ++i) {
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerTips[i].x, 4);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerTips[i].y, 4);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerTips[i].z, 4);
|
||||
}
|
||||
for (size_t i = 0; i < fingerRoots.size(); ++i) {
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerRoots[i].x, 4);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerRoots[i].y, 4);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerRoots[i].z, 4);
|
||||
}
|
||||
if (fingerVectors.size() > 255)
|
||||
fingerVectors.clear(); // safety. We shouldn't ever get over 255, so consider that invalid.
|
||||
|
||||
*destinationBuffer++ = (unsigned char)fingerVectors.size();
|
||||
|
||||
for (size_t i = 0; i < fingerVectors.size(); ++i) {
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerVectors[i].x, fingerVectorRadix);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerVectors[i].y, fingerVectorRadix);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerVectors[i].z, fingerVectorRadix);
|
||||
}
|
||||
|
||||
// skeleton joints
|
||||
|
@ -222,7 +210,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
memcpy(&handPositionRelative, sourceBuffer, sizeof(float) * 3);
|
||||
_handPosition = _position + handPositionRelative;
|
||||
sourceBuffer += sizeof(float) * 3;
|
||||
|
||||
|
||||
// Lookat Position
|
||||
memcpy(&_headData->_lookAtPosition, sourceBuffer, sizeof(_headData->_lookAtPosition));
|
||||
sourceBuffer += sizeof(_headData->_lookAtPosition);
|
||||
|
@ -263,25 +251,16 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
// leap hand data
|
||||
if (sourceBuffer - startPosition < numBytes) // safety check
|
||||
{
|
||||
std::vector<glm::vec3> fingerTips;
|
||||
std::vector<glm::vec3> fingerRoots;
|
||||
unsigned int numFingerVectors = *sourceBuffer++;
|
||||
unsigned int numFingerTips = numFingerVectors / 2;
|
||||
unsigned int numFingerRoots = numFingerVectors - numFingerTips;
|
||||
fingerTips.resize(numFingerTips);
|
||||
fingerRoots.resize(numFingerRoots);
|
||||
for (size_t i = 0; i < numFingerTips; ++i) {
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].x), 4);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].y), 4);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].z), 4);
|
||||
if (numFingerVectors > 0) {
|
||||
std::vector<glm::vec3> fingerVectors(numFingerVectors);
|
||||
for (size_t i = 0; i < numFingerVectors; ++i) {
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].x), fingerVectorRadix);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].y), fingerVectorRadix);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].z), fingerVectorRadix);
|
||||
}
|
||||
_handData->decodeRemoteData(fingerVectors);
|
||||
}
|
||||
for (size_t i = 0; i < numFingerRoots; ++i) {
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerRoots[i].x), 4);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerRoots[i].y), 4);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerRoots[i].z), 4);
|
||||
}
|
||||
_handData->setFingerTips(fingerTips);
|
||||
_handData->setFingerRoots(fingerRoots);
|
||||
}
|
||||
|
||||
// skeleton joints
|
||||
|
@ -430,4 +409,3 @@ int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy) {
|
|||
value = ((float)holder / (float) 255) * scaleBy;
|
||||
return sizeof(holder);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ const int WANT_OCCLUSION_CULLING_BIT = 7; // 8th bit
|
|||
|
||||
const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
|
||||
|
||||
|
||||
enum KeyState
|
||||
{
|
||||
NO_KEY_DOWN = 0,
|
||||
|
|
|
@ -9,7 +9,74 @@
|
|||
#include "HandData.h"
|
||||
|
||||
HandData::HandData(AvatarData* owningAvatar) :
|
||||
_basePosition(0.0f, 0.0f, 0.0f),
|
||||
_baseOrientation(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
_owningAvatarData(owningAvatar)
|
||||
{
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
_palms.push_back(PalmData(this));
|
||||
}
|
||||
}
|
||||
|
||||
PalmData::PalmData(HandData* owningHandData) :
|
||||
_rawPosition(0, 0, 0),
|
||||
_rawNormal(0, 1, 0),
|
||||
_isActive(false),
|
||||
_owningHandData(owningHandData)
|
||||
{
|
||||
for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) {
|
||||
_fingers.push_back(FingerData(this, owningHandData));
|
||||
}
|
||||
}
|
||||
|
||||
FingerData::FingerData(PalmData* owningPalmData, HandData* owningHandData) :
|
||||
_tipRawPosition(0, 0, 0),
|
||||
_rootRawPosition(0, 0, 0),
|
||||
_isActive(false),
|
||||
_owningPalmData(owningPalmData),
|
||||
_owningHandData(owningHandData)
|
||||
{
|
||||
}
|
||||
|
||||
void HandData::encodeRemoteData(std::vector<glm::vec3>& fingerVectors) {
|
||||
fingerVectors.clear();
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
fingerVectors.push_back(palm.getRawPosition());
|
||||
fingerVectors.push_back(palm.getRawNormal());
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
if (finger.isActive()) {
|
||||
fingerVectors.push_back(finger.getTipRawPosition());
|
||||
fingerVectors.push_back(finger.getRootRawPosition());
|
||||
}
|
||||
else {
|
||||
fingerVectors.push_back(glm::vec3(0,0,0));
|
||||
fingerVectors.push_back(glm::vec3(0,0,0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandData::decodeRemoteData(const std::vector<glm::vec3>& fingerVectors) {
|
||||
size_t vectorIndex = 0;
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
// If a palm is active, there will be
|
||||
// 1 vector for its position
|
||||
// 1 vector for normal
|
||||
// 10 vectors for fingers (5 tip/root pairs)
|
||||
bool palmActive = fingerVectors.size() >= i * 12;
|
||||
palm.setActive(palmActive);
|
||||
if (palmActive) {
|
||||
palm.setRawPosition(fingerVectors[vectorIndex++]);
|
||||
palm.setRawNormal(fingerVectors[vectorIndex++]);
|
||||
for (size_t f = 0; f < NUM_FINGERS_PER_HAND; ++f) {
|
||||
FingerData& finger = palm.getFingers()[i];
|
||||
finger.setRawTipPosition(fingerVectors[vectorIndex++]);
|
||||
finger.setRawRootPosition(fingerVectors[vectorIndex++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,13 @@
|
|||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
class AvatarData;
|
||||
class FingerData;
|
||||
class PalmData;
|
||||
|
||||
const int NUM_FINGERS_PER_HAND = 5;
|
||||
|
||||
class HandData {
|
||||
public:
|
||||
|
@ -22,26 +27,79 @@ public:
|
|||
|
||||
// These methods return the positions in Leap-relative space.
|
||||
// To convert to world coordinates, use Hand::leapPositionToWorldPosition.
|
||||
const std::vector<glm::vec3>& getFingerTips() const { return _fingerTips; }
|
||||
const std::vector<glm::vec3>& getFingerRoots() const { return _fingerRoots; }
|
||||
const std::vector<glm::vec3>& getHandPositions() const { return _handPositions; }
|
||||
const std::vector<glm::vec3>& getHandNormals() const { return _handNormals; }
|
||||
void setFingerTips(const std::vector<glm::vec3>& fingerTips) { _fingerTips = fingerTips; }
|
||||
void setFingerRoots(const std::vector<glm::vec3>& fingerRoots) { _fingerRoots = fingerRoots; }
|
||||
void setHandPositions(const std::vector<glm::vec3>& handPositons) { _handPositions = handPositons; }
|
||||
void setHandNormals(const std::vector<glm::vec3>& handNormals) { _handNormals = handNormals; }
|
||||
|
||||
// position conversion
|
||||
glm::vec3 leapPositionToWorldPosition(const glm::vec3& leapPosition) {
|
||||
const float unitScale = 0.001; // convert mm to meters
|
||||
return _basePosition + _baseOrientation * (leapPosition * unitScale);
|
||||
}
|
||||
glm::vec3 leapDirectionToWorldDirection(const glm::vec3& leapDirection) {
|
||||
return glm::normalize(_baseOrientation * leapDirection);
|
||||
}
|
||||
|
||||
std::vector<PalmData>& getPalms() { return _palms; }
|
||||
size_t getNumPalms() { return _palms.size(); }
|
||||
|
||||
// Use these for sending and receiving hand data
|
||||
void encodeRemoteData(std::vector<glm::vec3>& fingerVectors);
|
||||
void decodeRemoteData(const std::vector<glm::vec3>& fingerVectors);
|
||||
|
||||
friend class AvatarData;
|
||||
protected:
|
||||
std::vector<glm::vec3> _fingerTips;
|
||||
std::vector<glm::vec3> _fingerRoots;
|
||||
std::vector<glm::vec3> _handPositions;
|
||||
std::vector<glm::vec3> _handNormals;
|
||||
glm::vec3 _basePosition; // Hands are placed relative to this
|
||||
glm::quat _baseOrientation; // Hands are placed relative to this
|
||||
AvatarData* _owningAvatarData;
|
||||
std::vector<PalmData> _palms;
|
||||
private:
|
||||
// privatize copy ctor and assignment operator so copies of this object cannot be made
|
||||
HandData(const HandData&);
|
||||
HandData& operator= (const HandData&);
|
||||
};
|
||||
|
||||
class FingerData {
|
||||
public:
|
||||
FingerData(PalmData* owningPalmData, HandData* owningHandData);
|
||||
|
||||
glm::vec3 getTipPosition() const { return _owningHandData->leapPositionToWorldPosition(_tipRawPosition); }
|
||||
glm::vec3 getRootPosition() const { return _owningHandData->leapPositionToWorldPosition(_rootRawPosition); }
|
||||
const glm::vec3& getTipRawPosition() const { return _tipRawPosition; }
|
||||
const glm::vec3& getRootRawPosition() const { return _rootRawPosition; }
|
||||
bool isActive() const { return _isActive; }
|
||||
|
||||
void setActive(bool active) { _isActive = active; }
|
||||
void setRawTipPosition(const glm::vec3& pos) { _tipRawPosition = pos; }
|
||||
void setRawRootPosition(const glm::vec3& pos) { _rootRawPosition = pos; }
|
||||
|
||||
private:
|
||||
glm::vec3 _tipRawPosition;
|
||||
glm::vec3 _rootRawPosition;
|
||||
bool _isActive; // This has current valid data
|
||||
PalmData* _owningPalmData;
|
||||
HandData* _owningHandData;
|
||||
};
|
||||
|
||||
class PalmData {
|
||||
public:
|
||||
PalmData(HandData* owningHandData);
|
||||
glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); }
|
||||
glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); }
|
||||
const glm::vec3& getRawPosition() const { return _rawPosition; }
|
||||
const glm::vec3& getRawNormal() const { return _rawNormal; }
|
||||
bool isActive() const { return _isActive; }
|
||||
|
||||
std::vector<FingerData>& getFingers() { return _fingers; }
|
||||
size_t getNumFingers() { return _fingers.size(); }
|
||||
|
||||
void setActive(bool active) { _isActive = active; }
|
||||
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
|
||||
void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; }
|
||||
|
||||
private:
|
||||
std::vector<FingerData> _fingers;
|
||||
glm::vec3 _rawPosition;
|
||||
glm::vec3 _rawNormal;
|
||||
bool _isActive; // This has current valid data
|
||||
HandData* _owningHandData;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__HandData__) */
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
|
||||
set(TARGET_NAME shared)
|
||||
project(${TARGET_NAME})
|
||||
|
||||
# grab the implemenation and header files
|
||||
file(GLOB HIFI_SHARED_SRCS src/*.h src/*.cpp)
|
||||
|
||||
# create a library and set the property so it can be referenced later
|
||||
add_library(${TARGET_NAME} ${HIFI_SHARED_SRCS})
|
||||
set(HIFI_SHARED_LIBRARY ${TARGET_NAME})
|
||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||
setup_hifi_library(${TARGET_NAME})
|
||||
|
||||
set(EXTERNAL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external)
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
//
|
||||
// Log.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Tobias Schwinger on 4/17/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace std;
|
||||
int (* printLog)(char const*, ...) = & printf;
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
//
|
||||
// Log.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Tobias Schwinger on 4/17/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__shared_Log__
|
||||
#define __hifi__shared_Log__
|
||||
|
||||
//
|
||||
// Pointer to log function
|
||||
//
|
||||
// An application may reset this variable to receive the log messages
|
||||
// issued using 'printLog'. It defaults to a pointer to 'printf'.
|
||||
//
|
||||
extern int (* printLog)(char const*, ...);
|
||||
|
||||
#endif /* defined(__hifi__shared_Log__) */
|
||||
|
|
@ -6,15 +6,9 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include "Node.h"
|
||||
#include "NodeTypes.h"
|
||||
#include <cstring>
|
||||
#include "Log.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "SharedUtil.h"
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Syssocket.h"
|
||||
|
@ -22,6 +16,13 @@
|
|||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "Node.h"
|
||||
#include "NodeTypes.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
int unpackNodeId(unsigned char* packedData, uint16_t* nodeId) {
|
||||
memcpy(nodeId, packedData, sizeof(uint16_t));
|
||||
return sizeof(uint16_t);
|
||||
|
@ -140,18 +141,14 @@ float Node::getAverageKilobitsPerSecond() {
|
|||
}
|
||||
}
|
||||
|
||||
void Node::printLog(Node const& node) {
|
||||
|
||||
QDebug operator<<(QDebug debug, const Node &node) {
|
||||
char publicAddressBuffer[16] = {'\0'};
|
||||
unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, node._publicSocket);
|
||||
unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, node.getPublicSocket());
|
||||
|
||||
//char localAddressBuffer[16] = {'\0'};
|
||||
//unsigned short localAddressPort = loadBufferWithSocketInfo(localAddressBuffer, node.localSocket);
|
||||
|
||||
::printLog("# %d %s (%c) @ %s:%d\n",
|
||||
node._nodeID,
|
||||
node.getTypeName(),
|
||||
node._type,
|
||||
publicAddressBuffer,
|
||||
publicAddressPort);
|
||||
debug << "#" << node.getNodeID() << node.getTypeName() << node.getType();
|
||||
debug.nospace() << publicAddressBuffer << ":" << publicAddressPort;
|
||||
return debug.nospace();
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#ifndef __hifi__Node__
|
||||
#define __hifi__Node__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ostream>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Syssocket.h"
|
||||
|
@ -18,8 +18,10 @@
|
|||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "SimpleMovingAverage.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "NodeData.h"
|
||||
#include "SimpleMovingAverage.h"
|
||||
|
||||
class Node {
|
||||
public:
|
||||
|
@ -89,8 +91,9 @@ private:
|
|||
pthread_mutex_t _mutex;
|
||||
};
|
||||
|
||||
|
||||
int unpackNodeId(unsigned char *packedData, uint16_t *nodeId);
|
||||
int packNodeId(unsigned char *packStore, uint16_t nodeId);
|
||||
|
||||
QDebug operator<<(QDebug debug, const Node &message);
|
||||
|
||||
#endif /* defined(__hifi__Node__) */
|
||||
|
|
|
@ -11,11 +11,12 @@
|
|||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "NodeList.h"
|
||||
#include "NodeTypes.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "Log.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Syssocket.h"
|
||||
|
@ -42,7 +43,7 @@ NodeList* NodeList::createInstance(char ownerType, unsigned int socketListenPort
|
|||
if (!_sharedInstance) {
|
||||
_sharedInstance = new NodeList(ownerType, socketListenPort);
|
||||
} else {
|
||||
printLog("NodeList createInstance called with existing instance.\n");
|
||||
qDebug("NodeList createInstance called with existing instance.\n");
|
||||
}
|
||||
|
||||
return _sharedInstance;
|
||||
|
@ -50,7 +51,7 @@ NodeList* NodeList::createInstance(char ownerType, unsigned int socketListenPort
|
|||
|
||||
NodeList* NodeList::getInstance() {
|
||||
if (!_sharedInstance) {
|
||||
printLog("NodeList getInstance called before call to createInstance. Returning NULL pointer.\n");
|
||||
qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer.\n");
|
||||
}
|
||||
|
||||
return _sharedInstance;
|
||||
|
@ -274,12 +275,13 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
sockaddr_in tempAddress;
|
||||
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
|
||||
strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr));
|
||||
printLog("Domain Server: %s \n", _domainHostname);
|
||||
|
||||
qDebug("Domain Server: %s\n", _domainHostname);
|
||||
} else {
|
||||
printLog("Failed domain server lookup\n");
|
||||
qDebug("Failed domain server lookup\n");
|
||||
}
|
||||
} else if (!printedDomainServerIP) {
|
||||
printLog("Domain Server IP: %s\n", _domainIP);
|
||||
qDebug("Domain Server IP: %s\n", _domainIP);
|
||||
printedDomainServerIP = true;
|
||||
}
|
||||
|
||||
|
@ -418,8 +420,7 @@ void NodeList::addNodeToList(Node* newNode) {
|
|||
|
||||
++_numNodes;
|
||||
|
||||
printLog("Added ");
|
||||
Node::printLog(*newNode);
|
||||
qDebug() << "Added" << *newNode << "\n";
|
||||
}
|
||||
|
||||
unsigned NodeList::broadcastToNodes(unsigned char *broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes) {
|
||||
|
@ -471,11 +472,9 @@ void *removeSilentNodes(void *args) {
|
|||
|
||||
for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) {
|
||||
|
||||
if ((checkTimeUSecs - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS
|
||||
&& node->getType() != NODE_TYPE_VOXEL_SERVER) {
|
||||
if ((checkTimeUSecs - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) {
|
||||
|
||||
printLog("Killed ");
|
||||
Node::printLog(*node);
|
||||
qDebug() << "Killed" << *node << "\n";
|
||||
|
||||
node->setAlive(false);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
|||
|
||||
extern const char SOLO_NODE_TYPES[3];
|
||||
|
||||
const int MAX_HOSTNAME_BYTES = 255;
|
||||
const int MAX_HOSTNAME_BYTES = 256;
|
||||
|
||||
extern const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES];
|
||||
extern const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN]; // IP Address will be re-set by lookup on startup
|
||||
|
|
|
@ -6,14 +6,18 @@
|
|||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm> // std:min
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "SharedUtil.h"
|
||||
#include "OctalCode.h"
|
||||
#include "Log.h"
|
||||
|
||||
int numberOfThreeBitSectionsInCode(unsigned char * octalCode) {
|
||||
assert(octalCode);
|
||||
if (*octalCode == 255) {
|
||||
return *octalCode + numberOfThreeBitSectionsInCode(octalCode + 1);
|
||||
} else {
|
||||
|
@ -23,12 +27,12 @@ int numberOfThreeBitSectionsInCode(unsigned char * octalCode) {
|
|||
|
||||
void printOctalCode(unsigned char * octalCode) {
|
||||
if (!octalCode) {
|
||||
printLog("NULL\n");
|
||||
qDebug("NULL\n");
|
||||
} else {
|
||||
for (int i = 0; i < bytesRequiredForCodeLength(*octalCode); i++) {
|
||||
outputBits(octalCode[i],false);
|
||||
}
|
||||
printLog("\n");
|
||||
qDebug("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "PacketHeaders.h"
|
||||
#include "Log.h"
|
||||
|
||||
PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
|
||||
switch (type) {
|
||||
case PACKET_TYPE_HEAD_DATA:
|
||||
return 1;
|
||||
return 2;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -28,7 +29,7 @@ bool packetVersionMatch(unsigned char* packetHeader) {
|
|||
if (packetHeader[1] == versionForPacketType(packetHeader[0])) {
|
||||
return true;
|
||||
} else {
|
||||
printLog("There is a packet version mismatch for packet with header %c\n", packetHeader[0]);
|
||||
qDebug("There is a packet version mismatch for packet with header %c\n", packetHeader[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include "PerfStat.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "Log.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "PerfStat.h"
|
||||
|
||||
// Static class members initialization here!
|
||||
std::map<std::string,PerfStatHistory,std::less<std::string> > PerfStat::groupHistoryMap;
|
||||
|
@ -58,11 +59,11 @@ PerfStat::~PerfStat() {
|
|||
}
|
||||
|
||||
if (wantDebugOut) {
|
||||
printLog("PerfStats: %s elapsed:%f average:%lf count:%ld total:%lf ut:%d us:%d ue:%d t:%ld s:%ld e:%ld\n",
|
||||
this->group.c_str(),elapsed,average,count,totalTime,
|
||||
(end.tv_usec-start.tv_usec),start.tv_usec,end.tv_usec,
|
||||
(end.tv_sec-start.tv_sec),start.tv_sec,end.tv_sec
|
||||
);
|
||||
qDebug("PerfStats: %s elapsed:%f average:%lf count:%ld total:%lf ut:%d us:%d ue:%d t:%ld s:%ld e:%ld\n",
|
||||
this->group.c_str(),elapsed,average,count,totalTime,
|
||||
(end.tv_usec-start.tv_usec),start.tv_usec,end.tv_usec,
|
||||
(end.tv_sec-start.tv_sec),start.tv_sec,end.tv_sec
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -110,12 +111,12 @@ PerformanceWarning::~PerformanceWarning() {
|
|||
if ((_alwaysDisplay || _renderWarningsOn) && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - _start) / 1000000.0;
|
||||
printLog("%s%s took %lf seconds\n", (_alwaysDisplay ? "" : "WARNING!"), _message, elapsedsec);
|
||||
qDebug("%s%s took %lf seconds\n", (_alwaysDisplay ? "" : "WARNING!"), _message, elapsedsec);
|
||||
} else {
|
||||
printLog("%s%s took %lf milliseconds\n", (_alwaysDisplay ? "" : "WARNING!"), _message, elapsedmsec);
|
||||
qDebug("%s%s took %lf milliseconds\n", (_alwaysDisplay ? "" : "WARNING!"), _message, elapsedmsec);
|
||||
}
|
||||
} else if (_alwaysDisplay) {
|
||||
printLog("%s took %lf milliseconds\n", _message, elapsedmsec);
|
||||
qDebug("%s took %lf milliseconds\n", _message, elapsedmsec);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
#include "Log.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "OctalCode.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "SharedUtil.h"
|
||||
|
@ -64,24 +65,24 @@ void outputBufferBits(unsigned char* buffer, int length, bool withNewLine) {
|
|||
outputBits(buffer[i], false);
|
||||
}
|
||||
if (withNewLine) {
|
||||
printLog("\n");
|
||||
qDebug("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void outputBits(unsigned char byte, bool withNewLine) {
|
||||
if (isalnum(byte)) {
|
||||
printLog("[ %d (%c): ", byte, byte);
|
||||
qDebug("[ %d (%c): ", byte, byte);
|
||||
} else {
|
||||
printLog("[ %d (0x%x): ", byte, byte);
|
||||
qDebug("[ %d (0x%x): ", byte, byte);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
printLog("%d", byte >> (7 - i) & 1);
|
||||
qDebug("%d", byte >> (7 - i) & 1);
|
||||
}
|
||||
printLog(" ] ");
|
||||
qDebug(" ] ");
|
||||
|
||||
if (withNewLine) {
|
||||
printLog("\n");
|
||||
qDebug("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +188,10 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void sharedMessageHandler(QtMsgType type, const char* message) {
|
||||
fprintf(stdout, "%s", message);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Function: createVoxelEditMessage()
|
||||
// Description: creates an "insert" or "remove" voxel message for a voxel code
|
||||
|
@ -385,14 +390,14 @@ void printVoxelCode(unsigned char* voxelCode) {
|
|||
unsigned int voxelSizeInOctets = (voxelSizeInBits/3);
|
||||
unsigned int voxelBufferSize = voxelSizeInBytes+1+3; // 1 for size, 3 for color
|
||||
|
||||
printLog("octets=%d\n",octets);
|
||||
printLog("voxelSizeInBits=%d\n",voxelSizeInBits);
|
||||
printLog("voxelSizeInBytes=%d\n",voxelSizeInBytes);
|
||||
printLog("voxelSizeInOctets=%d\n",voxelSizeInOctets);
|
||||
printLog("voxelBufferSize=%d\n",voxelBufferSize);
|
||||
qDebug("octets=%d\n",octets);
|
||||
qDebug("voxelSizeInBits=%d\n",voxelSizeInBits);
|
||||
qDebug("voxelSizeInBytes=%d\n",voxelSizeInBytes);
|
||||
qDebug("voxelSizeInOctets=%d\n",voxelSizeInOctets);
|
||||
qDebug("voxelBufferSize=%d\n",voxelBufferSize);
|
||||
|
||||
for(int i=0;i<voxelBufferSize;i++) {
|
||||
printLog("i=%d ",i);
|
||||
qDebug("i=%d ",i);
|
||||
outputBits(voxelCode[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
#ifndef __hifi__SharedUtil__
|
||||
#define __hifi__SharedUtil__
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Systime.h"
|
||||
|
@ -66,6 +68,8 @@ void loadRandomIdentifier(unsigned char* identifierBuffer, int numBytes);
|
|||
const char* getCmdOption(int argc, const char * argv[],const char* option);
|
||||
bool cmdOptionExists(int argc, const char * argv[],const char* option);
|
||||
|
||||
void sharedMessageHandler(QtMsgType type, const char* message);
|
||||
|
||||
struct VoxelDetail {
|
||||
float x;
|
||||
float y;
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "UDPSocket.h"
|
||||
#include <fcntl.h>
|
||||
#include <cstdio>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -21,7 +20,9 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "Log.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
sockaddr_in destSockaddr, senderAddress;
|
||||
|
||||
|
@ -123,7 +124,7 @@ UDPSocket::UDPSocket(int listeningPort) : listeningPort(listeningPort), blocking
|
|||
handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (handle <= 0) {
|
||||
printLog("Failed to create socket.\n");
|
||||
qDebug("Failed to create socket.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -136,7 +137,7 @@ UDPSocket::UDPSocket(int listeningPort) : listeningPort(listeningPort), blocking
|
|||
bind_address.sin_port = htons((uint16_t) listeningPort);
|
||||
|
||||
if (bind(handle, (const sockaddr*) &bind_address, sizeof(sockaddr_in)) < 0) {
|
||||
printLog("Failed to bind socket to port %d.\n", listeningPort);
|
||||
qDebug("Failed to bind socket to port %d.\n", listeningPort);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -153,7 +154,7 @@ UDPSocket::UDPSocket(int listeningPort) : listeningPort(listeningPort), blocking
|
|||
tv.tv_usec = 500000;
|
||||
setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv);
|
||||
|
||||
printLog("Created UDP socket listening on port %d.\n", listeningPort);
|
||||
qDebug("Created UDP socket listening on port %d.\n", listeningPort);
|
||||
}
|
||||
|
||||
UDPSocket::~UDPSocket() {
|
||||
|
@ -233,7 +234,7 @@ int UDPSocket::send(sockaddr* destAddress, const void* data, size_t byteLength)
|
|||
0, (sockaddr *) destAddress, sizeof(sockaddr_in));
|
||||
|
||||
if (sent_bytes != byteLength) {
|
||||
printLog("Failed to send packet: %s\n", strerror(errno));
|
||||
qDebug("Failed to send packet: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,20 +6,17 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "UrlReader.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
// (Windows port is incomplete and the build files do not support CURL, yet)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "UrlReader.h"
|
||||
|
||||
//
|
||||
// ATTENTION: A certain part of the implementation lives in inlined code
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "CoverageMap.h"
|
||||
#include <SharedUtil.h>
|
||||
#include <cstring>
|
||||
#include "Log.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "CoverageMap.h"
|
||||
|
||||
int CoverageMap::_mapCount = 0;
|
||||
int CoverageMap::_checkMapRootCalls = 0;
|
||||
|
@ -60,7 +63,7 @@ CoverageMap::CoverageMap(BoundingBox boundingBox, bool isRoot, bool managePolygo
|
|||
{
|
||||
_mapCount++;
|
||||
init();
|
||||
//printLog("CoverageMap created... _mapCount=%d\n",_mapCount);
|
||||
//qDebug("CoverageMap created... _mapCount=%d\n",_mapCount);
|
||||
};
|
||||
|
||||
CoverageMap::~CoverageMap() {
|
||||
|
@ -68,19 +71,19 @@ CoverageMap::~CoverageMap() {
|
|||
};
|
||||
|
||||
void CoverageMap::printStats() {
|
||||
printLog("CoverageMap::printStats()...\n");
|
||||
printLog("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
printLog("_mapCount=%d\n",_mapCount);
|
||||
printLog("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
printLog("_notAllInView=%d\n",_notAllInView);
|
||||
printLog("_maxPolygonsUsed=%d\n",CoverageRegion::_maxPolygonsUsed);
|
||||
printLog("_totalPolygons=%d\n",CoverageRegion::_totalPolygons);
|
||||
printLog("_occlusionTests=%d\n",CoverageRegion::_occlusionTests);
|
||||
printLog("_regionSkips=%d\n",CoverageRegion::_regionSkips);
|
||||
printLog("_tooSmallSkips=%d\n",CoverageRegion::_tooSmallSkips);
|
||||
printLog("_regionFullSkips=%d\n",CoverageRegion::_regionFullSkips);
|
||||
printLog("_outOfOrderPolygon=%d\n",CoverageRegion::_outOfOrderPolygon);
|
||||
printLog("_clippedPolygons=%d\n",CoverageRegion::_clippedPolygons);
|
||||
qDebug("CoverageMap::printStats()...\n");
|
||||
qDebug("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
qDebug("_mapCount=%d\n",_mapCount);
|
||||
qDebug("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
qDebug("_notAllInView=%d\n",_notAllInView);
|
||||
qDebug("_maxPolygonsUsed=%d\n",CoverageRegion::_maxPolygonsUsed);
|
||||
qDebug("_totalPolygons=%d\n",CoverageRegion::_totalPolygons);
|
||||
qDebug("_occlusionTests=%d\n",CoverageRegion::_occlusionTests);
|
||||
qDebug("_regionSkips=%d\n",CoverageRegion::_regionSkips);
|
||||
qDebug("_tooSmallSkips=%d\n",CoverageRegion::_tooSmallSkips);
|
||||
qDebug("_regionFullSkips=%d\n",CoverageRegion::_regionFullSkips);
|
||||
qDebug("_outOfOrderPolygon=%d\n",CoverageRegion::_outOfOrderPolygon);
|
||||
qDebug("_clippedPolygons=%d\n",CoverageRegion::_clippedPolygons);
|
||||
}
|
||||
|
||||
void CoverageMap::erase() {
|
||||
|
@ -99,7 +102,7 @@ void CoverageMap::erase() {
|
|||
}
|
||||
|
||||
if (_isRoot && wantDebugging) {
|
||||
printLog("CoverageMap last to be deleted...\n");
|
||||
qDebug("CoverageMap last to be deleted...\n");
|
||||
printStats();
|
||||
|
||||
CoverageRegion::_maxPolygonsUsed = 0;
|
||||
|
@ -184,7 +187,7 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b
|
|||
if (_isRoot) {
|
||||
_checkMapRootCalls++;
|
||||
|
||||
//printLog("CoverageMap::checkMap()... storeIt=%s\n", debug::valueOf(storeIt));
|
||||
//qDebug("CoverageMap::checkMap()... storeIt=%s\n", debug::valueOf(storeIt));
|
||||
//polygon->printDebugDetails();
|
||||
|
||||
}
|
||||
|
@ -193,7 +196,7 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b
|
|||
// not in view, then we just discard it with a DOESNT_FIT, this saves us time checking values later.
|
||||
if (!polygon->getAllInView()) {
|
||||
_notAllInView++;
|
||||
//printLog("CoverageMap2::checkMap()... V2_OCCLUDED\n");
|
||||
//qDebug("CoverageMap2::checkMap()... V2_OCCLUDED\n");
|
||||
return DOESNT_FIT;
|
||||
}
|
||||
|
||||
|
@ -240,9 +243,9 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b
|
|||
|
||||
/*
|
||||
if (result == STORED)
|
||||
printLog("CoverageMap2::checkMap()... STORED\n");
|
||||
qDebug("CoverageMap2::checkMap()... STORED\n");
|
||||
else
|
||||
printLog("CoverageMap2::checkMap()... OCCLUDED\n");
|
||||
qDebug("CoverageMap2::checkMap()... OCCLUDED\n");
|
||||
*/
|
||||
|
||||
return result;
|
||||
|
@ -265,16 +268,16 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b
|
|||
/*
|
||||
switch (result) {
|
||||
case STORED:
|
||||
printLog("checkMap() = STORED\n");
|
||||
qDebug("checkMap() = STORED\n");
|
||||
break;
|
||||
case NOT_STORED:
|
||||
printLog("checkMap() = NOT_STORED\n");
|
||||
qDebug("checkMap() = NOT_STORED\n");
|
||||
break;
|
||||
case OCCLUDED:
|
||||
printLog("checkMap() = OCCLUDED\n");
|
||||
qDebug("checkMap() = OCCLUDED\n");
|
||||
break;
|
||||
default:
|
||||
printLog("checkMap() = ????? \n");
|
||||
qDebug("checkMap() = ????? \n");
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
@ -287,27 +290,27 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b
|
|||
// any of our child bounding boxes, so we should add it here.
|
||||
if (storeIt) {
|
||||
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
//printLog("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
//qDebug("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
if (storeIn->getPolygonCount() < MAX_POLYGONS_PER_REGION) {
|
||||
storeIn->storeInArray(polygon);
|
||||
//printLog("CoverageMap2::checkMap()... STORED\n");
|
||||
//qDebug("CoverageMap2::checkMap()... STORED\n");
|
||||
return STORED;
|
||||
} else {
|
||||
CoverageRegion::_regionFullSkips++;
|
||||
//printLog("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
//qDebug("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
CoverageRegion::_tooSmallSkips++;
|
||||
//printLog("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
//qDebug("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
//printLog("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
//qDebug("CoverageMap2::checkMap()... NOT_STORED\n");
|
||||
return NOT_STORED;
|
||||
}
|
||||
}
|
||||
//printLog("CoverageMap2::checkMap()... DOESNT_FIT\n");
|
||||
//qDebug("CoverageMap2::checkMap()... DOESNT_FIT\n");
|
||||
return DOESNT_FIT;
|
||||
}
|
||||
|
||||
|
@ -338,11 +341,11 @@ void CoverageRegion::erase() {
|
|||
|
||||
/**
|
||||
if (_polygonCount) {
|
||||
printLog("CoverageRegion::erase()...\n");
|
||||
printLog("_polygonCount=%d\n",_polygonCount);
|
||||
qDebug("CoverageRegion::erase()...\n");
|
||||
qDebug("_polygonCount=%d\n",_polygonCount);
|
||||
_myBoundingBox.printDebugDetails(getRegionName());
|
||||
//for (int i = 0; i < _polygonCount; i++) {
|
||||
// printLog("_polygons[%d]=",i);
|
||||
// qDebug("_polygons[%d]=",i);
|
||||
// _polygons[i]->getBoundingBox().printDebugDetails();
|
||||
//}
|
||||
}
|
||||
|
@ -390,7 +393,7 @@ void CoverageRegion::growPolygonArray() {
|
|||
_polygonDistances = newDistances;
|
||||
_polygonSizes = newSizes;
|
||||
_polygonArraySize = _polygonArraySize + DEFAULT_GROW_SIZE;
|
||||
//printLog("CoverageMap::growPolygonArray() _polygonArraySize=%d...\n",_polygonArraySize);
|
||||
//qDebug("CoverageMap::growPolygonArray() _polygonArraySize=%d...\n",_polygonArraySize);
|
||||
}
|
||||
|
||||
const char* CoverageRegion::getRegionName() const {
|
||||
|
@ -427,15 +430,15 @@ bool CoverageRegion::mergeItemsInArray(VoxelProjectedPolygon* seed, bool seedInA
|
|||
otherPolygon->merge(*seed);
|
||||
|
||||
if (seedInArray) {
|
||||
const int IGNORED = NULL;
|
||||
int* IGNORED_ADDRESS = NULL;
|
||||
// remove this otherOtherPolygon for our polygon array
|
||||
_polygonCount = removeFromSortedArrays((void*)seed,
|
||||
(void**)_polygons, _polygonDistances, IGNORED,
|
||||
(void**)_polygons, _polygonDistances, IGNORED_ADDRESS,
|
||||
_polygonCount, _polygonArraySize);
|
||||
_totalPolygons--;
|
||||
}
|
||||
|
||||
//printLog("_polygonCount=%d\n",_polygonCount);
|
||||
//qDebug("_polygonCount=%d\n",_polygonCount);
|
||||
|
||||
// clean up
|
||||
if (_managePolygons) {
|
||||
|
@ -476,31 +479,31 @@ void CoverageRegion::storeInArray(VoxelProjectedPolygon* polygon) {
|
|||
// in the list. We still check to see if the polygon is "in front" of the target polygon before we test occlusion. Since
|
||||
// sometimes things come out of order.
|
||||
const bool SORT_BY_SIZE = false;
|
||||
const int IGNORED = NULL;
|
||||
const int IGNORED = 0;
|
||||
int* IGNORED_ADDRESS = NULL;
|
||||
if (SORT_BY_SIZE) {
|
||||
// This old code assumes that polygons will always be added in z-buffer order, but that doesn't seem to
|
||||
// be a good assumption. So instead, we will need to sort this by distance. Use a binary search to find the
|
||||
// insertion point in this array, and shift the array accordingly
|
||||
float area = polygon->getBoundingBox().area();
|
||||
float reverseArea = 4.0f - area;
|
||||
//printLog("store by size area=%f reverse area=%f\n", area, reverseArea);
|
||||
//qDebug("store by size area=%f reverse area=%f\n", area, reverseArea);
|
||||
_polygonCount = insertIntoSortedArrays((void*)polygon, reverseArea, IGNORED,
|
||||
(void**)_polygons, _polygonSizes, IGNORED,
|
||||
(void**)_polygons, _polygonSizes, IGNORED_ADDRESS,
|
||||
_polygonCount, _polygonArraySize);
|
||||
} else {
|
||||
const int IGNORED = NULL;
|
||||
_polygonCount = insertIntoSortedArrays((void*)polygon, polygon->getDistance(), IGNORED,
|
||||
(void**)_polygons, _polygonDistances, IGNORED,
|
||||
(void**)_polygons, _polygonDistances, IGNORED_ADDRESS,
|
||||
_polygonCount, _polygonArraySize);
|
||||
}
|
||||
|
||||
// Debugging and Optimization Tuning code.
|
||||
if (_polygonCount > _maxPolygonsUsed) {
|
||||
_maxPolygonsUsed = _polygonCount;
|
||||
//printLog("CoverageRegion new _maxPolygonsUsed reached=%d region=%s\n",_maxPolygonsUsed, getRegionName());
|
||||
//qDebug("CoverageRegion new _maxPolygonsUsed reached=%d region=%s\n",_maxPolygonsUsed, getRegionName());
|
||||
//_myBoundingBox.printDebugDetails("map._myBoundingBox");
|
||||
} else {
|
||||
//printLog("CoverageRegion::storeInArray() _polygonCount=%d region=%s\n",_polygonCount, getRegionName());
|
||||
//qDebug("CoverageRegion::storeInArray() _polygonCount=%d region=%s\n",_polygonCount, getRegionName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "CoverageMapV2.h"
|
||||
#include <SharedUtil.h>
|
||||
#include <cstring>
|
||||
#include "Log.h"
|
||||
|
||||
int CoverageMapV2::_mapCount = 0;
|
||||
int CoverageMapV2::_checkMapRootCalls = 0;
|
||||
|
@ -59,7 +61,7 @@ CoverageMapV2::CoverageMapV2(BoundingBox boundingBox, bool isRoot, bool isCovere
|
|||
{
|
||||
_mapCount++;
|
||||
init();
|
||||
//printLog("CoverageMapV2 created... _mapCount=%d\n",_mapCount);
|
||||
//qDebug("CoverageMapV2 created... _mapCount=%d\n",_mapCount);
|
||||
};
|
||||
|
||||
CoverageMapV2::~CoverageMapV2() {
|
||||
|
@ -76,11 +78,11 @@ void CoverageMapV2::erase() {
|
|||
}
|
||||
|
||||
if (_isRoot && wantDebugging) {
|
||||
printLog("CoverageMapV2 last to be deleted...\n");
|
||||
printLog("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
printLog("_mapCount=%d\n",_mapCount);
|
||||
printLog("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
printLog("_notAllInView=%d\n",_notAllInView);
|
||||
qDebug("CoverageMapV2 last to be deleted...\n");
|
||||
qDebug("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
qDebug("_mapCount=%d\n",_mapCount);
|
||||
qDebug("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
qDebug("_notAllInView=%d\n",_notAllInView);
|
||||
_mapCount = 0;
|
||||
_checkMapRootCalls = 0;
|
||||
_notAllInView = 0;
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
#include <cstring>
|
||||
|
||||
#include <Log.h>
|
||||
#include <QDebug>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "GeometryUtil.h"
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
// These are some useful utilities that vec3 is missing
|
||||
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);
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Tags.h"
|
||||
#include <Log.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <zconf.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <zconf.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "Tags.h"
|
||||
|
||||
Tag::Tag(int tagId, std::stringstream &ss) : _tagId(tagId) {
|
||||
int size = ss.get() << 8 | ss.get();
|
||||
|
||||
|
|
|
@ -3,24 +3,23 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// Simple view frustum class.
|
||||
//
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include "SharedUtil.h"
|
||||
#include "Log.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "CoverageMap.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelConstants.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
ViewFrustum::ViewFrustum() :
|
||||
|
@ -323,40 +322,40 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const {
|
|||
testMatches(compareTo._eyeOffsetOrientation, _eyeOffsetOrientation);
|
||||
|
||||
if (!result && debug) {
|
||||
printLog("ViewFrustum::matches()... result=%s\n", debug::valueOf(result));
|
||||
printLog("%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f\n",
|
||||
qDebug("ViewFrustum::matches()... result=%s\n", debug::valueOf(result));
|
||||
qDebug("%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f\n",
|
||||
(testMatches(compareTo._position,_position) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._position.x, compareTo._position.y, compareTo._position.z,
|
||||
_position.x, _position.y, _position.z );
|
||||
printLog("%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f\n",
|
||||
qDebug("%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f\n",
|
||||
(testMatches(compareTo._direction, _direction) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._direction.x, compareTo._direction.y, compareTo._direction.z,
|
||||
_direction.x, _direction.y, _direction.z );
|
||||
printLog("%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f\n",
|
||||
qDebug("%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f\n",
|
||||
(testMatches(compareTo._up, _up) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._up.x, compareTo._up.y, compareTo._up.z,
|
||||
_up.x, _up.y, _up.z );
|
||||
printLog("%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f\n",
|
||||
qDebug("%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f\n",
|
||||
(testMatches(compareTo._right, _right) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._right.x, compareTo._right.y, compareTo._right.z,
|
||||
_right.x, _right.y, _right.z );
|
||||
printLog("%s -- compareTo._fieldOfView=%f _fieldOfView=%f\n",
|
||||
qDebug("%s -- compareTo._fieldOfView=%f _fieldOfView=%f\n",
|
||||
(testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._fieldOfView, _fieldOfView);
|
||||
printLog("%s -- compareTo._aspectRatio=%f _aspectRatio=%f\n",
|
||||
qDebug("%s -- compareTo._aspectRatio=%f _aspectRatio=%f\n",
|
||||
(testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._aspectRatio, _aspectRatio);
|
||||
printLog("%s -- compareTo._nearClip=%f _nearClip=%f\n",
|
||||
qDebug("%s -- compareTo._nearClip=%f _nearClip=%f\n",
|
||||
(testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._nearClip, _nearClip);
|
||||
printLog("%s -- compareTo._farClip=%f _farClip=%f\n",
|
||||
qDebug("%s -- compareTo._farClip=%f _farClip=%f\n",
|
||||
(testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._farClip, _farClip);
|
||||
printLog("%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f\n",
|
||||
qDebug("%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f\n",
|
||||
(testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._eyeOffsetPosition.x, compareTo._eyeOffsetPosition.y, compareTo._eyeOffsetPosition.z,
|
||||
_eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z);
|
||||
printLog("%s -- compareTo._eyeOffsetOrientation=%f,%f,%f,%f _eyeOffsetOrientation=%f,%f,%f,%f\n",
|
||||
qDebug("%s -- compareTo._eyeOffsetOrientation=%f,%f,%f,%f _eyeOffsetOrientation=%f,%f,%f,%f\n",
|
||||
(testMatches(compareTo._eyeOffsetOrientation, _eyeOffsetOrientation) ? "MATCHES " : "NO MATCH"),
|
||||
compareTo._eyeOffsetOrientation.x, compareTo._eyeOffsetOrientation.y,
|
||||
compareTo._eyeOffsetOrientation.z, compareTo._eyeOffsetOrientation.w,
|
||||
|
@ -419,17 +418,17 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom
|
|||
}
|
||||
|
||||
void ViewFrustum::printDebugDetails() const {
|
||||
printLog("ViewFrustum::printDebugDetails()... \n");
|
||||
printLog("_position=%f,%f,%f\n", _position.x, _position.y, _position.z );
|
||||
printLog("_direction=%f,%f,%f\n", _direction.x, _direction.y, _direction.z );
|
||||
printLog("_up=%f,%f,%f\n", _up.x, _up.y, _up.z );
|
||||
printLog("_right=%f,%f,%f\n", _right.x, _right.y, _right.z );
|
||||
printLog("_fieldOfView=%f\n", _fieldOfView);
|
||||
printLog("_aspectRatio=%f\n", _aspectRatio);
|
||||
printLog("_nearClip=%f\n", _nearClip);
|
||||
printLog("_farClip=%f\n", _farClip);
|
||||
printLog("_eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z );
|
||||
printLog("_eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y, _eyeOffsetOrientation.z,
|
||||
qDebug("ViewFrustum::printDebugDetails()... \n");
|
||||
qDebug("_position=%f,%f,%f\n", _position.x, _position.y, _position.z );
|
||||
qDebug("_direction=%f,%f,%f\n", _direction.x, _direction.y, _direction.z );
|
||||
qDebug("_up=%f,%f,%f\n", _up.x, _up.y, _up.z );
|
||||
qDebug("_right=%f,%f,%f\n", _right.x, _right.y, _right.z );
|
||||
qDebug("_fieldOfView=%f\n", _fieldOfView);
|
||||
qDebug("_aspectRatio=%f\n", _aspectRatio);
|
||||
qDebug("_nearClip=%f\n", _nearClip);
|
||||
qDebug("_farClip=%f\n", _farClip);
|
||||
qDebug("_eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z );
|
||||
qDebug("_eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y, _eyeOffsetOrientation.z,
|
||||
_eyeOffsetOrientation.w );
|
||||
}
|
||||
|
||||
|
|
|
@ -3,18 +3,20 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// Simple view frustum class.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__ViewFrustum__
|
||||
#define __hifi__ViewFrustum__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include "Plane.h"
|
||||
|
||||
#include "AABox.h"
|
||||
#include "Plane.h"
|
||||
|
||||
#include "VoxelProjectedPolygon.h"
|
||||
|
||||
const float DEFAULT_KEYHOLE_RADIUS = 3.0f;
|
||||
|
@ -135,7 +137,7 @@ private:
|
|||
glm::vec3 _nearBottomLeft;
|
||||
glm::vec3 _nearBottomRight;
|
||||
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||
Plane _planes[6]; // How will this be used?
|
||||
::Plane _planes[6]; // How will this be used?
|
||||
|
||||
const char* debugPlaneName (int plane) const;
|
||||
|
||||
|
|
|
@ -21,8 +21,10 @@ const glm::vec3 IDENTITY_UP = glm::vec3( 0.0f, 1.0f, 0.0f);
|
|||
const glm::vec3 IDENTITY_FRONT = glm::vec3( 0.0f, 0.0f,-1.0f);
|
||||
|
||||
const bool LOW_RES_MONO = false; // while in "low res mode" do voxels switch to monochrome
|
||||
const uint64_t CHANGE_FUDGE = 1000 * 200; // useconds of fudge in determining if we want to resend changed voxels
|
||||
|
||||
const int TREE_SCALE = 128;
|
||||
const int TREE_SCALE = 128; // This is the number of meters of the 0.0 to 1.0 voxel universe
|
||||
const float VOXEL_SIZE_SCALE = 50000.0f; // This controls the LOD bigger will make smaller voxels visible at greater distance
|
||||
|
||||
const int NUMBER_OF_CHILDREN = 8;
|
||||
const int MAX_VOXEL_PACKET_SIZE = 1492;
|
||||
|
@ -39,4 +41,4 @@ const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
|||
const float SIXTY_FPS_IN_MILLISECONDS = 1000.0f / 60.0f;
|
||||
const float VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0f; // once a second is fine
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -3,19 +3,21 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 3/13/13.
|
||||
//
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "AABox.h"
|
||||
#include "OctalCode.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "Log.h"
|
||||
#include "VoxelConstants.h"
|
||||
#include "VoxelNode.h"
|
||||
#include "VoxelTree.h"
|
||||
#include "VoxelConstants.h"
|
||||
#include "OctalCode.h"
|
||||
#include "AABox.h"
|
||||
|
||||
VoxelNode::VoxelNode() {
|
||||
unsigned char* rootCode = new unsigned char[1];
|
||||
|
@ -52,6 +54,8 @@ void VoxelNode::init(unsigned char * octalCode) {
|
|||
}
|
||||
|
||||
VoxelNode::~VoxelNode() {
|
||||
notifyDeleteHooks();
|
||||
|
||||
delete[] _octalCode;
|
||||
|
||||
// delete all of this node's children
|
||||
|
@ -257,7 +261,7 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
|||
// if no child, child isn't a leaf, or child doesn't have a color
|
||||
if (!_children[i] || _children[i]->isStagedForDeletion() || !_children[i]->isLeaf() || !_children[i]->isColored()) {
|
||||
allChildrenMatch=false;
|
||||
//printLog("SADNESS child missing or not colored! i=%d\n",i);
|
||||
//qDebug("SADNESS child missing or not colored! i=%d\n",i);
|
||||
break;
|
||||
} else {
|
||||
if (i==0) {
|
||||
|
@ -274,7 +278,7 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
|||
|
||||
|
||||
if (allChildrenMatch) {
|
||||
//printLog("allChildrenMatch: pruning tree\n");
|
||||
//qDebug("allChildrenMatch: pruning tree\n");
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
delete _children[i]; // delete all the child nodes
|
||||
_children[i]=NULL; // set it to NULL
|
||||
|
@ -308,13 +312,13 @@ void VoxelNode::printDebugDetails(const char* label) const {
|
|||
}
|
||||
}
|
||||
|
||||
printLog("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isColored=%s (%d,%d,%d,%d) isDirty=%s shouldRender=%s\n children=", label,
|
||||
qDebug("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isColored=%s (%d,%d,%d,%d) isDirty=%s shouldRender=%s\n children=", label,
|
||||
_box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getSize().x,
|
||||
debug::valueOf(isLeaf()), debug::valueOf(isColored()), getColor()[0], getColor()[1], getColor()[2], getColor()[3],
|
||||
debug::valueOf(isDirty()), debug::valueOf(getShouldRender()));
|
||||
|
||||
outputBits(childBits, false);
|
||||
printLog("\n octalCode=");
|
||||
qDebug("\n octalCode=");
|
||||
printOctalCode(_octalCode);
|
||||
}
|
||||
|
||||
|
@ -385,3 +389,44 @@ float VoxelNode::distanceToPoint(const glm::vec3& point) const {
|
|||
float distance = sqrtf(glm::dot(temp, temp));
|
||||
return distance;
|
||||
}
|
||||
|
||||
VoxelNodeDeleteHook VoxelNode::_hooks[VOXEL_NODE_MAX_DELETE_HOOKS];
|
||||
void* VoxelNode::_hooksExtraData[VOXEL_NODE_MAX_DELETE_HOOKS];
|
||||
int VoxelNode::_hooksInUse = 0;
|
||||
|
||||
int VoxelNode::addDeleteHook(VoxelNodeDeleteHook hook, void* extraData) {
|
||||
// If first use, initialize the _hooks array
|
||||
if (_hooksInUse == 0) {
|
||||
memset(_hooks, 0, sizeof(_hooks));
|
||||
memset(_hooksExtraData, 0, sizeof(_hooksExtraData));
|
||||
}
|
||||
// find first available slot
|
||||
for (int i = 0; i < VOXEL_NODE_MAX_DELETE_HOOKS; i++) {
|
||||
if (!_hooks[i]) {
|
||||
_hooks[i] = hook;
|
||||
_hooksExtraData[i] = extraData;
|
||||
_hooksInUse++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// if we got here, then we're out of room in our hooks, return error
|
||||
return VOXEL_NODE_NO_MORE_HOOKS_AVAILABLE;
|
||||
}
|
||||
|
||||
void VoxelNode::removeDeleteHook(int hookID) {
|
||||
if (_hooks[hookID]) {
|
||||
_hooks[hookID] = NULL;
|
||||
_hooksExtraData[hookID] = NULL;
|
||||
_hooksInUse--;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelNode::notifyDeleteHooks() {
|
||||
if (_hooksInUse > 0) {
|
||||
for (int i = 0; i < VOXEL_NODE_MAX_DELETE_HOOKS; i++) {
|
||||
if (_hooks[i]) {
|
||||
_hooks[i](this, _hooksExtraData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,33 +15,19 @@
|
|||
#include "VoxelConstants.h"
|
||||
|
||||
class VoxelTree; // forward delclaration
|
||||
class VoxelNode; // forward delclaration
|
||||
|
||||
typedef unsigned char colorPart;
|
||||
typedef unsigned char nodeColor[4];
|
||||
typedef unsigned char rgbColor[3];
|
||||
|
||||
// Callback function, for delete hook
|
||||
typedef void (*VoxelNodeDeleteHook)(VoxelNode* node, void* extraData);
|
||||
const int VOXEL_NODE_MAX_DELETE_HOOKS = 100;
|
||||
const int VOXEL_NODE_NO_MORE_HOOKS_AVAILABLE = -1;
|
||||
|
||||
|
||||
class VoxelNode {
|
||||
private:
|
||||
nodeColor _trueColor;
|
||||
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||
nodeColor _currentColor;
|
||||
bool _falseColored;
|
||||
#endif
|
||||
glBufferIndex _glBufferIndex;
|
||||
bool _isDirty;
|
||||
uint64_t _lastChanged;
|
||||
bool _shouldRender;
|
||||
bool _isStagedForDeletion;
|
||||
AABox _box;
|
||||
unsigned char* _octalCode;
|
||||
VoxelNode* _children[8];
|
||||
int _childCount;
|
||||
float _density; // If leaf: density = 1, if internal node: 0-1 density of voxels inside
|
||||
|
||||
void calculateAABox();
|
||||
|
||||
void init(unsigned char * octalCode);
|
||||
|
||||
public:
|
||||
VoxelNode(); // root node constructor
|
||||
VoxelNode(unsigned char * octalCode); // regular constructor
|
||||
|
@ -85,6 +71,7 @@ public:
|
|||
void clearDirtyBit() { _isDirty = false; };
|
||||
bool hasChangedSince(uint64_t time) const { return (_lastChanged > time); };
|
||||
void markWithChangedTime() { _lastChanged = usecTimestampNow(); };
|
||||
uint64_t getLastChanged() const { return _lastChanged; };
|
||||
void handleSubtreeChanged(VoxelTree* myTree);
|
||||
|
||||
glBufferIndex getBufferIndex() const { return _glBufferIndex; };
|
||||
|
@ -117,6 +104,33 @@ public:
|
|||
const nodeColor& getTrueColor() const { return _trueColor; };
|
||||
const nodeColor& getColor() const { return _trueColor; };
|
||||
#endif
|
||||
|
||||
static int addDeleteHook(VoxelNodeDeleteHook hook, void* extraData = NULL);
|
||||
static void removeDeleteHook(int hookID);
|
||||
private:
|
||||
void calculateAABox();
|
||||
void init(unsigned char * octalCode);
|
||||
void notifyDeleteHooks();
|
||||
|
||||
nodeColor _trueColor;
|
||||
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||
nodeColor _currentColor;
|
||||
bool _falseColored;
|
||||
#endif
|
||||
glBufferIndex _glBufferIndex;
|
||||
bool _isDirty;
|
||||
uint64_t _lastChanged;
|
||||
bool _shouldRender;
|
||||
bool _isStagedForDeletion;
|
||||
AABox _box;
|
||||
unsigned char* _octalCode;
|
||||
VoxelNode* _children[8];
|
||||
int _childCount;
|
||||
float _density; // If leaf: density = 1, if internal node: 0-1 density of voxels inside
|
||||
|
||||
static VoxelNodeDeleteHook _hooks[VOXEL_NODE_MAX_DELETE_HOOKS];
|
||||
static void* _hooksExtraData[VOXEL_NODE_MAX_DELETE_HOOKS];
|
||||
static int _hooksInUse;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__VoxelNode__) */
|
||||
|
|
|
@ -9,7 +9,15 @@
|
|||
#include "VoxelNodeBag.h"
|
||||
#include <OctalCode.h>
|
||||
|
||||
VoxelNodeBag::VoxelNodeBag() :
|
||||
_bagElements(NULL),
|
||||
_elementsInUse(0),
|
||||
_sizeOfElementsArray(0) {
|
||||
_hookID = VoxelNode::addDeleteHook(voxelNodeDeleteHook, (void*)this);
|
||||
};
|
||||
|
||||
VoxelNodeBag::~VoxelNodeBag() {
|
||||
VoxelNode::removeDeleteHook(_hookID);
|
||||
deleteAll();
|
||||
}
|
||||
|
||||
|
@ -118,3 +126,9 @@ void VoxelNodeBag::remove(VoxelNode* node) {
|
|||
}
|
||||
}
|
||||
|
||||
void VoxelNodeBag::voxelNodeDeleteHook(VoxelNode* node, void* extraData) {
|
||||
VoxelNodeBag* theBag = (VoxelNodeBag*)extraData;
|
||||
theBag->remove(node); // note: remove can safely handle nodes that aren't in it, so we don't need to check contains()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,11 +19,7 @@
|
|||
class VoxelNodeBag {
|
||||
|
||||
public:
|
||||
VoxelNodeBag() :
|
||||
_bagElements(NULL),
|
||||
_elementsInUse(0),
|
||||
_sizeOfElementsArray(0) {};
|
||||
|
||||
VoxelNodeBag();
|
||||
~VoxelNodeBag();
|
||||
|
||||
void insert(VoxelNode* node); // put a node into the bag
|
||||
|
@ -36,11 +32,14 @@ public:
|
|||
|
||||
void deleteAll();
|
||||
|
||||
static void voxelNodeDeleteHook(VoxelNode* node, void* extraData);
|
||||
|
||||
private:
|
||||
|
||||
VoxelNode** _bagElements;
|
||||
int _elementsInUse;
|
||||
int _sizeOfElementsArray;
|
||||
int _hookID;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__VoxelNodeBag__) */
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include "VoxelProjectedPolygon.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "GeometryUtil.h"
|
||||
#include "Log.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "VoxelProjectedPolygon.h"
|
||||
|
||||
|
||||
glm::vec2 BoundingBox::getVertex(int vertexNumber) const {
|
||||
switch (vertexNumber) {
|
||||
|
@ -88,11 +91,11 @@ void BoundingBox::explandToInclude(const BoundingBox& box) {
|
|||
|
||||
void BoundingBox::printDebugDetails(const char* label) const {
|
||||
if (label) {
|
||||
printLog(label);
|
||||
qDebug() << label;
|
||||
} else {
|
||||
printLog("BoundingBox");
|
||||
qDebug("BoundingBox");
|
||||
}
|
||||
printLog("\n _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]\n",
|
||||
qDebug("\n _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]\n",
|
||||
debug::valueOf(_set), corner.x, corner.y, size.x, size.y, corner.x, corner.y, corner.x+size.x, corner.y+size.y);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,33 +9,34 @@
|
|||
#ifdef _WIN32
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include "SharedUtil.h"
|
||||
#include "Log.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "OctalCode.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "VoxelTree.h"
|
||||
#include "VoxelNodeBag.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include <fstream> // to load voxels from file
|
||||
#include "VoxelConstants.h"
|
||||
#include "CoverageMap.h"
|
||||
#include "SquarePixelMap.h"
|
||||
#include "Tags.h"
|
||||
|
||||
|
||||
#include <glm/gtc/noise.hpp>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "CoverageMap.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "OctalCode.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "SquarePixelMap.h"
|
||||
#include "Tags.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelConstants.h"
|
||||
#include "VoxelNodeBag.h"
|
||||
#include "VoxelTree.h"
|
||||
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel) {
|
||||
const float voxelSizeScale = 50000.0f;
|
||||
return voxelSizeScale / powf(2, renderLevel);
|
||||
return ::VOXEL_SIZE_SCALE / powf(2, renderLevel);
|
||||
}
|
||||
|
||||
float boundaryDistanceSquaredForRenderLevel(unsigned int renderLevel) {
|
||||
const float voxelSizeScale = (50000.0f/TREE_SCALE) * (50000.0f/TREE_SCALE);
|
||||
const float voxelSizeScale = (::VOXEL_SIZE_SCALE/TREE_SCALE) * (::VOXEL_SIZE_SCALE/TREE_SCALE);
|
||||
return voxelSizeScale / powf(2, (2 * renderLevel));
|
||||
}
|
||||
|
||||
|
@ -155,7 +156,7 @@ void VoxelTree::recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseV
|
|||
if (childNode) {
|
||||
// chance to optimize, doesn't need to be actual distance!! Could be distance squared
|
||||
float distanceSquared = childNode->distanceSquareToPoint(point);
|
||||
//printLog("recurseNodeWithOperationDistanceSorted() CHECKING child[%d] point=%f,%f center=%f,%f distance=%f...\n", i, point.x, point.y, center.x, center.y, distance);
|
||||
//qDebug("recurseNodeWithOperationDistanceSorted() CHECKING child[%d] point=%f,%f center=%f,%f distance=%f...\n", i, point.x, point.y, center.x, center.y, distance);
|
||||
//childNode->printDebugDetails("");
|
||||
currentCount = insertIntoSortedArrays((void*)childNode, distanceSquared, i,
|
||||
(void**)&sortedChildren, (float*)&distancesToChildren,
|
||||
|
@ -166,7 +167,7 @@ void VoxelTree::recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseV
|
|||
for (int i = 0; i < currentCount; i++) {
|
||||
VoxelNode* childNode = sortedChildren[i];
|
||||
if (childNode) {
|
||||
//printLog("recurseNodeWithOperationDistanceSorted() PROCESSING child[%d] distance=%f...\n", i, distancesToChildren[i]);
|
||||
//qDebug("recurseNodeWithOperationDistanceSorted() PROCESSING child[%d] distance=%f...\n", i, distancesToChildren[i]);
|
||||
//childNode->printDebugDetails("");
|
||||
recurseNodeWithOperationDistanceSorted(childNode, operation, point, extraData);
|
||||
}
|
||||
|
@ -371,7 +372,6 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s, bool stage) {
|
|||
delete[] octalCode; // cleanup memory
|
||||
}
|
||||
|
||||
|
||||
class DeleteVoxelCodeFromTreeArgs {
|
||||
public:
|
||||
bool stage;
|
||||
|
@ -458,7 +458,7 @@ void VoxelTree::deleteVoxelCodeFromTreeRecursion(VoxelNode* node, void* extraDat
|
|||
// isn't a colored leaf, and the child branch doesn't exist, so there's nothing to do below and
|
||||
// we can safely return, ending the recursion and unwinding
|
||||
if (!childNode) {
|
||||
//printLog("new___deleteVoxelCodeFromTree() child branch doesn't exist, but parent is not a leaf, just unwind\n");
|
||||
//qDebug("new___deleteVoxelCodeFromTree() child branch doesn't exist, but parent is not a leaf, just unwind\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -546,7 +546,7 @@ void VoxelTree::readCodeColorBufferToTreeRecursion(VoxelNode* node, void* extraD
|
|||
}
|
||||
} else {
|
||||
if (!node->isLeaf()) {
|
||||
printLog("WARNING! operation would require deleting children, add Voxel ignored!\n ");
|
||||
qDebug("WARNING! operation would require deleting children, add Voxel ignored!\n ");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -619,13 +619,13 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
|||
}
|
||||
}
|
||||
|
||||
printLog("color mask: ");
|
||||
qDebug("color mask: ");
|
||||
outputBits(colorMask);
|
||||
|
||||
// output the colors we have
|
||||
for (int j = 0; j < NUMBER_OF_CHILDREN; j++) {
|
||||
if (startNode->getChildAtIndex(j) && startNode->getChildAtIndex(j)->isColored()) {
|
||||
printLog("color %d : ",j);
|
||||
qDebug("color %d : ",j);
|
||||
for (int c = 0; c < 3; c++) {
|
||||
outputBits(startNode->getChildAtIndex(j)->getTrueColor()[c],false);
|
||||
}
|
||||
|
@ -641,7 +641,7 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
|||
}
|
||||
}
|
||||
|
||||
printLog("child mask: ");
|
||||
qDebug("child mask: ");
|
||||
outputBits(childMask);
|
||||
|
||||
if (childMask > 0) {
|
||||
|
@ -686,7 +686,7 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
|||
|
||||
int totalBytesRead = 0;
|
||||
if(file.is_open()) {
|
||||
printLog("loading file...\n");
|
||||
qDebug("loading file...\n");
|
||||
bool bail = false;
|
||||
while (!file.eof() && !bail) {
|
||||
file.get(octets);
|
||||
|
@ -711,14 +711,14 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
|||
file.get(colorRead);
|
||||
blue = (unsigned char)colorRead;
|
||||
|
||||
printLog("voxel color from file red:%d, green:%d, blue:%d \n",red,green,blue);
|
||||
qDebug("voxel color from file red:%d, green:%d, blue:%d \n",red,green,blue);
|
||||
vCount++;
|
||||
|
||||
int colorRandomizer = wantColorRandomizer ? randIntInRange (-5, 5) : 0;
|
||||
voxelData[lengthInBytes+1] = std::max(0,std::min(255,red + colorRandomizer));
|
||||
voxelData[lengthInBytes+2] = std::max(0,std::min(255,green + colorRandomizer));
|
||||
voxelData[lengthInBytes+3] = std::max(0,std::min(255,blue + colorRandomizer));
|
||||
printLog("voxel color after rand red:%d, green:%d, blue:%d\n",
|
||||
qDebug("voxel color after rand red:%d, green:%d, blue:%d\n",
|
||||
voxelData[lengthInBytes+1], voxelData[lengthInBytes+2], voxelData[lengthInBytes+3]);
|
||||
|
||||
//printVoxelCode(voxelData);
|
||||
|
@ -819,7 +819,7 @@ void VoxelTree::createSphere(float radius, float xc, float yc, float zc, float v
|
|||
|
||||
if (debug) {
|
||||
int percentComplete = 100 * (thisRadius/radius);
|
||||
printLog("percentComplete=%d\n",percentComplete);
|
||||
qDebug("percentComplete=%d\n",percentComplete);
|
||||
}
|
||||
|
||||
for (float theta=0.0; theta <= 2 * M_PI; theta += angleDelta) {
|
||||
|
@ -835,7 +835,7 @@ void VoxelTree::createSphere(float radius, float xc, float yc, float zc, float v
|
|||
// 2) In all modes, we will use our "outer" color to draw the voxels. Otherwise we will use the average color
|
||||
if (lastLayer) {
|
||||
if (false && debug) {
|
||||
printLog("adding candy shell: theta=%f phi=%f thisRadius=%f radius=%f\n",
|
||||
qDebug("adding candy shell: theta=%f phi=%f thisRadius=%f radius=%f\n",
|
||||
theta, phi, thisRadius,radius);
|
||||
}
|
||||
switch (mode) {
|
||||
|
@ -859,7 +859,7 @@ void VoxelTree::createSphere(float radius, float xc, float yc, float zc, float v
|
|||
green = (unsigned char)std::min(255, std::max(0, (int)(g1 + ((g2 - g1) * gradient))));
|
||||
blue = (unsigned char)std::min(255, std::max(0, (int)(b1 + ((b2 - b1) * gradient))));
|
||||
if (debug) {
|
||||
printLog("perlin=%f gradient=%f color=(%d,%d,%d)\n",perlin, gradient, red, green, blue);
|
||||
qDebug("perlin=%f gradient=%f color=(%d,%d,%d)\n",perlin, gradient, red, green, blue);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -1003,17 +1003,18 @@ bool VoxelTree::findCapsulePenetration(const glm::vec3& start, const glm::vec3&
|
|||
return args.found;
|
||||
}
|
||||
|
||||
|
||||
int VoxelTree::encodeTreeBitstream(VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,
|
||||
EncodeBitstreamParams& params) const {
|
||||
|
||||
// How many bytes have we written so far at this level;
|
||||
int bytesWritten = 0;
|
||||
|
||||
|
||||
// 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 (params.viewFrustum && !node->isInView(*params.viewFrustum)) {
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
// write the octal code
|
||||
int codeLength;
|
||||
if (params.chopLevels) {
|
||||
|
@ -1072,7 +1073,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
if (currentEncodeLevel >= params.maxEncodeLevel) {
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
||||
// caller can pass NULL as viewFrustum if they want everything
|
||||
if (params.viewFrustum) {
|
||||
float distance = node->distanceToCamera(*params.viewFrustum);
|
||||
|
@ -1105,10 +1106,19 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
}
|
||||
}
|
||||
|
||||
// If we were in view, then bail out early!
|
||||
if (wasInView) {
|
||||
// If we were previously in the view, then we normally will return out of here and stop recursing. But
|
||||
// if we're in deltaViewFrustum mode, and this node has changed since it was last sent, then we do
|
||||
// need to send it.
|
||||
if (wasInView && !(params.deltaViewFrustum && node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed,
|
||||
// then we can also bail early and save bits
|
||||
if (!params.forceSendScene && !params.deltaViewFrustum &&
|
||||
!node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
// If the user also asked for occlusion culling, check if this node is occluded, but only if it's not a leaf.
|
||||
// leaf occlusion is handled down below when we check child nodes
|
||||
|
@ -1176,7 +1186,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
if (childNode) {
|
||||
// chance to optimize, doesn't need to be actual distance!! Could be distance squared
|
||||
//float distanceSquared = childNode->distanceSquareToPoint(point);
|
||||
//printLog("recurseNodeWithOperationDistanceSorted() CHECKING child[%d] point=%f,%f center=%f,%f distance=%f...\n", i, point.x, point.y, center.x, center.y, distance);
|
||||
//qDebug("recurseNodeWithOperationDistanceSorted() CHECKING child[%d] point=%f,%f center=%f,%f distance=%f...\n", i, point.x, point.y, center.x, center.y, distance);
|
||||
//childNode->printDebugDetails("");
|
||||
|
||||
float distance = params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0;
|
||||
|
@ -1268,8 +1278,12 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
}
|
||||
}
|
||||
|
||||
// If our child wasn't in view (or we're ignoring wasInView) then we add it to our sending items
|
||||
if (!childWasInView) {
|
||||
// If our child wasn't in view (or we're ignoring wasInView) then we add it to our sending items.
|
||||
// Or if we were previously in the view, but this node has changed since it was last sent, then we do
|
||||
// need to send it.
|
||||
if (!childWasInView ||
|
||||
(params.deltaViewFrustum &&
|
||||
childNode->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
|
||||
childrenColoredBits += (1 << (7 - originalIndex));
|
||||
inViewWithColorCount++;
|
||||
} else {
|
||||
|
@ -1353,7 +1367,6 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
if (oneAtBit(childrenExistInPacketBits, originalIndex)) {
|
||||
|
||||
int thisLevel = currentEncodeLevel;
|
||||
|
||||
// remember this for reshuffling
|
||||
recursiveSliceStarts[originalIndex] = outputBuffer;
|
||||
|
||||
|
@ -1432,7 +1445,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
bool VoxelTree::readFromSVOFile(const char* fileName) {
|
||||
std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate);
|
||||
if(file.is_open()) {
|
||||
printLog("loading file %s...\n", fileName);
|
||||
qDebug("loading file %s...\n", fileName);
|
||||
|
||||
// get file length....
|
||||
unsigned long fileLength = file.tellg();
|
||||
|
@ -1460,14 +1473,14 @@ bool VoxelTree::readFromSchematicFile(const char *fileName) {
|
|||
std::stringstream ss;
|
||||
int err = retrieveData(fileName, ss);
|
||||
if (err && ss.get() != TAG_Compound) {
|
||||
printLog("[ERROR] Invalid schematic file.\n");
|
||||
qDebug("[ERROR] Invalid schematic file.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ss.get();
|
||||
TagCompound schematics(ss);
|
||||
if (!schematics.getBlocksId() || !schematics.getBlocksData()) {
|
||||
printLog("[ERROR] Invalid schematic file.\n");
|
||||
qDebug("[ERROR] Invalid schematic file.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1530,7 +1543,7 @@ bool VoxelTree::readFromSchematicFile(const char *fileName) {
|
|||
}
|
||||
}
|
||||
|
||||
printLog("Created %d voxels from minecraft import.\n", count);
|
||||
qDebug("Created %d voxels from minecraft import.\n", count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1540,7 +1553,7 @@ void VoxelTree::writeToSVOFile(const char* fileName, VoxelNode* node) const {
|
|||
std::ofstream file(fileName, std::ios::out|std::ios::binary);
|
||||
|
||||
if(file.is_open()) {
|
||||
printLog("saving to file %s...\n", fileName);
|
||||
qDebug("saving to file %s...\n", fileName);
|
||||
|
||||
VoxelNodeBag nodeBag;
|
||||
// If we were given a specific node, start from there, otherwise start from root
|
||||
|
|
|
@ -35,6 +35,7 @@ typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
|
|||
#define DONT_CHOP 0
|
||||
#define NO_BOUNDARY_ADJUST 0
|
||||
#define LOW_RES_MOVING_ADJUST 1
|
||||
#define IGNORE_LAST_SENT 0
|
||||
|
||||
class EncodeBitstreamParams {
|
||||
public:
|
||||
|
@ -49,7 +50,8 @@ public:
|
|||
bool wantOcclusionCulling;
|
||||
long childWasInViewDiscarded;
|
||||
int boundaryLevelAdjust;
|
||||
|
||||
uint64_t lastViewFrustumSent;
|
||||
bool forceSendScene;
|
||||
CoverageMap* map;
|
||||
|
||||
EncodeBitstreamParams(
|
||||
|
@ -62,7 +64,9 @@ public:
|
|||
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
|
||||
bool wantOcclusionCulling= NO_OCCLUSION_CULLING,
|
||||
CoverageMap* map = IGNORE_COVERAGE_MAP,
|
||||
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST) :
|
||||
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
|
||||
uint64_t lastViewFrustumSent = IGNORE_LAST_SENT,
|
||||
bool forceSendScene = true) :
|
||||
maxEncodeLevel (maxEncodeLevel),
|
||||
maxLevelReached (0),
|
||||
viewFrustum (viewFrustum),
|
||||
|
@ -74,6 +78,8 @@ public:
|
|||
wantOcclusionCulling (wantOcclusionCulling),
|
||||
childWasInViewDiscarded (0),
|
||||
boundaryLevelAdjust (boundaryLevelAdjust),
|
||||
lastViewFrustumSent (lastViewFrustumSent),
|
||||
forceSendScene (forceSendScene),
|
||||
map (map)
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
|||
set(TARGET_NAME pairing-server)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# link the shared hifi library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
|
|
|
@ -7,7 +7,7 @@ set(TARGET_NAME space-server)
|
|||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
|
@ -14,7 +14,7 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
|
|||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# link in the shared library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
|
|
|
@ -14,7 +14,7 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
|
|||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# link in the shared library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#include "PacketHeaders.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "VoxelNodeData.h"
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
@ -19,11 +20,11 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
|
|||
_maxLevelReachedInLastSearch(1),
|
||||
_lastTimeBagEmpty(0),
|
||||
_viewFrustumChanging(false),
|
||||
_viewFrustumJustStoppedChanging(true),
|
||||
_currentPacketIsColor(true)
|
||||
{
|
||||
_voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
||||
_voxelPacketAt = _voxelPacket;
|
||||
|
||||
resetVoxelPacket();
|
||||
}
|
||||
|
||||
|
@ -69,10 +70,25 @@ bool VoxelNodeData::updateCurrentViewFrustum() {
|
|||
_currentViewFrustum.calculate();
|
||||
currentViewFrustumChanged = true;
|
||||
}
|
||||
|
||||
// When we first detect that the view stopped changing, we record this.
|
||||
// but we don't change it back to false until we've completely sent this
|
||||
// scene.
|
||||
if (_viewFrustumChanging && !currentViewFrustumChanged) {
|
||||
_viewFrustumJustStoppedChanging = true;
|
||||
}
|
||||
_viewFrustumChanging = currentViewFrustumChanged;
|
||||
return currentViewFrustumChanged;
|
||||
}
|
||||
|
||||
void VoxelNodeData::setViewSent(bool viewSent) {
|
||||
_viewSent = viewSent;
|
||||
if (viewSent) {
|
||||
_viewFrustumJustStoppedChanging = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VoxelNodeData::updateLastKnownViewFrustum() {
|
||||
bool frustumChanges = !_lastKnownViewFrustum.matches(_currentViewFrustum);
|
||||
|
||||
|
@ -80,5 +96,9 @@ void VoxelNodeData::updateLastKnownViewFrustum() {
|
|||
// save our currentViewFrustum into our lastKnownViewFrustum
|
||||
_lastKnownViewFrustum = _currentViewFrustum;
|
||||
}
|
||||
|
||||
// save that we know the view has been sent.
|
||||
uint64_t now = usecTimestampNow();
|
||||
setLastTimeBagEmpty(now); // is this what we want? poor names
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,11 @@ public:
|
|||
void updateLastKnownViewFrustum();
|
||||
|
||||
bool getViewSent() const { return _viewSent; };
|
||||
void setViewSent(bool viewSent) { _viewSent = viewSent; }
|
||||
void setViewSent(bool viewSent);
|
||||
|
||||
bool getViewFrustumChanging() const { return _viewFrustumChanging; };
|
||||
bool getViewFrustumJustStoppedChanging() const { return _viewFrustumJustStoppedChanging; };
|
||||
|
||||
|
||||
uint64_t getLastTimeBagEmpty() const { return _lastTimeBagEmpty; };
|
||||
void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; };
|
||||
|
@ -69,6 +73,7 @@ private:
|
|||
ViewFrustum _lastKnownViewFrustum;
|
||||
uint64_t _lastTimeBagEmpty;
|
||||
bool _viewFrustumChanging;
|
||||
bool _viewFrustumJustStoppedChanging;
|
||||
bool _currentPacketIsColor;
|
||||
};
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ const int MIN_BRIGHTNESS = 64;
|
|||
const float DEATH_STAR_RADIUS = 4.0;
|
||||
const float MAX_CUBE = 0.05f;
|
||||
|
||||
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
|
||||
int PACKETS_PER_CLIENT_PER_INTERVAL = 30;
|
||||
const int SENDING_TIME_TO_SPARE = 20 * 1000; // usec of sending interval to spare for calculating voxels
|
||||
const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps
|
||||
int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
|
||||
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels
|
||||
|
||||
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
||||
|
||||
|
@ -173,10 +173,10 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
// If the current view frustum has changed OR we have nothing to send, then search against
|
||||
// the current view frustum for things to send.
|
||||
if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (::debugVoxelSending) {
|
||||
printf("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n",
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()));
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (nodeData->getLastTimeBagEmpty() > 0) {
|
||||
float elapsedSceneSend = (now - nodeData->getLastTimeBagEmpty()) / 1000000.0f;
|
||||
if (viewFrustumChanged) {
|
||||
|
@ -188,15 +188,24 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
debug::valueOf(nodeData->getWantOcclusionCulling()), debug::valueOf(wantDelta),
|
||||
debug::valueOf(wantColor));
|
||||
}
|
||||
nodeData->setLastTimeBagEmpty(now); // huh? why is this inside debug? probably not what we want
|
||||
}
|
||||
|
||||
// if our view has changed, we need to reset these things...
|
||||
if (viewFrustumChanged) {
|
||||
nodeData->nodeBag.deleteAll();
|
||||
nodeData->map.erase();
|
||||
}
|
||||
|
||||
if (!viewFrustumChanged && !nodeData->getWantDelta()) {
|
||||
// only set our last sent time if we weren't resetting due to frustum change
|
||||
uint64_t now = usecTimestampNow();
|
||||
nodeData->setLastTimeBagEmpty(now);
|
||||
if (::debugVoxelSending) {
|
||||
printf("ENTIRE SCENE SENT! nodeData->setLastTimeBagEmpty(now=[%lld])\n", now);
|
||||
}
|
||||
}
|
||||
|
||||
// This is the start of "resending" the scene.
|
||||
nodeData->nodeBag.insert(serverTree.rootNode);
|
||||
}
|
||||
|
||||
|
@ -233,15 +242,13 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
|
||||
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor,
|
||||
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
|
||||
wantOcclusionCulling, coverageMap, boundaryLevelAdjust);
|
||||
|
||||
wantOcclusionCulling, coverageMap, boundaryLevelAdjust,
|
||||
nodeData->getLastTimeBagEmpty(),
|
||||
nodeData->getViewFrustumJustStoppedChanging());
|
||||
|
||||
bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
||||
nodeData->nodeBag, params);
|
||||
|
||||
if (::debugVoxelSending && wantDelta) {
|
||||
printf("encodeTreeBitstream() childWasInViewDiscarded=%ld\n", params.childWasInViewDiscarded);
|
||||
}
|
||||
|
||||
if (nodeData->getAvailable() >= bytesWritten) {
|
||||
nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||
} else {
|
||||
|
@ -375,9 +382,10 @@ void attachVoxelNodeDataToNode(Node* newNode) {
|
|||
}
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
pthread_mutex_init(&::treeLock, NULL);
|
||||
|
||||
|
||||
qInstallMsgHandler(sharedMessageHandler);
|
||||
|
||||
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, VOXEL_LISTEN_PORT);
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
|
||||
|
|
Loading…
Reference in a new issue