mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:49:05 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into tile_import
Conflicts: interface/src/Application.cpp
This commit is contained in:
commit
0a4fcdccb5
33 changed files with 1285 additions and 522 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,6 +4,7 @@ CMakeFiles/
|
||||||
CMakeScripts/
|
CMakeScripts/
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
build/
|
build/
|
||||||
|
Makefile
|
||||||
|
|
||||||
# Xcode
|
# Xcode
|
||||||
*.xcodeproj
|
*.xcodeproj
|
||||||
|
|
|
@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
project(hifi)
|
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(animation-server)
|
||||||
add_subdirectory(avatar-mixer)
|
add_subdirectory(avatar-mixer)
|
||||||
add_subdirectory(audio-mixer)
|
add_subdirectory(audio-mixer)
|
||||||
|
|
|
@ -3,13 +3,13 @@ MACRO(SETUP_HIFI_LIBRARY TARGET)
|
||||||
|
|
||||||
# grab the implemenation and header files
|
# grab the implemenation and header files
|
||||||
file(GLOB LIB_SRCS src/*.h src/*.cpp)
|
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
|
# create a library and set the property so it can be referenced later
|
||||||
add_library(${TARGET} ${LIB_SRCS})
|
add_library(${TARGET} ${LIB_SRCS})
|
||||||
|
|
||||||
find_package(Qt4 REQUIRED QtCore)
|
find_package(Qt5Core REQUIRED)
|
||||||
include(${QT_USE_FILE})
|
qt5_use_modules(${TARGET} Core)
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
|
||||||
|
|
||||||
target_link_libraries(${TARGET} ${QT_LIBRARIES})
|
target_link_libraries(${TARGET} ${QT_LIBRARIES})
|
||||||
ENDMACRO(SETUP_HIFI_LIBRARY _target)
|
ENDMACRO(SETUP_HIFI_LIBRARY _target)
|
|
@ -8,9 +8,8 @@ MACRO(SETUP_HIFI_PROJECT TARGET INCLUDE_QT)
|
||||||
add_executable(${TARGET} ${TARGET_SRCS})
|
add_executable(${TARGET} ${TARGET_SRCS})
|
||||||
|
|
||||||
IF (${INCLUDE_QT})
|
IF (${INCLUDE_QT})
|
||||||
find_package(Qt4 REQUIRED QtCore)
|
find_package(Qt5Core REQUIRED)
|
||||||
include(${QT_USE_FILE})
|
qt5_use_modules(${TARGET} Core)
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
target_link_libraries(${TARGET} ${QT_LIBRARIES})
|
target_link_libraries(${TARGET} ${QT_LIBRARIES})
|
||||||
|
|
|
@ -55,10 +55,10 @@ int main(int argc, const char * argv[])
|
||||||
// domain server
|
// domain server
|
||||||
bool isLocalMode = cmdOptionExists(argc, argv, "--local");
|
bool isLocalMode = cmdOptionExists(argc, argv, "--local");
|
||||||
if (isLocalMode) {
|
if (isLocalMode) {
|
||||||
printf("NOTE: Running in Local Mode!\n");
|
printf("NOTE: Running in local mode!\n");
|
||||||
} else {
|
} else {
|
||||||
printf("--------------------------------------------------\n");
|
printf("--------------------------------------------------\n");
|
||||||
printf("NOTE: Running in EC2 Mode. \n");
|
printf("NOTE: Not running in local mode. \n");
|
||||||
printf("If you're a developer testing a local system, you\n");
|
printf("If you're a developer testing a local system, you\n");
|
||||||
printf("probably want to include --local on command line.\n");
|
printf("probably want to include --local on command line.\n");
|
||||||
printf("--------------------------------------------------\n");
|
printf("--------------------------------------------------\n");
|
||||||
|
@ -104,9 +104,10 @@ int main(int argc, const char * argv[])
|
||||||
// so hardcode the EC2 public address for now
|
// so hardcode the EC2 public address for now
|
||||||
if (nodePublicAddress.sin_addr.s_addr == serverLocalAddress) {
|
if (nodePublicAddress.sin_addr.s_addr == serverLocalAddress) {
|
||||||
// If we're not running "local" then we do replace the IP
|
// If we're not running "local" then we do replace the IP
|
||||||
// with the EC2 IP. Otherwise, we use our normal public IP
|
// with 0. This designates to clients that the server is reachable
|
||||||
|
// at the same IP address
|
||||||
if (!isLocalMode) {
|
if (!isLocalMode) {
|
||||||
nodePublicAddress.sin_addr.s_addr = 895283510; // local IP in this format...
|
nodePublicAddress.sin_addr.s_addr = 0;
|
||||||
destinationSocket = (sockaddr*) &nodeLocalAddress;
|
destinationSocket = (sockaddr*) &nodeLocalAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
interface/CMakeLists.txt
Executable file → Normal file
15
interface/CMakeLists.txt
Executable file → Normal file
|
@ -67,18 +67,16 @@ if (APPLE)
|
||||||
|
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|
||||||
find_package(Qt4 REQUIRED QtCore QtGui QtNetwork QtOpenGL QtWebKit QtSvg)
|
find_package(Qt5Core REQUIRED)
|
||||||
include(${QT_USE_FILE})
|
find_package(Qt5Gui REQUIRED)
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
find_package(Qt5Network REQUIRED)
|
||||||
|
find_package(Qt5OpenGL REQUIRED)
|
||||||
|
find_package(Qt5Svg REQUIRED)
|
||||||
|
|
||||||
set(QUAZIP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/quazip)
|
set(QUAZIP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/quazip)
|
||||||
add_subdirectory(external/fervor/)
|
add_subdirectory(external/fervor/)
|
||||||
include_directories(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
|
# create the executable, make it a bundle on OS X
|
||||||
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS})
|
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS})
|
||||||
|
|
||||||
|
@ -110,6 +108,8 @@ if (OPENNI_FOUND)
|
||||||
target_link_libraries(${TARGET_NAME} ${OPENNI_LIBRARIES})
|
target_link_libraries(${TARGET_NAME} ${OPENNI_LIBRARIES})
|
||||||
endif (OPENNI_FOUND)
|
endif (OPENNI_FOUND)
|
||||||
|
|
||||||
|
qt5_use_modules(${TARGET_NAME} Core Gui Network OpenGL Svg)
|
||||||
|
|
||||||
# include headers for interface and InterfaceConfig.
|
# include headers for interface and InterfaceConfig.
|
||||||
include_directories(
|
include_directories(
|
||||||
${PROJECT_SOURCE_DIR}/src
|
${PROJECT_SOURCE_DIR}/src
|
||||||
|
@ -131,7 +131,6 @@ include_directories(
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENCV_INCLUDE_DIRS}")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENCV_INCLUDE_DIRS}")
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
${TARGET_NAME}
|
${TARGET_NAME}
|
||||||
${QT_LIBRARIES}
|
|
||||||
${LIBVPX_LIBRARIES}
|
${LIBVPX_LIBRARIES}
|
||||||
${MOTIONDRIVER_LIBRARIES}
|
${MOTIONDRIVER_LIBRARIES}
|
||||||
${OPENCV_LIBRARIES}
|
${OPENCV_LIBRARIES}
|
||||||
|
|
15
interface/external/fervor/CMakeLists.txt
vendored
15
interface/external/fervor/CMakeLists.txt
vendored
|
@ -1,21 +1,26 @@
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(Fervor)
|
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)
|
add_definitions(-DFV_GUI)
|
||||||
|
|
||||||
file(GLOB FERVOR_SOURCES *.cpp)
|
file(GLOB FERVOR_SOURCES *.cpp)
|
||||||
file(GLOB FERVOR_HEADERS *.h)
|
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)
|
LIST(GET FERVOR_HEADERS 1 FIRST_HEADER)
|
||||||
GET_FILENAME_COMPONENT(HEADER_PATH ${FIRST_HEADER} PATH)
|
GET_FILENAME_COMPONENT(HEADER_PATH ${FIRST_HEADER} PATH)
|
||||||
list(REMOVE_ITEM FERVOR_HEADERS ${HEADER_PATH}/fvversioncomparator.h)
|
list(REMOVE_ITEM FERVOR_HEADERS ${HEADER_PATH}/fvversioncomparator.h)
|
||||||
|
|
||||||
file(GLOB FERVOR_UI *.ui)
|
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/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||||
find_package(Quazip REQUIRED)
|
find_package(Quazip REQUIRED)
|
||||||
|
|
||||||
|
@ -26,3 +31,5 @@ include_directories(
|
||||||
|
|
||||||
add_library(fervor ${FERVOR_SOURCES} ${FERVOR_HEADERS} ${FERVOR_MOC_SOURCES} ${FERVOR_WRAPPED_UI})
|
add_library(fervor ${FERVOR_SOURCES} ${FERVOR_HEADERS} ${FERVOR_MOC_SOURCES} ${FERVOR_WRAPPED_UI})
|
||||||
target_link_libraries(fervor ${QUAZIP_LIBRARIES})
|
target_link_libraries(fervor ${QUAZIP_LIBRARIES})
|
||||||
|
|
||||||
|
qt5_use_modules(fervor Core Network Widgets WebKit)
|
2
interface/external/fervor/fvplatform.h
vendored
2
interface/external/fervor/fvplatform.h
vendored
|
@ -1,7 +1,7 @@
|
||||||
#ifndef FVPLATFORM_H
|
#ifndef FVPLATFORM_H
|
||||||
#define FVPLATFORM_H
|
#define FVPLATFORM_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
class FvPlatform : public QObject
|
class FvPlatform : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,9 +164,9 @@ void GLCanvas::wheelEvent(QWheelEvent* event) {
|
||||||
Application::getInstance()->wheelEvent(event);
|
Application::getInstance()->wheelEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void messageHandler(QtMsgType type, const char* message) {
|
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) {
|
||||||
fprintf(stdout, "%s", message);
|
fprintf(stdout, "%s", message.toLocal8Bit().constData());
|
||||||
LogDisplay::instance.addMessage(message);
|
LogDisplay::instance.addMessage(message.toLocal8Bit().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::Application(int& argc, char** argv, timeval &startup_time) :
|
Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
|
@ -222,7 +222,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
_applicationStartupTime = startup_time;
|
_applicationStartupTime = startup_time;
|
||||||
_window->setWindowTitle("Interface");
|
_window->setWindowTitle("Interface");
|
||||||
|
|
||||||
qInstallMsgHandler(messageHandler);
|
qInstallMessageHandler(messageHandler);
|
||||||
|
|
||||||
unsigned int listenPort = 0; // bind to an ephemeral port by default
|
unsigned int listenPort = 0; // bind to an ephemeral port by default
|
||||||
const char** constArgv = const_cast<const char**>(argv);
|
const char** constArgv = const_cast<const char**>(argv);
|
||||||
|
@ -565,6 +565,11 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
return;
|
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);
|
bool shifted = event->modifiers().testFlag(Qt::ShiftModifier);
|
||||||
switch (event->key()) {
|
switch (event->key()) {
|
||||||
case Qt::Key_BracketLeft:
|
case Qt::Key_BracketLeft:
|
||||||
|
@ -1216,7 +1221,7 @@ void Application::editPreferences() {
|
||||||
|
|
||||||
if (domainServerHostname->text().size() > 0) {
|
if (domainServerHostname->text().size() > 0) {
|
||||||
// the user input a new hostname, use that
|
// the user input a new hostname, use that
|
||||||
newHostname = domainServerHostname->text().toAscii();
|
newHostname = domainServerHostname->text().toLocal8Bit();
|
||||||
} else {
|
} else {
|
||||||
// the user left the field blank, use the default hostname
|
// the user left the field blank, use the default hostname
|
||||||
newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME);
|
newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME);
|
||||||
|
@ -1514,12 +1519,12 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::exportVoxels() {
|
void Application::exportVoxels() {
|
||||||
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
QString suggestedName = desktopLocation.append("/voxels.svo");
|
QString suggestedName = desktopLocation.append("/voxels.svo");
|
||||||
|
|
||||||
QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), suggestedName,
|
QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), suggestedName,
|
||||||
tr("Sparse Voxel Octree Files (*.svo)"));
|
tr("Sparse Voxel Octree Files (*.svo)"));
|
||||||
QByteArray fileNameAscii = fileNameString.toAscii();
|
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
|
||||||
const char* fileName = fileNameAscii.data();
|
const char* fileName = fileNameAscii.data();
|
||||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
if (selectedNode) {
|
if (selectedNode) {
|
||||||
|
@ -1534,11 +1539,11 @@ void Application::exportVoxels() {
|
||||||
|
|
||||||
const char* IMPORT_FILE_TYPES = "Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)";
|
const char* IMPORT_FILE_TYPES = "Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)";
|
||||||
void Application::importVoxelsToClipboard() {
|
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,
|
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels to Clipboard"), desktopLocation,
|
||||||
tr(IMPORT_FILE_TYPES));
|
tr(IMPORT_FILE_TYPES));
|
||||||
|
|
||||||
QByteArray fileNameAscii = fileNameString.toAscii();
|
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
|
||||||
const char* fileName = fileNameAscii.data();
|
const char* fileName = fileNameAscii.data();
|
||||||
|
|
||||||
_clipboardTree.eraseAllVoxels();
|
_clipboardTree.eraseAllVoxels();
|
||||||
|
@ -1568,7 +1573,7 @@ void Application::importVoxelsToClipboard() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::importVoxels() {
|
void Application::importVoxels() {
|
||||||
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
|
|
||||||
QStringList fileNameStringList = QFileDialog::getOpenFileNames(_glWidget, tr("Import Voxels"), desktopLocation,
|
QStringList fileNameStringList = QFileDialog::getOpenFileNames(_glWidget, tr("Import Voxels"), desktopLocation,
|
||||||
tr(IMPORT_FILE_TYPES));
|
tr(IMPORT_FILE_TYPES));
|
||||||
|
@ -2043,8 +2048,11 @@ const float MAX_VOXEL_EDIT_DISTANCE = 20.0f;
|
||||||
const float HEAD_SPHERE_RADIUS = 0.07;
|
const float HEAD_SPHERE_RADIUS = 0.07;
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t DEFAULT_NODE_ID_REF = 1;
|
||||||
|
|
||||||
|
|
||||||
bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
|
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();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
|
@ -2101,8 +2109,8 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
// Set where I am looking based on my mouse ray (so that other people can see)
|
// Set where I am looking based on my mouse ray (so that other people can see)
|
||||||
glm::vec3 eyePosition;
|
glm::vec3 eyePosition;
|
||||||
uint16_t ignored;
|
|
||||||
_isLookingAtOtherAvatar = isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition, ignored);
|
_isLookingAtOtherAvatar = isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition);
|
||||||
if (_isLookingAtOtherAvatar) {
|
if (_isLookingAtOtherAvatar) {
|
||||||
// If the mouse is over another avatar's head...
|
// If the mouse is over another avatar's head...
|
||||||
glm::vec3 myLookAtFromMouse(eyePosition);
|
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||||
|
@ -2368,8 +2376,8 @@ void Application::updateAvatar(float deltaTime) {
|
||||||
_viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection);
|
_viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection);
|
||||||
|
|
||||||
glm::vec3 eyePosition;
|
glm::vec3 eyePosition;
|
||||||
uint16_t ignored;
|
|
||||||
_isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition, ignored);
|
_isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition);
|
||||||
if (_isLookingAtOtherAvatar) {
|
if (_isLookingAtOtherAvatar) {
|
||||||
glm::vec3 myLookAtFromMouse(eyePosition);
|
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||||
|
@ -2408,7 +2416,7 @@ void Application::updateAvatar(float deltaTime) {
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
if (nodeList->getOwnerID() != UNKNOWN_NODE_ID) {
|
if (nodeList->getOwnerID() != UNKNOWN_NODE_ID) {
|
||||||
// if I know my ID, send head/hand data to the avatar mixer and voxel server
|
// 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;
|
unsigned char* endOfBroadcastStringWrite = broadcastString;
|
||||||
|
|
||||||
endOfBroadcastStringWrite += populateTypeAndVersion(endOfBroadcastStringWrite, PACKET_TYPE_HEAD_DATA);
|
endOfBroadcastStringWrite += populateTypeAndVersion(endOfBroadcastStringWrite, PACKET_TYPE_HEAD_DATA);
|
||||||
|
@ -2727,13 +2735,14 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
if (_mouseVoxel.s != 0) {
|
if (_mouseVoxel.s != 0) {
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);
|
||||||
|
renderMouseVoxelGrid(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
if (_addVoxelMode->isChecked()) {
|
if (_addVoxelMode->isChecked()) {
|
||||||
// use a contrasting color so that we can see what we're doing
|
// use a contrasting color so that we can see what we're doing
|
||||||
glColor3ub(_mouseVoxel.red + 128, _mouseVoxel.green + 128, _mouseVoxel.blue + 128);
|
glColor3ub(_mouseVoxel.red + 128, _mouseVoxel.green + 128, _mouseVoxel.blue + 128);
|
||||||
} else {
|
} else {
|
||||||
glColor3ub(_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue);
|
glColor3ub(_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue);
|
||||||
}
|
}
|
||||||
glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);
|
|
||||||
glTranslatef(_mouseVoxel.x + _mouseVoxel.s*0.5f,
|
glTranslatef(_mouseVoxel.x + _mouseVoxel.s*0.5f,
|
||||||
_mouseVoxel.y + _mouseVoxel.s*0.5f,
|
_mouseVoxel.y + _mouseVoxel.s*0.5f,
|
||||||
_mouseVoxel.z + _mouseVoxel.s*0.5f);
|
_mouseVoxel.z + _mouseVoxel.s*0.5f);
|
||||||
|
@ -2785,7 +2794,6 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
|
|
||||||
// brad's frustum for debugging
|
// brad's frustum for debugging
|
||||||
if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum);
|
if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::displayOverlay() {
|
void Application::displayOverlay() {
|
||||||
|
@ -3682,7 +3690,7 @@ void Application::saveSettings(QSettings* settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::importSettings() {
|
void Application::importSettings() {
|
||||||
QString locationDir(QDesktopServices::displayName(QDesktopServices::DesktopLocation));
|
QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation));
|
||||||
QString fileName = QFileDialog::getOpenFileName(_window,
|
QString fileName = QFileDialog::getOpenFileName(_window,
|
||||||
tr("Open .ini config file"),
|
tr("Open .ini config file"),
|
||||||
locationDir,
|
locationDir,
|
||||||
|
@ -3694,7 +3702,7 @@ void Application::importSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::exportSettings() {
|
void Application::exportSettings() {
|
||||||
QString locationDir(QDesktopServices::displayName(QDesktopServices::DesktopLocation));
|
QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation));
|
||||||
QString fileName = QFileDialog::getSaveFileName(_window,
|
QString fileName = QFileDialog::getSaveFileName(_window,
|
||||||
tr("Save .ini config file"),
|
tr("Save .ini config file"),
|
||||||
locationDir,
|
locationDir,
|
||||||
|
@ -3707,20 +3715,24 @@ void Application::exportSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Application::updateParticleSystem(float deltaTime) {
|
void Application::updateParticleSystem(float deltaTime) {
|
||||||
|
|
||||||
if (!_particleSystemInitialized) {
|
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
|
// create a stable test emitter and spit out a bunch of particles
|
||||||
_coolDemoParticleEmitter = _particleSystem.addEmitter();
|
_coolDemoParticleEmitter = _particleSystem.addEmitter();
|
||||||
|
|
||||||
if (_coolDemoParticleEmitter != -1) {
|
if (_coolDemoParticleEmitter != -1) {
|
||||||
|
|
||||||
_particleSystem.setShowingEmitter(_coolDemoParticleEmitter, true);
|
_particleSystem.setShowingEmitter(_coolDemoParticleEmitter, true);
|
||||||
glm::vec3 particleEmitterPosition = glm::vec3(5.0f, 1.0f, 5.0f);
|
glm::vec3 particleEmitterPosition = glm::vec3(5.0f, 1.0f, 5.0f);
|
||||||
|
|
||||||
_particleSystem.setEmitterPosition (_coolDemoParticleEmitter, particleEmitterPosition);
|
_particleSystem.setEmitterPosition (_coolDemoParticleEmitter, particleEmitterPosition);
|
||||||
glm::vec3 velocity(0.0f, 0.1f, 0.0f);
|
_particleSystem.setEmitterParticleLifespan(_coolDemoParticleEmitter, LIFESPAN_IN_SECONDS);
|
||||||
float lifespan = 100000.0f;
|
_particleSystem.setEmitterThrust (_coolDemoParticleEmitter, 0.0f);
|
||||||
_particleSystem.emitParticlesNow(_coolDemoParticleEmitter, 1500, velocity, lifespan);
|
_particleSystem.setEmitterRate (_coolDemoParticleEmitter, EMIT_RATE_IN_SECONDS); // to emit a pile o particles now
|
||||||
}
|
}
|
||||||
|
|
||||||
// signal that the particle system has been initialized
|
// signal that the particle system has been initialized
|
||||||
|
@ -3728,35 +3740,32 @@ void Application::updateParticleSystem(float deltaTime) {
|
||||||
} else {
|
} else {
|
||||||
// update the particle system
|
// update the particle system
|
||||||
|
|
||||||
static float t = 0.0f;
|
static bool emitting = true;
|
||||||
t += deltaTime;
|
static float effectsTimer = 0.0f;
|
||||||
|
effectsTimer += deltaTime;
|
||||||
|
|
||||||
if (_coolDemoParticleEmitter != -1) {
|
if (_coolDemoParticleEmitter != -1) {
|
||||||
|
|
||||||
glm::vec3 tilt = glm::vec3
|
_particleSystem.setEmitterDirection(_coolDemoParticleEmitter, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
(
|
|
||||||
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;
|
ParticleSystem::ParticleAttributes attributes;
|
||||||
|
|
||||||
attributes.radius = 0.01f;
|
attributes.radius = 0.01f;
|
||||||
attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f);
|
attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
attributes.gravity = 0.0f + 0.05f * sinf( t * 0.52f );
|
attributes.gravity = 0.0f + 0.05f * sinf( effectsTimer * 0.52f );
|
||||||
attributes.airFriction = 2.5 + 2.0f * sinf( t * 0.32f );
|
attributes.airFriction = 2.5 + 2.0f * sinf( effectsTimer * 0.32f );
|
||||||
attributes.jitter = 0.05f + 0.05f * sinf( t * 0.42f );
|
attributes.jitter = 0.05f + 0.05f * sinf( effectsTimer * 0.42f );
|
||||||
attributes.emitterAttraction = 0.015f + 0.015f * cosf( t * 0.6f );
|
attributes.emitterAttraction = 0.015f + 0.015f * cosf( effectsTimer * 0.6f );
|
||||||
attributes.tornadoForce = 0.0f + 0.03f * sinf( t * 0.7f );
|
attributes.tornadoForce = 0.0f + 0.03f * sinf( effectsTimer * 0.7f );
|
||||||
attributes.neighborAttraction = 0.1f + 0.1f * cosf( t * 0.8f );
|
attributes.neighborAttraction = 0.1f + 0.1f * cosf( effectsTimer * 0.8f );
|
||||||
attributes.neighborRepulsion = 0.2f + 0.2f * sinf( t * 0.4f );
|
attributes.neighborRepulsion = 0.2f + 0.2f * sinf( effectsTimer * 0.4f );
|
||||||
attributes.bounce = 1.0f;
|
attributes.bounce = 1.0f;
|
||||||
attributes.usingCollisionSphere = true;
|
attributes.usingCollisionSphere = true;
|
||||||
attributes.collisionSpherePosition = glm::vec3( 5.0f, 0.5f, 5.0f );
|
attributes.collisionSpherePosition = glm::vec3( 5.0f, 0.5f, 5.0f );
|
||||||
attributes.collisionSphereRadius = 0.5f;
|
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) {
|
if (attributes.gravity < 0.0f) {
|
||||||
attributes.gravity = 0.0f;
|
attributes.gravity = 0.0f;
|
||||||
|
@ -3767,6 +3776,15 @@ void Application::updateParticleSystem(float deltaTime) {
|
||||||
|
|
||||||
_particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
|
_particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
_particleSystem.simulate(deltaTime);
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
interface/src/LeapManager.cpp
Executable file → Normal file
0
interface/src/LeapManager.cpp
Executable file → Normal file
|
@ -14,28 +14,151 @@
|
||||||
const float DEFAULT_PARTICLE_RADIUS = 0.01f;
|
const float DEFAULT_PARTICLE_RADIUS = 0.01f;
|
||||||
const float DEFAULT_PARTICLE_BOUNCE = 1.0f;
|
const float DEFAULT_PARTICLE_BOUNCE = 1.0f;
|
||||||
const float DEFAULT_PARTICLE_AIR_FRICTION = 2.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() {
|
ParticleSystem::ParticleSystem() {
|
||||||
|
|
||||||
|
_timer = 0.0f;
|
||||||
_numEmitters = 0;
|
_numEmitters = 0;
|
||||||
_numParticles = 0;
|
|
||||||
_upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
|
_upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
|
||||||
|
|
||||||
for (unsigned int emitterIndex = 0; emitterIndex < MAX_EMITTERS; emitterIndex++) {
|
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 * e = &_emitter[emitterIndex];
|
||||||
_emitter[emitterIndex].visible = false;
|
e->position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_emitter[emitterIndex].baseParticle.alive = false;
|
e->previousPosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_emitter[emitterIndex].baseParticle.age = 0.0f;
|
e->direction = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
_emitter[emitterIndex].baseParticle.lifespan = 0.0f;
|
e->visible = false;
|
||||||
_emitter[emitterIndex].baseParticle.radius = 0.0f;
|
e->particleResolution = DEFAULT_PARTICLE_SPHERE_RESOLUTION;
|
||||||
_emitter[emitterIndex].baseParticle.emitterIndex = 0;
|
e->particleLifespan = DEFAULT_PARTICLE_LIFESPAN;
|
||||||
_emitter[emitterIndex].baseParticle.position = glm::vec3(0.0f, 0.0f, 0.0f);
|
e->showingBaseParticle = false;
|
||||||
_emitter[emitterIndex].baseParticle.velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
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; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage++) {
|
for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage++) {
|
||||||
|
setParticleAttributesToDefault(&_emitter[emitterIndex].particleAttributes[lifeStage]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage];
|
for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
|
||||||
|
_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() {
|
||||||
|
|
||||||
|
if (_numEmitters < MAX_EMITTERS) {
|
||||||
|
_numEmitters ++;
|
||||||
|
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 (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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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].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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
_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, (ParticleLifeStage)lifeStage, attributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::setParticleAttributesToDefault(ParticleAttributes * a) {
|
||||||
|
|
||||||
a->radius = DEFAULT_PARTICLE_RADIUS;
|
a->radius = DEFAULT_PARTICLE_RADIUS;
|
||||||
a->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
a->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
@ -50,95 +173,20 @@ ParticleSystem::ParticleSystem() {
|
||||||
a->collisionSphereRadius = 0.0f;
|
a->collisionSphereRadius = 0.0f;
|
||||||
a->collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
a->collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
a->usingCollisionSphere = false;
|
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;
|
||||||
|
|
||||||
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) {
|
void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes) {
|
||||||
|
|
||||||
// update particles
|
assert(lifeStage >= 0);
|
||||||
for (unsigned int p = 0; p < _numParticles; p++) {
|
assert(lifeStage < NUM_PARTICLE_LIFE_STAGES);
|
||||||
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) {
|
|
||||||
|
|
||||||
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];
|
ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage];
|
||||||
|
|
||||||
|
@ -155,29 +203,37 @@ void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, Part
|
||||||
a->usingCollisionSphere = attributes.usingCollisionSphere;
|
a->usingCollisionSphere = attributes.usingCollisionSphere;
|
||||||
a->collisionSpherePosition = attributes.collisionSpherePosition;
|
a->collisionSpherePosition = attributes.collisionSpherePosition;
|
||||||
a->collisionSphereRadius = attributes.collisionSphereRadius;
|
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) {
|
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];
|
Emitter myEmitter = _emitter[_particle[p].emitterIndex];
|
||||||
|
|
||||||
|
assert(_particle[p].age <= myEmitter.particleLifespan);
|
||||||
|
|
||||||
|
float ageFraction = 0.0f;
|
||||||
|
int lifeStage = 0;
|
||||||
|
float lifeStageFraction = 0.0f;
|
||||||
|
|
||||||
|
if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) {
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
// apply random jitter
|
// apply random jitter
|
||||||
float j = myEmitter.particleAttributes[lifeStage].jitter;
|
float j = myEmitter.particleAttributes[lifeStage].jitter;
|
||||||
_particle[p].velocity +=
|
_particle[p].velocity +=
|
||||||
|
@ -194,7 +250,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||||
|
|
||||||
// apply neighbor attraction
|
// apply neighbor attraction
|
||||||
int neighbor = p + 1;
|
int neighbor = p + 1;
|
||||||
if (neighbor == _numParticles ) {
|
if (neighbor == MAX_PARTICLES) {
|
||||||
neighbor = 0;
|
neighbor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,11 +266,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply tornado force
|
// apply tornado force
|
||||||
|
glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.direction);
|
||||||
|
|
||||||
glm::vec3 emitterUp = myEmitter.rotation * IDENTITY_UP;
|
|
||||||
|
|
||||||
glm::vec3 tornadoDirection = glm::cross(vectorToHome, emitterUp);
|
|
||||||
_particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
|
_particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
|
||||||
|
|
||||||
// apply air friction
|
// apply air friction
|
||||||
|
@ -231,12 +283,15 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||||
// update position by velocity
|
// update position by velocity
|
||||||
_particle[p].position += _particle[p].velocity;
|
_particle[p].position += _particle[p].velocity;
|
||||||
|
|
||||||
// collision with ground
|
// collision with the plane surface
|
||||||
if (_particle[p].position.y < _particle[p].radius) {
|
if (myEmitter.particleAttributes[lifeStage].usingCollisionPlane) {
|
||||||
_particle[p].position.y = _particle[p].radius;
|
glm::vec3 vectorFromParticleToPlanePosition = _particle[p].position - myEmitter.particleAttributes[lifeStage].collisionPlanePosition;
|
||||||
|
glm::vec3 normal = myEmitter.particleAttributes[lifeStage].collisionPlaneNormal;
|
||||||
if (_particle[p].velocity.y < 0.0f) {
|
float dot = glm::dot(vectorFromParticleToPlanePosition, normal);
|
||||||
_particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,57 +308,91 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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...
|
// 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;
|
void ParticleSystem::killAllParticles() {
|
||||||
_emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing, float radius, glm::vec4 color ) {
|
for (int p = 0; p < MAX_PARTICLES; p++) {
|
||||||
|
killParticle(p);
|
||||||
_emitter[emitterIndex].baseParticle.alive = true;
|
}
|
||||||
_emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
|
|
||||||
_emitter[emitterIndex].baseParticle.radius = radius;
|
|
||||||
_emitter[emitterIndex].baseParticle.color = color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ParticleSystem::render() {
|
void ParticleSystem::render() {
|
||||||
|
|
||||||
// render the emitters
|
// render the emitters
|
||||||
for (int e = 0; e < _numEmitters; e++) {
|
for (int e = 0; e < _numEmitters; e++) {
|
||||||
|
|
||||||
if (_emitter[e].baseParticle.alive) {
|
if (_emitter[e].showingBaseParticle) {
|
||||||
glColor4f(_emitter[e].baseParticle.color.r, _emitter[e].baseParticle.color.g, _emitter[e].baseParticle.color.b, _emitter[e].baseParticle.color.a );
|
glColor4f(_particle[0].color.r, _particle[0].color.g, _particle[0].color.b, _particle[0].color.a);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
|
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();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_emitter[e].visible) {
|
if (_emitter[e].visible) {
|
||||||
renderEmitter(e, 0.2f);
|
renderEmitter(e, DEFAULT_EMITTER_RENDER_LENGTH);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// render the particles
|
// render the particles
|
||||||
for (unsigned int p = 0; p < _numParticles; p++) {
|
for (int p = 0; p < MAX_PARTICLES; p++) {
|
||||||
if (_particle[p].alive) {
|
if (_particle[p].alive) {
|
||||||
|
if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) {
|
||||||
renderParticle(p);
|
renderParticle(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ParticleSystem::renderParticle(int 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 cameraPosition = Application::getInstance()->getCamera()->getPosition();
|
||||||
glm::vec3 viewVector = _particle[p].position - cameraPosition;
|
glm::vec3 viewVector = _particle[p].position - cameraPosition;
|
||||||
float distance = glm::length(viewVector);
|
float distance = glm::length(viewVector);
|
||||||
|
@ -330,49 +419,89 @@ void ParticleSystem::renderParticle(int p) {
|
||||||
glVertex3f(p3.x, p3.y, p3.z);
|
glVertex3f(p3.x, p3.y, p3.z);
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
} else {
|
} else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_SPHERE) {
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
||||||
glutSolidSphere(_particle[p].radius, 6, 6);
|
glutSolidSphere(_particle[p].radius, _emitter[_particle[p].emitterIndex].particleResolution, _emitter[_particle[p].emitterIndex].particleResolution);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
if (SHOW_VELOCITY_TAILS) {
|
} else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_RIBBON) {
|
||||||
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;
|
if (_particle[p].previousParticle != NULL_PARTICLE) {
|
||||||
glBegin(GL_LINES);
|
if ((_particle[p].alive)
|
||||||
glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
|
&& (_particle[_particle[p].previousParticle].alive)
|
||||||
glVertex3f(end.x, end.y, end.z);
|
&& (_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();
|
glEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ParticleSystem::renderEmitter(int e, float size) {
|
void ParticleSystem::renderEmitter(int e, float size) {
|
||||||
|
|
||||||
glm::vec3 r = _emitter[e].rotation * IDENTITY_FRONT * size;
|
glm::vec3 v = _emitter[e].direction * 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);
|
glColor3f(0.4f, 0.4, 0.8);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
|
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();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,5 +509,3 @@ void ParticleSystem::renderEmitter(int e, float size) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,45 +11,81 @@
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
const int MAX_PARTICLES = 5000;
|
const int MAX_PARTICLES = 5000;
|
||||||
const int MAX_EMITTERS = 20;
|
const int NULL_EMITTER = -1;
|
||||||
const int NUM_PARTICLE_LIFE_STAGES = 4;
|
const int NULL_PARTICLE = -1;
|
||||||
const bool USE_BILLBOARD_RENDERING = false;
|
const int MAX_EMITTERS = 100;
|
||||||
const bool SHOW_VELOCITY_TAILS = false;
|
|
||||||
|
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 {
|
class ParticleSystem {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct ParticleAttributes {
|
struct ParticleAttributes {
|
||||||
float radius;
|
float radius; // radius of the particle
|
||||||
glm::vec4 color;
|
glm::vec4 color; // color (rgba) of the particle
|
||||||
float bounce;
|
float bounce; // how much reflection when the particle collides with floor/ground
|
||||||
float gravity;
|
float gravity; // force opposite of up direction
|
||||||
float airFriction;
|
float airFriction; // continual dampening of velocity
|
||||||
float jitter;
|
float jitter; // random forces on velocity
|
||||||
float emitterAttraction;
|
float emitterAttraction; // an attraction to the emitter position
|
||||||
float tornadoForce;
|
float tornadoForce; // force perpendicular to direction axis
|
||||||
float neighborAttraction;
|
float neighborAttraction; // causes particle to be pulled towards next particle in list
|
||||||
float neighborRepulsion;
|
float neighborRepulsion; // causes particle to be repelled by previous particle in list
|
||||||
bool usingCollisionSphere;
|
bool usingCollisionSphere; // set to true to allow collision with a sphere
|
||||||
glm::vec3 collisionSpherePosition;
|
glm::vec3 collisionSpherePosition; // position of the collision sphere
|
||||||
float collisionSphereRadius;
|
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();
|
ParticleSystem();
|
||||||
|
|
||||||
int addEmitter(); // add (create new) emitter and get its unique id
|
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 simulate(float deltaTime);
|
||||||
|
void killAllParticles();
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
void setUpDirection(glm::vec3 upDirection) {_upDirection = upDirection;} // tell particle system which direction is up
|
void setUpDirection(glm::vec3 upDirection) {_upDirection = upDirection;} // tell particle system which direction is up
|
||||||
void setEmitterBaseParticle(int emitterIndex, bool showing );
|
void setParticleAttributesToDefault(ParticleAttributes * attributes); // set these attributes to their default values
|
||||||
void setEmitterBaseParticle(int emitterIndex, bool showing, float radius, glm::vec4 color );
|
void setParticleAttributes (int emitterIndex, ParticleAttributes attributes); // set attributes for whole life of particles
|
||||||
void setParticleAttributes (int emitterIndex, ParticleAttributes attributes);
|
void setParticleAttributes (int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes); // set attributes for this life stage
|
||||||
void setParticleAttributes (int emitterIndex, int lifeStage, ParticleAttributes attributes);
|
void setEmitterPosition (int emitterIndex, glm::vec3 position );
|
||||||
void setEmitterPosition (int emitterIndex, glm::vec3 position) { _emitter[emitterIndex].position = position; } // set position of emitter
|
void setEmitterParticleResolution (int emitterIndex, int resolution ) {_emitter[emitterIndex].particleResolution = resolution; }
|
||||||
void setEmitterRotation (int emitterIndex, glm::quat rotation) { _emitter[emitterIndex].rotation = rotation; } // set rotation of emitter
|
void setEmitterDirection (int emitterIndex, glm::vec3 direction ) {_emitter[emitterIndex].direction = direction; }
|
||||||
void setShowingEmitter (int emitterIndex, bool showing ) { _emitter[emitterIndex].visible = showing; } // set its visibiity
|
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:
|
private:
|
||||||
|
|
||||||
|
@ -60,27 +96,36 @@ private:
|
||||||
glm::vec4 color; // color (rgba)
|
glm::vec4 color; // color (rgba)
|
||||||
float age; // age in seconds
|
float age; // age in seconds
|
||||||
float radius; // radius
|
float radius; // radius
|
||||||
float lifespan; // how long this particle stays alive (in seconds)
|
|
||||||
int emitterIndex; // which emitter created this particle?
|
int emitterIndex; // which emitter created this particle?
|
||||||
|
int previousParticle; // the last particle that this particle's emitter emitted;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Emitter {
|
struct Emitter {
|
||||||
glm::vec3 position;
|
glm::vec3 position; // the position of the emitter in world coordinates
|
||||||
glm::quat rotation;
|
glm::vec3 previousPosition; // the position of the emitter in the previous time step
|
||||||
bool visible;
|
glm::vec3 direction; // a normalized vector used as an axis for particle emission and other effects
|
||||||
Particle baseParticle; // a non-physical particle at the emitter position
|
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
|
ParticleAttributes particleAttributes[NUM_PARTICLE_LIFE_STAGES]; // the attributes of particles emitted from this emitter
|
||||||
|
ParticleRenderStyle particleRenderStyle;
|
||||||
};
|
};
|
||||||
|
|
||||||
glm::vec3 _upDirection;
|
glm::vec3 _upDirection;
|
||||||
Emitter _emitter[MAX_EMITTERS];
|
Emitter _emitter[MAX_EMITTERS];
|
||||||
Particle _particle[MAX_PARTICLES];
|
Particle _particle[MAX_PARTICLES];
|
||||||
int _numParticles;
|
|
||||||
int _numEmitters;
|
int _numEmitters;
|
||||||
|
float _timer;
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
void updateParticle(int index, float deltaTime);
|
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 killParticle(int p);
|
||||||
void renderEmitter(int emitterIndex, float size);
|
void renderEmitter(int emitterIndex, float size);
|
||||||
void renderParticle(int p);
|
void renderParticle(int p);
|
||||||
|
|
|
@ -365,7 +365,33 @@ void renderGroundPlaneGrid(float size, float impact) {
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, const float& mouseVoxelZ, const float& mouseVoxelS) {
|
||||||
|
glm::vec3 origin = glm::vec3(mouseVoxelX, mouseVoxelY, mouseVoxelZ);
|
||||||
|
|
||||||
|
glLineWidth(3.0);
|
||||||
|
|
||||||
|
const int HALF_GRID_DIMENSIONS = 4;
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
|
||||||
|
glm::vec3 xColor(0.0, 0.6, 0.0);
|
||||||
|
glColor3fv(&xColor.x);
|
||||||
|
|
||||||
|
glVertex3f(origin.x + HALF_GRID_DIMENSIONS * mouseVoxelS, 0, origin.z);
|
||||||
|
glVertex3f(origin.x - HALF_GRID_DIMENSIONS * mouseVoxelS, 0, origin.z);
|
||||||
|
|
||||||
|
glm::vec3 zColor(0.0, 0.0, 0.6);
|
||||||
|
glColor3fv(&zColor.x);
|
||||||
|
|
||||||
|
glVertex3f(origin.x, 0, origin.z + HALF_GRID_DIMENSIONS * mouseVoxelS);
|
||||||
|
glVertex3f(origin.x, 0, origin.z - HALF_GRID_DIMENSIONS * mouseVoxelS);
|
||||||
|
|
||||||
|
glm::vec3 yColor(0.6, 0.0, 0.0);
|
||||||
|
glColor3fv(&yColor.x);
|
||||||
|
|
||||||
|
glVertex3f(origin.x, 0, origin.z);
|
||||||
|
glVertex3f(origin.x, origin.y, origin.z);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness) {
|
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness) {
|
||||||
|
|
||||||
|
|
|
@ -59,8 +59,9 @@ double diffclock(timeval *clock1,timeval *clock2);
|
||||||
|
|
||||||
void renderGroundPlaneGrid(float size, float impact);
|
void renderGroundPlaneGrid(float size, float impact);
|
||||||
|
|
||||||
void renderCollisionOverlay(int width, int height, float magnitude);
|
void renderMouseVoxelGrid(const float& mouseVoxelX, const float& mouseVoxelY, const float& mouseVoxelZ, const float& mouseVoxelS);
|
||||||
|
|
||||||
|
void renderCollisionOverlay(int width, int height, float magnitude);
|
||||||
|
|
||||||
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness);
|
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness);
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,11 @@ void Webcam::setEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float UNINITIALIZED_FACE_DEPTH = 0.0f;
|
||||||
|
|
||||||
void Webcam::reset() {
|
void Webcam::reset() {
|
||||||
_initialFaceRect = RotatedRect();
|
_initialFaceRect = RotatedRect();
|
||||||
|
_initialFaceDepth = UNINITIALIZED_FACE_DEPTH;
|
||||||
|
|
||||||
if (_enabled) {
|
if (_enabled) {
|
||||||
// send a message to the grabber
|
// send a message to the grabber
|
||||||
|
@ -149,7 +152,10 @@ Webcam::~Webcam() {
|
||||||
delete _grabber;
|
delete _grabber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Webcam::setFrame(const Mat& color, int format, const Mat& depth, const RotatedRect& faceRect, const JointVector& joints) {
|
const float METERS_PER_MM = 1.0f / 1000.0f;
|
||||||
|
|
||||||
|
void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float meanFaceDepth,
|
||||||
|
const RotatedRect& faceRect, const JointVector& joints) {
|
||||||
IplImage colorImage = color;
|
IplImage colorImage = color;
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, colorImage.widthStep / 3);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, colorImage.widthStep / 3);
|
||||||
if (_colorTextureID == 0) {
|
if (_colorTextureID == 0) {
|
||||||
|
@ -232,22 +238,28 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, const Rota
|
||||||
const float ROTATION_SMOOTHING = 0.95f;
|
const float ROTATION_SMOOTHING = 0.95f;
|
||||||
_estimatedRotation.z = glm::mix(_faceRect.angle, _estimatedRotation.z, ROTATION_SMOOTHING);
|
_estimatedRotation.z = glm::mix(_faceRect.angle, _estimatedRotation.z, ROTATION_SMOOTHING);
|
||||||
|
|
||||||
// determine position based on translation and scaling of the face rect
|
// determine position based on translation and scaling of the face rect/mean face depth
|
||||||
if (_initialFaceRect.size.area() == 0) {
|
if (_initialFaceRect.size.area() == 0) {
|
||||||
_initialFaceRect = _faceRect;
|
_initialFaceRect = _faceRect;
|
||||||
_estimatedPosition = glm::vec3();
|
_estimatedPosition = glm::vec3();
|
||||||
|
_initialFaceDepth = meanFaceDepth;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
float proportion = sqrtf(_initialFaceRect.size.area() / (float)_faceRect.size.area());
|
float proportion, z;
|
||||||
const float DISTANCE_TO_CAMERA = 0.333f;
|
if (meanFaceDepth == UNINITIALIZED_FACE_DEPTH) {
|
||||||
|
proportion = sqrtf(_initialFaceRect.size.area() / (float)_faceRect.size.area());
|
||||||
|
const float INITIAL_DISTANCE_TO_CAMERA = 0.333f;
|
||||||
|
z = INITIAL_DISTANCE_TO_CAMERA * proportion - INITIAL_DISTANCE_TO_CAMERA;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
z = (meanFaceDepth - _initialFaceDepth) * METERS_PER_MM;
|
||||||
|
proportion = meanFaceDepth / _initialFaceDepth;
|
||||||
|
}
|
||||||
const float POSITION_SCALE = 0.5f;
|
const float POSITION_SCALE = 0.5f;
|
||||||
float z = DISTANCE_TO_CAMERA * proportion - DISTANCE_TO_CAMERA;
|
_estimatedPosition = glm::vec3(
|
||||||
glm::vec3 position = glm::vec3(
|
|
||||||
(_faceRect.center.x - _initialFaceRect.center.x) * proportion * POSITION_SCALE / _textureSize.width,
|
(_faceRect.center.x - _initialFaceRect.center.x) * proportion * POSITION_SCALE / _textureSize.width,
|
||||||
(_faceRect.center.y - _initialFaceRect.center.y) * proportion * POSITION_SCALE / _textureSize.width,
|
(_faceRect.center.y - _initialFaceRect.center.y) * proportion * POSITION_SCALE / _textureSize.width,
|
||||||
z);
|
z);
|
||||||
const float POSITION_SMOOTHING = 0.95f;
|
|
||||||
_estimatedPosition = glm::mix(position, _estimatedPosition, POSITION_SMOOTHING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +271,7 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, const Rota
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameGrabber::FrameGrabber() : _initialized(false), _capture(0), _searchWindow(0, 0, 0, 0),
|
FrameGrabber::FrameGrabber() : _initialized(false), _capture(0), _searchWindow(0, 0, 0, 0),
|
||||||
_depthOffset(0.0), _codec(), _frameCount(0) {
|
_smoothedMeanFaceDepth(UNINITIALIZED_FACE_DEPTH), _colorCodec(), _depthCodec(), _frameCount(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameGrabber::~FrameGrabber() {
|
FrameGrabber::~FrameGrabber() {
|
||||||
|
@ -367,9 +379,13 @@ void FrameGrabber::shutdown() {
|
||||||
cvReleaseCapture(&_capture);
|
cvReleaseCapture(&_capture);
|
||||||
_capture = 0;
|
_capture = 0;
|
||||||
}
|
}
|
||||||
if (_codec.name != 0) {
|
if (_colorCodec.name != 0) {
|
||||||
vpx_codec_destroy(&_codec);
|
vpx_codec_destroy(&_colorCodec);
|
||||||
_codec.name = 0;
|
_colorCodec.name = 0;
|
||||||
|
}
|
||||||
|
if (_depthCodec.name != 0) {
|
||||||
|
vpx_codec_destroy(&_depthCodec);
|
||||||
|
_depthCodec.name = 0;
|
||||||
}
|
}
|
||||||
_initialized = false;
|
_initialized = false;
|
||||||
|
|
||||||
|
@ -423,7 +439,6 @@ void FrameGrabber::grabFrame() {
|
||||||
_userID, (XnSkeletonJoint)parentJoint, parentOrientation);
|
_userID, (XnSkeletonJoint)parentJoint, parentOrientation);
|
||||||
rotation = glm::inverse(xnToGLM(parentOrientation.orientation)) * rotation;
|
rotation = glm::inverse(xnToGLM(parentOrientation.orientation)) * rotation;
|
||||||
}
|
}
|
||||||
const float METERS_PER_MM = 1.0f / 1000.0f;
|
|
||||||
joints[avatarJoint] = Joint(xnToGLM(transform.position.position, true) * METERS_PER_MM,
|
joints[avatarJoint] = Joint(xnToGLM(transform.position.position, true) * METERS_PER_MM,
|
||||||
rotation, xnToGLM(projected));
|
rotation, xnToGLM(projected));
|
||||||
}
|
}
|
||||||
|
@ -480,31 +495,23 @@ void FrameGrabber::grabFrame() {
|
||||||
_searchWindow = Rect(clip(faceBounds.tl(), imageBounds), clip(faceBounds.br(), imageBounds));
|
_searchWindow = Rect(clip(faceBounds.tl(), imageBounds), clip(faceBounds.br(), imageBounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_OPENNI
|
|
||||||
if (_depthGenerator.IsValid()) {
|
|
||||||
// convert from 11 to 8 bits, centered about the mean face depth (if possible)
|
|
||||||
if (_searchWindow.area() > 0) {
|
|
||||||
const double DEPTH_OFFSET_SMOOTHING = 0.95;
|
|
||||||
const double EIGHT_BIT_MIDPOINT = 128.0;
|
|
||||||
double meanOffset = EIGHT_BIT_MIDPOINT - mean(depth(_searchWindow))[0];
|
|
||||||
_depthOffset = (_depthOffset == 0.0) ? meanOffset : glm::mix(meanOffset, _depthOffset, DEPTH_OFFSET_SMOOTHING);
|
|
||||||
}
|
|
||||||
depth.convertTo(_grayDepthFrame, CV_8UC1, 1.0, _depthOffset);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const int ENCODED_FACE_WIDTH = 128;
|
const int ENCODED_FACE_WIDTH = 128;
|
||||||
const int ENCODED_FACE_HEIGHT = 128;
|
const int ENCODED_FACE_HEIGHT = 128;
|
||||||
int combinedFaceHeight = ENCODED_FACE_HEIGHT * (depth.empty() ? 1 : 2);
|
if (_colorCodec.name == 0) {
|
||||||
if (_codec.name == 0) {
|
// initialize encoder context(s)
|
||||||
// initialize encoder context
|
|
||||||
vpx_codec_enc_cfg_t codecConfig;
|
vpx_codec_enc_cfg_t codecConfig;
|
||||||
vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &codecConfig, 0);
|
vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &codecConfig, 0);
|
||||||
codecConfig.rc_target_bitrate = ENCODED_FACE_WIDTH * combinedFaceHeight * codecConfig.rc_target_bitrate /
|
codecConfig.rc_target_bitrate = ENCODED_FACE_WIDTH * ENCODED_FACE_HEIGHT *
|
||||||
codecConfig.g_w / codecConfig.g_h;
|
codecConfig.rc_target_bitrate / codecConfig.g_w / codecConfig.g_h;
|
||||||
codecConfig.g_w = ENCODED_FACE_WIDTH;
|
codecConfig.g_w = ENCODED_FACE_WIDTH;
|
||||||
codecConfig.g_h = combinedFaceHeight;
|
codecConfig.g_h = ENCODED_FACE_HEIGHT;
|
||||||
vpx_codec_enc_init(&_codec, vpx_codec_vp8_cx(), &codecConfig, 0);
|
vpx_codec_enc_init(&_colorCodec, vpx_codec_vp8_cx(), &codecConfig, 0);
|
||||||
|
|
||||||
|
if (!depth.empty()) {
|
||||||
|
int DEPTH_BITRATE_MULTIPLIER = 2;
|
||||||
|
codecConfig.rc_target_bitrate *= 2;
|
||||||
|
vpx_codec_enc_init(&_depthCodec, vpx_codec_vp8_cx(), &codecConfig, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// correct for 180 degree rotations
|
// correct for 180 degree rotations
|
||||||
|
@ -541,9 +548,9 @@ void FrameGrabber::grabFrame() {
|
||||||
const int ENCODED_BITS_PER_VU = 2;
|
const int ENCODED_BITS_PER_VU = 2;
|
||||||
const int ENCODED_BITS_PER_PIXEL = ENCODED_BITS_PER_Y + 2 * ENCODED_BITS_PER_VU;
|
const int ENCODED_BITS_PER_PIXEL = ENCODED_BITS_PER_Y + 2 * ENCODED_BITS_PER_VU;
|
||||||
const int BITS_PER_BYTE = 8;
|
const int BITS_PER_BYTE = 8;
|
||||||
_encodedFace.fill(128, ENCODED_FACE_WIDTH * combinedFaceHeight * ENCODED_BITS_PER_PIXEL / BITS_PER_BYTE);
|
_encodedFace.resize(ENCODED_FACE_WIDTH * ENCODED_FACE_HEIGHT * ENCODED_BITS_PER_PIXEL / BITS_PER_BYTE);
|
||||||
vpx_image_t vpxImage;
|
vpx_image_t vpxImage;
|
||||||
vpx_img_wrap(&vpxImage, VPX_IMG_FMT_YV12, ENCODED_FACE_WIDTH, combinedFaceHeight, 1, (unsigned char*)_encodedFace.data());
|
vpx_img_wrap(&vpxImage, VPX_IMG_FMT_YV12, ENCODED_FACE_WIDTH, ENCODED_FACE_HEIGHT, 1, (unsigned char*)_encodedFace.data());
|
||||||
uchar* yline = vpxImage.planes[0];
|
uchar* yline = vpxImage.planes[0];
|
||||||
uchar* vline = vpxImage.planes[1];
|
uchar* vline = vpxImage.planes[1];
|
||||||
uchar* uline = vpxImage.planes[2];
|
uchar* uline = vpxImage.planes[2];
|
||||||
|
@ -571,9 +578,9 @@ void FrameGrabber::grabFrame() {
|
||||||
|
|
||||||
ydest[0] = (tl[redIndex] * Y_RED_WEIGHT + tl[1] * Y_GREEN_WEIGHT + tl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
ydest[0] = (tl[redIndex] * Y_RED_WEIGHT + tl[1] * Y_GREEN_WEIGHT + tl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||||
ydest[1] = (tr[redIndex] * Y_RED_WEIGHT + tr[1] * Y_GREEN_WEIGHT + tr[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
ydest[1] = (tr[redIndex] * Y_RED_WEIGHT + tr[1] * Y_GREEN_WEIGHT + tr[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||||
ydest[ENCODED_FACE_WIDTH] = (bl[redIndex] * Y_RED_WEIGHT + bl[greenIndex] *
|
ydest[vpxImage.stride[0]] = (bl[redIndex] * Y_RED_WEIGHT + bl[greenIndex] *
|
||||||
Y_GREEN_WEIGHT + bl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
Y_GREEN_WEIGHT + bl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||||
ydest[ENCODED_FACE_WIDTH + 1] = (br[redIndex] * Y_RED_WEIGHT + br[greenIndex] *
|
ydest[vpxImage.stride[0] + 1] = (br[redIndex] * Y_RED_WEIGHT + br[greenIndex] *
|
||||||
Y_GREEN_WEIGHT + br[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
Y_GREEN_WEIGHT + br[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||||
ydest += 2;
|
ydest += 2;
|
||||||
|
|
||||||
|
@ -590,37 +597,107 @@ void FrameGrabber::grabFrame() {
|
||||||
uline += vpxImage.stride[2];
|
uline += vpxImage.stride[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have depth data, warp that and just copy it in
|
|
||||||
if (!depth.empty()) {
|
|
||||||
_faceDepth.create(ENCODED_FACE_WIDTH, ENCODED_FACE_HEIGHT, CV_8UC1);
|
|
||||||
warpAffine(_grayDepthFrame, _faceDepth, transform, _faceDepth.size());
|
|
||||||
|
|
||||||
uchar* dest = (uchar*)_encodedFace.data() + vpxImage.stride[0] * ENCODED_FACE_HEIGHT;
|
|
||||||
for (int i = 0; i < ENCODED_FACE_HEIGHT; i++) {
|
|
||||||
memcpy(dest, _faceDepth.ptr(i), ENCODED_FACE_WIDTH);
|
|
||||||
dest += vpxImage.stride[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode the frame
|
// encode the frame
|
||||||
vpx_codec_encode(&_codec, &vpxImage, ++_frameCount, 1, 0, VPX_DL_REALTIME);
|
vpx_codec_encode(&_colorCodec, &vpxImage, ++_frameCount, 1, 0, VPX_DL_REALTIME);
|
||||||
|
|
||||||
|
// start the payload off with the aspect ratio
|
||||||
|
QByteArray payload(sizeof(float), 0);
|
||||||
|
*(float*)payload.data() = _smoothedFaceRect.size.width / _smoothedFaceRect.size.height;
|
||||||
|
|
||||||
// extract the encoded frame
|
// extract the encoded frame
|
||||||
vpx_codec_iter_t iterator = 0;
|
vpx_codec_iter_t iterator = 0;
|
||||||
const vpx_codec_cx_pkt_t* packet;
|
const vpx_codec_cx_pkt_t* packet;
|
||||||
while ((packet = vpx_codec_get_cx_data(&_codec, &iterator)) != 0) {
|
while ((packet = vpx_codec_get_cx_data(&_colorCodec, &iterator)) != 0) {
|
||||||
if (packet->kind == VPX_CODEC_CX_FRAME_PKT) {
|
if (packet->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||||
// prepend the aspect ratio
|
// prepend the length, which will indicate whether there's a depth frame too
|
||||||
QByteArray payload(sizeof(float), 0);
|
payload.append((const char*)&packet->data.frame.sz, sizeof(packet->data.frame.sz));
|
||||||
*(float*)payload.data() = _smoothedFaceRect.size.width / _smoothedFaceRect.size.height;
|
|
||||||
payload.append((const char*)packet->data.frame.buf, packet->data.frame.sz);
|
payload.append((const char*)packet->data.frame.buf, packet->data.frame.sz);
|
||||||
QMetaObject::invokeMethod(Application::getInstance(), "sendAvatarFaceVideoMessage", Q_ARG(int, _frameCount),
|
|
||||||
Q_ARG(QByteArray, payload));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!depth.empty()) {
|
||||||
|
// warp the face depth without interpolation (because it will contain invalid zero values)
|
||||||
|
_faceDepth.create(ENCODED_FACE_WIDTH, ENCODED_FACE_HEIGHT, CV_16UC1);
|
||||||
|
warpAffine(depth, _faceDepth, transform, _faceDepth.size(), INTER_NEAREST);
|
||||||
|
|
||||||
|
// find the mean of the valid values
|
||||||
|
qint64 depthTotal = 0;
|
||||||
|
qint64 depthSamples = 0;
|
||||||
|
ushort* src = _faceDepth.ptr<ushort>();
|
||||||
|
const ushort ELEVEN_BIT_MINIMUM = 0;
|
||||||
|
const ushort ELEVEN_BIT_MAXIMUM = 2047;
|
||||||
|
for (int i = 0; i < ENCODED_FACE_HEIGHT; i++) {
|
||||||
|
for (int j = 0; j < ENCODED_FACE_WIDTH; j++) {
|
||||||
|
ushort depth = *src++;
|
||||||
|
if (depth != ELEVEN_BIT_MINIMUM && depth != ELEVEN_BIT_MAXIMUM) {
|
||||||
|
depthTotal += depth;
|
||||||
|
depthSamples++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float mean = (depthSamples == 0) ? UNINITIALIZED_FACE_DEPTH : depthTotal / (float)depthSamples;
|
||||||
|
|
||||||
|
// smooth the mean over time
|
||||||
|
const float DEPTH_OFFSET_SMOOTHING = 0.95f;
|
||||||
|
_smoothedMeanFaceDepth = (_smoothedMeanFaceDepth == UNINITIALIZED_FACE_DEPTH) ? mean :
|
||||||
|
glm::mix(mean, _smoothedMeanFaceDepth, DEPTH_OFFSET_SMOOTHING);
|
||||||
|
|
||||||
|
// convert from 11 to 8 bits for preview/local display
|
||||||
|
const uchar EIGHT_BIT_MIDPOINT = 128;
|
||||||
|
double depthOffset = EIGHT_BIT_MIDPOINT - _smoothedMeanFaceDepth;
|
||||||
|
depth.convertTo(_grayDepthFrame, CV_8UC1, 1.0, depthOffset);
|
||||||
|
|
||||||
|
// likewise for the encoded representation
|
||||||
|
uchar* yline = vpxImage.planes[0];
|
||||||
|
uchar* vline = vpxImage.planes[1];
|
||||||
|
uchar* uline = vpxImage.planes[2];
|
||||||
|
const uchar EIGHT_BIT_MAXIMUM = 255;
|
||||||
|
for (int i = 0; i < ENCODED_FACE_HEIGHT; i += 2) {
|
||||||
|
uchar* ydest = yline;
|
||||||
|
uchar* vdest = vline;
|
||||||
|
uchar* udest = uline;
|
||||||
|
for (int j = 0; j < ENCODED_FACE_WIDTH; j += 2) {
|
||||||
|
ushort tl = *_faceDepth.ptr<ushort>(i, j);
|
||||||
|
ushort tr = *_faceDepth.ptr<ushort>(i, j + 1);
|
||||||
|
ushort bl = *_faceDepth.ptr<ushort>(i + 1, j);
|
||||||
|
ushort br = *_faceDepth.ptr<ushort>(i + 1, j + 1);
|
||||||
|
|
||||||
|
uchar mask = EIGHT_BIT_MAXIMUM;
|
||||||
|
|
||||||
|
ydest[0] = (tl == ELEVEN_BIT_MINIMUM) ? (mask = EIGHT_BIT_MIDPOINT) : saturate_cast<uchar>(tl + depthOffset);
|
||||||
|
ydest[1] = (tr == ELEVEN_BIT_MINIMUM) ? (mask = EIGHT_BIT_MIDPOINT) : saturate_cast<uchar>(tr + depthOffset);
|
||||||
|
ydest[vpxImage.stride[0]] = (bl == ELEVEN_BIT_MINIMUM) ?
|
||||||
|
(mask = EIGHT_BIT_MIDPOINT) : saturate_cast<uchar>(bl + depthOffset);
|
||||||
|
ydest[vpxImage.stride[0] + 1] = (br == ELEVEN_BIT_MINIMUM) ?
|
||||||
|
(mask = EIGHT_BIT_MIDPOINT) : saturate_cast<uchar>(br + depthOffset);
|
||||||
|
ydest += 2;
|
||||||
|
|
||||||
|
*vdest++ = mask;
|
||||||
|
*udest++ = EIGHT_BIT_MIDPOINT;
|
||||||
|
}
|
||||||
|
yline += vpxImage.stride[0] * 2;
|
||||||
|
vline += vpxImage.stride[1];
|
||||||
|
uline += vpxImage.stride[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode the frame
|
||||||
|
vpx_codec_encode(&_depthCodec, &vpxImage, _frameCount, 1, 0, VPX_DL_REALTIME);
|
||||||
|
|
||||||
|
// extract the encoded frame
|
||||||
|
vpx_codec_iter_t iterator = 0;
|
||||||
|
const vpx_codec_cx_pkt_t* packet;
|
||||||
|
while ((packet = vpx_codec_get_cx_data(&_depthCodec, &iterator)) != 0) {
|
||||||
|
if (packet->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||||
|
payload.append((const char*)packet->data.frame.buf, packet->data.frame.sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(Application::getInstance(), "sendAvatarFaceVideoMessage",
|
||||||
|
Q_ARG(int, _frameCount), Q_ARG(QByteArray, payload));
|
||||||
|
|
||||||
QMetaObject::invokeMethod(Application::getInstance()->getWebcam(), "setFrame",
|
QMetaObject::invokeMethod(Application::getInstance()->getWebcam(), "setFrame",
|
||||||
Q_ARG(cv::Mat, color), Q_ARG(int, format), Q_ARG(cv::Mat, _grayDepthFrame),
|
Q_ARG(cv::Mat, color), Q_ARG(int, format), Q_ARG(cv::Mat, _grayDepthFrame), Q_ARG(float, _smoothedMeanFaceDepth),
|
||||||
Q_ARG(cv::RotatedRect, _smoothedFaceRect), Q_ARG(JointVector, joints));
|
Q_ARG(cv::RotatedRect, _smoothedFaceRect), Q_ARG(JointVector, joints));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
#ifdef HAVE_OPENNI
|
#if defined(HAVE_OPENNI) && !defined(Q_MOC_RUN)
|
||||||
#include <XnCppWrapper.h>
|
#include <XnCppWrapper.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setFrame(const cv::Mat& color, int format, const cv::Mat& depth,
|
void setFrame(const cv::Mat& color, int format, const cv::Mat& depth, float meanFaceDepth,
|
||||||
const cv::RotatedRect& faceRect, const JointVector& joints);
|
const cv::RotatedRect& faceRect, const JointVector& joints);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -77,6 +77,7 @@ private:
|
||||||
cv::Size2f _textureSize;
|
cv::Size2f _textureSize;
|
||||||
cv::RotatedRect _faceRect;
|
cv::RotatedRect _faceRect;
|
||||||
cv::RotatedRect _initialFaceRect;
|
cv::RotatedRect _initialFaceRect;
|
||||||
|
float _initialFaceDepth;
|
||||||
JointVector _joints;
|
JointVector _joints;
|
||||||
|
|
||||||
uint64_t _startTimestamp;
|
uint64_t _startTimestamp;
|
||||||
|
@ -117,9 +118,10 @@ private:
|
||||||
cv::Mat _backProject;
|
cv::Mat _backProject;
|
||||||
cv::Rect _searchWindow;
|
cv::Rect _searchWindow;
|
||||||
cv::Mat _grayDepthFrame;
|
cv::Mat _grayDepthFrame;
|
||||||
double _depthOffset;
|
float _smoothedMeanFaceDepth;
|
||||||
|
|
||||||
vpx_codec_ctx_t _codec;
|
vpx_codec_ctx_t _colorCodec;
|
||||||
|
vpx_codec_ctx_t _depthCodec;
|
||||||
int _frameCount;
|
int _frameCount;
|
||||||
cv::Mat _faceColor;
|
cv::Mat _faceColor;
|
||||||
cv::Mat _faceDepth;
|
cv::Mat _faceDepth;
|
||||||
|
|
|
@ -121,7 +121,7 @@ void AvatarVoxelSystem::setVoxelURL(const QUrl& url) {
|
||||||
// handle "file://" urls...
|
// handle "file://" urls...
|
||||||
if (url.isLocalFile()) {
|
if (url.isLocalFile()) {
|
||||||
QString pathString = url.path();
|
QString pathString = url.path();
|
||||||
QByteArray pathAsAscii = pathString.toAscii();
|
QByteArray pathAsAscii = pathString.toLocal8Bit();
|
||||||
const char* path = pathAsAscii.data();
|
const char* path = pathAsAscii.data();
|
||||||
readFromSVOFile(path);
|
readFromSVOFile(path);
|
||||||
return;
|
return;
|
||||||
|
@ -255,7 +255,7 @@ void AvatarVoxelSystem::handleVoxelDownloadProgress(qint64 bytesReceived, qint64
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarVoxelSystem::handleVoxelReplyError() {
|
void AvatarVoxelSystem::handleVoxelReplyError() {
|
||||||
qDebug("%s\n", _voxelReply->errorString().toAscii().constData());
|
qDebug("%s\n", _voxelReply->errorString().toLocal8Bit().constData());
|
||||||
|
|
||||||
_voxelReply->disconnect(this);
|
_voxelReply->disconnect(this);
|
||||||
_voxelReply->deleteLater();
|
_voxelReply->deleteLater();
|
||||||
|
|
|
@ -30,19 +30,25 @@ GLuint Face::_vboID;
|
||||||
GLuint Face::_iboID;
|
GLuint Face::_iboID;
|
||||||
|
|
||||||
Face::Face(Head* owningHead) : _owningHead(owningHead), _renderMode(MESH),
|
Face::Face(Head* owningHead) : _owningHead(owningHead), _renderMode(MESH),
|
||||||
_colorTextureID(0), _depthTextureID(0), _codec(), _frameCount(0) {
|
_colorTextureID(0), _depthTextureID(0), _colorCodec(), _depthCodec(), _frameCount(0) {
|
||||||
// we may have been created in the network thread, but we live in the main thread
|
// we may have been created in the network thread, but we live in the main thread
|
||||||
moveToThread(Application::getInstance()->thread());
|
moveToThread(Application::getInstance()->thread());
|
||||||
}
|
}
|
||||||
|
|
||||||
Face::~Face() {
|
Face::~Face() {
|
||||||
if (_codec.name != 0) {
|
if (_colorCodec.name != 0) {
|
||||||
vpx_codec_destroy(&_codec);
|
vpx_codec_destroy(&_colorCodec);
|
||||||
|
|
||||||
// delete our textures, since we know that we own them
|
// delete our texture, since we know that we own it
|
||||||
if (_colorTextureID != 0) {
|
if (_colorTextureID != 0) {
|
||||||
glDeleteTextures(1, &_colorTextureID);
|
glDeleteTextures(1, &_colorTextureID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (_depthCodec.name != 0) {
|
||||||
|
vpx_codec_destroy(&_depthCodec);
|
||||||
|
|
||||||
|
// delete our texture, since we know that we own it
|
||||||
if (_depthTextureID != 0) {
|
if (_depthTextureID != 0) {
|
||||||
glDeleteTextures(1, &_depthTextureID);
|
glDeleteTextures(1, &_depthTextureID);
|
||||||
}
|
}
|
||||||
|
@ -55,9 +61,9 @@ void Face::setTextureRect(const cv::RotatedRect& textureRect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) {
|
int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) {
|
||||||
if (_codec.name == 0) {
|
if (_colorCodec.name == 0) {
|
||||||
// initialize decoder context
|
// initialize decoder context
|
||||||
vpx_codec_dec_init(&_codec, vpx_codec_vp8_dx(), 0, 0);
|
vpx_codec_dec_init(&_colorCodec, vpx_codec_vp8_dx(), 0, 0);
|
||||||
}
|
}
|
||||||
// skip the header
|
// skip the header
|
||||||
unsigned char* packetPosition = packetData;
|
unsigned char* packetPosition = packetData;
|
||||||
|
@ -85,14 +91,14 @@ int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) {
|
||||||
|
|
||||||
if ((_frameBytesRemaining -= payloadSize) <= 0) {
|
if ((_frameBytesRemaining -= payloadSize) <= 0) {
|
||||||
float aspectRatio = *(const float*)_arrivingFrame.constData();
|
float aspectRatio = *(const float*)_arrivingFrame.constData();
|
||||||
vpx_codec_decode(&_codec, (const uint8_t*)_arrivingFrame.constData() + sizeof(float),
|
size_t colorSize = *(const size_t*)(_arrivingFrame.constData() + sizeof(float));
|
||||||
_arrivingFrame.size() - sizeof(float), 0, 0);
|
const uint8_t* colorData = (const uint8_t*)(_arrivingFrame.constData() + sizeof(float) + sizeof(size_t));
|
||||||
|
vpx_codec_decode(&_colorCodec, colorData, colorSize, 0, 0);
|
||||||
vpx_codec_iter_t iterator = 0;
|
vpx_codec_iter_t iterator = 0;
|
||||||
vpx_image_t* image;
|
vpx_image_t* image;
|
||||||
while ((image = vpx_codec_get_frame(&_codec, &iterator)) != 0) {
|
while ((image = vpx_codec_get_frame(&_colorCodec, &iterator)) != 0) {
|
||||||
// convert from YV12 to RGB
|
// convert from YV12 to RGB
|
||||||
const int imageHeight = image->d_w;
|
Mat color(image->d_h, image->d_w, CV_8UC3);
|
||||||
Mat color(imageHeight, image->d_w, CV_8UC3);
|
|
||||||
uchar* yline = image->planes[0];
|
uchar* yline = image->planes[0];
|
||||||
uchar* vline = image->planes[1];
|
uchar* vline = image->planes[1];
|
||||||
uchar* uline = image->planes[2];
|
uchar* uline = image->planes[2];
|
||||||
|
@ -100,7 +106,7 @@ int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) {
|
||||||
const int GREEN_V_WEIGHT = (int)(0.714 * 256);
|
const int GREEN_V_WEIGHT = (int)(0.714 * 256);
|
||||||
const int GREEN_U_WEIGHT = (int)(0.344 * 256);
|
const int GREEN_U_WEIGHT = (int)(0.344 * 256);
|
||||||
const int BLUE_U_WEIGHT = (int)(1.773 * 256);
|
const int BLUE_U_WEIGHT = (int)(1.773 * 256);
|
||||||
for (int i = 0; i < imageHeight; i += 2) {
|
for (int i = 0; i < image->d_h; i += 2) {
|
||||||
uchar* ysrc = yline;
|
uchar* ysrc = yline;
|
||||||
uchar* vsrc = vline;
|
uchar* vsrc = vline;
|
||||||
uchar* usrc = uline;
|
uchar* usrc = uline;
|
||||||
|
@ -144,13 +150,44 @@ int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) {
|
||||||
uline += image->stride[2];
|
uline += image->stride[2];
|
||||||
}
|
}
|
||||||
Mat depth;
|
Mat depth;
|
||||||
if (image->d_h > imageHeight) {
|
|
||||||
// if the height is greater than the width, we have depth data
|
const uint8_t* depthData = colorData + colorSize;
|
||||||
depth.create(imageHeight, image->d_w, CV_8UC1);
|
int depthSize = _arrivingFrame.size() - ((const char*)depthData - _arrivingFrame.constData());
|
||||||
uchar* src = image->planes[0] + image->stride[0] * imageHeight;
|
if (depthSize > 0) {
|
||||||
for (int i = 0; i < imageHeight; i++) {
|
if (_depthCodec.name == 0) {
|
||||||
memcpy(depth.ptr(i), src, image->d_w);
|
// initialize decoder context
|
||||||
src += image->stride[0];
|
vpx_codec_dec_init(&_depthCodec, vpx_codec_vp8_dx(), 0, 0);
|
||||||
|
}
|
||||||
|
vpx_codec_decode(&_depthCodec, depthData, depthSize, 0, 0);
|
||||||
|
vpx_codec_iter_t iterator = 0;
|
||||||
|
vpx_image_t* image;
|
||||||
|
while ((image = vpx_codec_get_frame(&_depthCodec, &iterator)) != 0) {
|
||||||
|
depth.create(image->d_h, image->d_w, CV_8UC1);
|
||||||
|
uchar* yline = image->planes[0];
|
||||||
|
uchar* vline = image->planes[1];
|
||||||
|
const uchar EIGHT_BIT_MAXIMUM = 255;
|
||||||
|
const uchar MASK_THRESHOLD = 192;
|
||||||
|
for (int i = 0; i < image->d_h; i += 2) {
|
||||||
|
uchar* ysrc = yline;
|
||||||
|
uchar* vsrc = vline;
|
||||||
|
for (int j = 0; j < image->d_w; j += 2) {
|
||||||
|
if (*vsrc++ < MASK_THRESHOLD) {
|
||||||
|
*depth.ptr(i, j) = EIGHT_BIT_MAXIMUM;
|
||||||
|
*depth.ptr(i, j + 1) = EIGHT_BIT_MAXIMUM;
|
||||||
|
*depth.ptr(i + 1, j) = EIGHT_BIT_MAXIMUM;
|
||||||
|
*depth.ptr(i + 1, j + 1) = EIGHT_BIT_MAXIMUM;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
*depth.ptr(i, j) = ysrc[0];
|
||||||
|
*depth.ptr(i, j + 1) = ysrc[1];
|
||||||
|
*depth.ptr(i + 1, j) = ysrc[image->stride[0]];
|
||||||
|
*depth.ptr(i + 1, j + 1) = ysrc[image->stride[0] + 1];
|
||||||
|
}
|
||||||
|
ysrc += 2;
|
||||||
|
}
|
||||||
|
yline += image->stride[0] * 2;
|
||||||
|
vline += image->stride[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QMetaObject::invokeMethod(this, "setFrame", Q_ARG(cv::Mat, color),
|
QMetaObject::invokeMethod(this, "setFrame", Q_ARG(cv::Mat, color),
|
||||||
|
|
|
@ -57,7 +57,8 @@ private:
|
||||||
cv::RotatedRect _textureRect;
|
cv::RotatedRect _textureRect;
|
||||||
float _aspectRatio;
|
float _aspectRatio;
|
||||||
|
|
||||||
vpx_codec_ctx_t _codec;
|
vpx_codec_ctx_t _colorCodec;
|
||||||
|
vpx_codec_ctx_t _depthCodec;
|
||||||
|
|
||||||
QByteArray _arrivingFrame;
|
QByteArray _arrivingFrame;
|
||||||
int _frameCount;
|
int _frameCount;
|
||||||
|
|
|
@ -14,19 +14,25 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "renderer/ProgramObject.h"
|
#include "renderer/ProgramObject.h"
|
||||||
|
|
||||||
|
const bool SHOW_LEAP_HAND = false;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Hand::Hand(Avatar* owningAvatar) :
|
Hand::Hand(Avatar* owningAvatar) :
|
||||||
HandData((AvatarData*)owningAvatar),
|
HandData((AvatarData*)owningAvatar),
|
||||||
|
|
||||||
|
_raveGloveClock(0.0f),
|
||||||
|
_raveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR),
|
||||||
|
_raveGloveInitialized(false),
|
||||||
|
_isRaveGloveActive(false),
|
||||||
_owningAvatar(owningAvatar),
|
_owningAvatar(owningAvatar),
|
||||||
_renderAlpha(1.0),
|
_renderAlpha(1.0),
|
||||||
_lookingInMirror(false),
|
_lookingInMirror(false),
|
||||||
_ballColor(0.0, 0.0, 0.4),
|
_ballColor(0.0, 0.0, 0.4)
|
||||||
_particleSystemInitialized(false)
|
|
||||||
{
|
{
|
||||||
// initialize all finger particle emitters with an invalid id as default
|
// initialize all finger particle emitters with an invalid id as default
|
||||||
for (int f = 0; f< NUM_FINGERS_PER_HAND; f ++ ) {
|
for (int f = 0; f< NUM_FINGERS; f ++ ) {
|
||||||
_fingerParticleEmitter[f] = -1;
|
_raveGloveEmitter[f] = NULL_EMITTER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,16 +41,18 @@ void Hand::init() {
|
||||||
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
||||||
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
_ballColor = glm::vec3(0.0, 0.0, 0.4);
|
_ballColor = glm::vec3(0.0, 0.0, 0.4);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Hand::reset() {
|
void Hand::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Hand::simulate(float deltaTime, bool isMine) {
|
void Hand::simulate(float deltaTime, bool isMine) {
|
||||||
if (_isRaveGloveActive) {
|
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) {
|
void Hand::render(bool lookingInMirror) {
|
||||||
|
|
||||||
|
@ -87,17 +110,20 @@ void Hand::render(bool lookingInMirror) {
|
||||||
if (_isRaveGloveActive) {
|
if (_isRaveGloveActive) {
|
||||||
renderRaveGloveStage();
|
renderRaveGloveStage();
|
||||||
|
|
||||||
if (_particleSystemInitialized) {
|
if (_raveGloveInitialized) {
|
||||||
_particleSystem.render();
|
updateRaveGloveEmitters(); // do this after calculateGeometry
|
||||||
|
_raveGloveParticleSystem.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_RESCALE_NORMAL);
|
glEnable(GL_RESCALE_NORMAL);
|
||||||
|
|
||||||
|
if ( SHOW_LEAP_HAND ) {
|
||||||
renderFingerTrails();
|
renderFingerTrails();
|
||||||
renderHandSpheres();
|
renderHandSpheres();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Hand::renderRaveGloveStage() {
|
void Hand::renderRaveGloveStage() {
|
||||||
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
||||||
|
@ -203,69 +229,61 @@ void Hand::renderFingerTrails() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::updateFingerParticles(float deltaTime) {
|
void Hand::setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||||
|
const std::vector<glm::vec3>& handNormals) {
|
||||||
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) {
|
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||||
PalmData& palm = getPalms()[i];
|
PalmData& palm = getPalms()[i];
|
||||||
|
if (i < handPositions.size()) {
|
||||||
|
palm.setActive(true);
|
||||||
|
palm.setRawPosition(handPositions[i]);
|
||||||
|
palm.setRawNormal(handNormals[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
palm.setActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// call this right after the geometry of the leap hands are set
|
||||||
|
void Hand::updateRaveGloveEmitters() {
|
||||||
|
|
||||||
|
bool debug = false;
|
||||||
|
|
||||||
|
if (_raveGloveInitialized) {
|
||||||
|
|
||||||
|
if(debug) printf( "\n" );
|
||||||
|
if(debug) printf( "------------------------------------\n" );
|
||||||
|
if(debug) printf( "updating rave glove emitters:\n" );
|
||||||
|
if(debug) printf( "------------------------------------\n" );
|
||||||
|
|
||||||
|
int emitterIndex = 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 (palm.isActive()) {
|
||||||
|
|
||||||
|
if(debug) printf( "is active\n" );
|
||||||
|
|
||||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||||
FingerData& finger = palm.getFingers()[f];
|
FingerData& finger = palm.getFingers()[f];
|
||||||
|
|
||||||
|
if(debug) printf( "emitterIndex %d: ", emitterIndex );
|
||||||
|
|
||||||
if (finger.isActive()) {
|
if (finger.isActive()) {
|
||||||
if (_fingerParticleEmitter[fingerIndex] != -1) {
|
|
||||||
|
|
||||||
glm::vec3 particleEmitterPosition = finger.getTipPosition();
|
if ((emitterIndex >=0)
|
||||||
|
&& (emitterIndex < NUM_FINGERS)) {
|
||||||
|
|
||||||
glm::vec3 fingerDirection = particleEmitterPosition - leapPositionToWorldPosition(finger.getRootPosition());
|
assert(emitterIndex >=0 );
|
||||||
|
assert(emitterIndex < NUM_FINGERS );
|
||||||
|
|
||||||
|
if(debug) printf( "_raveGloveEmitter[%d] = %d\n", emitterIndex, _raveGloveEmitter[emitterIndex] );
|
||||||
|
|
||||||
|
glm::vec3 fingerDirection = finger.getTipPosition() - finger.getRootPosition();
|
||||||
float fingerLength = glm::length(fingerDirection);
|
float fingerLength = glm::length(fingerDirection);
|
||||||
|
|
||||||
if (fingerLength > 0.0f) {
|
if (fingerLength > 0.0f) {
|
||||||
|
@ -274,26 +292,390 @@ void Hand::updateFingerParticles(float deltaTime) {
|
||||||
fingerDirection = IDENTITY_UP;
|
fingerDirection = IDENTITY_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat particleEmitterRotation = rotationBetween(palm.getNormal(), fingerDirection);
|
assert(_raveGloveEmitter[emitterIndex] >=0 );
|
||||||
|
assert(_raveGloveEmitter[emitterIndex] < NUM_FINGERS );
|
||||||
|
|
||||||
//glm::quat particleEmitterRotation = glm::angleAxis(0.0f, fingerDirection);
|
_raveGloveParticleSystem.setEmitterPosition (_raveGloveEmitter[emitterIndex], finger.getTipPosition());
|
||||||
|
_raveGloveParticleSystem.setEmitterDirection(_raveGloveEmitter[emitterIndex], 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);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if(debug) printf( "BOGUS finger\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
emitterIndex ++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(debug) printf( "is NOT active\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
|
|
||||||
_particleSystem.simulate(deltaTime);
|
// 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 {
|
||||||
|
|
||||||
|
_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#ifndef hifi_Hand_h
|
#ifndef hifi_Hand_h
|
||||||
#define hifi_Hand_h
|
#define hifi_Hand_h
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
#include <HandData.h>
|
#include <HandData.h>
|
||||||
|
@ -22,6 +23,22 @@
|
||||||
class Avatar;
|
class Avatar;
|
||||||
class ProgramObject;
|
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 {
|
class Hand : public HandData {
|
||||||
public:
|
public:
|
||||||
Hand(Avatar* owningAvatar);
|
Hand(Avatar* owningAvatar);
|
||||||
|
@ -42,9 +59,10 @@ public:
|
||||||
void render(bool lookingInMirror);
|
void render(bool lookingInMirror);
|
||||||
|
|
||||||
void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; }
|
void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; }
|
||||||
void updateFingerParticles(float deltaTime);
|
void updateRaveGloveParticles(float deltaTime);
|
||||||
|
void updateRaveGloveEmitters();
|
||||||
void setRaveGloveActive(bool active) { _isRaveGloveActive = active; }
|
void setRaveGloveActive(bool active) { _isRaveGloveActive = active; }
|
||||||
|
void setRaveGloveEffectsMode(QKeyEvent* event);
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
const glm::vec3& getLeapBallPosition (int ball) const { return _leapBalls[ball].position;}
|
const glm::vec3& getLeapBallPosition (int ball) const { return _leapBalls[ball].position;}
|
||||||
|
@ -55,20 +73,25 @@ private:
|
||||||
Hand(const Hand&);
|
Hand(const Hand&);
|
||||||
Hand& operator= (const Hand&);
|
Hand& operator= (const Hand&);
|
||||||
|
|
||||||
ParticleSystem _particleSystem;
|
ParticleSystem _raveGloveParticleSystem;
|
||||||
|
float _raveGloveClock;
|
||||||
|
int _raveGloveMode;
|
||||||
|
bool _raveGloveInitialized;
|
||||||
|
int _raveGloveEmitter[NUM_FINGERS];
|
||||||
|
bool _isRaveGloveActive;
|
||||||
|
|
||||||
Avatar* _owningAvatar;
|
Avatar* _owningAvatar;
|
||||||
float _renderAlpha;
|
float _renderAlpha;
|
||||||
bool _lookingInMirror;
|
bool _lookingInMirror;
|
||||||
bool _isRaveGloveActive;
|
|
||||||
glm::vec3 _ballColor;
|
glm::vec3 _ballColor;
|
||||||
std::vector<HandBall> _leapBalls;
|
std::vector<HandBall> _leapBalls;
|
||||||
|
|
||||||
bool _particleSystemInitialized;
|
|
||||||
int _fingerParticleEmitter[NUM_FINGERS_PER_HAND];
|
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
|
void setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||||
|
const std::vector<glm::vec3>& handNormals);
|
||||||
|
|
||||||
void renderRaveGloveStage();
|
void renderRaveGloveStage();
|
||||||
|
void setRaveGloveMode(int mode);
|
||||||
void renderHandSpheres();
|
void renderHandSpheres();
|
||||||
void renderFingerTrails();
|
void renderFingerTrails();
|
||||||
void calculateGeometry();
|
void calculateGeometry();
|
||||||
|
|
|
@ -66,7 +66,7 @@ bool ChatEntry::keyPressEvent(QKeyEvent* event) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (_contents.size() < MAX_CONTENT_LENGTH) {
|
if (_contents.size() < MAX_CONTENT_LENGTH) {
|
||||||
_contents.insert(_cursorPos, 1, text.at(0).toAscii());
|
_contents.insert(_cursorPos, 1, text.at(0).toLatin1());
|
||||||
_cursorPos++;
|
_cursorPos++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -81,12 +81,12 @@ def hifiJob(String targetName, Boolean deploy) {
|
||||||
static Closure cmakeBuild(srcDir, instCommand) {
|
static Closure cmakeBuild(srcDir, instCommand) {
|
||||||
return { project ->
|
return { project ->
|
||||||
project / 'builders' / 'hudson.plugins.cmake.CmakeBuilder' {
|
project / 'builders' / 'hudson.plugins.cmake.CmakeBuilder' {
|
||||||
sourceDir srcDir
|
sourceDir '.'
|
||||||
buildDir 'build'
|
buildDir 'build'
|
||||||
installDir ''
|
installDir ''
|
||||||
buildType 'RelWithDebInfo'
|
buildType 'RelWithDebInfo'
|
||||||
generator 'Unix Makefiles'
|
generator 'Unix Makefiles'
|
||||||
makeCommand 'make'
|
makeCommand "make ${srcDir}"
|
||||||
installCommand instCommand
|
installCommand instCommand
|
||||||
preloadScript ''
|
preloadScript ''
|
||||||
cmakeArgs ''
|
cmakeArgs ''
|
||||||
|
|
|
@ -132,10 +132,6 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
||||||
std::vector<glm::vec3> fingerVectors;
|
std::vector<glm::vec3> fingerVectors;
|
||||||
_handData->encodeRemoteData(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)
|
if (fingerVectors.size() > 255)
|
||||||
fingerVectors.clear(); // safety. We shouldn't ever get over 255, so consider that invalid.
|
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);
|
_handState = getSemiNibbleAt(bitItems,HAND_STATE_START_BIT);
|
||||||
|
|
||||||
// leap hand data
|
// leap hand data
|
||||||
if (sourceBuffer - startPosition < numBytes) // safety check
|
if (sourceBuffer - startPosition < numBytes) {
|
||||||
{
|
// check passed, bytes match
|
||||||
unsigned int numFingerVectors = *sourceBuffer++;
|
unsigned int numFingerVectors = *sourceBuffer++;
|
||||||
if (numFingerVectors > 0) {
|
if (numFingerVectors > 0) {
|
||||||
std::vector<glm::vec3> fingerVectors(numFingerVectors);
|
std::vector<glm::vec3> fingerVectors(numFingerVectors);
|
||||||
|
@ -264,8 +260,8 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// skeleton joints
|
// skeleton joints
|
||||||
if (sourceBuffer - startPosition < numBytes) // safety check
|
if (sourceBuffer - startPosition < numBytes) {
|
||||||
{
|
// check passed, bytes match
|
||||||
_joints.resize(*sourceBuffer++);
|
_joints.resize(*sourceBuffer++);
|
||||||
for (vector<JointData>::iterator it = _joints.begin(); it != _joints.end(); it++) {
|
for (vector<JointData>::iterator it = _joints.begin(); it != _joints.end(); it++) {
|
||||||
it->jointID = *sourceBuffer++;
|
it->jointID = *sourceBuffer++;
|
||||||
|
|
|
@ -19,7 +19,10 @@ class AvatarData;
|
||||||
class FingerData;
|
class FingerData;
|
||||||
class PalmData;
|
class PalmData;
|
||||||
|
|
||||||
|
const int NUM_HANDS = 2;
|
||||||
const int NUM_FINGERS_PER_HAND = 5;
|
const int NUM_FINGERS_PER_HAND = 5;
|
||||||
|
const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND;
|
||||||
|
|
||||||
const int LEAPID_INVALID = -1;
|
const int LEAPID_INVALID = -1;
|
||||||
|
|
||||||
class HandData {
|
class HandData {
|
||||||
|
|
|
@ -352,6 +352,12 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte
|
||||||
readPtr += unpackSocket(readPtr, (sockaddr*) &nodePublicSocket);
|
readPtr += unpackSocket(readPtr, (sockaddr*) &nodePublicSocket);
|
||||||
readPtr += unpackSocket(readPtr, (sockaddr*) &nodeLocalSocket);
|
readPtr += unpackSocket(readPtr, (sockaddr*) &nodeLocalSocket);
|
||||||
|
|
||||||
|
// if the public socket address is 0 then it's reachable at the same IP
|
||||||
|
// as the domain server
|
||||||
|
if (nodePublicSocket.sin_addr.s_addr == 0) {
|
||||||
|
inet_aton(_domainIP, &nodePublicSocket.sin_addr);
|
||||||
|
}
|
||||||
|
|
||||||
addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId);
|
addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +518,7 @@ void NodeList::loadData(QSettings *settings) {
|
||||||
|
|
||||||
if (domainServerHostname.size() > 0) {
|
if (domainServerHostname.size() > 0) {
|
||||||
memset(_domainHostname, 0, MAX_HOSTNAME_BYTES);
|
memset(_domainHostname, 0, MAX_HOSTNAME_BYTES);
|
||||||
memcpy(_domainHostname, domainServerHostname.toAscii().constData(), domainServerHostname.size());
|
memcpy(_domainHostname, domainServerHostname.toLocal8Bit().constData(), domainServerHostname.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
|
|
|
@ -18,14 +18,15 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
|
||||||
case PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO:
|
case PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO:
|
||||||
case PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO:
|
case PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO:
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
|
||||||
|
|
||||||
case PACKET_TYPE_HEAD_DATA:
|
case PACKET_TYPE_HEAD_DATA:
|
||||||
return 2;
|
return 2;
|
||||||
break;
|
|
||||||
|
case PACKET_TYPE_AVATAR_FACE_VIDEO:
|
||||||
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,8 @@ PerfStat::~PerfStat() {
|
||||||
if (wantDebugOut) {
|
if (wantDebugOut) {
|
||||||
qDebug("PerfStats: %s elapsed:%f average:%lf count:%ld total:%lf ut:%ld us:%ld ue:%ld t:%ld s:%ld e:%ld\n",
|
qDebug("PerfStats: %s elapsed:%f average:%lf count:%ld total:%lf ut:%ld us:%ld ue:%ld t:%ld s:%ld e:%ld\n",
|
||||||
this->group.c_str(),elapsed,average,count,totalTime,
|
this->group.c_str(),elapsed,average,count,totalTime,
|
||||||
(end.tv_usec-start.tv_usec),start.tv_usec,end.tv_usec,
|
(long)(end.tv_usec-start.tv_usec), (long)start.tv_usec, (long)end.tv_usec,
|
||||||
(end.tv_sec-start.tv_sec),start.tv_sec,end.tv_sec
|
(long)(end.tv_sec-start.tv_sec), (long)start.tv_sec, (long)end.tv_sec
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -188,8 +188,8 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sharedMessageHandler(QtMsgType type, const char* message) {
|
void sharedMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) {
|
||||||
fprintf(stdout, "%s", message);
|
fprintf(stdout, "%s", message.toLocal8Bit().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -68,7 +68,7 @@ void loadRandomIdentifier(unsigned char* identifierBuffer, int numBytes);
|
||||||
const char* getCmdOption(int argc, const char * argv[],const char* option);
|
const char* getCmdOption(int argc, const char * argv[],const char* option);
|
||||||
bool cmdOptionExists(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 {
|
struct VoxelDetail {
|
||||||
float x;
|
float x;
|
||||||
|
|
|
@ -8,9 +8,13 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm
|
||||||
|
|
||||||
set(TARGET_NAME voxels)
|
set(TARGET_NAME voxels)
|
||||||
|
|
||||||
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
|
||||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||||
setup_hifi_library(${TARGET_NAME})
|
setup_hifi_library(${TARGET_NAME})
|
||||||
|
|
||||||
|
qt5_use_modules(${TARGET_NAME} Widgets)
|
||||||
|
|
||||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
|
|
|
@ -432,7 +432,7 @@ int receivedPacketCount = 0;
|
||||||
int main(int argc, const char * argv[]) {
|
int main(int argc, const char * argv[]) {
|
||||||
pthread_mutex_init(&::treeLock, NULL);
|
pthread_mutex_init(&::treeLock, NULL);
|
||||||
|
|
||||||
qInstallMsgHandler(sharedMessageHandler);
|
qInstallMessageHandler(sharedMessageHandler);
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, VOXEL_LISTEN_PORT);
|
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, VOXEL_LISTEN_PORT);
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
Loading…
Reference in a new issue