diff --git a/.gitignore b/.gitignore index cebf9eb113..9dc509bc19 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ CMakeFiles/ CMakeScripts/ cmake_install.cmake build/ +Makefile # Xcode *.xcodeproj diff --git a/CMakeLists.txt b/CMakeLists.txt index 8af8081975..d803ff373e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 2.8) project(hifi) +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{QT_CMAKE_PREFIX_PATH}) + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) + add_subdirectory(animation-server) add_subdirectory(avatar-mixer) add_subdirectory(audio-mixer) diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index b7d0af7499..79bf16e1a0 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -3,13 +3,13 @@ MACRO(SETUP_HIFI_LIBRARY TARGET) # grab the implemenation and header files file(GLOB LIB_SRCS src/*.h src/*.cpp) + set(LIB_SRCS ${LIB_SRCS} ${WRAPPED_SRCS}) # create a library and set the property so it can be referenced later 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}") + find_package(Qt5Core REQUIRED) + qt5_use_modules(${TARGET} Core) target_link_libraries(${TARGET} ${QT_LIBRARIES}) ENDMACRO(SETUP_HIFI_LIBRARY _target) \ No newline at end of file diff --git a/cmake/macros/SetupHifiProject.cmake b/cmake/macros/SetupHifiProject.cmake index 8360dc66b6..455ca89701 100644 --- a/cmake/macros/SetupHifiProject.cmake +++ b/cmake/macros/SetupHifiProject.cmake @@ -8,9 +8,8 @@ MACRO(SETUP_HIFI_PROJECT TARGET INCLUDE_QT) add_executable(${TARGET} ${TARGET_SRCS}) IF (${INCLUDE_QT}) - find_package(Qt4 REQUIRED QtCore) - include(${QT_USE_FILE}) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}") + find_package(Qt5Core REQUIRED) + qt5_use_modules(${TARGET} Core) ENDIF() target_link_libraries(${TARGET} ${QT_LIBRARIES}) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt old mode 100755 new mode 100644 index ae87d53939..17967c5f42 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -67,18 +67,16 @@ if (APPLE) endif (APPLE) -find_package(Qt4 REQUIRED QtCore QtGui QtNetwork QtOpenGL QtWebKit QtSvg) -include(${QT_USE_FILE}) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}") +find_package(Qt5Core REQUIRED) +find_package(Qt5Gui REQUIRED) +find_package(Qt5Network REQUIRED) +find_package(Qt5OpenGL REQUIRED) +find_package(Qt5Svg REQUIRED) set(QUAZIP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/quazip) add_subdirectory(external/fervor/) include_directories(external/fervor/) -# run qt moc on qt-enabled headers -qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/Webcam.h src/avatar/AvatarVoxelSystem.h - src/avatar/Face.h src/ui/BandwidthDialog.h src/ui/VoxelStatsDialog.h) - # create the executable, make it a bundle on OS X add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS}) @@ -110,6 +108,8 @@ if (OPENNI_FOUND) target_link_libraries(${TARGET_NAME} ${OPENNI_LIBRARIES}) endif (OPENNI_FOUND) +qt5_use_modules(${TARGET_NAME} Core Gui Network OpenGL Svg) + # include headers for interface and InterfaceConfig. include_directories( ${PROJECT_SOURCE_DIR}/src @@ -130,8 +130,7 @@ include_directories( SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENCV_INCLUDE_DIRS}") target_link_libraries( - ${TARGET_NAME} - ${QT_LIBRARIES} + ${TARGET_NAME} ${LIBVPX_LIBRARIES} ${MOTIONDRIVER_LIBRARIES} ${OPENCV_LIBRARIES} diff --git a/interface/external/fervor/CMakeLists.txt b/interface/external/fervor/CMakeLists.txt index f257bb4431..a8b37ba9d0 100644 --- a/interface/external/fervor/CMakeLists.txt +++ b/interface/external/fervor/CMakeLists.txt @@ -1,21 +1,26 @@ cmake_minimum_required(VERSION 2.8) project(Fervor) -find_package(Qt4 REQUIRED) + +find_package(Qt5Core REQUIRED) +find_package(Qt5Network REQUIRED) +find_package(Qt5WebKit REQUIRED) +find_package(Qt5Widgets REQUIRED) add_definitions(-DFV_GUI) file(GLOB FERVOR_SOURCES *.cpp) file(GLOB FERVOR_HEADERS *.h) +file(GLOB FERVOR_UI *.ui) + +qt5_wrap_ui(FERVOR_WRAPPED_UI ${FERVOR_UI}) + LIST(GET FERVOR_HEADERS 1 FIRST_HEADER) GET_FILENAME_COMPONENT(HEADER_PATH ${FIRST_HEADER} PATH) list(REMOVE_ITEM FERVOR_HEADERS ${HEADER_PATH}/fvversioncomparator.h) file(GLOB FERVOR_UI *.ui) -qt4_wrap_ui(FERVOR_WRAPPED_UI ${FERVOR_UI}) -qt4_wrap_cpp(FERVOR_MOC_SOURCES ${FERVOR_HEADERS}) - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/") find_package(Quazip REQUIRED) @@ -25,4 +30,6 @@ include_directories( ) add_library(fervor ${FERVOR_SOURCES} ${FERVOR_HEADERS} ${FERVOR_MOC_SOURCES} ${FERVOR_WRAPPED_UI}) -target_link_libraries(fervor ${QUAZIP_LIBRARIES}) \ No newline at end of file +target_link_libraries(fervor ${QUAZIP_LIBRARIES}) + +qt5_use_modules(fervor Core Network Widgets WebKit) \ No newline at end of file diff --git a/interface/external/fervor/fvplatform.h b/interface/external/fervor/fvplatform.h index a527518097..a98f04a1ce 100755 --- a/interface/external/fervor/fvplatform.h +++ b/interface/external/fervor/fvplatform.h @@ -1,7 +1,7 @@ #ifndef FVPLATFORM_H #define FVPLATFORM_H -#include +#include class FvPlatform : public QObject { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8150eb5632..b6c2187256 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -164,9 +164,9 @@ void GLCanvas::wheelEvent(QWheelEvent* event) { Application::getInstance()->wheelEvent(event); } -void messageHandler(QtMsgType type, const char* message) { - fprintf(stdout, "%s", message); - LogDisplay::instance.addMessage(message); +void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { + fprintf(stdout, "%s", message.toLocal8Bit().constData()); + LogDisplay::instance.addMessage(message.toLocal8Bit().constData()); } Application::Application(int& argc, char** argv, timeval &startup_time) : @@ -224,7 +224,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _applicationStartupTime = startup_time; _window->setWindowTitle("Interface"); - qInstallMsgHandler(messageHandler); + qInstallMessageHandler(messageHandler); unsigned int listenPort = 0; // bind to an ephemeral port by default const char** constArgv = const_cast(argv); @@ -566,6 +566,11 @@ void Application::keyPressEvent(QKeyEvent* event) { } return; } + + //this is for switching between modes for the leap rave glove test + if (_simulateLeapHand->isChecked() || _testRaveGlove->isChecked()) { + _myAvatar.getHand().setRaveGloveEffectsMode((QKeyEvent*)event); + } bool shifted = event->modifiers().testFlag(Qt::ShiftModifier); switch (event->key()) { @@ -1226,7 +1231,7 @@ void Application::editPreferences() { if (domainServerHostname->text().size() > 0) { // the user input a new hostname, use that - newHostname = domainServerHostname->text().toAscii(); + newHostname = domainServerHostname->text().toLocal8Bit(); } else { // the user left the field blank, use the default hostname newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME); @@ -1522,12 +1527,12 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) { } void Application::exportVoxels() { - QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); + QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); QString suggestedName = desktopLocation.append("/voxels.svo"); QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), suggestedName, tr("Sparse Voxel Octree Files (*.svo)")); - QByteArray fileNameAscii = fileNameString.toAscii(); + QByteArray fileNameAscii = fileNameString.toLocal8Bit(); const char* fileName = fileNameAscii.data(); VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode) { @@ -1542,11 +1547,11 @@ void Application::exportVoxels() { const char* IMPORT_FILE_TYPES = "Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)"; void Application::importVoxelsToClipboard() { - QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); + QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels to Clipboard"), desktopLocation, tr(IMPORT_FILE_TYPES)); - QByteArray fileNameAscii = fileNameString.toAscii(); + QByteArray fileNameAscii = fileNameString.toLocal8Bit(); const char* fileName = fileNameAscii.data(); _clipboardTree.eraseAllVoxels(); @@ -1576,11 +1581,11 @@ void Application::importVoxelsToClipboard() { } void Application::importVoxels() { - QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); + QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation, tr(IMPORT_FILE_TYPES)); - QByteArray fileNameAscii = fileNameString.toAscii(); + QByteArray fileNameAscii = fileNameString.toLocal8Bit(); const char* fileName = fileNameAscii.data(); VoxelTree importVoxels; @@ -1994,8 +1999,11 @@ const float MAX_VOXEL_EDIT_DISTANCE = 20.0f; const float HEAD_SPHERE_RADIUS = 0.07; +static uint16_t DEFAULT_NODE_ID_REF = 1; + + bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, - glm::vec3& eyePosition, uint16_t& nodeID) { + glm::vec3& eyePosition, uint16_t& nodeID = DEFAULT_NODE_ID_REF) { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { @@ -2052,8 +2060,8 @@ void Application::update(float deltaTime) { // Set where I am looking based on my mouse ray (so that other people can see) glm::vec3 eyePosition; - uint16_t ignored; - _isLookingAtOtherAvatar = isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition, ignored); + + _isLookingAtOtherAvatar = isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition); if (_isLookingAtOtherAvatar) { // If the mouse is over another avatar's head... glm::vec3 myLookAtFromMouse(eyePosition); @@ -2353,8 +2361,8 @@ void Application::updateAvatar(float deltaTime) { _viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection); glm::vec3 eyePosition; - uint16_t ignored; - _isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition, ignored); + + _isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition); if (_isLookingAtOtherAvatar) { glm::vec3 myLookAtFromMouse(eyePosition); _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); @@ -2393,7 +2401,7 @@ void Application::updateAvatar(float deltaTime) { NodeList* nodeList = NodeList::getInstance(); if (nodeList->getOwnerID() != UNKNOWN_NODE_ID) { // if I know my ID, send head/hand data to the avatar mixer and voxel server - unsigned char broadcastString[200]; + unsigned char broadcastString[MAX_PACKET_SIZE]; unsigned char* endOfBroadcastStringWrite = broadcastString; endOfBroadcastStringWrite += populateTypeAndVersion(endOfBroadcastStringWrite, PACKET_TYPE_HEAD_DATA); @@ -2764,13 +2772,12 @@ void Application::displaySide(Camera& whichCamera) { _particleSystem.render(); } } - + // Render the world box if (!_lookingInMirror->isChecked() && _renderStatsOn->isChecked()) { render_world_box(); } // brad's frustum for debugging if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum); - } void Application::displayOverlay() { @@ -3668,7 +3675,7 @@ void Application::saveSettings(QSettings* settings) { } void Application::importSettings() { - QString locationDir(QDesktopServices::displayName(QDesktopServices::DesktopLocation)); + QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); QString fileName = QFileDialog::getOpenFileName(_window, tr("Open .ini config file"), locationDir, @@ -3680,7 +3687,7 @@ void Application::importSettings() { } void Application::exportSettings() { - QString locationDir(QDesktopServices::displayName(QDesktopServices::DesktopLocation)); + QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); QString fileName = QFileDialog::getSaveFileName(_window, tr("Save .ini config file"), locationDir, @@ -3693,56 +3700,57 @@ void Application::exportSettings() { } - void Application::updateParticleSystem(float deltaTime) { if (!_particleSystemInitialized) { + + const int LIFESPAN_IN_SECONDS = 100000.0f; + const float EMIT_RATE_IN_SECONDS = 10000.0; // 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); + + _particleSystem.setEmitterPosition (_coolDemoParticleEmitter, particleEmitterPosition); + _particleSystem.setEmitterParticleLifespan(_coolDemoParticleEmitter, LIFESPAN_IN_SECONDS); + _particleSystem.setEmitterThrust (_coolDemoParticleEmitter, 0.0f); + _particleSystem.setEmitterRate (_coolDemoParticleEmitter, EMIT_RATE_IN_SECONDS); // to emit a pile o particles now } // signal that the particle system has been initialized _particleSystemInitialized = true; } else { // update the particle system - - static float t = 0.0f; - t += deltaTime; + + static bool emitting = true; + static float effectsTimer = 0.0f; + effectsTimer += 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.setEmitterDirection(_coolDemoParticleEmitter, glm::vec3(0.0f, 1.0f, 0.0f)); 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.gravity = 0.0f + 0.05f * sinf( effectsTimer * 0.52f ); + attributes.airFriction = 2.5 + 2.0f * sinf( effectsTimer * 0.32f ); + attributes.jitter = 0.05f + 0.05f * sinf( effectsTimer * 0.42f ); + attributes.emitterAttraction = 0.015f + 0.015f * cosf( effectsTimer * 0.6f ); + attributes.tornadoForce = 0.0f + 0.03f * sinf( effectsTimer * 0.7f ); + attributes.neighborAttraction = 0.1f + 0.1f * cosf( effectsTimer * 0.8f ); + attributes.neighborRepulsion = 0.2f + 0.2f * sinf( effectsTimer * 0.4f ); attributes.bounce = 1.0f; attributes.usingCollisionSphere = true; attributes.collisionSpherePosition = glm::vec3( 5.0f, 0.5f, 5.0f ); attributes.collisionSphereRadius = 0.5f; + attributes.usingCollisionPlane = true; + attributes.collisionPlanePosition = glm::vec3( 5.0f, 0.0f, 5.0f ); + attributes.collisionPlaneNormal = glm::vec3( 0.0f, 1.0f, 0.0f ); if (attributes.gravity < 0.0f) { attributes.gravity = 0.0f; @@ -3753,6 +3761,15 @@ void Application::updateParticleSystem(float deltaTime) { _particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f)); _particleSystem.simulate(deltaTime); + + const float EMIT_RATE_IN_SECONDS = 0.0; + + if (_coolDemoParticleEmitter != -1) { + if (emitting) { + _particleSystem.setEmitterRate(_coolDemoParticleEmitter, EMIT_RATE_IN_SECONDS); // stop emitter + emitting = false; + } + } } } diff --git a/interface/src/LeapManager.cpp b/interface/src/LeapManager.cpp old mode 100755 new mode 100644 diff --git a/interface/src/ParticleSystem.cpp b/interface/src/ParticleSystem.cpp index 9dcdbe5f06..5e2b92bb64 100644 --- a/interface/src/ParticleSystem.cpp +++ b/interface/src/ParticleSystem.cpp @@ -11,77 +11,89 @@ #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; +const float DEFAULT_PARTICLE_RADIUS = 0.01f; +const float DEFAULT_PARTICLE_BOUNCE = 1.0f; +const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f; +const float DEFAULT_PARTICLE_LIFESPAN = 1.0f; +const int DEFAULT_PARTICLE_SPHERE_RESOLUTION = 6; +const float DEFAULT_EMITTER_RENDER_LENGTH = 0.2f; ParticleSystem::ParticleSystem() { + _timer = 0.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); + + Emitter * e = &_emitter[emitterIndex]; + e->position = glm::vec3(0.0f, 0.0f, 0.0f); + e->previousPosition = glm::vec3(0.0f, 0.0f, 0.0f); + e->direction = glm::vec3(0.0f, 1.0f, 0.0f); + e->visible = false; + e->particleResolution = DEFAULT_PARTICLE_SPHERE_RESOLUTION; + e->particleLifespan = DEFAULT_PARTICLE_LIFESPAN; + e->showingBaseParticle = false; + e->emitReserve = 0.0; + e->thrust = 0.0f; + e->rate = 0.0f; + e->currentParticle = 0; + e->particleRenderStyle = PARTICLE_RENDER_STYLE_SPHERE; + e->numParticlesEmittedThisTime = 0; - for (int lifeStage = 0; lifeStageradius = 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 (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage++) { + setParticleAttributesToDefault(&_emitter[emitterIndex].particleAttributes[lifeStage]); } }; 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); + _particle[p].alive = false; + _particle[p].age = 0.0f; + _particle[p].radius = 0.0f; + _particle[p].emitterIndex = 0; + _particle[p].previousParticle = NULL_PARTICLE; + _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; + if (_numEmitters < MAX_EMITTERS) { + _numEmitters ++; + return _numEmitters - 1; } - return _numEmitters - 1; + return NULL_EMITTER; } void ParticleSystem::simulate(float deltaTime) { + _timer += deltaTime; + + // emit particles + for (int e = 0; e < _numEmitters; e++) { + + assert(e >= 0); + assert(e <= MAX_EMITTERS); + assert(_emitter[e].rate >= 0); + + _emitter[e].emitReserve += _emitter[e].rate * deltaTime; + _emitter[e].numParticlesEmittedThisTime = (int)_emitter[e].emitReserve; + _emitter[e].emitReserve -= _emitter[e].numParticlesEmittedThisTime; + + for (int p = 0; p < _emitter[e].numParticlesEmittedThisTime; p++) { + float timeFraction = (float)p / (float)_emitter[e].numParticlesEmittedThisTime; + createParticle(e, timeFraction); + } + } + // update particles - for (unsigned int p = 0; p < _numParticles; p++) { - if (_particle[p].alive) { - if (_particle[p].age > _particle[p].lifespan) { + + for (int p = 0; p < MAX_PARTICLES; p++) { + if (_particle[p].alive) { + if (_particle[p].age > _emitter[_particle[p].emitterIndex].particleLifespan) { killParticle(p); } else { updateParticle(p, deltaTime); @@ -90,55 +102,91 @@ void ParticleSystem::simulate(float deltaTime) { } } -void ParticleSystem::emitParticlesNow(int e, int num, glm::vec3 velocity, float lifespan) { - - for (unsigned int p = 0; p < num; p++) { - createParticle(e, velocity, lifespan); - } -} - -void ParticleSystem::createParticle(int e, glm::vec3 velocity, float lifespan) { +void ParticleSystem::createParticle(int e, float timeFraction) { 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); + + _particle[p].emitterIndex = e; + _particle[p].alive = true; + _particle[p].age = 0.0f; + _particle[p].velocity = _emitter[e].direction * _emitter[e].thrust; + _particle[p].position = _emitter[e].previousPosition + timeFraction * (_emitter[e].position - _emitter[e].previousPosition); + _particle[p].radius = _emitter[e].particleAttributes[PARTICLE_LIFESTAGE_0].radius; + _particle[p].color = _emitter[e].particleAttributes[PARTICLE_LIFESTAGE_0].color; + _particle[p].previousParticle = NULL_PARTICLE; - return; + if (_particle[_emitter[e].currentParticle].alive) { + if (_particle[_emitter[e].currentParticle].emitterIndex == e) { + _particle[p].previousParticle = _emitter[e].currentParticle; + } + } + + _emitter[e].currentParticle = p; + + break; } } } void ParticleSystem::killParticle(int p) { - assert( p >= 0); - assert( p < MAX_PARTICLES); - assert( _numParticles > 0); + assert(p >= 0); + assert(p < MAX_PARTICLES); - _particle[p].alive = false; - _numParticles --; -} + _particle[p].alive = false; + _particle[p].previousParticle = NULL_PARTICLE; + _particle[p].position = _emitter[_particle[p].emitterIndex].position; + _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); + _particle[p].age = 0.0f; + _particle[p].emitterIndex = NULL_PARTICLE; + _particle[p].color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); + _particle[p].radius = 0.0f; + } + + +void ParticleSystem::setEmitterPosition(int emitterIndex, glm::vec3 position) { + _emitter[emitterIndex].previousPosition = _emitter[emitterIndex].position; + _emitter[emitterIndex].position = position; +} void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) { - for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++ ) { - setParticleAttributes(emitterIndex, lifeStage, attributes); + for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++) { + setParticleAttributes(emitterIndex, (ParticleLifeStage)lifeStage, attributes); } } -void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, ParticleAttributes attributes) { +void ParticleSystem::setParticleAttributesToDefault(ParticleAttributes * a) { + + 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; + a->collisionPlaneNormal = _upDirection; + a->collisionPlanePosition = glm::vec3(0.0f, 0.0f, 0.0f); + a->usingCollisionPlane = false; + a->modulationAmplitude = 0.0f; + a->modulationRate = 0.0; + a->modulationStyle = COLOR_MODULATION_STYLE_NULL; + +} + + +void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes) { + + assert(lifeStage >= 0); + assert(lifeStage < NUM_PARTICLE_LIFE_STAGES); ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage]; @@ -155,155 +203,196 @@ void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, Part a->usingCollisionSphere = attributes.usingCollisionSphere; a->collisionSpherePosition = attributes.collisionSpherePosition; a->collisionSphereRadius = attributes.collisionSphereRadius; + a->usingCollisionPlane = attributes.usingCollisionPlane; + a->collisionPlanePosition = attributes.collisionPlanePosition; + a->collisionPlaneNormal = attributes.collisionPlaneNormal; + a->modulationAmplitude = attributes.modulationAmplitude; + a->modulationRate = attributes.modulationRate; + a->modulationStyle = attributes.modulationStyle; } + void ParticleSystem::updateParticle(int p, float 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 - ( - -j * ONE_HALF + j * randFloat(), - -j * ONE_HALF + j * randFloat(), - -j * ONE_HALF + j * randFloat() - ) * deltaTime; - - // apply attraction to home position - 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 == _numParticles ) { - neighbor = 0; - } - - 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; + assert(_particle[p].age <= myEmitter.particleLifespan); - 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 emitterUp = myEmitter.rotation * IDENTITY_UP; - - glm::vec3 tornadoDirection = glm::cross(vectorToHome, emitterUp); - _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime; + float ageFraction = 0.0f; + int lifeStage = 0; + float lifeStageFraction = 0.0f; - // apply air friction - 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 { - _particle[p].velocity *= drag; - } - - // apply gravity - _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime; - - // update position by velocity - _particle[p].position += _particle[p].velocity; - - // collision with ground - if (_particle[p].position.y < _particle[p].radius) { - _particle[p].position.y = _particle[p].radius; + if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) { - if (_particle[p].velocity.y < 0.0f) { - _particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce; - } - } - - // collision with sphere - 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) { + ageFraction = _particle[p].age / myEmitter.particleLifespan; + lifeStage = (int)(ageFraction * (NUM_PARTICLE_LIFE_STAGES - 1)); + lifeStageFraction = ageFraction * (NUM_PARTICLE_LIFE_STAGES - 1) - lifeStage; + + // adjust radius + _particle[p].radius + = myEmitter.particleAttributes[lifeStage ].radius * (1.0f - lifeStageFraction) + + myEmitter.particleAttributes[lifeStage+1].radius * lifeStageFraction; - if (distanceToSphereCenter > 0.0f){ - glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter; - _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius; + // apply random jitter + float j = myEmitter.particleAttributes[lifeStage].jitter; + _particle[p].velocity += + glm::vec3 + ( + -j * ONE_HALF + j * randFloat(), + -j * ONE_HALF + j * randFloat(), + -j * ONE_HALF + j * randFloat() + ) * deltaTime; + + // apply attraction to home position + 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 == MAX_PARTICLES) { + neighbor = 0; + } + + 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)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime; + } + } + + // apply tornado force + glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.direction); + _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime; + + // apply air friction + 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 { + _particle[p].velocity *= drag; + } + + // apply gravity + _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime; + + // update position by velocity + _particle[p].position += _particle[p].velocity; + + // collision with the plane surface + if (myEmitter.particleAttributes[lifeStage].usingCollisionPlane) { + glm::vec3 vectorFromParticleToPlanePosition = _particle[p].position - myEmitter.particleAttributes[lifeStage].collisionPlanePosition; + glm::vec3 normal = myEmitter.particleAttributes[lifeStage].collisionPlaneNormal; + float dot = glm::dot(vectorFromParticleToPlanePosition, normal); + if (dot < _particle[p].radius) { + _particle[p].position += normal * (_particle[p].radius - dot); + float planeNormalComponentOfVelocity = glm::dot(_particle[p].velocity, normal); + _particle[p].velocity -= normal * planeNormalComponentOfVelocity * (1.0f + myEmitter.particleAttributes[lifeStage].bounce); + } + } + + // collision with sphere + 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; + } } } } + // adjust color + _particle[p].color + = myEmitter.particleAttributes[lifeStage ].color * (1.0f - lifeStageFraction) + + myEmitter.particleAttributes[lifeStage+1].color * lifeStageFraction; + + // apply color modulation + if (myEmitter.particleAttributes[lifeStage ].modulationAmplitude > 0.0f) { + float modulation = 0.0f; + float radian = _timer * myEmitter.particleAttributes[lifeStage ].modulationRate * PI_TIMES_TWO; + if (myEmitter.particleAttributes[lifeStage ].modulationStyle == COLOR_MODULATION_STYLE_LIGHNTESS_PULSE) { + if (sinf(radian) > 0.0f) { + modulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude; + } + } else if (myEmitter.particleAttributes[lifeStage].modulationStyle == COLOR_MODULATION_STYLE_LIGHTNESS_WAVE) { + float a = myEmitter.particleAttributes[lifeStage].modulationAmplitude; + modulation = a * ONE_HALF + sinf(radian) * a * ONE_HALF; + } + + _particle[p].color.r += modulation; + _particle[p].color.g += modulation; + _particle[p].color.b += modulation; + _particle[p].color.a += modulation; + + if (_particle[p].color.r > 1.0f) {_particle[p].color.r = 1.0f;} + if (_particle[p].color.g > 1.0f) {_particle[p].color.g = 1.0f;} + if (_particle[p].color.b > 1.0f) {_particle[p].color.b = 1.0f;} + if (_particle[p].color.a > 1.0f) {_particle[p].color.a = 1.0f;} + } + // do this at the end... - _particle[p].age += deltaTime; + _particle[p].age += deltaTime; } -void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing ) { - _emitter[emitterIndex].baseParticle.alive = true; - _emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex; +void ParticleSystem::killAllParticles() { + + for (int e = 0; e < _numEmitters; e++) { + _emitter[e].currentParticle = NULL_PARTICLE; + _emitter[e].emitReserve = 0.0f; + _emitter[e].previousPosition = _emitter[e].position; + _emitter[e].rate = 0.0f; + _emitter[e].currentParticle = 0; + _emitter[e].numParticlesEmittedThisTime = 0; + } + + for (int p = 0; p < MAX_PARTICLES; p++) { + killParticle(p); + } } -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() { // 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 ); + if (_emitter[e].showingBaseParticle) { + glColor4f(_particle[0].color.r, _particle[0].color.g, _particle[0].color.b, _particle[0].color.a); glPushMatrix(); glTranslatef(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z); - glutSolidSphere(_emitter[e].baseParticle.radius, 6, 6); + glutSolidSphere(_particle[0].radius, _emitter[e].particleResolution, _emitter[e].particleResolution); glPopMatrix(); } if (_emitter[e].visible) { - renderEmitter(e, 0.2f); + renderEmitter(e, DEFAULT_EMITTER_RENDER_LENGTH); } }; - - // render the particles - for (unsigned int p = 0; p < _numParticles; p++) { + + // render the particles + for (int p = 0; p < MAX_PARTICLES; p++) { if (_particle[p].alive) { - renderParticle(p); + if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) { + renderParticle(p); + } } } } void ParticleSystem::renderParticle(int p) { - glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a ); + glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a); - if (USE_BILLBOARD_RENDERING) { + if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_BILLBOARD) { glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); glm::vec3 viewVector = _particle[p].position - cameraPosition; float distance = glm::length(viewVector); @@ -330,49 +419,89 @@ void ParticleSystem::renderParticle(int p) { glVertex3f(p3.x, p3.y, p3.z); glEnd(); } - } else { + } else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_SPHERE) { + glPushMatrix(); - glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z); - glutSolidSphere(_particle[p].radius, 6, 6); + glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z); + glutSolidSphere(_particle[p].radius, _emitter[_particle[p].emitterIndex].particleResolution, _emitter[_particle[p].emitterIndex].particleResolution); glPopMatrix(); - 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(); + } else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_RIBBON) { + + if (_particle[p].previousParticle != NULL_PARTICLE) { + if ((_particle[p].alive) + && (_particle[_particle[p].previousParticle].alive) + && (_particle[_particle[p].previousParticle].emitterIndex == _particle[p].emitterIndex)) { + + glm::vec3 vectorFromPreviousParticle = _particle[p].position - _particle[_particle[p].previousParticle].position; + float distance = glm::length(vectorFromPreviousParticle); + + if (distance > 0.0f) { + + vectorFromPreviousParticle /= distance; + + glm::vec3 up = glm::normalize(glm::cross(vectorFromPreviousParticle, _upDirection)) * _particle[p].radius; + glm::vec3 right = glm::normalize(glm::cross(up, vectorFromPreviousParticle )) * _particle[p].radius; + + glm::vec3 p0Left = _particle[p ].position - right; + glm::vec3 p0Right = _particle[p ].position + right; + glm::vec3 p0Down = _particle[p ].position - up; + glm::vec3 p0Up = _particle[p ].position + up; + + glm::vec3 ppLeft = _particle[_particle[p].previousParticle].position - right; + glm::vec3 ppRight = _particle[_particle[p].previousParticle].position + right; + glm::vec3 ppDown = _particle[_particle[p].previousParticle].position - up; + glm::vec3 ppUp = _particle[_particle[p].previousParticle].position + up; + + glBegin(GL_TRIANGLES); + + glVertex3f(p0Left.x, p0Left.y, p0Left.z ); + glVertex3f(p0Right.x, p0Right.y, p0Right.z); + glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z ); + + glVertex3f(p0Right.x, p0Right.y, p0Right.z); + glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z ); + glVertex3f(ppRight.x, ppRight.y, ppRight.z); + + glVertex3f(p0Up.x, p0Up.y, p0Up.z ); + glVertex3f(p0Down.x, p0Down.y, p0Down.z ); + glVertex3f(ppDown.x, ppDown.y, ppDown.z ); + + glVertex3f(p0Up.x, p0Up.y, p0Up.z ); + glVertex3f(ppUp.x, ppUp.y, ppUp.z ); + glVertex3f(ppDown.x, ppDown.y, ppDown.z ); + + glVertex3f(p0Up.x, p0Up.y, p0Left.z ); + glVertex3f(p0Right.x, p0Right.y, p0Right.z); + glVertex3f(p0Down.x, p0Down.y, p0Down.z ); + + glVertex3f(p0Up.x, p0Up.y, p0Left.z ); + glVertex3f(p0Left.x, p0Left.y, p0Left.z ); + glVertex3f(p0Down.x, p0Down.y, p0Down.z ); + + glVertex3f(ppUp.x, ppUp.y, ppLeft.z ); + glVertex3f(ppRight.x, ppRight.y, ppRight.z); + glVertex3f(ppDown.x, ppDown.y, ppDown.z ); + + glVertex3f(ppUp.x, ppUp.y, ppLeft.z ); + glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z ); + glVertex3f(ppDown.x, ppDown.y, ppDown.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(); + glm::vec3 v = _emitter[e].direction * size; + 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); + glVertex3f(_emitter[e].position.x + v.x, _emitter[e].position.y + v.y, _emitter[e].position.z + v.z); glEnd(); } @@ -380,5 +509,3 @@ void ParticleSystem::renderEmitter(int e, float size) { - - diff --git a/interface/src/ParticleSystem.h b/interface/src/ParticleSystem.h index 764800f23e..d79f621f69 100644 --- a/interface/src/ParticleSystem.h +++ b/interface/src/ParticleSystem.h @@ -11,76 +11,121 @@ #include 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; +const int NULL_EMITTER = -1; +const int NULL_PARTICLE = -1; +const int MAX_EMITTERS = 100; + +enum ParticleRenderStyle +{ + PARTICLE_RENDER_STYLE_SPHERE = 0, + PARTICLE_RENDER_STYLE_BILLBOARD, + PARTICLE_RENDER_STYLE_RIBBON, + NUM_PARTICLE_RENDER_STYLES +}; + +enum ColorModulationStyle +{ + COLOR_MODULATION_STYLE_NULL = -1, + COLOR_MODULATION_STYLE_LIGHNTESS_PULSE, + COLOR_MODULATION_STYLE_LIGHTNESS_WAVE, + NUM_COLOR_MODULATION_STYLES +}; + +enum ParticleLifeStage +{ + PARTICLE_LIFESTAGE_0 = 0, + PARTICLE_LIFESTAGE_1, + PARTICLE_LIFESTAGE_2, + PARTICLE_LIFESTAGE_3, + NUM_PARTICLE_LIFE_STAGES +}; 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; + float radius; // radius of the particle + glm::vec4 color; // color (rgba) of the particle + float bounce; // how much reflection when the particle collides with floor/ground + float gravity; // force opposite of up direction + float airFriction; // continual dampening of velocity + float jitter; // random forces on velocity + float emitterAttraction; // an attraction to the emitter position + float tornadoForce; // force perpendicular to direction axis + float neighborAttraction; // causes particle to be pulled towards next particle in list + float neighborRepulsion; // causes particle to be repelled by previous particle in list + bool usingCollisionSphere; // set to true to allow collision with a sphere + glm::vec3 collisionSpherePosition; // position of the collision sphere + float collisionSphereRadius; // radius of the collision sphere + bool usingCollisionPlane; // set to true to allow collision with a plane + glm::vec3 collisionPlanePosition; // reference position of the collision plane + glm::vec3 collisionPlaneNormal; // the surface normal of the collision plane + float modulationAmplitude; // sets the degree (from 0 to 1) of the modulating effect + float modulationRate; // the period of modulation, in seconds + ColorModulationStyle modulationStyle; // to choose between color modulation styles }; + // public methods... 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 killAllParticles(); 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 + void setUpDirection(glm::vec3 upDirection) {_upDirection = upDirection;} // tell particle system which direction is up + void setParticleAttributesToDefault(ParticleAttributes * attributes); // set these attributes to their default values + void setParticleAttributes (int emitterIndex, ParticleAttributes attributes); // set attributes for whole life of particles + void setParticleAttributes (int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes); // set attributes for this life stage + void setEmitterPosition (int emitterIndex, glm::vec3 position ); + void setEmitterParticleResolution (int emitterIndex, int resolution ) {_emitter[emitterIndex].particleResolution = resolution; } + void setEmitterDirection (int emitterIndex, glm::vec3 direction ) {_emitter[emitterIndex].direction = direction; } + void setShowingEmitter (int emitterIndex, bool showing ) {_emitter[emitterIndex].visible = showing; } + void setEmitterParticleLifespan (int emitterIndex, float lifespan ) {_emitter[emitterIndex].particleLifespan = lifespan; } + void setParticleRenderStyle (int emitterIndex, ParticleRenderStyle renderStyle ) {_emitter[emitterIndex].particleRenderStyle = renderStyle; } + void setEmitterThrust (int emitterIndex, float thrust ) {_emitter[emitterIndex].thrust = thrust; } + void setEmitterRate (int emitterIndex, float rate ) {_emitter[emitterIndex].rate = rate; } + void setShowingEmitterBaseParticle(int emitterIndex, bool showing ) {_emitter[emitterIndex].showingBaseParticle = showing; } + private: 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? + 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 + int emitterIndex; // which emitter created this particle? + int previousParticle; // the last particle that this particle's emitter emitted; }; struct Emitter { - glm::vec3 position; - glm::quat rotation; - bool visible; - Particle baseParticle; // a non-physical particle at the emitter position + glm::vec3 position; // the position of the emitter in world coordinates + glm::vec3 previousPosition; // the position of the emitter in the previous time step + glm::vec3 direction; // a normalized vector used as an axis for particle emission and other effects + bool visible; // whether or not a line is shown indicating the emitter (indicating its direction) + float particleLifespan; // how long the particle shall live, in seconds + int particleResolution; // for sphere-based particles + float emitReserve; // baed on 'rate', this is the number of particles that need to be emitted at a given time step + int numParticlesEmittedThisTime; //the integer number of particles to emit at the preent time step + float thrust; // the initial velocity upon emitting along the emitter direction + float rate; // currently, how many particles emitted during a simulation time step + bool showingBaseParticle; // if true, a copy of particle 0 is shown on the emitter position + int currentParticle; // the index of the most recently-emitted particle ParticleAttributes particleAttributes[NUM_PARTICLE_LIFE_STAGES]; // the attributes of particles emitted from this emitter - }; + ParticleRenderStyle particleRenderStyle; + }; glm::vec3 _upDirection; Emitter _emitter[MAX_EMITTERS]; Particle _particle[MAX_PARTICLES]; - int _numParticles; int _numEmitters; + float _timer; // private methods void updateParticle(int index, float deltaTime); - void createParticle(int e, glm::vec3 velocity, float lifespan); + void createParticle(int e, float timeFraction); void killParticle(int p); void renderEmitter(int emitterIndex, float size); void renderParticle(int p); diff --git a/interface/src/Webcam.h b/interface/src/Webcam.h index 6c6d250897..3910bb4a19 100644 --- a/interface/src/Webcam.h +++ b/interface/src/Webcam.h @@ -19,8 +19,8 @@ #include -#ifdef HAVE_OPENNI - #include +#if defined(HAVE_OPENNI) && !defined(Q_MOC_RUN) +#include #endif #include diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0bf2c94b10..1af82083ae 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -451,7 +451,7 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { } void Avatar::simulate(float deltaTime, Transmitter* transmitter) { - + glm::quat orientation = getOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; diff --git a/interface/src/avatar/AvatarVoxelSystem.cpp b/interface/src/avatar/AvatarVoxelSystem.cpp index c85ea1a343..a9f6b31072 100644 --- a/interface/src/avatar/AvatarVoxelSystem.cpp +++ b/interface/src/avatar/AvatarVoxelSystem.cpp @@ -121,7 +121,7 @@ void AvatarVoxelSystem::setVoxelURL(const QUrl& url) { // handle "file://" urls... if (url.isLocalFile()) { QString pathString = url.path(); - QByteArray pathAsAscii = pathString.toAscii(); + QByteArray pathAsAscii = pathString.toLocal8Bit(); const char* path = pathAsAscii.data(); readFromSVOFile(path); return; @@ -255,7 +255,7 @@ void AvatarVoxelSystem::handleVoxelDownloadProgress(qint64 bytesReceived, qint64 } void AvatarVoxelSystem::handleVoxelReplyError() { - qDebug("%s\n", _voxelReply->errorString().toAscii().constData()); + qDebug("%s\n", _voxelReply->errorString().toLocal8Bit().constData()); _voxelReply->disconnect(this); _voxelReply->deleteLater(); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 97594d0f50..28b1af0603 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -14,19 +14,25 @@ #include "Util.h" #include "renderer/ProgramObject.h" +const bool SHOW_LEAP_HAND = false; + using namespace std; Hand::Hand(Avatar* owningAvatar) : HandData((AvatarData*)owningAvatar), + + _raveGloveClock(0.0f), + _raveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR), + _raveGloveInitialized(false), + _isRaveGloveActive(false), _owningAvatar(owningAvatar), _renderAlpha(1.0), _lookingInMirror(false), - _ballColor(0.0, 0.0, 0.4), - _particleSystemInitialized(false) -{ + _ballColor(0.0, 0.0, 0.4) + { // initialize all finger particle emitters with an invalid id as default - for (int f = 0; f< NUM_FINGERS_PER_HAND; f ++ ) { - _fingerParticleEmitter[f] = -1; + for (int f = 0; f< NUM_FINGERS; f ++ ) { + _raveGloveEmitter[f] = NULL_EMITTER; } } @@ -35,16 +41,18 @@ void Hand::init() { if (_owningAvatar && _owningAvatar->isMyAvatar()) { _ballColor = glm::vec3(0.0, 0.4, 0.0); } - else + else { _ballColor = glm::vec3(0.0, 0.0, 0.4); + } } void Hand::reset() { } + void Hand::simulate(float deltaTime, bool isMine) { if (_isRaveGloveActive) { - updateFingerParticles(deltaTime); + updateRaveGloveParticles(deltaTime); } } @@ -76,6 +84,21 @@ void Hand::calculateGeometry() { } } +void Hand::setRaveGloveEffectsMode(QKeyEvent* event) { + switch (event->key()) { + + case Qt::Key_0: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR); break; + case Qt::Key_1: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_TRAILS ); break; + case Qt::Key_2: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FIRE ); break; + case Qt::Key_3: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_WATER ); break; + case Qt::Key_4: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FLASHY ); break; + case Qt::Key_5: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER ); break; + case Qt::Key_6: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER ); break; + case Qt::Key_7: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_SNAKE ); break; + case Qt::Key_8: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_PULSE ); break; + case Qt::Key_9: setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROB ); break; + }; +} void Hand::render(bool lookingInMirror) { @@ -87,16 +110,19 @@ void Hand::render(bool lookingInMirror) { if (_isRaveGloveActive) { renderRaveGloveStage(); - if (_particleSystemInitialized) { - _particleSystem.render(); + if (_raveGloveInitialized) { + updateRaveGloveEmitters(); // do this after calculateGeometry + _raveGloveParticleSystem.render(); } } glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); - renderFingerTrails(); - renderHandSpheres(); + if ( SHOW_LEAP_HAND ) { + renderFingerTrails(); + renderHandSpheres(); + } } void Hand::renderRaveGloveStage() { @@ -203,69 +229,61 @@ void Hand::renderFingerTrails() { } } -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); +void Hand::setLeapHands(const std::vector& handPositions, + const std::vector& 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); + } + } +} - _particleSystemInitialized = true; - } else { - // update the particles +// call this right after the geometry of the leap hands are set +void Hand::updateRaveGloveEmitters() { + + bool debug = false; + + if (_raveGloveInitialized) { - static float t = 0.0f; - t += deltaTime; + if(debug) printf( "\n" ); + if(debug) printf( "------------------------------------\n" ); + if(debug) printf( "updating rave glove emitters:\n" ); + if(debug) printf( "------------------------------------\n" ); + + int emitterIndex = 0; - int fingerIndex = 0; for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; + + if(debug) printf( "\n" ); + if(debug) printf( "palm %d ", (int)i ); + if (palm.isActive()) { + + if(debug) printf( "is active\n" ); + for (size_t f = 0; f < palm.getNumFingers(); ++f) { FingerData& finger = palm.getFingers()[f]; + + if(debug) printf( "emitterIndex %d: ", emitterIndex ); + if (finger.isActive()) { - if (_fingerParticleEmitter[fingerIndex] != -1) { + + if ((emitterIndex >=0) + && (emitterIndex < NUM_FINGERS)) { + + assert(emitterIndex >=0 ); + assert(emitterIndex < NUM_FINGERS ); + + if(debug) printf( "_raveGloveEmitter[%d] = %d\n", emitterIndex, _raveGloveEmitter[emitterIndex] ); - glm::vec3 particleEmitterPosition = finger.getTipPosition(); - - glm::vec3 fingerDirection = particleEmitterPosition - leapPositionToWorldPosition(finger.getRootPosition()); + glm::vec3 fingerDirection = finger.getTipPosition() - finger.getRootPosition(); float fingerLength = glm::length(fingerDirection); if (fingerLength > 0.0f) { @@ -273,27 +291,391 @@ void Hand::updateFingerParticles(float deltaTime) { } else { fingerDirection = IDENTITY_UP; } - - glm::quat particleEmitterRotation = rotationBetween(palm.getNormal(), fingerDirection); - //glm::quat particleEmitterRotation = glm::angleAxis(0.0f, fingerDirection); + assert(_raveGloveEmitter[emitterIndex] >=0 ); + assert(_raveGloveEmitter[emitterIndex] < NUM_FINGERS ); - _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); + _raveGloveParticleSystem.setEmitterPosition (_raveGloveEmitter[emitterIndex], finger.getTipPosition()); + _raveGloveParticleSystem.setEmitterDirection(_raveGloveEmitter[emitterIndex], fingerDirection); } + } else { + if(debug) printf( "BOGUS finger\n" ); } + + emitterIndex ++; } + } else { + if(debug) printf( "is NOT active\n" ); } } + } +} + + +// call this from within the simulate method +void Hand::updateRaveGloveParticles(float deltaTime) { + + if (!_raveGloveInitialized) { + + //printf( "Initializing rave glove emitters:\n" ); + //printf( "The indices of the emitters are:\n" ); + + // start up the rave glove finger particles... + for ( int f = 0; f< NUM_FINGERS; f ++ ) { + _raveGloveEmitter[f] = _raveGloveParticleSystem.addEmitter(); + assert( _raveGloveEmitter[f] >= 0 ); + assert( _raveGloveEmitter[f] != NULL_EMITTER ); + + //printf( "%d\n", _raveGloveEmitter[f] ); + } + + setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FIRE); + _raveGloveParticleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f)); + _raveGloveInitialized = true; + } else { - _particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f)); - _particleSystem.simulate(deltaTime); + _raveGloveClock += deltaTime; + + // this rave glove effect oscillates though various colors and radii that are meant to show off some effects + if (_raveGloveMode == RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR) { + ParticleSystem::ParticleAttributes attributes; + float red = 0.5f + 0.5f * sinf(_raveGloveClock * 1.4f); + float green = 0.5f + 0.5f * cosf(_raveGloveClock * 1.7f); + float blue = 0.5f + 0.5f * sinf(_raveGloveClock * 2.0f); + float alpha = 1.0f; + + attributes.color = glm::vec4(red, green, blue, alpha); + attributes.radius = 0.01f + 0.005f * sinf(_raveGloveClock * 2.2f); + attributes.modulationAmplitude = 0.0f; + + for ( int f = 0; f< NUM_FINGERS; f ++ ) { + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + } + } + + _raveGloveParticleSystem.simulate(deltaTime); + } +} + +void Hand::setRaveGloveMode(int mode) { + + _raveGloveMode = mode; + + _raveGloveParticleSystem.killAllParticles(); + + for ( int f = 0; f< NUM_FINGERS; f ++ ) { + + ParticleSystem::ParticleAttributes attributes; + + //----------------------------------------- + // throbbing color cycle + //----------------------------------------- + if (mode == RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR) { + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.0f ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0f ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.02f; + attributes.gravity = 0.0f; + attributes.airFriction = 0.0f; + attributes.jitter = 0.0f; + attributes.bounce = 0.0f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // trails + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_TRAILS) { + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_RIBBON ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0f ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 50.0f ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 5 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.001f; + attributes.color = glm::vec4( 1.0f, 0.5f, 0.2f, 1.0f); + attributes.gravity = 0.005f; + attributes.airFriction = 0.0f; + attributes.jitter = 0.0f; + attributes.bounce = 0.0f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + + attributes.radius = 0.002f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + + attributes.color = glm::vec4( 1.0f, 0.2f, 0.2f, 0.5f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + + attributes.color = glm::vec4( 1.0f, 0.2f, 0.2f, 0.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + } + + //----------------------------------------- + // Fire! + //----------------------------------------- + if (mode == RAVE_GLOVE_EFFECTS_MODE_FIRE) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0f ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 120.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 6 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.005f; + attributes.color = glm::vec4( 1.0f, 1.0f, 0.5f, 0.5f); + attributes.airFriction = 0.0f; + attributes.jitter = 0.003f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_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); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + + attributes.radius = 0.01f; + attributes.gravity = 0.0f; + attributes.color = glm::vec4( 0.4f, 0.4f, 0.4f, 0.2f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + + attributes.radius = 0.02f; + attributes.color = glm::vec4( 0.4f, 0.6f, 0.9f, 0.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // water + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_WATER) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.6f ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.001f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 5 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.001f; + attributes.color = glm::vec4( 0.8f, 0.9f, 1.0f, 0.5f); + attributes.airFriction = 0.0f; + attributes.jitter = 0.004f; + attributes.bounce = 1.0f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + + attributes.gravity = 0.01f; + attributes.jitter = 0.0f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + + attributes.color = glm::vec4( 0.8f, 0.9f, 1.0f, 0.2f); + attributes.radius = 0.002f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + + attributes.color = glm::vec4( 0.8f, 0.9f, 1.0f, 0.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // flashy + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_FLASHY) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.1 ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 12 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.0f; + attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f); + attributes.airFriction = 0.0f; + attributes.jitter = 0.05f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + + attributes.radius = 0.01f; + attributes.color = glm::vec4( 1.0f, 1.0f, 0.0f, 1.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + + attributes.radius = 0.01f; + attributes.color = glm::vec4( 1.0f, 0.0f, 1.0f, 1.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + + attributes.radius = 0.01f; + attributes.color = glm::vec4( 0.0f, 0.0f, 0.0f, 1.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // Bozo sparkler + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_RIBBON ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.2 ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 12 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.0f; + attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f); + attributes.airFriction = 0.0f; + attributes.jitter = 0.01f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + + attributes.radius = 0.01f; + attributes.color = glm::vec4( 1.0f, 1.0f, 0.0f, 1.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + + attributes.radius = 0.01f; + attributes.color = glm::vec4( 1.0f, 0.0f, .0f, 1.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + + attributes.radius = 0.0f; + attributes.color = glm::vec4( 0.0f, 0.0f, 1.0f, 0.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // long sparkler + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_RIBBON ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], false ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0 ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 7 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.color = glm::vec4( 0.3f, 0.3f, 0.3f, 0.4f); + attributes.radius = 0.0f; + attributes.airFriction = 0.0f; + attributes.jitter = 0.0001f; + attributes.bounce = 1.0f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + + attributes.radius = 0.005f; + attributes.color = glm::vec4( 0.0f, 0.5f, 0.5f, 0.8f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + + attributes.radius = 0.007f; + attributes.color = glm::vec4( 0.5f, 0.0f, 0.5f, 0.5f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + + attributes.radius = 0.02f; + attributes.color = glm::vec4( 0.0f, 0.0f, 1.0f, 0.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // bubble snake + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_SNAKE) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 1.0 ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.002f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 100.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 7 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.001f; + attributes.color = glm::vec4( 0.5f, 1.0f, 0.5f, 1.0f); + attributes.airFriction = 0.01f; + attributes.jitter = 0.0f; + attributes.emitterAttraction = 0.0f; + attributes.tornadoForce = 1.1f; + attributes.neighborAttraction = 1.1f; + attributes.neighborRepulsion = 1.1f; + attributes.bounce = 0.0f; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + + attributes.radius = 0.002f; + attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + + attributes.radius = 0.003f; + attributes.color = glm::vec4( 0.3f, 0.3f, 0.3f, 0.5f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + + attributes.radius = 0.004f; + attributes.color = glm::vec4( 0.3f, 0.3f, 0.3f, 0.0f); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // pulse + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_PULSE) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.0 ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.01f; + attributes.color = glm::vec4( 0.1f, 0.2f, 0.4f, 0.5f); + attributes.modulationAmplitude = 0.9; + attributes.modulationRate = 7.0; + attributes.modulationStyle = COLOR_MODULATION_STYLE_LIGHNTESS_PULSE; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + + //----------------------------------------- + // throb + //----------------------------------------- + } else if (mode == RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER) { + + _raveGloveParticleSystem.setParticleRenderStyle (_raveGloveEmitter[f], PARTICLE_RENDER_STYLE_SPHERE ); + _raveGloveParticleSystem.setShowingEmitterBaseParticle(_raveGloveEmitter[f], true ); + _raveGloveParticleSystem.setEmitterParticleLifespan (_raveGloveEmitter[f], 0.0 ); + _raveGloveParticleSystem.setEmitterThrust (_raveGloveEmitter[f], 0.0f ); + _raveGloveParticleSystem.setEmitterRate (_raveGloveEmitter[f], 30.0 ); + _raveGloveParticleSystem.setEmitterParticleResolution (_raveGloveEmitter[f], 20 ); + + _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); + + attributes.radius = 0.01f; + attributes.color = glm::vec4( 0.5f, 0.4f, 0.3f, 0.5f); + attributes.modulationAmplitude = 0.3; + attributes.modulationRate = 1.0; + attributes.modulationStyle = COLOR_MODULATION_STYLE_LIGHTNESS_WAVE; + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes); + _raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes); + } } } + diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index f37046ed3a..a3a00beb96 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -8,6 +8,7 @@ #ifndef hifi_Hand_h #define hifi_Hand_h +#include #include #include #include @@ -22,6 +23,22 @@ class Avatar; class ProgramObject; +enum RaveGloveEffectsMode +{ + RAVE_GLOVE_EFFECTS_MODE_NULL = -1, + RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR, + RAVE_GLOVE_EFFECTS_MODE_TRAILS, + RAVE_GLOVE_EFFECTS_MODE_FIRE, + RAVE_GLOVE_EFFECTS_MODE_WATER, + RAVE_GLOVE_EFFECTS_MODE_FLASHY, + RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER, + RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER, + RAVE_GLOVE_EFFECTS_MODE_SNAKE, + RAVE_GLOVE_EFFECTS_MODE_PULSE, + RAVE_GLOVE_EFFECTS_MODE_THROB, + NUM_RAVE_GLOVE_EFFECTS_MODES +}; + class Hand : public HandData { public: Hand(Avatar* owningAvatar); @@ -42,9 +59,10 @@ public: void render(bool lookingInMirror); void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; } - void updateFingerParticles(float deltaTime); + void updateRaveGloveParticles(float deltaTime); + void updateRaveGloveEmitters(); void setRaveGloveActive(bool active) { _isRaveGloveActive = active; } - + void setRaveGloveEffectsMode(QKeyEvent* event); // getters const glm::vec3& getLeapBallPosition (int ball) const { return _leapBalls[ball].position;} @@ -55,20 +73,25 @@ private: Hand(const Hand&); Hand& operator= (const Hand&); - ParticleSystem _particleSystem; + ParticleSystem _raveGloveParticleSystem; + float _raveGloveClock; + int _raveGloveMode; + bool _raveGloveInitialized; + int _raveGloveEmitter[NUM_FINGERS]; + bool _isRaveGloveActive; - Avatar* _owningAvatar; - float _renderAlpha; - bool _lookingInMirror; - bool _isRaveGloveActive; - glm::vec3 _ballColor; - std::vector _leapBalls; - - bool _particleSystemInitialized; - int _fingerParticleEmitter[NUM_FINGERS_PER_HAND]; + Avatar* _owningAvatar; + float _renderAlpha; + bool _lookingInMirror; + glm::vec3 _ballColor; + std::vector _leapBalls; // private methods + void setLeapHands(const std::vector& handPositions, + const std::vector& handNormals); + void renderRaveGloveStage(); + void setRaveGloveMode(int mode); void renderHandSpheres(); void renderFingerTrails(); void calculateGeometry(); diff --git a/interface/src/ui/ChatEntry.cpp b/interface/src/ui/ChatEntry.cpp index 588c394eb1..f9ea4eb1f6 100644 --- a/interface/src/ui/ChatEntry.cpp +++ b/interface/src/ui/ChatEntry.cpp @@ -66,7 +66,7 @@ bool ChatEntry::keyPressEvent(QKeyEvent* event) { return true; } if (_contents.size() < MAX_CONTENT_LENGTH) { - _contents.insert(_cursorPos, 1, text.at(0).toAscii()); + _contents.insert(_cursorPos, 1, text.at(0).toLatin1()); _cursorPos++; } return true; diff --git a/jenkins/jobs.groovy b/jenkins/jobs.groovy index 5acf313a9a..a7be662df6 100644 --- a/jenkins/jobs.groovy +++ b/jenkins/jobs.groovy @@ -81,12 +81,12 @@ def hifiJob(String targetName, Boolean deploy) { static Closure cmakeBuild(srcDir, instCommand) { return { project -> project / 'builders' / 'hudson.plugins.cmake.CmakeBuilder' { - sourceDir srcDir + sourceDir '.' buildDir 'build' installDir '' buildType 'RelWithDebInfo' generator 'Unix Makefiles' - makeCommand 'make' + makeCommand "make ${srcDir}" installCommand instCommand preloadScript '' cmakeArgs '' diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index 207057e244..7968b5a003 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -8,9 +8,13 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm set(TARGET_NAME avatars) +find_package(Qt5Core) + include(${MACRO_DIR}/SetupHifiLibrary.cmake) setup_hifi_library(${TARGET_NAME}) +qt5_use_modules(${TARGET_NAME} Core) + include(${MACRO_DIR}/IncludeGLM.cmake) include_glm(${TARGET_NAME} ${ROOT_DIR}) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 01907b92f4..65ae0c6952 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -132,10 +132,6 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { std::vector fingerVectors; _handData->encodeRemoteData(fingerVectors); - ///////////////////////////////// - // Temporarily disable Leap finger sending, as it's causing a crash whenever someone's got a Leap connected - fingerVectors.clear(); - ///////////////////////////////// if (fingerVectors.size() > 255) fingerVectors.clear(); // safety. We shouldn't ever get over 255, so consider that invalid. @@ -249,8 +245,8 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { _handState = getSemiNibbleAt(bitItems,HAND_STATE_START_BIT); // leap hand data - if (sourceBuffer - startPosition < numBytes) // safety check - { + if (sourceBuffer - startPosition < numBytes) { + // check passed, bytes match unsigned int numFingerVectors = *sourceBuffer++; if (numFingerVectors > 0) { std::vector fingerVectors(numFingerVectors); @@ -264,8 +260,8 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { } // skeleton joints - if (sourceBuffer - startPosition < numBytes) // safety check - { + if (sourceBuffer - startPosition < numBytes) { + // check passed, bytes match _joints.resize(*sourceBuffer++); for (vector::iterator it = _joints.begin(); it != _joints.end(); it++) { it->jointID = *sourceBuffer++; diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index d2b5cae90d..1a7a99f2db 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -19,7 +19,10 @@ class AvatarData; class FingerData; class PalmData; +const int NUM_HANDS = 2; const int NUM_FINGERS_PER_HAND = 5; +const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND; + const int LEAPID_INVALID = -1; class HandData { diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index cf1c603b7d..b0c2771f48 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -6,9 +6,13 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros) set(TARGET_NAME shared) project(${TARGET_NAME}) +find_package(Qt5Core REQUIRED) + include(${MACRO_DIR}/SetupHifiLibrary.cmake) setup_hifi_library(${TARGET_NAME}) +qt5_use_modules(${TARGET_NAME} Core) + set(EXTERNAL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external) if (WIN32) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 9406c6b14d..42aa024e9d 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -512,7 +512,7 @@ void NodeList::loadData(QSettings *settings) { if (domainServerHostname.size() > 0) { memset(_domainHostname, 0, MAX_HOSTNAME_BYTES); - memcpy(_domainHostname, domainServerHostname.toAscii().constData(), domainServerHostname.size()); + memcpy(_domainHostname, domainServerHostname.toLocal8Bit().constData(), domainServerHostname.size()); } settings->endGroup(); diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 72b5b02f15..b6674fdb32 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -188,8 +188,8 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option) { return false; } -void sharedMessageHandler(QtMsgType type, const char* message) { - fprintf(stdout, "%s", message); +void sharedMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { + fprintf(stdout, "%s", message.toLocal8Bit().constData()); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 37443c2778..d840a83ed9 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -68,7 +68,7 @@ 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); +void sharedMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message); struct VoxelDetail { float x; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index c009eec2a5..0854dfa4b7 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -429,7 +429,7 @@ void attachVoxelNodeDataToNode(Node* newNode) { int main(int argc, const char * argv[]) { pthread_mutex_init(&::treeLock, NULL); - qInstallMsgHandler(sharedMessageHandler); + qInstallMessageHandler(sharedMessageHandler); NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, VOXEL_LISTEN_PORT); setvbuf(stdout, NULL, _IOLBF, 0);