Merge branch 'master' of https://github.com/worklist/hifi into pointy

This commit is contained in:
Andrzej Kapolka 2013-08-01 15:52:58 -07:00
commit 0052221c33
29 changed files with 1218 additions and 498 deletions

1
.gitignore vendored
View file

@ -4,6 +4,7 @@ CMakeFiles/
CMakeScripts/ CMakeScripts/
cmake_install.cmake cmake_install.cmake
build/ build/
Makefile
# Xcode # Xcode
*.xcodeproj *.xcodeproj

View file

@ -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)

View file

@ -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)

View file

@ -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})

View file

@ -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;
} }
} }

17
interface/CMakeLists.txt Executable file → Normal file
View 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
@ -130,8 +130,7 @@ 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}

View file

@ -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)
@ -25,4 +30,6 @@ 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)

View file

@ -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
{ {

View file

@ -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);
@ -564,6 +564,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()) {
@ -1217,7 +1222,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);
@ -1491,16 +1496,18 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
uint64_t now = usecTimestampNow(); uint64_t now = usecTimestampNow();
// dynamically sleep until we need to fire off the next set of voxels // dynamically sleep until we need to fire off the next set of voxels
const uint64_t CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packet every 10 milliseconds
uint64_t elapsed = now - args->lastSendTime; uint64_t elapsed = now - args->lastSendTime;
int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed; int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed;
if (usecToSleep > 0) { if (usecToSleep > 0) {
qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, sleeping for %d usecs!\n", //qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, sleeping for %d usecs!\n",
args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed, usecToSleep); // args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed, usecToSleep);
Application::getInstance()->timer();
usleep(usecToSleep); usleep(usecToSleep);
} else { } else {
qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, no need to sleep!\n", //qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, no need to sleep!\n",
args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed); // args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed);
} }
args->lastSendTime = now; args->lastSendTime = now;
} }
@ -1513,12 +1520,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) {
@ -1533,11 +1540,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();
@ -1567,71 +1574,128 @@ void Application::importVoxelsToClipboard() {
} }
void Application::importVoxels() { void Application::importVoxels() {
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation,
QStringList fileNameStringList = QFileDialog::getOpenFileNames(_glWidget, tr("Import Voxels"), desktopLocation,
tr(IMPORT_FILE_TYPES)); tr(IMPORT_FILE_TYPES));
QByteArray fileNameAscii = fileNameString.toAscii();
const char* fileName = fileNameAscii.data(); // remember the "selected" voxel point before we do any importing...
float originalX = _mouseVoxel.x;
float originalZ = _mouseVoxel.z;
const int PNG_TYPE_NAME_LENGTH = 4;
const int SVO_TYPE_NAME_LENGTH = 4;
const int SCH_TYPE_NAME_LENGTH = 10;
for (int i = 0; i < fileNameStringList.size(); i++) {
QString fileNameString = fileNameStringList.at(i);
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
const char* fileName = fileNameAscii.data();
VoxelTree importVoxels; int fileTypeNameLength = 0;
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) { VoxelTree importVoxels;
QImage pngImage = QImage(fileName); if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
if (pngImage.height() != pngImage.width()) { QImage pngImage = QImage(fileName);
qDebug("ERROR: Bad PNG size: height != width.\n"); fileTypeNameLength = PNG_TYPE_NAME_LENGTH;
return; if (pngImage.height() != pngImage.width()) {
qDebug("ERROR: Bad PNG size: height != width.\n");
return;
}
const uint32_t* pixels;
if (pngImage.format() == QImage::Format_ARGB32) {
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits());
} else {
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
}
importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height());
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
importVoxels.readFromSVOFile(fileName);
fileTypeNameLength = SVO_TYPE_NAME_LENGTH;
} else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) {
importVoxels.readFromSchematicFile(fileName);
fileTypeNameLength = SCH_TYPE_NAME_LENGTH;
} }
const uint32_t* pixels; int indexOfFirstPeriod = fileNameString.indexOf('.');
if (pngImage.format() == QImage::Format_ARGB32) {
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits()); QString fileCoord = fileNameString.mid(indexOfFirstPeriod + 1,
fileNameString.length() - indexOfFirstPeriod - fileTypeNameLength - 1);
indexOfFirstPeriod = fileCoord.indexOf('.');
QString columnNumString = fileCoord.right(fileCoord.length() - indexOfFirstPeriod - 1);
QString rowNumString = fileCoord.left(indexOfFirstPeriod);
int columnNum = columnNumString.toFloat();
int rowNum = rowNumString.toFloat();
qDebug("columnNum: %d\t rowNum: %d\n", columnNum, rowNum);
_mouseVoxel.x = originalX + (columnNum - 1) * _mouseVoxel.s;
_mouseVoxel.z = originalZ + (rowNum - 1) * _mouseVoxel.s;
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
// Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to
// the server as an set voxel message, this will also rebase the voxels to the new location
unsigned char* calculatedOctCode = NULL;
SendVoxelsOperationArgs args;
args.lastSendTime = usecTimestampNow();
args.packetsSent = 0;
args.bytesSent = 0;
int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[numBytesPacketHeader];
*sequenceAt = 0;
args.bufferInUse = numBytesPacketHeader + sizeof(unsigned short int); // set to command + sequence
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
// voxel size/position details.
if (selectedNode) {
args.newBaseOctCode = selectedNode->getOctalCode();
} else { } else {
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32); args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits()); }
qDebug("column:%d, row:%d, voxel:%f,%f,%f,%f\n", columnNum, rowNum, _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s );
// send the insert/paste of these voxels
importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args);
// If we have voxels left in the packet, then send the packet
if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) {
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
args.packetsSent++;
args.bytesSent += args.bufferInUse;
uint64_t now = usecTimestampNow();
// dynamically sleep until we need to fire off the next set of voxels
uint64_t elapsed = now - args.lastSendTime;
int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed;
if (usecToSleep > 0) {
//qDebug("after sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, sleeping for %d usecs!\n",
// args.packetsSent, (long long int)args.bytesSent, (long long int)elapsed, usecToSleep);
usleep(usecToSleep);
} else {
//qDebug("after sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, no need to sleep!\n",
// args.packetsSent, (long long int)args.bytesSent, (long long int)elapsed);
}
args.lastSendTime = now;
} }
importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height()); if (calculatedOctCode) {
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) { delete[] calculatedOctCode;
importVoxels.readFromSVOFile(fileName); }
} else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) {
importVoxels.readFromSchematicFile(fileName);
} }
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
// Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to
// the server as an set voxel message, this will also rebase the voxels to the new location
unsigned char* calculatedOctCode = NULL;
SendVoxelsOperationArgs args;
args.lastSendTime = usecTimestampNow();
args.packetsSent = 0;
args.bytesSent = 0;
int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[numBytesPacketHeader];
*sequenceAt = 0;
args.bufferInUse = numBytesPacketHeader + sizeof(unsigned short int); // set to command + sequence
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
// voxel size/position details.
if (selectedNode) {
args.newBaseOctCode = selectedNode->getOctalCode();
} else {
args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
}
importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args);
// If we have voxels left in the packet, then send the packet
if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) {
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
}
if (calculatedOctCode) {
delete[] calculatedOctCode;
}
// restore the main window's active state // restore the main window's active state
_window->activateWindow(); _window->activateWindow();
} }
@ -1986,8 +2050,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++) {
@ -2044,8 +2111,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);
@ -2311,8 +2378,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);
@ -2351,7 +2418,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);
@ -2670,13 +2737,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);
@ -2722,13 +2790,12 @@ void Application::displaySide(Camera& whichCamera) {
_particleSystem.render(); _particleSystem.render();
} }
} }
// Render the world box // Render the world box
if (!_lookingInMirror->isChecked() && _renderStatsOn->isChecked()) { render_world_box(); } if (!_lookingInMirror->isChecked() && _renderStatsOn->isChecked()) { render_world_box(); }
// 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() {
@ -3456,6 +3523,7 @@ void* Application::networkReceive(void* args) {
} }
if (NodeList::getInstance()->getNodeSocket()->receive(&senderAddress, app->_incomingPacket, &bytesReceived)) { if (NodeList::getInstance()->getNodeSocket()->receive(&senderAddress, app->_incomingPacket, &bytesReceived)) {
app->_packetCount++; app->_packetCount++;
app->_bytesCount += bytesReceived; app->_bytesCount += bytesReceived;
@ -3500,13 +3568,11 @@ void* Application::networkReceive(void* args) {
Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER); Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) { if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) {
voxelServer->lock(); voxelServer->lock();
if (messageData[0] == PACKET_TYPE_ENVIRONMENT_DATA) { if (messageData[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
app->_environment.parseData(&senderAddress, messageData, messageLength); app->_environment.parseData(&senderAddress, messageData, messageLength);
} else { } else {
app->_voxels.parseData(messageData, messageLength); app->_voxels.parseData(messageData, messageLength);
} }
voxelServer->unlock(); voxelServer->unlock();
} }
} }
@ -3626,7 +3692,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,
@ -3638,7 +3704,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,
@ -3651,56 +3717,57 @@ 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);
glm::vec3 velocity(0.0f, 0.1f, 0.0f); _particleSystem.setEmitterPosition (_coolDemoParticleEmitter, particleEmitterPosition);
float lifespan = 100000.0f; _particleSystem.setEmitterParticleLifespan(_coolDemoParticleEmitter, LIFESPAN_IN_SECONDS);
_particleSystem.emitParticlesNow(_coolDemoParticleEmitter, 1500, velocity, lifespan); _particleSystem.setEmitterThrust (_coolDemoParticleEmitter, 0.0f);
_particleSystem.setEmitterRate (_coolDemoParticleEmitter, EMIT_RATE_IN_SECONDS); // to emit a pile o particles now
} }
// signal that the particle system has been initialized // signal that the particle system has been initialized
_particleSystemInitialized = true; _particleSystemInitialized = true;
} 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;
@ -3711,6 +3778,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
View file

View file

@ -11,77 +11,89 @@
#include "ParticleSystem.h" #include "ParticleSystem.h"
#include "Application.h" #include "Application.h"
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];
a->radius = DEFAULT_PARTICLE_RADIUS;
a->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
a->bounce = DEFAULT_PARTICLE_BOUNCE;
a->airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
a->gravity = 0.0f;
a->jitter = 0.0f;
a->emitterAttraction = 0.0f;
a->tornadoForce = 0.0f;
a->neighborAttraction = 0.0f;
a->neighborRepulsion = 0.0f;
a->collisionSphereRadius = 0.0f;
a->collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
a->usingCollisionSphere = false;
} }
}; };
for (unsigned int p = 0; p < MAX_PARTICLES; p++) { for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
_particle[p].alive = false; _particle[p].alive = false;
_particle[p].age = 0.0f; _particle[p].age = 0.0f;
_particle[p].lifespan = 0.0f; _particle[p].radius = 0.0f;
_particle[p].radius = 0.0f; _particle[p].emitterIndex = 0;
_particle[p].emitterIndex = 0; _particle[p].previousParticle = NULL_PARTICLE;
_particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f); _particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f);
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f); _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
} }
} }
int ParticleSystem::addEmitter() { int ParticleSystem::addEmitter() {
_numEmitters ++; if (_numEmitters < MAX_EMITTERS) {
_numEmitters ++;
if (_numEmitters > MAX_EMITTERS) { return _numEmitters - 1;
return -1;
} }
return _numEmitters - 1; return NULL_EMITTER;
} }
void ParticleSystem::simulate(float deltaTime) { 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 // update particles
for (unsigned int p = 0; p < _numParticles; p++) {
if (_particle[p].alive) { for (int p = 0; p < MAX_PARTICLES; p++) {
if (_particle[p].age > _particle[p].lifespan) { if (_particle[p].alive) {
if (_particle[p].age > _emitter[_particle[p].emitterIndex].particleLifespan) {
killParticle(p); killParticle(p);
} else { } else {
updateParticle(p, deltaTime); updateParticle(p, deltaTime);
@ -90,55 +102,91 @@ void ParticleSystem::simulate(float deltaTime) {
} }
} }
void ParticleSystem::emitParticlesNow(int e, int num, glm::vec3 velocity, float lifespan) { void ParticleSystem::createParticle(int e, float timeFraction) {
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++) { for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
if (!_particle[p].alive) { if (!_particle[p].alive) {
_particle[p].emitterIndex = e; _particle[p].emitterIndex = e;
_particle[p].lifespan = lifespan; _particle[p].alive = true;
_particle[p].alive = true; _particle[p].age = 0.0f;
_particle[p].age = 0.0f; _particle[p].velocity = _emitter[e].direction * _emitter[e].thrust;
_particle[p].velocity = velocity; _particle[p].position = _emitter[e].previousPosition + timeFraction * (_emitter[e].position - _emitter[e].previousPosition);
_particle[p].position = _emitter[e].position; _particle[p].radius = _emitter[e].particleAttributes[PARTICLE_LIFESTAGE_0].radius;
_particle[p].radius = _emitter[e].particleAttributes[0].radius; _particle[p].color = _emitter[e].particleAttributes[PARTICLE_LIFESTAGE_0].color;
_particle[p].color = _emitter[e].particleAttributes[0].color; _particle[p].previousParticle = NULL_PARTICLE;
_numParticles ++;
assert(_numParticles <= MAX_PARTICLES);
return; if (_particle[_emitter[e].currentParticle].alive) {
if (_particle[_emitter[e].currentParticle].emitterIndex == e) {
_particle[p].previousParticle = _emitter[e].currentParticle;
}
}
_emitter[e].currentParticle = p;
break;
} }
} }
} }
void ParticleSystem::killParticle(int p) { void ParticleSystem::killParticle(int p) {
assert( p >= 0); assert(p >= 0);
assert( p < MAX_PARTICLES); assert(p < MAX_PARTICLES);
assert( _numParticles > 0);
_particle[p].alive = false; _particle[p].alive = false;
_numParticles --; _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) { void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) {
for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++ ) { for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++) {
setParticleAttributes(emitterIndex, lifeStage, attributes); setParticleAttributes(emitterIndex, (ParticleLifeStage)lifeStage, attributes);
} }
} }
void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, ParticleAttributes attributes) { void ParticleSystem::setParticleAttributesToDefault(ParticleAttributes * a) {
a->radius = DEFAULT_PARTICLE_RADIUS;
a->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
a->bounce = DEFAULT_PARTICLE_BOUNCE;
a->airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
a->gravity = 0.0f;
a->jitter = 0.0f;
a->emitterAttraction = 0.0f;
a->tornadoForce = 0.0f;
a->neighborAttraction = 0.0f;
a->neighborRepulsion = 0.0f;
a->collisionSphereRadius = 0.0f;
a->collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
a->usingCollisionSphere = false;
a->collisionPlaneNormal = _upDirection;
a->collisionPlanePosition = glm::vec3(0.0f, 0.0f, 0.0f);
a->usingCollisionPlane = false;
a->modulationAmplitude = 0.0f;
a->modulationRate = 0.0;
a->modulationStyle = COLOR_MODULATION_STYLE_NULL;
}
void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes) {
assert(lifeStage >= 0);
assert(lifeStage < NUM_PARTICLE_LIFE_STAGES);
ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage]; ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage];
@ -155,155 +203,196 @@ 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];
// apply random jitter assert(_particle[p].age <= myEmitter.particleLifespan);
float j = myEmitter.particleAttributes[lifeStage].jitter;
_particle[p].velocity +=
glm::vec3
(
-j * ONE_HALF + j * randFloat(),
-j * ONE_HALF + j * randFloat(),
-j * ONE_HALF + j * randFloat()
) * deltaTime;
// apply attraction to home position
glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;
_particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime;
// apply neighbor attraction
int neighbor = p + 1;
if (neighbor == _numParticles ) {
neighbor = 0;
}
if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
_particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
float distanceToNeighbor = glm::length(vectorToNeighbor); float ageFraction = 0.0f;
if (distanceToNeighbor > 0.0f) { int lifeStage = 0;
_particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime; float lifeStageFraction = 0.0f;
}
}
// apply tornado force
glm::vec3 emitterUp = myEmitter.rotation * IDENTITY_UP;
glm::vec3 tornadoDirection = glm::cross(vectorToHome, emitterUp);
_particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
// apply air friction if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) {
float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
if (drag < 0.0f) {
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
} else {
_particle[p].velocity *= drag;
}
// apply gravity
_particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
// update position by velocity
_particle[p].position += _particle[p].velocity;
// collision with ground
if (_particle[p].position.y < _particle[p].radius) {
_particle[p].position.y = _particle[p].radius;
if (_particle[p].velocity.y < 0.0f) { ageFraction = _particle[p].age / myEmitter.particleLifespan;
_particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce; lifeStage = (int)(ageFraction * (NUM_PARTICLE_LIFE_STAGES - 1));
} lifeStageFraction = ageFraction * (NUM_PARTICLE_LIFE_STAGES - 1) - lifeStage;
}
// adjust radius
// collision with sphere _particle[p].radius
if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) { = myEmitter.particleAttributes[lifeStage ].radius * (1.0f - lifeStageFraction)
glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position; + myEmitter.particleAttributes[lifeStage+1].radius * lifeStageFraction;
float distanceToSphereCenter = glm::length(vectorToSphereCenter);
float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
if (distanceToSphereCenter < combinedRadius) {
if (distanceToSphereCenter > 0.0f){ // apply random jitter
glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter; float j = myEmitter.particleAttributes[lifeStage].jitter;
_particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius; _particle[p].velocity +=
glm::vec3
(
-j * ONE_HALF + j * randFloat(),
-j * ONE_HALF + j * randFloat(),
-j * ONE_HALF + j * randFloat()
) * deltaTime;
// apply attraction to home position
glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;
_particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime;
// apply neighbor attraction
int neighbor = p + 1;
if (neighbor == MAX_PARTICLES) {
neighbor = 0;
}
if (_particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
_particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
float distanceToNeighbor = glm::length(vectorToNeighbor);
if (distanceToNeighbor > 0.0f) {
_particle[neighbor].velocity += (vectorToNeighbor / (1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime;
}
}
// apply tornado force
glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.direction);
_particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
// apply air friction
float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
if (drag < 0.0f) {
_particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
} else {
_particle[p].velocity *= drag;
}
// apply gravity
_particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
// update position by velocity
_particle[p].position += _particle[p].velocity;
// collision with the plane surface
if (myEmitter.particleAttributes[lifeStage].usingCollisionPlane) {
glm::vec3 vectorFromParticleToPlanePosition = _particle[p].position - myEmitter.particleAttributes[lifeStage].collisionPlanePosition;
glm::vec3 normal = myEmitter.particleAttributes[lifeStage].collisionPlaneNormal;
float dot = glm::dot(vectorFromParticleToPlanePosition, normal);
if (dot < _particle[p].radius) {
_particle[p].position += normal * (_particle[p].radius - dot);
float planeNormalComponentOfVelocity = glm::dot(_particle[p].velocity, normal);
_particle[p].velocity -= normal * planeNormalComponentOfVelocity * (1.0f + myEmitter.particleAttributes[lifeStage].bounce);
}
}
// collision with sphere
if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
float distanceToSphereCenter = glm::length(vectorToSphereCenter);
float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
if (distanceToSphereCenter < combinedRadius) {
if (distanceToSphereCenter > 0.0f){
glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
_particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius;
}
} }
} }
} }
// adjust color
_particle[p].color
= myEmitter.particleAttributes[lifeStage ].color * (1.0f - lifeStageFraction)
+ myEmitter.particleAttributes[lifeStage+1].color * lifeStageFraction;
// apply color modulation
if (myEmitter.particleAttributes[lifeStage ].modulationAmplitude > 0.0f) {
float modulation = 0.0f;
float radian = _timer * myEmitter.particleAttributes[lifeStage ].modulationRate * PI_TIMES_TWO;
if (myEmitter.particleAttributes[lifeStage ].modulationStyle == COLOR_MODULATION_STYLE_LIGHNTESS_PULSE) {
if (sinf(radian) > 0.0f) {
modulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude;
}
} else if (myEmitter.particleAttributes[lifeStage].modulationStyle == COLOR_MODULATION_STYLE_LIGHTNESS_WAVE) {
float a = myEmitter.particleAttributes[lifeStage].modulationAmplitude;
modulation = a * ONE_HALF + sinf(radian) * a * ONE_HALF;
}
_particle[p].color.r += modulation;
_particle[p].color.g += modulation;
_particle[p].color.b += modulation;
_particle[p].color.a += modulation;
if (_particle[p].color.r > 1.0f) {_particle[p].color.r = 1.0f;}
if (_particle[p].color.g > 1.0f) {_particle[p].color.g = 1.0f;}
if (_particle[p].color.b > 1.0f) {_particle[p].color.b = 1.0f;}
if (_particle[p].color.a > 1.0f) {_particle[p].color.a = 1.0f;}
}
// do this at the end... // 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;
}
for (int p = 0; p < MAX_PARTICLES; p++) {
killParticle(p);
}
} }
void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing, float radius, glm::vec4 color ) {
_emitter[emitterIndex].baseParticle.alive = true;
_emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
_emitter[emitterIndex].baseParticle.radius = radius;
_emitter[emitterIndex].baseParticle.color = color;
}
void ParticleSystem::render() { 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) {
renderParticle(p); if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) {
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)) {
glEnd();
glm::vec3 vectorFromPreviousParticle = _particle[p].position - _particle[_particle[p].previousParticle].position;
float distance = glm::length(vectorFromPreviousParticle);
if (distance > 0.0f) {
vectorFromPreviousParticle /= distance;
glm::vec3 up = glm::normalize(glm::cross(vectorFromPreviousParticle, _upDirection)) * _particle[p].radius;
glm::vec3 right = glm::normalize(glm::cross(up, vectorFromPreviousParticle )) * _particle[p].radius;
glm::vec3 p0Left = _particle[p ].position - right;
glm::vec3 p0Right = _particle[p ].position + right;
glm::vec3 p0Down = _particle[p ].position - up;
glm::vec3 p0Up = _particle[p ].position + up;
glm::vec3 ppLeft = _particle[_particle[p].previousParticle].position - right;
glm::vec3 ppRight = _particle[_particle[p].previousParticle].position + right;
glm::vec3 ppDown = _particle[_particle[p].previousParticle].position - up;
glm::vec3 ppUp = _particle[_particle[p].previousParticle].position + up;
glBegin(GL_TRIANGLES);
glVertex3f(p0Left.x, p0Left.y, p0Left.z );
glVertex3f(p0Right.x, p0Right.y, p0Right.z);
glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z );
glVertex3f(p0Right.x, p0Right.y, p0Right.z);
glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z );
glVertex3f(ppRight.x, ppRight.y, ppRight.z);
glVertex3f(p0Up.x, p0Up.y, p0Up.z );
glVertex3f(p0Down.x, p0Down.y, p0Down.z );
glVertex3f(ppDown.x, ppDown.y, ppDown.z );
glVertex3f(p0Up.x, p0Up.y, p0Up.z );
glVertex3f(ppUp.x, ppUp.y, ppUp.z );
glVertex3f(ppDown.x, ppDown.y, ppDown.z );
glVertex3f(p0Up.x, p0Up.y, p0Left.z );
glVertex3f(p0Right.x, p0Right.y, p0Right.z);
glVertex3f(p0Down.x, p0Down.y, p0Down.z );
glVertex3f(p0Up.x, p0Up.y, p0Left.z );
glVertex3f(p0Left.x, p0Left.y, p0Left.z );
glVertex3f(p0Down.x, p0Down.y, p0Down.z );
glVertex3f(ppUp.x, ppUp.y, ppLeft.z );
glVertex3f(ppRight.x, ppRight.y, ppRight.z);
glVertex3f(ppDown.x, ppDown.y, ppDown.z );
glVertex3f(ppUp.x, ppUp.y, ppLeft.z );
glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z );
glVertex3f(ppDown.x, ppDown.y, ppDown.z );
glEnd();
}
}
} }
} }
} }
void ParticleSystem::renderEmitter(int e, float size) { void ParticleSystem::renderEmitter(int e, float size) {
glm::vec3 r = _emitter[e].rotation * IDENTITY_FRONT * size;
glm::vec3 u = _emitter[e].rotation * IDENTITY_RIGHT * size;
glm::vec3 f = _emitter[e].rotation * IDENTITY_UP * size;
glLineWidth(2.0f);
glColor3f(0.8f, 0.4, 0.4);
glBegin(GL_LINES);
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
glVertex3f(_emitter[e].position.x + r.x, _emitter[e].position.y + r.y, _emitter[e].position.z + r.z);
glEnd();
glColor3f(0.4f, 0.8, 0.4);
glBegin(GL_LINES);
glVertex3f(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
glVertex3f(_emitter[e].position.x + u.x, _emitter[e].position.y + u.y, _emitter[e].position.z + u.z);
glEnd();
glm::vec3 v = _emitter[e].direction * size;
glColor3f(0.4f, 0.4, 0.8); 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) {

View file

@ -11,76 +11,121 @@
#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 setEmitterBaseParticle(int emitterIndex, bool showing );
void setEmitterBaseParticle(int emitterIndex, bool showing, float radius, glm::vec4 color );
void setParticleAttributes (int emitterIndex, ParticleAttributes attributes);
void setParticleAttributes (int emitterIndex, int lifeStage, ParticleAttributes attributes);
void setEmitterPosition (int emitterIndex, glm::vec3 position) { _emitter[emitterIndex].position = position; } // set position of emitter
void setEmitterRotation (int emitterIndex, glm::quat rotation) { _emitter[emitterIndex].rotation = rotation; } // set rotation of emitter
void setShowingEmitter (int emitterIndex, bool showing ) { _emitter[emitterIndex].visible = showing; } // set its visibiity
void setUpDirection(glm::vec3 upDirection) {_upDirection = upDirection;} // tell particle system which direction is up
void setParticleAttributesToDefault(ParticleAttributes * attributes); // set these attributes to their default values
void setParticleAttributes (int emitterIndex, ParticleAttributes attributes); // set attributes for whole life of particles
void setParticleAttributes (int emitterIndex, ParticleLifeStage lifeStage, ParticleAttributes attributes); // set attributes for this life stage
void setEmitterPosition (int emitterIndex, glm::vec3 position );
void setEmitterParticleResolution (int emitterIndex, int resolution ) {_emitter[emitterIndex].particleResolution = resolution; }
void setEmitterDirection (int emitterIndex, glm::vec3 direction ) {_emitter[emitterIndex].direction = direction; }
void setShowingEmitter (int emitterIndex, bool showing ) {_emitter[emitterIndex].visible = showing; }
void setEmitterParticleLifespan (int emitterIndex, float lifespan ) {_emitter[emitterIndex].particleLifespan = lifespan; }
void setParticleRenderStyle (int emitterIndex, ParticleRenderStyle renderStyle ) {_emitter[emitterIndex].particleRenderStyle = renderStyle; }
void setEmitterThrust (int emitterIndex, float thrust ) {_emitter[emitterIndex].thrust = thrust; }
void setEmitterRate (int emitterIndex, float rate ) {_emitter[emitterIndex].rate = rate; }
void setShowingEmitterBaseParticle(int emitterIndex, bool showing ) {_emitter[emitterIndex].showingBaseParticle = showing; }
private: private:
struct Particle { struct Particle {
bool alive; // is the particle active? bool alive; // is the particle active?
glm::vec3 position; // position glm::vec3 position; // position
glm::vec3 velocity; // velocity glm::vec3 velocity; // velocity
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);

View file

@ -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) {

View file

@ -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);

View file

@ -19,8 +19,8 @@
#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
#include <vpx_codec.h> #include <vpx_codec.h>

View file

@ -448,7 +448,7 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) {
} }
void Avatar::simulate(float deltaTime, Transmitter* transmitter) { void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
glm::quat orientation = getOrientation(); glm::quat orientation = getOrientation();
glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 front = orientation * IDENTITY_FRONT;
glm::vec3 right = orientation * IDENTITY_RIGHT; glm::vec3 right = orientation * IDENTITY_RIGHT;

View file

@ -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();

View file

@ -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,16 +110,19 @@ 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);
renderFingerTrails(); if ( SHOW_LEAP_HAND ) {
renderHandSpheres(); renderFingerTrails();
renderHandSpheres();
}
} }
void Hand::renderRaveGloveStage() { void Hand::renderRaveGloveStage() {
@ -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 (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
for ( int f = 0; f< NUM_FINGERS_PER_HAND; f ++ ) { if (i < handPositions.size()) {
palm.setActive(true);
_particleSystem.setShowingEmitter(f, true ); palm.setRawPosition(handPositions[i]);
palm.setRawNormal(handNormals[i]);
_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);
} }
else {
palm.setActive(false);
}
}
}
_particleSystemInitialized = true; // call this right after the geometry of the leap hands are set
} else { void Hand::updateRaveGloveEmitters() {
// update the particles
bool debug = false;
if (_raveGloveInitialized) {
static float t = 0.0f; if(debug) printf( "\n" );
t += deltaTime; if(debug) printf( "------------------------------------\n" );
if(debug) printf( "updating rave glove emitters:\n" );
if(debug) printf( "------------------------------------\n" );
int emitterIndex = 0;
int fingerIndex = 0;
for (size_t i = 0; i < getNumPalms(); ++i) { for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[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) {
if ((emitterIndex >=0)
&& (emitterIndex < NUM_FINGERS)) {
assert(emitterIndex >=0 );
assert(emitterIndex < NUM_FINGERS );
if(debug) printf( "_raveGloveEmitter[%d] = %d\n", emitterIndex, _raveGloveEmitter[emitterIndex] );
glm::vec3 particleEmitterPosition = finger.getTipPosition(); glm::vec3 fingerDirection = finger.getTipPosition() - finger.getRootPosition();
glm::vec3 fingerDirection = particleEmitterPosition - leapPositionToWorldPosition(finger.getRootPosition());
float fingerLength = glm::length(fingerDirection); float fingerLength = glm::length(fingerDirection);
if (fingerLength > 0.0f) { if (fingerLength > 0.0f) {
@ -273,27 +291,391 @@ void Hand::updateFingerParticles(float deltaTime) {
} else { } else {
fingerDirection = IDENTITY_UP; fingerDirection = IDENTITY_UP;
} }
glm::quat particleEmitterRotation = rotationBetween(palm.getNormal(), fingerDirection);
//glm::quat particleEmitterRotation = glm::angleAxis(0.0f, fingerDirection); assert(_raveGloveEmitter[emitterIndex] >=0 );
assert(_raveGloveEmitter[emitterIndex] < NUM_FINGERS );
_particleSystem.setEmitterPosition(_fingerParticleEmitter[f], particleEmitterPosition); _raveGloveParticleSystem.setEmitterPosition (_raveGloveEmitter[emitterIndex], finger.getTipPosition());
_particleSystem.setEmitterRotation(_fingerParticleEmitter[f], particleEmitterRotation); _raveGloveParticleSystem.setEmitterDirection(_raveGloveEmitter[emitterIndex], fingerDirection);
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" );
} }
} }
}
}
// call this from within the simulate method
void Hand::updateRaveGloveParticles(float deltaTime) {
if (!_raveGloveInitialized) {
//printf( "Initializing rave glove emitters:\n" );
//printf( "The indices of the emitters are:\n" );
// start up the rave glove finger particles...
for ( int f = 0; f< NUM_FINGERS; f ++ ) {
_raveGloveEmitter[f] = _raveGloveParticleSystem.addEmitter();
assert( _raveGloveEmitter[f] >= 0 );
assert( _raveGloveEmitter[f] != NULL_EMITTER );
//printf( "%d\n", _raveGloveEmitter[f] );
}
setRaveGloveMode(RAVE_GLOVE_EFFECTS_MODE_FIRE);
_raveGloveParticleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
_raveGloveInitialized = true;
} else {
_particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f)); _raveGloveClock += deltaTime;
_particleSystem.simulate(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);
}
} }
} }

View file

@ -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();

View file

@ -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;

View file

@ -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 ''

View file

@ -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++;

View file

@ -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 {

View file

@ -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();

View file

@ -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());
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////

View file

@ -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;

View file

@ -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})

View file

@ -41,4 +41,6 @@ const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
const float SIXTY_FPS_IN_MILLISECONDS = 1000.0f / 60.0f; const float SIXTY_FPS_IN_MILLISECONDS = 1000.0f / 60.0f;
const float VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0f; // once a second is fine const float VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0f; // once a second is fine
const uint64_t CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packet every 50 milliseconds
#endif #endif

View file

@ -61,6 +61,7 @@ bool wantColorRandomizer = false;
bool debugVoxelSending = false; bool debugVoxelSending = false;
bool shouldShowAnimationDebug = false; bool shouldShowAnimationDebug = false;
bool displayVoxelStats = false; bool displayVoxelStats = false;
bool debugVoxelReceiving = false;
EnvironmentData environmentData[3]; EnvironmentData environmentData[3];
@ -426,10 +427,12 @@ void attachVoxelNodeDataToNode(Node* newNode) {
} }
} }
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);
@ -455,6 +458,10 @@ int main(int argc, const char * argv[]) {
::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING);
printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending));
const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving";
::debugVoxelReceiving = cmdOptionExists(argc, argv, DEBUG_VOXEL_RECEIVING);
printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving));
const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug";
::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG); ::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG);
printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug));
@ -584,12 +591,20 @@ int main(int argc, const char * argv[]) {
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
::shouldShowAnimationDebug); ::shouldShowAnimationDebug);
::receivedPacketCount++;
unsigned short int itemNumber = (*((unsigned short int*)(packetData + numBytesPacketHeader))); unsigned short int itemNumber = (*((unsigned short int*)(packetData + numBytesPacketHeader)));
if (::shouldShowAnimationDebug) { if (::shouldShowAnimationDebug) {
printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n", printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n",
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
receivedBytes,itemNumber); receivedBytes,itemNumber);
} }
if (::debugVoxelReceiving) {
printf("got %s - %d command from client receivedBytes=%ld itemNumber=%d\n",
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
::receivedPacketCount, receivedBytes,itemNumber);
}
int atByte = numBytesPacketHeader + sizeof(itemNumber); int atByte = numBytesPacketHeader + sizeof(itemNumber);
unsigned char* voxelData = (unsigned char*)&packetData[atByte]; unsigned char* voxelData = (unsigned char*)&packetData[atByte];
while (atByte < receivedBytes) { while (atByte < receivedBytes) {