3
0
Fork 0
mirror of https://github.com/JulianGro/overte.git synced 2025-04-15 16:06:45 +02:00

merge with upstream

This commit is contained in:
wangyix 2014-08-13 11:09:55 -07:00
commit db0fbcab97
153 changed files with 2812 additions and 4081 deletions
CMakeLists.txt
animation-server
assignment-client
cmake
domain-server
CMakeLists.txt
resources/web/settings
interface
libraries

View file

@ -44,10 +44,17 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
# targets not supported on windows
if (NOT WIN32)
add_subdirectory(animation-server)
endif ()
set(HIFI_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros")
file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake")
foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS})
include(${CUSTOM_MACRO})
endforeach()
# targets on all platforms
add_subdirectory(assignment-client)

View file

@ -1,39 +0,0 @@
if (WIN32)
cmake_policy (SET CMP0020 NEW)
endif (WIN32)
set(TARGET_NAME animation-server)
set(ROOT_DIR ..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
find_package(Qt5 COMPONENTS Script)
include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
# set up the external glm library
include("${MACRO_DIR}/IncludeGLM.cmake")
include_glm(${TARGET_NAME} "${ROOT_DIR}")
include("${MACRO_DIR}/SetupHifiProject.cmake")
setup_hifi_project(${TARGET_NAME} TRUE)
# link in the shared library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
# link in the hifi octree library
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
# link in the hifi voxels library
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
# link the hifi networking library
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()

View file

@ -1,852 +0,0 @@
//
// AnimationServer.cpp
// animation-server/src
//
// Created by Stephen Birarda on 12/5/2013.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <QtCore/QTimer>
#include <EnvironmentData.h>
#include <NodeList.h>
#include <OctalCode.h>
#include <PacketHeaders.h>
#include <JurisdictionListener.h>
#include <SharedUtil.h>
#include <VoxelEditPacketSender.h>
#include <VoxelTree.h>
#include "AnimationServer.h"
bool shouldShowPacketsPerSecond = false; // do we want to debug packets per second
bool includeBillboard = true;
bool includeBorderTracer = true;
bool includeMovingBug = true;
bool includeBlinkingVoxel = false;
bool includeDanceFloor = true;
bool buildStreet = false;
bool nonThreadedPacketSender = false;
int packetsPerSecond = PacketSender::DEFAULT_PACKETS_PER_SECOND;
bool waitForVoxelServer = true;
const int ANIMATION_LISTEN_PORT = 40107;
int ANIMATE_FPS = 60;
double ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS
quint64 ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000); // converts from milliseconds to usecs
int PROCESSING_FPS = 60;
double PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS
int FUDGE_USECS = 650; // a little bit of fudge to actually do some processing
quint64 PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000) - FUDGE_USECS; // converts from milliseconds to usecs
bool wantLocalDomain = false;
unsigned long packetsSent = 0;
unsigned long bytesSent = 0;
JurisdictionListener* jurisdictionListener = NULL;
VoxelEditPacketSender* voxelEditPacketSender = NULL;
pthread_t animateVoxelThread;
glm::vec3 rotatePoint(glm::vec3 point, float angle) {
// First, create the quaternion based on this angle of rotation
glm::quat q(glm::vec3(0, -angle, 0));
// Next, create a rotation matrix from that quaternion
glm::mat4 rotation = glm::mat4_cast(q);
// Transform the original vectors by the rotation matrix to get the new vectors
glm::vec4 quatPoint(point.x, point.y, point.z, 0);
glm::vec4 newPoint = quatPoint * rotation;
return glm::vec3(newPoint.x, newPoint.y, newPoint.z);
}
const float BUG_VOXEL_SIZE = 0.0625f / TREE_SCALE;
glm::vec3 bugPosition = glm::vec3(BUG_VOXEL_SIZE * 20.0, BUG_VOXEL_SIZE * 30.0, BUG_VOXEL_SIZE * 20.0);
glm::vec3 bugDirection = glm::vec3(0, 0, 1);
const int VOXELS_PER_BUG = 18;
glm::vec3 bugPathCenter = glm::vec3(0.25f,0.15f,0.25f); // glm::vec3(BUG_VOXEL_SIZE * 150.0, BUG_VOXEL_SIZE * 30.0, BUG_VOXEL_SIZE * 150.0);
float bugPathRadius = 0.2f; //BUG_VOXEL_SIZE * 140.0;
float bugPathTheta = 0.0f * RADIANS_PER_DEGREE;
float bugRotation = 0.0f * RADIANS_PER_DEGREE;
float bugAngleDelta = 0.2f * RADIANS_PER_DEGREE;
bool moveBugInLine = false;
class BugPart {
public:
glm::vec3 partLocation;
unsigned char partColor[3];
BugPart(const glm::vec3& location, unsigned char red, unsigned char green, unsigned char blue ) {
partLocation = location;
partColor[0] = red;
partColor[1] = green;
partColor[2] = blue;
}
};
const BugPart bugParts[VOXELS_PER_BUG] = {
// tail
BugPart(glm::vec3( 0, 0, -3), 51, 51, 153) ,
BugPart(glm::vec3( 0, 0, -2), 51, 51, 153) ,
BugPart(glm::vec3( 0, 0, -1), 51, 51, 153) ,
// body
BugPart(glm::vec3( 0, 0, 0), 255, 200, 0) ,
BugPart(glm::vec3( 0, 0, 1), 255, 200, 0) ,
// head
BugPart(glm::vec3( 0, 0, 2), 200, 0, 0) ,
// eyes
BugPart(glm::vec3( 1, 0, 3), 64, 64, 64) ,
BugPart(glm::vec3(-1, 0, 3), 64, 64, 64) ,
// wings
BugPart(glm::vec3( 3, 1, 1), 0, 153, 0) ,
BugPart(glm::vec3( 2, 1, 1), 0, 153, 0) ,
BugPart(glm::vec3( 1, 0, 1), 0, 153, 0) ,
BugPart(glm::vec3(-1, 0, 1), 0, 153, 0) ,
BugPart(glm::vec3(-2, 1, 1), 0, 153, 0) ,
BugPart(glm::vec3(-3, 1, 1), 0, 153, 0) ,
BugPart(glm::vec3( 2, -1, 0), 153, 200, 0) ,
BugPart(glm::vec3( 1, -1, 0), 153, 200, 0) ,
BugPart(glm::vec3(-1, -1, 0), 153, 200, 0) ,
BugPart(glm::vec3(-2, -1, 0), 153, 200, 0) ,
};
static void renderMovingBug() {
VoxelDetail details[VOXELS_PER_BUG];
// Generate voxels for where bug used to be
for (int i = 0; i < VOXELS_PER_BUG; i++) {
details[i].s = BUG_VOXEL_SIZE;
glm::vec3 partAt = bugParts[i].partLocation * BUG_VOXEL_SIZE * (bugDirection.x < 0 ? -1.0f : 1.0f);
glm::vec3 rotatedPartAt = rotatePoint(partAt, bugRotation);
glm::vec3 offsetPartAt = rotatedPartAt + bugPosition;
details[i].x = offsetPartAt.x;
details[i].y = offsetPartAt.y;
details[i].z = offsetPartAt.z;
details[i].red = bugParts[i].partColor[0];
details[i].green = bugParts[i].partColor[1];
details[i].blue = bugParts[i].partColor[2];
}
// send the "erase message" first...
PacketType message = PacketTypeVoxelErase;
::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_BUG, (VoxelDetail*)&details);
// Move the bug...
if (moveBugInLine) {
bugPosition.x += (bugDirection.x * BUG_VOXEL_SIZE);
bugPosition.y += (bugDirection.y * BUG_VOXEL_SIZE);
bugPosition.z += (bugDirection.z * BUG_VOXEL_SIZE);
// Check boundaries
if (bugPosition.z > 1.0f) {
bugDirection.z = -1.f;
}
if (bugPosition.z < BUG_VOXEL_SIZE) {
bugDirection.z = 1.f;
}
} else {
//qDebug("bugPathCenter=(%f,%f,%f)", bugPathCenter.x, bugPathCenter.y, bugPathCenter.z);
bugPathTheta += bugAngleDelta; // move slightly
bugRotation -= bugAngleDelta; // rotate slightly
// If we loop past end of circle, just reset back into normal range
if (bugPathTheta > TWO_PI) {
bugPathTheta = 0.f;
bugRotation = 0.f;
}
float x = bugPathCenter.x + bugPathRadius * cos(bugPathTheta);
float z = bugPathCenter.z + bugPathRadius * sin(bugPathTheta);
float y = bugPathCenter.y;
bugPosition = glm::vec3(x, y, z);
//qDebug("bugPathTheta=%f", bugPathTheta);
//qDebug("bugRotation=%f", bugRotation);
}
//qDebug("bugPosition=(%f,%f,%f)", bugPosition.x, bugPosition.y, bugPosition.z);
//qDebug("bugDirection=(%f,%f,%f)", bugDirection.x, bugDirection.y, bugDirection.z);
// would be nice to add some randomness here...
// Generate voxels for where bug is going to
for (int i = 0; i < VOXELS_PER_BUG; i++) {
details[i].s = BUG_VOXEL_SIZE;
glm::vec3 partAt = bugParts[i].partLocation * BUG_VOXEL_SIZE * (bugDirection.x < 0 ? -1.0f : 1.0f);
glm::vec3 rotatedPartAt = rotatePoint(partAt, bugRotation);
glm::vec3 offsetPartAt = rotatedPartAt + bugPosition;
details[i].x = offsetPartAt.x;
details[i].y = offsetPartAt.y;
details[i].z = offsetPartAt.z;
details[i].red = bugParts[i].partColor[0];
details[i].green = bugParts[i].partColor[1];
details[i].blue = bugParts[i].partColor[2];
}
// send the "create message" ...
message = PacketTypeVoxelSetDestructive;
::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_BUG, (VoxelDetail*)&details);
}
float intensity = 0.5f;
float intensityIncrement = 0.1f;
const float MAX_INTENSITY = 1.0f;
const float MIN_INTENSITY = 0.5f;
const float BEACON_SIZE = 0.25f / TREE_SCALE; // approximately 1/4th meter
static void sendVoxelBlinkMessage() {
VoxelDetail detail;
detail.s = BEACON_SIZE;
glm::vec3 position = glm::vec3(0.f, 0.f, detail.s);
detail.x = detail.s * floor(position.x / detail.s);
detail.y = detail.s * floor(position.y / detail.s);
detail.z = detail.s * floor(position.z / detail.s);
::intensity += ::intensityIncrement;
if (::intensity >= MAX_INTENSITY) {
::intensity = MAX_INTENSITY;
::intensityIncrement = -::intensityIncrement;
}
if (::intensity <= MIN_INTENSITY) {
::intensity = MIN_INTENSITY;
::intensityIncrement = -::intensityIncrement;
}
detail.red = 255 * ::intensity;
detail.green = 0 * ::intensity;
detail.blue = 0 * ::intensity;
PacketType message = PacketTypeVoxelSetDestructive;
::voxelEditPacketSender->sendVoxelEditMessage(message, detail);
}
bool stringOfLightsInitialized = false;
int currentLight = 0;
int lightMovementDirection = 1;
const int SEGMENT_COUNT = 4;
const int LIGHTS_PER_SEGMENT = 80;
const int LIGHT_COUNT = LIGHTS_PER_SEGMENT * SEGMENT_COUNT;
glm::vec3 stringOfLights[LIGHT_COUNT];
unsigned char offColor[3] = { 240, 240, 240 };
unsigned char onColor[3] = { 0, 255, 255 };
const float STRING_OF_LIGHTS_SIZE = 0.125f / TREE_SCALE; // approximately 1/8th meter
static void sendBlinkingStringOfLights() {
PacketType message = PacketTypeVoxelSetDestructive; // we're a bully!
float lightScale = STRING_OF_LIGHTS_SIZE;
static VoxelDetail details[LIGHTS_PER_SEGMENT];
// first initialized the string of lights if needed...
if (!stringOfLightsInitialized) {
for (int segment = 0; segment < SEGMENT_COUNT; segment++) {
for (int indexInSegment = 0; indexInSegment < LIGHTS_PER_SEGMENT; indexInSegment++) {
int i = (segment * LIGHTS_PER_SEGMENT) + indexInSegment;
// four different segments on sides of initial platform
switch (segment) {
case 0:
// along x axis
stringOfLights[i] = glm::vec3(indexInSegment * lightScale, 0, 0);
break;
case 1:
// parallel to Z axis at outer X edge
stringOfLights[i] = glm::vec3(LIGHTS_PER_SEGMENT * lightScale, 0, indexInSegment * lightScale);
break;
case 2:
// parallel to X axis at outer Z edge
stringOfLights[i] = glm::vec3((LIGHTS_PER_SEGMENT-indexInSegment) * lightScale, 0,
LIGHTS_PER_SEGMENT * lightScale);
break;
case 3:
// on Z axis
stringOfLights[i] = glm::vec3(0, 0, (LIGHTS_PER_SEGMENT-indexInSegment) * lightScale);
break;
}
details[indexInSegment].s = STRING_OF_LIGHTS_SIZE;
details[indexInSegment].x = stringOfLights[i].x;
details[indexInSegment].y = stringOfLights[i].y;
details[indexInSegment].z = stringOfLights[i].z;
details[indexInSegment].red = offColor[0];
details[indexInSegment].green = offColor[1];
details[indexInSegment].blue = offColor[2];
}
::voxelEditPacketSender->queueVoxelEditMessages(message, LIGHTS_PER_SEGMENT, (VoxelDetail*)&details);
}
stringOfLightsInitialized = true;
} else {
// turn off current light
details[0].x = stringOfLights[currentLight].x;
details[0].y = stringOfLights[currentLight].y;
details[0].z = stringOfLights[currentLight].z;
details[0].red = offColor[0];
details[0].green = offColor[1];
details[0].blue = offColor[2];
// move current light...
// if we're at the end of our string, then change direction
if (currentLight == LIGHT_COUNT-1) {
lightMovementDirection = -1;
}
if (currentLight == 0) {
lightMovementDirection = 1;
}
currentLight += lightMovementDirection;
// turn on new current light
details[1].x = stringOfLights[currentLight].x;
details[1].y = stringOfLights[currentLight].y;
details[1].z = stringOfLights[currentLight].z;
details[1].red = onColor[0];
details[1].green = onColor[1];
details[1].blue = onColor[2];
// send both changes in same message
::voxelEditPacketSender->queueVoxelEditMessages(message, 2, (VoxelDetail*)&details);
}
}
bool danceFloorInitialized = false;
const float DANCE_FLOOR_LIGHT_SIZE = 1.0f / TREE_SCALE; // approximately 1 meter
const int DANCE_FLOOR_LENGTH = 10;
const int DANCE_FLOOR_WIDTH = 10;
glm::vec3 danceFloorPosition(100.0f / TREE_SCALE, 30.0f / TREE_SCALE, 10.0f / TREE_SCALE);
glm::vec3 danceFloorLights[DANCE_FLOOR_LENGTH][DANCE_FLOOR_WIDTH];
unsigned char danceFloorOffColor[3] = { 240, 240, 240 };
const int DANCE_FLOOR_COLORS = 6;
unsigned char danceFloorOnColorA[DANCE_FLOOR_COLORS][3] = {
{ 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 },
{ 0, 191, 255 }, { 0, 250, 154 }, { 255, 69, 0 },
};
unsigned char danceFloorOnColorB[DANCE_FLOOR_COLORS][3] = {
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } ,
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }
};
float danceFloorGradient = 0.5f;
const float BEATS_PER_MINUTE = 118.0f;
const float SECONDS_PER_MINUTE = 60.0f;
const float FRAMES_PER_BEAT = (SECONDS_PER_MINUTE * ANIMATE_FPS) / BEATS_PER_MINUTE;
float danceFloorGradientIncrement = 1.0f / FRAMES_PER_BEAT;
const float DANCE_FLOOR_MAX_GRADIENT = 1.0f;
const float DANCE_FLOOR_MIN_GRADIENT = 0.0f;
const int DANCE_FLOOR_VOXELS_PER_PACKET = 100;
int danceFloorColors[DANCE_FLOOR_WIDTH][DANCE_FLOOR_LENGTH];
void sendDanceFloor() {
PacketType message = PacketTypeVoxelSetDestructive; // we're a bully!
float lightScale = DANCE_FLOOR_LIGHT_SIZE;
static VoxelDetail details[DANCE_FLOOR_VOXELS_PER_PACKET];
// first initialized the billboard of lights if needed...
if (!::danceFloorInitialized) {
for (int i = 0; i < DANCE_FLOOR_WIDTH; i++) {
for (int j = 0; j < DANCE_FLOOR_LENGTH; j++) {
int randomColorIndex = randIntInRange(-DANCE_FLOOR_COLORS, DANCE_FLOOR_COLORS);
::danceFloorColors[i][j] = randomColorIndex;
::danceFloorLights[i][j] = ::danceFloorPosition +
glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE);
}
}
::danceFloorInitialized = true;
}
::danceFloorGradient += ::danceFloorGradientIncrement;
if (::danceFloorGradient >= DANCE_FLOOR_MAX_GRADIENT) {
::danceFloorGradient = DANCE_FLOOR_MAX_GRADIENT;
::danceFloorGradientIncrement = -::danceFloorGradientIncrement;
}
if (::danceFloorGradient <= DANCE_FLOOR_MIN_GRADIENT) {
::danceFloorGradient = DANCE_FLOOR_MIN_GRADIENT;
::danceFloorGradientIncrement = -::danceFloorGradientIncrement;
}
for (int i = 0; i < DANCE_FLOOR_LENGTH; i++) {
for (int j = 0; j < DANCE_FLOOR_WIDTH; j++) {
int nthVoxel = ((i * DANCE_FLOOR_WIDTH) + j);
int item = nthVoxel % DANCE_FLOOR_VOXELS_PER_PACKET;
::danceFloorLights[i][j] = ::danceFloorPosition +
glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE);
details[item].s = lightScale;
details[item].x = ::danceFloorLights[i][j].x;
details[item].y = ::danceFloorLights[i][j].y;
details[item].z = ::danceFloorLights[i][j].z;
if (danceFloorColors[i][j] > 0) {
int color = danceFloorColors[i][j] - 1;
details[item].red = (::danceFloorOnColorA[color][0] +
((::danceFloorOnColorB[color][0] - ::danceFloorOnColorA[color][0])
* ::danceFloorGradient));
details[item].green = (::danceFloorOnColorA[color][1] +
((::danceFloorOnColorB[color][1] - ::danceFloorOnColorA[color][1])
* ::danceFloorGradient));
details[item].blue = (::danceFloorOnColorA[color][2] +
((::danceFloorOnColorB[color][2] - ::danceFloorOnColorA[color][2])
* ::danceFloorGradient));
} else if (::danceFloorColors[i][j] < 0) {
int color = -(::danceFloorColors[i][j] + 1);
details[item].red = (::danceFloorOnColorB[color][0] +
((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0])
* ::danceFloorGradient));
details[item].green = (::danceFloorOnColorB[color][1] +
((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1])
* ::danceFloorGradient));
details[item].blue = (::danceFloorOnColorB[color][2] +
((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2])
* ::danceFloorGradient));
} else {
int color = 0;
details[item].red = (::danceFloorOnColorB[color][0] +
((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0])
* ::danceFloorGradient));
details[item].green = (::danceFloorOnColorB[color][1] +
((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1])
* ::danceFloorGradient));
details[item].blue = (::danceFloorOnColorB[color][2] +
((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2])
* ::danceFloorGradient));
}
if (item == DANCE_FLOOR_VOXELS_PER_PACKET - 1) {
::voxelEditPacketSender->queueVoxelEditMessages(message, DANCE_FLOOR_VOXELS_PER_PACKET, (VoxelDetail*)&details);
}
}
}
}
bool billboardInitialized = false;
const int BILLBOARD_HEIGHT = 9;
const int BILLBOARD_WIDTH = 45;
glm::vec3 billboardPosition((0.125f / TREE_SCALE),(0.125f / TREE_SCALE),0);
glm::vec3 billboardLights[BILLBOARD_HEIGHT][BILLBOARD_WIDTH];
unsigned char billboardOffColor[3] = { 240, 240, 240 };
unsigned char billboardOnColorA[3] = { 0, 0, 255 };
unsigned char billboardOnColorB[3] = { 0, 255, 0 };
float billboardGradient = 0.5f;
float billboardGradientIncrement = 0.01f;
const float BILLBOARD_MAX_GRADIENT = 1.0f;
const float BILLBOARD_MIN_GRADIENT = 0.0f;
const float BILLBOARD_LIGHT_SIZE = 0.125f / TREE_SCALE; // approximately 1/8 meter per light
const int VOXELS_PER_PACKET = 81;
// top to bottom...
bool billboardMessage[BILLBOARD_HEIGHT][BILLBOARD_WIDTH] = {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,0,0 },
{ 0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,0,0 },
{ 0,0,1,1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,0 },
{ 0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0 },
{ 0,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,1,1,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0 },
{ 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
};
static void sendBillboard() {
PacketType message = PacketTypeVoxelSetDestructive; // we're a bully!
float lightScale = BILLBOARD_LIGHT_SIZE;
static VoxelDetail details[VOXELS_PER_PACKET];
// first initialized the billboard of lights if needed...
if (!billboardInitialized) {
for (int i = 0; i < BILLBOARD_HEIGHT; i++) {
for (int j = 0; j < BILLBOARD_WIDTH; j++) {
billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0);
}
}
billboardInitialized = true;
}
::billboardGradient += ::billboardGradientIncrement;
if (::billboardGradient >= BILLBOARD_MAX_GRADIENT) {
::billboardGradient = BILLBOARD_MAX_GRADIENT;
::billboardGradientIncrement = -::billboardGradientIncrement;
}
if (::billboardGradient <= BILLBOARD_MIN_GRADIENT) {
::billboardGradient = BILLBOARD_MIN_GRADIENT;
::billboardGradientIncrement = -::billboardGradientIncrement;
}
for (int i = 0; i < BILLBOARD_HEIGHT; i++) {
for (int j = 0; j < BILLBOARD_WIDTH; j++) {
int nthVoxel = ((i * BILLBOARD_WIDTH) + j);
int item = nthVoxel % VOXELS_PER_PACKET;
billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0);
details[item].s = lightScale;
details[item].x = billboardLights[i][j].x;
details[item].y = billboardLights[i][j].y;
details[item].z = billboardLights[i][j].z;
if (billboardMessage[i][j]) {
details[item].red = (billboardOnColorA[0] + ((billboardOnColorB[0] - billboardOnColorA[0]) * ::billboardGradient));
details[item].green = (billboardOnColorA[1] + ((billboardOnColorB[1] - billboardOnColorA[1]) * ::billboardGradient));
details[item].blue = (billboardOnColorA[2] + ((billboardOnColorB[2] - billboardOnColorA[2]) * ::billboardGradient));
} else {
details[item].red = billboardOffColor[0];
details[item].green = billboardOffColor[1];
details[item].blue = billboardOffColor[2];
}
if (item == VOXELS_PER_PACKET - 1) {
::voxelEditPacketSender->queueVoxelEditMessages(message, VOXELS_PER_PACKET, (VoxelDetail*)&details);
}
}
}
}
bool roadInitialized = false;
const int BRICKS_ACROSS_ROAD = 32;
const float ROAD_BRICK_SIZE = 0.125f/TREE_SCALE; //(ROAD_WIDTH_METERS / TREE_SCALE) / BRICKS_ACROSS_ROAD; // in voxel units
const int ROAD_LENGTH = 1.0f / ROAD_BRICK_SIZE; // in bricks
const int ROAD_WIDTH = BRICKS_ACROSS_ROAD; // in bricks
glm::vec3 roadPosition(0.5f - (ROAD_BRICK_SIZE * BRICKS_ACROSS_ROAD), 0.0f, 0.0f);
const int BRICKS_PER_PACKET = 32; // guessing
void doBuildStreet() {
if (roadInitialized) {
return;
}
PacketType message = PacketTypeVoxelSetDestructive; // we're a bully!
static VoxelDetail details[BRICKS_PER_PACKET];
for (int z = 0; z < ROAD_LENGTH; z++) {
for (int x = 0; x < ROAD_WIDTH; x++) {
int nthVoxel = ((z * ROAD_WIDTH) + x);
int item = nthVoxel % BRICKS_PER_PACKET;
glm::vec3 brick = roadPosition + glm::vec3(x * ROAD_BRICK_SIZE, 0, z * ROAD_BRICK_SIZE);
details[item].s = ROAD_BRICK_SIZE;
details[item].x = brick.x;
details[item].y = brick.y;
details[item].z = brick.z;
unsigned char randomTone = randIntInRange(118,138);
details[item].red = randomTone;
details[item].green = randomTone;
details[item].blue = randomTone;
if (item == BRICKS_PER_PACKET - 1) {
::voxelEditPacketSender->queueVoxelEditMessages(message, BRICKS_PER_PACKET, (VoxelDetail*)&details);
}
}
}
roadInitialized = true;
}
double start = 0;
void* animateVoxels(void* args) {
quint64 lastAnimateTime = 0;
quint64 lastProcessTime = 0;
int processesPerAnimate = 0;
bool firstTime = true;
qDebug() << "Setting PPS to " << ::packetsPerSecond;
::voxelEditPacketSender->setPacketsPerSecond(::packetsPerSecond);
qDebug() << "PPS set to " << ::voxelEditPacketSender->getPacketsPerSecond();
while (true) {
// If we're asked to wait for voxel servers, and there isn't one available yet, then
// let the voxelEditPacketSender process and move on.
if (::waitForVoxelServer && !::voxelEditPacketSender->voxelServersExist()) {
if (::nonThreadedPacketSender) {
::voxelEditPacketSender->process();
}
} else {
if (firstTime) {
lastAnimateTime = usecTimestampNow();
firstTime = false;
}
lastProcessTime = usecTimestampNow();
// The while loop will be running at PROCESSING_FPS, but we only want to call these animation functions at
// ANIMATE_FPS. So we check out last animate time and only call these if we've elapsed that time.
quint64 now = usecTimestampNow();
quint64 animationElapsed = now - lastAnimateTime;
int withinAnimationTarget = ANIMATE_VOXELS_INTERVAL_USECS - animationElapsed;
const int CLOSE_ENOUGH_TO_ANIMATE = 2000; // approximately 2 ms
int animateLoopsPerAnimate = 0;
while (withinAnimationTarget < CLOSE_ENOUGH_TO_ANIMATE) {
processesPerAnimate = 0;
animateLoopsPerAnimate++;
lastAnimateTime = now;
// some animations
//sendVoxelBlinkMessage();
if (::includeBillboard) {
sendBillboard();
}
if (::includeBorderTracer) {
sendBlinkingStringOfLights();
}
if (::includeMovingBug) {
renderMovingBug();
}
if (::includeBlinkingVoxel) {
sendVoxelBlinkMessage();
}
if (::includeDanceFloor) {
sendDanceFloor();
}
if (::buildStreet) {
doBuildStreet();
}
if (animationElapsed > ANIMATE_VOXELS_INTERVAL_USECS) {
animationElapsed -= ANIMATE_VOXELS_INTERVAL_USECS; // credit ourselves one animation frame
} else {
animationElapsed = 0;
}
withinAnimationTarget = ANIMATE_VOXELS_INTERVAL_USECS - animationElapsed;
::voxelEditPacketSender->releaseQueuedMessages();
}
if (::nonThreadedPacketSender) {
::voxelEditPacketSender->process();
}
processesPerAnimate++;
}
// dynamically sleep until we need to fire off the next set of voxels
quint64 usecToSleep = ::PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime);
if (usecToSleep > ::PROCESSING_INTERVAL_USECS) {
usecToSleep = ::PROCESSING_INTERVAL_USECS;
}
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
pthread_exit(0);
}
AnimationServer::AnimationServer(int &argc, char **argv) :
QCoreApplication(argc, argv)
{
::start = usecTimestampNow();
NodeList* nodeList = NodeList::createInstance(NodeType::AnimationServer, ANIMATION_LISTEN_PORT);
setvbuf(stdout, NULL, _IOLBF, 0);
// Handle Local Domain testing with the --local command line
const char* NON_THREADED_PACKETSENDER = "--NonThreadedPacketSender";
::nonThreadedPacketSender = cmdOptionExists(argc, (const char**) argv, NON_THREADED_PACKETSENDER);
qDebug("nonThreadedPacketSender=%s", debug::valueOf(::nonThreadedPacketSender));
// Handle Local Domain testing with the --local command line
const char* NO_BILLBOARD = "--NoBillboard";
::includeBillboard = !cmdOptionExists(argc, (const char**) argv, NO_BILLBOARD);
qDebug("includeBillboard=%s", debug::valueOf(::includeBillboard));
const char* NO_BORDER_TRACER = "--NoBorderTracer";
::includeBorderTracer = !cmdOptionExists(argc, (const char**) argv, NO_BORDER_TRACER);
qDebug("includeBorderTracer=%s", debug::valueOf(::includeBorderTracer));
const char* NO_MOVING_BUG = "--NoMovingBug";
::includeMovingBug = !cmdOptionExists(argc, (const char**) argv, NO_MOVING_BUG);
qDebug("includeMovingBug=%s", debug::valueOf(::includeMovingBug));
const char* INCLUDE_BLINKING_VOXEL = "--includeBlinkingVoxel";
::includeBlinkingVoxel = cmdOptionExists(argc, (const char**) argv, INCLUDE_BLINKING_VOXEL);
qDebug("includeBlinkingVoxel=%s", debug::valueOf(::includeBlinkingVoxel));
const char* NO_DANCE_FLOOR = "--NoDanceFloor";
::includeDanceFloor = !cmdOptionExists(argc, (const char**) argv, NO_DANCE_FLOOR);
qDebug("includeDanceFloor=%s", debug::valueOf(::includeDanceFloor));
const char* BUILD_STREET = "--BuildStreet";
::buildStreet = cmdOptionExists(argc, (const char**) argv, BUILD_STREET);
qDebug("buildStreet=%s", debug::valueOf(::buildStreet));
// Handle Local Domain testing with the --local command line
const char* showPPS = "--showPPS";
::shouldShowPacketsPerSecond = cmdOptionExists(argc, (const char**) argv, showPPS);
// Handle Local Domain testing with the --local command line
const char* local = "--local";
::wantLocalDomain = cmdOptionExists(argc, (const char**) argv,local);
if (::wantLocalDomain) {
qDebug("Local Domain MODE!");
nodeList->getDomainHandler().setIPToLocalhost();
}
const char* domainHostname = getCmdOption(argc, (const char**) argv, "--domain");
if (domainHostname) {
NodeList::getInstance()->getDomainHandler().setHostname(domainHostname);
}
const char* packetsPerSecondCommand = getCmdOption(argc, (const char**) argv, "--pps");
if (packetsPerSecondCommand) {
::packetsPerSecond = atoi(packetsPerSecondCommand);
}
qDebug("packetsPerSecond=%d",packetsPerSecond);
const char* animateFPSCommand = getCmdOption(argc, (const char**) argv, "--AnimateFPS");
const char* animateIntervalCommand = getCmdOption(argc, (const char**) argv, "--AnimateInterval");
if (animateFPSCommand || animateIntervalCommand) {
if (animateIntervalCommand) {
::ANIMATE_FPS_IN_MILLISECONDS = atoi(animateIntervalCommand);
::ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs
::ANIMATE_FPS = PacketSender::USECS_PER_SECOND / ::ANIMATE_VOXELS_INTERVAL_USECS;
} else {
::ANIMATE_FPS = atoi(animateFPSCommand);
::ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS
::ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs
}
}
qDebug("ANIMATE_FPS=%d",ANIMATE_FPS);
qDebug("ANIMATE_VOXELS_INTERVAL_USECS=%llu",ANIMATE_VOXELS_INTERVAL_USECS);
const char* processingFPSCommand = getCmdOption(argc, (const char**) argv, "--ProcessingFPS");
const char* processingIntervalCommand = getCmdOption(argc, (const char**) argv, "--ProcessingInterval");
if (processingFPSCommand || processingIntervalCommand) {
if (processingIntervalCommand) {
::PROCESSING_FPS_IN_MILLISECONDS = atoi(processingIntervalCommand);
::PROCESSING_INTERVAL_USECS = ::PROCESSING_FPS_IN_MILLISECONDS * 1000.0;
::PROCESSING_FPS = PacketSender::USECS_PER_SECOND / ::PROCESSING_INTERVAL_USECS;
} else {
::PROCESSING_FPS = atoi(processingFPSCommand);
::PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS
::PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs
}
}
qDebug("PROCESSING_FPS=%d",PROCESSING_FPS);
qDebug("PROCESSING_INTERVAL_USECS=%llu",PROCESSING_INTERVAL_USECS);
nodeList->linkedDataCreateCallback = NULL; // do we need a callback?
// Create our JurisdictionListener so we'll know where to send edit packets
::jurisdictionListener = new JurisdictionListener();
if (::jurisdictionListener) {
::jurisdictionListener->initialize(true);
}
// Create out VoxelEditPacketSender
::voxelEditPacketSender = new VoxelEditPacketSender;
::voxelEditPacketSender->initialize(!::nonThreadedPacketSender);
if (::jurisdictionListener) {
::voxelEditPacketSender->setVoxelServerJurisdictions(::jurisdictionListener->getJurisdictions());
}
if (::nonThreadedPacketSender) {
::voxelEditPacketSender->setProcessCallIntervalHint(PROCESSING_INTERVAL_USECS);
}
srand((unsigned)time(0));
pthread_create(&::animateVoxelThread, NULL, animateVoxels, NULL);
NodeList::getInstance()->addNodeTypeToInterestSet(NodeType::VoxelServer);
QTimer* domainServerTimer = new QTimer(this);
connect(domainServerTimer, SIGNAL(timeout()), nodeList, SLOT(sendDomainServerCheckIn()));
domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
QTimer* silentNodeTimer = new QTimer(this);
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS);
connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readPendingDatagrams()));
}
void AnimationServer::readPendingDatagrams() {
NodeList* nodeList = NodeList::getInstance();
static QByteArray receivedPacket;
static HifiSockAddr nodeSockAddr;
// Nodes sending messages to us...
while (nodeList->getNodeSocket().hasPendingDatagrams()) {
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
nodeSockAddr.getAddressPointer(), nodeSockAddr.getPortPointer());
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
if (packetTypeForPacket(receivedPacket) == PacketTypeJurisdiction) {
int headerBytes = numBytesForPacketHeader(receivedPacket);
// PacketType_JURISDICTION, first byte is the node type...
if (receivedPacket.data()[headerBytes] == NodeType::VoxelServer && ::jurisdictionListener) {
SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(receivedPacket);
if (matchedNode) {
::jurisdictionListener->queueReceivedPacket(matchedNode, receivedPacket);
}
}
}
NodeList::getInstance()->processNodeData(nodeSockAddr, receivedPacket);
}
}
}
AnimationServer::~AnimationServer() {
pthread_join(animateVoxelThread, NULL);
if (::jurisdictionListener) {
::jurisdictionListener->terminate();
delete ::jurisdictionListener;
}
if (::voxelEditPacketSender) {
::voxelEditPacketSender->terminate();
delete ::voxelEditPacketSender;
}
}

View file

@ -1,27 +0,0 @@
//
// AnimationServer.h
// animation-server/src
//
// Created by Stephen Birarda on 12/5/2013.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AnimationServer_h
#define hifi_AnimationServer_h
#include <QtCore/QCoreApplication>
class AnimationServer : public QCoreApplication {
Q_OBJECT
public:
AnimationServer(int &argc, char **argv);
~AnimationServer();
private slots:
void readPendingDatagrams();
};
#endif // hifi_AnimationServer_h

View file

@ -1,17 +0,0 @@
//
// main.cpp
// animation-server/src
//
// Created by Brad Hefta-Gaub on 05/16/2013.
// Copyright 2012 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AnimationServer.h"
int main(int argc, char * argv[]) {
AnimationServer animationServer(argc, argv);
return animationServer.exec();
}

View file

@ -1,47 +1,17 @@
set(TARGET_NAME assignment-client)
set(ROOT_DIR ..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
setup_hifi_project(Core Gui Network Script Widgets)
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
find_package(Qt5 COMPONENTS Network Script Widgets)
include("${MACRO_DIR}/SetupHifiProject.cmake")
setup_hifi_project(${TARGET_NAME} TRUE)
# include glm
include("${MACRO_DIR}/IncludeGLM.cmake")
include_glm(${TARGET_NAME} "${ROOT_DIR}")
include_glm()
# link in the shared libraries
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(audio ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(avatars ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(fbx ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(particles ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(models ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(metavoxels ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(animation ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(script-engine ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(embedded-webserver ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_libraries(
audio avatars octree voxels fbx particles models metavoxels
networking animation shared script-engine embedded-webserver
)
if (UNIX)
target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS})
list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK ${CMAKE_DL_LIBS})
endif (UNIX)
IF (WIN32)
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
ENDIF(WIN32)
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
link_shared_dependencies()

View file

@ -120,7 +120,7 @@ void Agent::readPendingDatagrams() {
sourceNode->setLastHeardMicrostamp(usecTimestampNow());
QByteArray mutablePacket = receivedPacket;
ssize_t messageLength = mutablePacket.size();
int messageLength = mutablePacket.size();
if (datagramPacketType == PacketTypeOctreeStats) {

View file

@ -69,6 +69,8 @@ void attachNewNodeDataToNode(Node *newNode) {
InboundAudioStream::Settings AudioMixer::_streamSettings;
bool AudioMixer::_printStreamStats = false;
AudioMixer::AudioMixer(const QByteArray& packet) :
ThreadedAssignment(packet),
_trailingSleepRatio(1.0f),
@ -475,7 +477,7 @@ void AudioMixer::run() {
_streamSettings._maxFramesOverDesired = DEFAULT_MAX_FRAMES_OVER_DESIRED;
}
qDebug() << "Max frames over desired:" << _streamSettings._maxFramesOverDesired;
const QString USE_STDEV_FOR_DESIRED_CALC_JSON_KEY = "D-use-stdev-for-desired-calc";
_streamSettings._useStDevForJitterCalc = audioGroupObject[USE_STDEV_FOR_DESIRED_CALC_JSON_KEY].toBool();
if (_streamSettings._useStDevForJitterCalc) {
@ -512,7 +514,12 @@ void AudioMixer::run() {
} else {
qDebug() << "Repetition with fade disabled";
}
const QString PRINT_STREAM_STATS_JSON_KEY = "I-print-stream-stats";
_printStreamStats = audioGroupObject[PRINT_STREAM_STATS_JSON_KEY].toBool();
if (_printStreamStats) {
qDebug() << "Stream stats will be printed to stdout";
}
const QString UNATTENUATED_ZONE_KEY = "Z-unattenuated-zone";
@ -610,6 +617,7 @@ void AudioMixer::run() {
sendAudioStreamStats = true;
}
bool streamStatsPrinted = false;
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
if (node->getLinkedData()) {
AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData();
@ -661,12 +669,21 @@ void AudioMixer::run() {
// send an audio stream stats packet if it's time
if (sendAudioStreamStats) {
nodeData->sendAudioStreamStatsPackets(node);
if (_printStreamStats) {
printf("\nStats for agent %s:\n", node->getUUID().toString().toLatin1().data());
nodeData->printUpstreamDownstreamStats();
streamStatsPrinted = true;
}
}
++_sumListeners;
}
}
}
if (streamStatsPrinted) {
printf("\n----------------------------------------------------------------\n");
}
++_numStatFrames;

View file

@ -62,6 +62,8 @@ private:
static InboundAudioStream::Settings _streamSettings;
static bool _printStreamStats;
quint64 _lastSendAudioStreamStatsTime;
};

View file

@ -22,7 +22,8 @@
AudioMixerClientData::AudioMixerClientData() :
_audioStreams(),
_outgoingMixedAudioSequenceNumber(0)
_outgoingMixedAudioSequenceNumber(0),
_downstreamAudioStreamStats()
{
}
@ -259,3 +260,45 @@ QString AudioMixerClientData::getAudioStreamStatsString() const {
}
return result;
}
void AudioMixerClientData::printUpstreamDownstreamStats() const {
// print the upstream (mic stream) stats if the mic stream exists
if (_audioStreams.contains(QUuid())) {
printf("Upstream:\n");
printAudioStreamStats(_audioStreams.value(QUuid())->getAudioStreamStats());
}
// print the downstream stats if they contain valid info
if (_downstreamAudioStreamStats._packetStreamStats._received > 0) {
printf("Downstream:\n");
printAudioStreamStats(_downstreamAudioStreamStats);
}
}
void AudioMixerClientData::printAudioStreamStats(const AudioStreamStats& streamStats) const {
printf(" Packet loss | overall: %5.2f%% (%d lost), last_30s: %5.2f%% (%d lost)\n",
streamStats._packetStreamStats.getLostRate() * 100.0f,
streamStats._packetStreamStats._lost,
streamStats._packetStreamWindowStats.getLostRate() * 100.0f,
streamStats._packetStreamWindowStats._lost);
printf(" Ringbuffer frames | desired: %u, avg_available(10s): %u, available: %u\n",
streamStats._desiredJitterBufferFrames,
streamStats._framesAvailableAverage,
streamStats._framesAvailable);
printf(" Ringbuffer stats | starves: %u, prev_starve_lasted: %u, frames_dropped: %u, overflows: %u\n",
streamStats._starveCount,
streamStats._consecutiveNotMixedCount,
streamStats._framesDropped,
streamStats._overflowCount);
printf(" Inter-packet timegaps (overall) | min: %9s, max: %9s, avg: %9s\n",
formatUsecTime(streamStats._timeGapMin).toLatin1().data(),
formatUsecTime(streamStats._timeGapMax).toLatin1().data(),
formatUsecTime(streamStats._timeGapAverage).toLatin1().data());
printf(" Inter-packet timegaps (last 30s) | min: %9s, max: %9s, avg: %9s\n",
formatUsecTime(streamStats._timeGapWindowMin).toLatin1().data(),
formatUsecTime(streamStats._timeGapWindowMax).toLatin1().data(),
formatUsecTime(streamStats._timeGapWindowAverage).toLatin1().data());
}

View file

@ -38,6 +38,11 @@ public:
void incrementOutgoingMixedAudioSequenceNumber() { _outgoingMixedAudioSequenceNumber++; }
quint16 getOutgoingSequenceNumber() const { return _outgoingMixedAudioSequenceNumber; }
void printUpstreamDownstreamStats() const;
private:
void printAudioStreamStats(const AudioStreamStats& streamStats) const;
private:
QHash<QUuid, PositionalAudioStream*> _audioStreams; // mic stream stored under key of null UUID

View file

@ -11,6 +11,8 @@
#include <QThread>
#include <GLMHelpers.h>
#include "ScriptableAvatar.h"
ScriptableAvatar::ScriptableAvatar(ScriptEngine* scriptEngine) : _scriptEngine(scriptEngine), _animation(NULL) {

View file

@ -8,8 +8,8 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(AUTO_MTC TARGET ROOT_DIR)
set(AUTOMTC_SRC ${TARGET}_automtc.cpp)
macro(AUTO_MTC)
set(AUTOMTC_SRC ${TARGET_NAME}_automtc.cpp)
file(GLOB INCLUDE_FILES src/*.h)

View file

@ -7,7 +7,7 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(INCLUDE_GLM TARGET ROOT_DIR)
macro(INCLUDE_GLM)
find_package(GLM REQUIRED)
include_directories("${GLM_INCLUDE_DIRS}")
@ -16,4 +16,4 @@ macro(INCLUDE_GLM TARGET ROOT_DIR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${GLM_INCLUDE_DIRS}")
endif ()
endmacro(INCLUDE_GLM _target _root_dir)
endmacro(INCLUDE_GLM)

View file

@ -0,0 +1,14 @@
#
# IncludeHifiLibraryHeaders.cmake
# cmake/macros
#
# Copyright 2014 High Fidelity, Inc.
# Created by Stephen Birarda on August 8, 2014
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(include_hifi_library_headers LIBRARY)
include_directories("${HIFI_LIBRARY_DIR}/${LIBRARY}/src")
endmacro(include_hifi_library_headers _library _root_dir)

View file

@ -0,0 +1,34 @@
#
# LinkHifiLibrary.cmake
#
# Copyright 2013 High Fidelity, Inc.
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(LINK_HIFI_LIBRARIES)
file(RELATIVE_PATH RELATIVE_LIBRARY_DIR_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${HIFI_LIBRARY_DIR}")
set(LIBRARIES_TO_LINK ${ARGN})
foreach(HIFI_LIBRARY ${LIBRARIES_TO_LINK})
if (NOT TARGET ${HIFI_LIBRARY})
add_subdirectory("${RELATIVE_LIBRARY_DIR_PATH}/${HIFI_LIBRARY}" "${RELATIVE_LIBRARY_DIR_PATH}/${HIFI_LIBRARY}")
endif ()
include_directories("${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src")
add_dependencies(${TARGET_NAME} ${HIFI_LIBRARY})
# link the actual library - it is static so don't bubble it up
target_link_libraries(${TARGET_NAME} ${HIFI_LIBRARY})
# ask the library what its dynamic dependencies are and link them
get_target_property(LINKED_TARGET_DEPENDENCY_LIBRARIES ${HIFI_LIBRARY} DEPENDENCY_LIBRARIES)
list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK ${LINKED_TARGET_DEPENDENCY_LIBRARIES})
endforeach()
endmacro(LINK_HIFI_LIBRARIES)

View file

@ -1,27 +0,0 @@
#
# LinkHifiLibrary.cmake
#
# Copyright 2013 High Fidelity, Inc.
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(LINK_HIFI_LIBRARY LIBRARY TARGET ROOT_DIR)
if (NOT TARGET ${LIBRARY})
add_subdirectory("${ROOT_DIR}/libraries/${LIBRARY}" "${ROOT_DIR}/libraries/${LIBRARY}")
endif ()
include_directories("${ROOT_DIR}/libraries/${LIBRARY}/src")
add_dependencies(${TARGET} ${LIBRARY})
target_link_libraries(${TARGET} ${LIBRARY})
if (APPLE)
# currently the "shared" library requires CoreServices
# link in required OS X framework
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreServices")
endif ()
endmacro(LINK_HIFI_LIBRARY _library _target _root_dir)

View file

@ -0,0 +1,25 @@
#
# LinkSharedDependencies.cmake
# cmake/macros
#
# Copyright 2014 High Fidelity, Inc.
# Created by Stephen Birarda on August 8, 2014
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(LINK_SHARED_DEPENDENCIES)
if (${TARGET_NAME}_LIBRARIES_TO_LINK)
list(REMOVE_DUPLICATES ${TARGET_NAME}_LIBRARIES_TO_LINK)
# link these libraries to our target
target_link_libraries(${TARGET_NAME} ${${TARGET_NAME}_LIBRARIES_TO_LINK})
endif ()
# we've already linked our Qt modules, but we need to bubble them up to parents
list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${${TARGET}_QT_MODULES_TO_LINK}")
# set the property on this target so it can be retreived by targets linking to us
set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_LIBRARIES "${${TARGET}_LIBRARIES_TO_LINK}")
endmacro(LINK_SHARED_DEPENDENCIES)

View file

@ -7,20 +7,27 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(SETUP_HIFI_LIBRARY TARGET)
macro(SETUP_HIFI_LIBRARY)
project(${TARGET})
project(${TARGET_NAME})
# grab the implemenation and header files
file(GLOB LIB_SRCS src/*.h src/*.cpp)
set(LIB_SRCS ${LIB_SRCS} ${WRAPPED_SRCS})
set(LIB_SRCS ${LIB_SRCS})
# create a library and set the property so it can be referenced later
add_library(${TARGET} ${LIB_SRCS} ${ARGN})
add_library(${TARGET_NAME} ${LIB_SRCS} ${AUTOMTC_SRC})
find_package(Qt5Core REQUIRED)
qt5_use_modules(${TARGET} Core)
target_link_libraries(${TARGET} ${QT_LIBRARIES})
endmacro(SETUP_HIFI_LIBRARY _target)
set(QT_MODULES_TO_LINK ${ARGN})
list(APPEND QT_MODULES_TO_LINK Core)
find_package(Qt5 COMPONENTS ${QT_MODULES_TO_LINK} REQUIRED)
foreach(QT_MODULE ${QT_MODULES_TO_LINK})
get_target_property(QT_LIBRARY_LOCATION Qt5::${QT_MODULE} LOCATION)
# add the actual path to the Qt module to our LIBRARIES_TO_LINK variable
target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE})
list(APPEND ${TARGET_NAME}_QT_MODULES_TO_LINK ${QT_LIBRARY_LOCATION})
endforeach()
endmacro(SETUP_HIFI_LIBRARY)

View file

@ -7,8 +7,8 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(SETUP_HIFI_PROJECT TARGET INCLUDE_QT)
project(${TARGET})
macro(SETUP_HIFI_PROJECT)
project(${TARGET_NAME})
# grab the implemenation and header files
file(GLOB TARGET_SRCS src/*)
@ -23,12 +23,19 @@ macro(SETUP_HIFI_PROJECT TARGET INCLUDE_QT)
endforeach()
# add the executable, include additional optional sources
add_executable(${TARGET} ${TARGET_SRCS} ${ARGN})
add_executable(${TARGET_NAME} ${TARGET_SRCS} "${AUTOMTC_SRC}")
if (${INCLUDE_QT})
find_package(Qt5Core REQUIRED)
qt5_use_modules(${TARGET} Core)
endif ()
set(QT_MODULES_TO_LINK ${ARGN})
list(APPEND QT_MODULES_TO_LINK Core)
find_package(Qt5 COMPONENTS ${QT_MODULES_TO_LINK} REQUIRED)
foreach(QT_MODULE ${QT_MODULES_TO_LINK})
target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE})
# add the actual path to the Qt module to our LIBRARIES_TO_LINK variable
get_target_property(QT_LIBRARY_LOCATION Qt5::${QT_MODULE} LOCATION)
list(APPEND ${TARGET_NAME}_QT_MODULES_TO_LINK ${QT_LIBRARY_LOCATION})
endforeach()
target_link_libraries(${TARGET} ${QT_LIBRARIES})
endmacro()

View file

@ -0,0 +1,29 @@
#
# FindATL.cmake
#
# Try to find the ATL library needed to use the LibOVR
#
# Once done this will define
#
# ATL_FOUND - system found ATL
# ATL_LIBRARIES - Link this to use ATL
#
# Created on 8/13/2013 by Stephen Birarda
# Copyright 2014 High Fidelity, Inc.
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
if (WIN32)
find_library(ATL_LIBRARY_RELEASE atls PATH_SUFFIXES "7600.16385.1/lib/ATL/i386" HINTS "C:\\WinDDK")
find_library(ATL_LIBRARY_DEBUG atlsd PATH_SUFFIXES "7600.16385.1/lib/ATL/i386" HINTS "C:\\WinDDK")
include(SelectLibraryConfigurations)
select_library_configurations(ATL)
endif ()
set(ATL_LIBRARIES "${ATL_LIBRARY}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ATL DEFAULT_MSG ATL_LIBRARIES)

View file

@ -19,6 +19,6 @@ if (WIN32)
endif (WIN32)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FACEPLUS DEFAULT_MSG FACEPLUS_INCLUDE_DIRS FACEPLUS_LIBRARIES)
find_package_handle_standard_args(Faceplus DEFAULT_MSG FACEPLUS_INCLUDE_DIRS FACEPLUS_LIBRARIES)
mark_as_advanced(FACEPLUS_INCLUDE_DIRS FACEPLUS_LIBRARIES)

View file

@ -40,6 +40,6 @@ select_library_configurations(FACESHIFT)
set(FACESHIFT_LIBRARIES ${FACESHIFT_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FACESHIFT DEFAULT_MSG FACESHIFT_INCLUDE_DIRS FACESHIFT_LIBRARIES)
find_package_handle_standard_args(Faceshift DEFAULT_MSG FACESHIFT_INCLUDE_DIRS FACESHIFT_LIBRARIES)
mark_as_advanced(FACESHIFT_INCLUDE_DIRS FACESHIFT_LIBRARIES FACESHIFT_SEARCH_DIRS)

View file

@ -30,6 +30,6 @@ select_library_configurations(LEAPMOTION)
set(LEAPMOTION_LIBRARIES "${LEAPMOTION_LIBRARY}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LEAPMOTION DEFAULT_MSG LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES)
find_package_handle_standard_args(LeapMotion DEFAULT_MSG LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES)
mark_as_advanced(LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES LEAPMOTION_SEARCH_DIRS)

View file

@ -19,16 +19,18 @@
#
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
hifi_library_search_hints("oculus")
hifi_library_search_hints("libovr")
find_path(LIBOVR_INCLUDE_DIRS OVR.h PATH_SUFFIXES Include HINTS ${OCULUS_SEARCH_DIRS})
find_path(LIBOVR_SRC_DIR Util_Render_Stereo.h PATH_SUFFIXES Src/Util HINTS ${OCULUS_SEARCH_DIRS})
find_path(LIBOVR_INCLUDE_DIRS OVR.h PATH_SUFFIXES Include HINTS ${LIBOVR_SEARCH_DIRS})
find_path(LIBOVR_SRC_DIR Util_Render_Stereo.h PATH_SUFFIXES Src/Util HINTS ${LIBOVR_SEARCH_DIRS})
include(SelectLibraryConfigurations)
if (APPLE)
find_library(LIBOVR_LIBRARY_DEBUG NAMES ovr PATH_SUFFIXES Lib/MacOS/Debug HINTS ${OCULUS_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_RELEASE NAMES ovr PATH_SUFFIXES Lib/MacOS/Release HINTS ${OCULUS_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_DEBUG NAMES ovr PATH_SUFFIXES Lib/Mac/Debug HINTS ${LIBOVR_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_RELEASE NAMES ovr PATH_SUFFIXES Lib/Mac/Release HINTS ${LIBOVR_SEARCH_DIRS})
find_library(ApplicationServices ApplicationServices)
find_library(IOKit IOKit)
elseif (UNIX)
find_library(UDEV_LIBRARY_RELEASE udev /usr/lib/x86_64-linux-gnu/)
find_library(XINERAMA_LIBRARY_RELEASE Xinerama /usr/lib/x86_64-linux-gnu/)
@ -39,29 +41,36 @@ elseif (UNIX)
set(LINUX_ARCH_DIR "x86_64")
endif()
find_library(LIBOVR_LIBRARY_DEBUG NAMES ovr PATH_SUFFIXES Lib/Linux/Debug/${LINUX_ARCH_DIR} HINTS ${OCULUS_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_RELEASE NAMES ovr PATH_SUFFIXES Lib/Linux/Release/${LINUX_ARCH_DIR} HINTS ${OCULUS_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_DEBUG NAMES ovr PATH_SUFFIXES Lib/Linux/Debug/${LINUX_ARCH_DIR} HINTS ${LIBOVR_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_RELEASE NAMES ovr PATH_SUFFIXES Lib/Linux/Release/${LINUX_ARCH_DIR} HINTS ${LIBOVR_SEARCH_DIRS})
select_library_configurations(UDEV)
select_library_configurations(XINERAMA)
elseif (WIN32)
find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${OCULUS_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${OCULUS_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS})
find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS})
find_package(ATL)
endif ()
select_library_configurations(LIBOVR)
set(LIBOVR_LIBRARIES "${LIBOVR_LIBRARY}")
set(LIBOVR_LIBRARIES ${LIBOVR_LIBRARY})
if (UNIX AND NOT APPLE)
set(LIBOVR_LIBRARIES "${LIBOVR_LIBRARIES}" "${UDEV_LIBRARY}" "${XINERAMA_LIBRARY}")
list(APPEND LIBOVR_ARGS_LIST LIBOVR_INCLUDE_DIRS LIBOVR_SRC_DIR LIBOVR_LIBRARY)
if (APPLE)
list(APPEND LIBOVR_LIBRARIES ${IOKit} ${ApplicationServices})
list(APPEND LIBOVR_ARGS_LIST IOKit ApplicationServices)
elseif (UNIX)
list(APPEND LIBOVR_LIBRARIES "${UDEV_LIBRARY}" "${XINERAMA_LIBRARY}")
list(APPEND LIBOVR_ARGS_LIST UDEV_LIBRARY XINERAMA_LIBRARY)
elseif (WIN32)
list(APPEND LIBOVR_LIBRARIES ${ATL_LIBRARIES})
list(APPEND LIBOVR_ARGS_LIST ATL_LIBRARIES)
endif ()
include(FindPackageHandleStandardArgs)
if (UNIX AND NOT APPLE)
find_package_handle_standard_args(LIBOVR DEFAULT_MSG LIBOVR_INCLUDE_DIRS LIBOVR_SRC_DIR LIBOVR_LIBRARIES UDEV_LIBRARY XINERAMA_LIBRARY)
else ()
find_package_handle_standard_args(LIBOVR DEFAULT_MSG LIBOVR_INCLUDE_DIRS LIBOVR_SRC_DIR LIBOVR_LIBRARIES)
endif ()
mark_as_advanced(LIBOVR_INCLUDE_DIRS LIBOVR_LIBRARIES OCULUS_SEARCH_DIRS)
find_package_handle_standard_args(LibOVR DEFAULT_MSG ${LIBOVR_ARGS_LIST})
mark_as_advanced(LIBOVR_INCLUDE_DIRS LIBOVR_LIBRARIES LIBOVR_SEARCH_DIRS)

View file

@ -19,6 +19,6 @@ if (WIN32)
endif (WIN32)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PRIOVR DEFAULT_MSG PRIOVR_INCLUDE_DIRS PRIOVR_LIBRARIES)
find_package_handle_standard_args(PrioVR DEFAULT_MSG PRIOVR_INCLUDE_DIRS PRIOVR_LIBRARIES)
mark_as_advanced(PRIOVR_INCLUDE_DIRS PRIOVR_LIBRARIES)

View file

@ -26,12 +26,14 @@ find_path(QXMPP_INCLUDE_DIRS QXmppClient.h PATH_SUFFIXES include/qxmpp HINTS ${Q
find_library(QXMPP_LIBRARY_RELEASE NAMES qxmpp PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS})
find_library(QXMPP_LIBRARY_DEBUG NAMES qxmpp_d PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS})
find_package(Qt5 COMPONENTS Xml REQUIRED)
include(SelectLibraryConfigurations)
select_library_configurations(QXMPP)
set(QXMPP_LIBRARIES "${QXMPP_LIBRARY}")
set(QXMPP_LIBRARIES "${QXMPP_LIBRARY}" Qt5::Xml)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QXMPP DEFAULT_MSG QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES)
find_package_handle_standard_args(QXmpp DEFAULT_MSG QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES QXMPP_LIBRARY)
mark_as_advanced(QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES QXMPP_SEARCH_DIRS)

View file

@ -25,6 +25,6 @@ find_path(RTMIDI_INCLUDE_DIRS RtMidi.h PATH_SUFFIXES include HINTS ${RTMIDI_SEAR
find_library(RTMIDI_LIBRARIES NAMES rtmidi PATH_SUFFIXES lib HINTS ${RTMIDI_SEARCH_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(RTMIDI DEFAULT_MSG RTMIDI_INCLUDE_DIRS RTMIDI_LIBRARIES)
find_package_handle_standard_args(RtMidi DEFAULT_MSG RTMIDI_INCLUDE_DIRS RTMIDI_LIBRARIES)
mark_as_advanced(RTMIDI_INCLUDE_DIRS RTMIDI_LIBRARIES RTMIDI_SEARCH_DIRS)

View file

@ -40,6 +40,6 @@ select_library_configurations(SIXENSE)
set(SIXENSE_LIBRARIES "${SIXENSE_LIBRARY}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SIXENSE DEFAULT_MSG SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES)
find_package_handle_standard_args(Sixense DEFAULT_MSG SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES)
mark_as_advanced(SIXENSE_LIBRARIES SIXENSE_INCLUDE_DIRS SIXENSE_SEARCH_DIRS)

View file

@ -30,8 +30,11 @@ if (APPLE)
find_library(VISAGE_CORE_LIBRARY NAME vscore PATH_SUFFIXES lib HINTS ${VISAGE_SEARCH_DIRS})
find_library(VISAGE_VISION_LIBRARY NAME vsvision PATH_SUFFIXES lib HINTS ${VISAGE_SEARCH_DIRS})
find_library(VISAGE_OPENCV_LIBRARY NAME OpenCV PATH_SUFFIXES dependencies/OpenCV_MacOSX/lib ${VISAGE_SEARCH_DIRS})
find_library(VISAGE_OPENCV_LIBRARY NAME OpenCV PATH_SUFFIXES dependencies/OpenCV_MacOSX/lib HINTS ${VISAGE_SEARCH_DIRS})
find_library(AppKit AppKit)
find_library(QuartzCore QuartzCore)
find_library(QTKit QTKit)
elseif (WIN32)
find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h PATH_SUFFIXES dependencies/libxml2/include HINTS ${VISAGE_SEARCH_DIRS})
find_path(VISAGE_OPENCV_INCLUDE_DIR opencv/cv.h PATH_SUFFIXES dependencies/OpenCV/include HINTS ${VISAGE_SEARCH_DIRS})
@ -43,16 +46,22 @@ elseif (WIN32)
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(VISAGE DEFAULT_MSG
VISAGE_BASE_INCLUDE_DIR VISAGE_XML_INCLUDE_DIR VISAGE_OPENCV_INCLUDE_DIR VISAGE_OPENCV2_INCLUDE_DIR
VISAGE_CORE_LIBRARY VISAGE_VISION_LIBRARY VISAGE_OPENCV_LIBRARY
)
list(APPEND VISAGE_ARGS_LIST VISAGE_BASE_INCLUDE_DIR VISAGE_XML_INCLUDE_DIR
VISAGE_OPENCV_INCLUDE_DIR VISAGE_OPENCV2_INCLUDE_DIR
VISAGE_CORE_LIBRARY VISAGE_VISION_LIBRARY VISAGE_OPENCV_LIBRARY)
if (APPLE)
list(APPEND VISAGE_ARGS_LIST QuartzCore AppKit QTKit)
endif ()
find_package_handle_standard_args(Visage DEFAULT_MSG ${VISAGE_ARGS_LIST})
set(VISAGE_INCLUDE_DIRS "${VISAGE_XML_INCLUDE_DIR}" "${VISAGE_OPENCV_INCLUDE_DIR}" "${VISAGE_OPENCV2_INCLUDE_DIR}" "${VISAGE_BASE_INCLUDE_DIR}")
set(VISAGE_LIBRARIES "${VISAGE_CORE_LIBRARY}" "${VISAGE_VISION_LIBRARY}" "${VISAGE_OPENCV_LIBRARY}")
mark_as_advanced(
VISAGE_INCLUDE_DIRS VISAGE_LIBRARIES
VISAGE_BASE_INCLUDE_DIR VISAGE_XML_INCLUDE_DIR VISAGE_OPENCV_INCLUDE_DIR VISAGE_OPENCV2_INCLUDE_DIR
VISAGE_CORE_LIBRARY VISAGE_VISION_LIBRARY VISAGE_OPENCV_LIBRARY VISAGE_SEARCH_DIRS
)
if (APPLE)
list(APPEND VISAGE_LIBRARIES ${QuartzCore} ${AppKit} ${QTKit})
endif ()
mark_as_advanced(VISAGE_INCLUDE_DIRS VISAGE_LIBRARIES)

View file

@ -1,24 +1,7 @@
if (WIN32)
cmake_policy (SET CMP0020 NEW)
endif (WIN32)
set(TARGET_NAME domain-server)
set(ROOT_DIR ..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
# set up the external glm library
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
find_package(Qt5Network REQUIRED)
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE)
# setup the project and link required Qt modules
setup_hifi_project(Network)
# remove and then copy the files for the webserver
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
@ -29,20 +12,7 @@ add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
"${PROJECT_SOURCE_DIR}/resources/web"
$<TARGET_FILE_DIR:${TARGET_NAME}>/resources/web)
# link the shared hifi library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(embedded-webserver ${TARGET_NAME} "${ROOT_DIR}")
# link the shared hifi libraries
link_hifi_libraries(embedded-webserver networking shared)
IF (WIN32)
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
ENDIF(WIN32)
# link QtNetwork
target_link_libraries(${TARGET_NAME} Qt5::Network)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
link_shared_dependencies()

View file

@ -51,6 +51,12 @@
"help": "If enabled, dropped frames and mixing during starves will repeat the last frame, eventually fading to silence",
"default": false
},
"I-print-stream-stats": {
"type": "checkbox",
"label": "Print Stream Stats:",
"help": "If enabled, audio upstream and downstream stats of each agent will be printed each second to stdout",
"default": false
},
"Z-unattenuated-zone": {
"label": "Unattenuated Zone",
"help": "Boxes for source and listener (corner x, corner y, corner z, size x, size y, size z, corner x, corner y, corner z, size x, size y, size z)",

View file

@ -1,18 +1,13 @@
set(ROOT_DIR ..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
set(TARGET_NAME interface)
project(${TARGET_NAME})
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
# set a default root dir for each of our optional externals if it was not passed
set(OPTIONAL_EXTERNALS "faceplus" "faceshift" "oculus" "priovr" "sixense" "visage" "leapmotion" "rtmidi" "qxmpp")
set(OPTIONAL_EXTERNALS "Faceplus" "Faceshift" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp")
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
string(TOUPPER ${EXTERNAL} UPPER_EXTERNAL)
if (NOT ${UPPER_EXTERNAL}_ROOT_DIR)
set(${UPPER_EXTERNAL}_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/${EXTERNAL}")
string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE)
if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR)
string(TOLOWER ${EXTERNAL} ${EXTERNAL}_LOWERCASE)
set(${${EXTERNAL}_UPPERCASE}_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/${${EXTERNAL}_LOWERCASE}")
endif ()
endforeach()
@ -38,8 +33,7 @@ elseif (WIN32)
endif ()
# set up the external glm library
include("${MACRO_DIR}/IncludeGLM.cmake")
include_glm(${TARGET_NAME} "${ROOT_DIR}")
include_glm()
# create the InterfaceConfig.h file based on GL_HEADERS above
configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h")
@ -52,7 +46,7 @@ foreach(SUBDIR avatar devices renderer ui starfield location scripting voxels pa
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
endforeach(SUBDIR)
find_package(Qt5 COMPONENTS Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Script Svg WebKitWidgets)
# grab the ui files in resources/ui
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
@ -97,60 +91,36 @@ endif()
# create the executable, make it a bundle on OS X
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
# link in the hifi shared library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
# link required hifi libraries
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(fbx ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(metavoxels ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(particles ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(models ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(avatars ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(audio ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(animation ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(script-engine ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_libraries(shared octree voxels fbx metavoxels networking particles models avatars audio animation script-engine)
# find any optional and required libraries
find_package(Faceplus)
find_package(Faceshift)
find_package(LibOVR)
find_package(PrioVR)
find_package(SDL)
find_package(Sixense)
find_package(Visage)
find_package(LeapMotion)
find_package(ZLIB)
find_package(Qxmpp)
find_package(RtMidi)
find_package(ZLIB REQUIRED)
find_package(OpenSSL REQUIRED)
# perform standard include and linking for found externals
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
string(TOUPPER ${EXTERNAL} UPPER_EXTERNAL)
if (${UPPER_EXTERNAL} MATCHES "OCULUS")
# the oculus directory is named OCULUS and not LIBOVR so hack to fix that here
set(UPPER_EXTERNAL "LIBOVR")
if (${${EXTERNAL}_UPPERCASE}_REQUIRED)
find_package(${EXTERNAL} REQUIRED)
else ()
find_package(${EXTERNAL})
endif ()
if (${UPPER_EXTERNAL}_FOUND AND NOT DISABLE_${UPPER_EXTERNAL})
add_definitions(-DHAVE_${UPPER_EXTERNAL})
if (${${EXTERNAL}_UPPERCASE}_FOUND AND NOT DISABLE_${${EXTERNAL}_UPPERCASE})
add_definitions(-DHAVE_${${EXTERNAL}_UPPERCASE})
# include the library directories (ignoring warnings)
include_directories(SYSTEM ${${UPPER_EXTERNAL}_INCLUDE_DIRS})
include_directories(SYSTEM ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS})
# perform the system include hack for OS X to ignore warnings
if (APPLE)
foreach(EXTERNAL_INCLUDE_DIR ${${UPPER_EXTERNAL}_INCLUDE_DIRS})
foreach(EXTERNAL_INCLUDE_DIR ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS})
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${EXTERNAL_INCLUDE_DIR}")
endforeach()
endif ()
target_link_libraries(${TARGET_NAME} ${${UPPER_EXTERNAL}_LIBRARIES})
target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES})
endif ()
endforeach()
@ -179,17 +149,11 @@ endif ()
# include headers for interface and InterfaceConfig.
include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes")
# include external library headers
# use system flag so warnings are supressed
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
include_directories("${OPENSSL_INCLUDE_DIR}")
target_link_libraries(
${TARGET_NAME}
"${ZLIB_LIBRARIES}"
${OPENSSL_LIBRARIES}
Qt5::Core Qt5::Gui Qt5::Multimedia Qt5::Network Qt5::OpenGL
Qt5::Script Qt5::Svg Qt5::WebKit Qt5::WebKitWidgets Qt5::Xml Qt5::UiTools
${TARGET_NAME} ${ZLIB_LIBRARIES} ${OPENSSL_LIBRARIES}
Qt5::Gui Qt5::Network Qt5::Multimedia Qt5::OpenGL Qt5::Script Qt5::Svg Qt5::WebKitWidgets
)
# assume we are using a Qt build without bearer management
@ -197,30 +161,12 @@ add_definitions(-DQT_NO_BEARERMANAGEMENT)
if (APPLE)
# link in required OS X frameworks and include the right GL headers
find_library(AppKit AppKit)
find_library(CoreAudio CoreAudio)
find_library(CoreServices CoreServices)
find_library(Carbon Carbon)
find_library(Foundation Foundation)
find_library(CoreFoundation CoreFoundation)
find_library(GLUT GLUT)
find_library(OpenGL OpenGL)
find_library(IOKit IOKit)
find_library(QTKit QTKit)
find_library(QuartzCore QuartzCore)
target_link_libraries(
${TARGET_NAME}
${AppKit}
${CoreAudio}
${CoreServices}
${Carbon}
${Foundation}
${GLUT}
${OpenGL}
${IOKit}
${QTKit}
${QuartzCore}
)
target_link_libraries(${TARGET_NAME} ${CoreAudio} ${CoreFoundation} ${GLUT} ${OpenGL})
# install command for OS X bundle
INSTALL(TARGETS ${TARGET_NAME}
@ -254,9 +200,9 @@ else (APPLE)
# we're using static GLEW, so define GLEW_STATIC
add_definitions(-DGLEW_STATIC)
# add a definition for ssize_t so that windows doesn't bail
add_definitions(-Dssize_t=long)
target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" wsock32.lib opengl32.lib)
endif()
endif (APPLE)
# link any dependencies bubbled up from our linked dependencies
link_shared_dependencies()

View file

@ -0,0 +1,32 @@
#version 120
//
// metavoxel_heightfield_cursor.frag
// fragment shader
//
// Created by Andrzej Kapolka on 8/7/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the inner radius of the outline, squared
const float SQUARED_OUTLINE_INNER_RADIUS = 0.81;
// the outer radius of the outline, squared
const float SQUARED_OUTLINE_OUTER_RADIUS = 1.0;
// the inner radius of the inset, squared
const float SQUARED_INSET_INNER_RADIUS = 0.855625;
// the outer radius of the inset, squared
const float SQUARED_INSET_OUTER_RADIUS = 0.950625;
void main(void) {
// use the distance to compute the ring color, then multiply it by the varying color
float squaredDistance = dot(gl_TexCoord[0].st, gl_TexCoord[0].st);
float alpha = step(SQUARED_OUTLINE_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_OUTLINE_OUTER_RADIUS);
float white = step(SQUARED_INSET_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_INSET_OUTER_RADIUS);
gl_FragColor = gl_Color * vec4(white, white, white, alpha);
}

View file

@ -0,0 +1,31 @@
#version 120
//
// metavoxel_heighfield_cursor.vert
// vertex shader
//
// Created by Andrzej Kapolka on 8/7/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the height texture
uniform sampler2D heightMap;
// the distance between height points in texture space
uniform float heightScale;
void main(void) {
// compute the view space coordinates
float height = texture2D(heightMap, gl_MultiTexCoord0.st).r;
vec4 viewPosition = gl_ModelViewMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0));
gl_Position = gl_ProjectionMatrix * viewPosition;
// generate the texture coordinates from the view position
gl_TexCoord[0] = vec4(dot(viewPosition, gl_EyePlaneS[4]), dot(viewPosition, gl_EyePlaneT[4]), 0.0, 1.0);
// the zero height should be invisible
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0 - step(height, 0.0));
}

View file

@ -261,8 +261,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer)));
connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle);
connect(nodeList, SIGNAL(uuidChanged(const QUuid&)), _myAvatar, SLOT(setSessionUUID(const QUuid&)));
connect(nodeList, &NodeList::uuidChanged, _myAvatar, &MyAvatar::setSessionUUID);
connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset);
// connect to appropriate slots on AccountManager
@ -600,7 +599,7 @@ void Application::paintGL() {
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
_myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay
_myCamera.setTargetPosition(_myAvatar->getHead()->getFilteredEyePosition());
_myCamera.setTargetPosition(_myAvatar->getHead()->getEyePosition());
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
@ -622,7 +621,7 @@ void Application::paintGL() {
_myCamera.setTargetPosition(_myAvatar->getHead()->getEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0));
} else {
_myCamera.setTightness(0.0f);
glm::vec3 eyePosition = _myAvatar->getHead()->getFilteredEyePosition();
glm::vec3 eyePosition = _myAvatar->getHead()->getEyePosition();
float headHeight = eyePosition.y - _myAvatar->getPosition().y;
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
_myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0));
@ -1441,6 +1440,15 @@ void Application::setEnable3DTVMode(bool enable3DTVMode) {
}
void Application::setEnableVRMode(bool enableVRMode) {
if (enableVRMode) {
if (!OculusManager::isConnected()) {
// attempt to reconnect the Oculus manager - it's possible this was a workaround
// for the sixense crash
OculusManager::disconnect();
OculusManager::connect();
}
}
resizeGL(_glWidget->width(), _glWidget->height());
}

View file

@ -56,7 +56,6 @@ static const int MUTE_ICON_SIZE = 24;
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 100;
Audio::Audio(QObject* parent) :
AbstractAudioInterface(parent),
_audioInput(NULL),
@ -83,6 +82,7 @@ Audio::Audio(QObject* parent) :
_noiseGateSampleCounter(0),
_noiseGateOpen(false),
_noiseGateEnabled(true),
_peqEnabled(false),
_toneInjectionEnabled(false),
_noiseGateFramesToClose(0),
_totalInputAudioSamples(0),
@ -136,6 +136,7 @@ void Audio::init(QGLWidget *parent) {
void Audio::reset() {
_receivedAudioStream.reset();
resetStats();
_peq.reset();
}
void Audio::resetStats() {
@ -422,9 +423,15 @@ void Audio::start() {
if (!outputFormatSupported) {
qDebug() << "Unable to set up audio output because of a problem with output format.";
}
_peq.initialize( _inputFormat.sampleRate(), _audioInput->bufferSize() );
}
void Audio::stop() {
_peq.finalize();
// "switch" to invalid devices in order to shut down the state
switchInputToAudioDevice(QAudioDeviceInfo());
switchOutputToAudioDevice(QAudioDeviceInfo());
@ -469,7 +476,15 @@ void Audio::handleAudioInput() {
int inputSamplesRequired = (int)((float)NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * inputToNetworkInputRatio);
QByteArray inputByteArray = _inputDevice->readAll();
if (_peqEnabled && !_muted) {
// we wish to pre-filter our captured input, prior to loopback
int16_t* ioBuffer = (int16_t*)inputByteArray.data();
_peq.render( ioBuffer, ioBuffer, inputByteArray.size() / sizeof(int16_t) );
}
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio) && !_muted && _audioOutput) {
// if this person wants local loopback add that to the locally injected audio
@ -1193,6 +1208,31 @@ void Audio::renderToolBox(int x, int y, bool boxed) {
glDisable(GL_TEXTURE_2D);
}
void Audio::toggleAudioFilter() {
_peqEnabled = !_peqEnabled;
}
void Audio::selectAudioFilterFlat() {
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioFilterFlat)) {
_peq.loadProfile(0);
}
}
void Audio::selectAudioFilterTrebleCut() {
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioFilterTrebleCut)) {
_peq.loadProfile(1);
}
}
void Audio::selectAudioFilterBassCut() {
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioFilterBassCut)) {
_peq.loadProfile(2);
}
}
void Audio::selectAudioFilterSmiley() {
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioFilterSmiley)) {
_peq.loadProfile(3);
}
}
void Audio::toggleScope() {
_scopeEnabled = !_scopeEnabled;
if (_scopeEnabled) {

View file

@ -19,6 +19,7 @@
#include "AudioStreamStats.h"
#include "RingBufferHistory.h"
#include "MovingMinMaxAvg.h"
#include "AudioFilter.h"
#include <QAudio>
#include <QAudioInput>
@ -121,12 +122,16 @@ public slots:
void selectAudioScopeFiveFrames();
void selectAudioScopeTwentyFrames();
void selectAudioScopeFiftyFrames();
void addStereoSilenceToScope(int silentSamplesPerChannel);
void addLastFrameRepeatedWithFadeToScope(int samplesPerChannel);
void addStereoSamplesToScope(const QByteArray& samples);
void processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer);
void toggleAudioFilter();
void selectAudioFilterFlat();
void selectAudioFilterTrebleCut();
void selectAudioFilterBassCut();
void selectAudioFilterSmiley();
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
void sendDownstreamAudioStatsPacket();
@ -254,12 +259,12 @@ private:
// Audio scope methods for rendering
void renderBackground(const float* color, int x, int y, int width, int height);
void renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols);
void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray);
void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray);
// audio stats methods for rendering
void renderAudioStreamStats(const AudioStreamStats& streamStats, int horizontalOffset, int& verticalOffset,
float scale, float rotation, int font, const float* color, bool isDownstreamStats = false);
// Audio scope data
static const unsigned int NETWORK_SAMPLES_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
static const unsigned int DEFAULT_FRAMES_PER_SCOPE = 5;
@ -272,6 +277,11 @@ private:
int _scopeOutputOffset;
int _framesPerScope;
int _samplesPerScope;
// Multi-band parametric EQ
bool _peqEnabled;
AudioFilterPEQ3 _peq;
QMutex _guard;
QByteArray* _scopeInput;
QByteArray* _scopeOutputLeft;

View file

@ -485,6 +485,48 @@ Menu::Menu() :
true,
appInstance->getAudio(),
SLOT(toggleAudioNoiseReduction()));
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioFilter,
0,
false,
appInstance->getAudio(),
SLOT(toggleAudioFilter()));
QMenu* audioFilterMenu = audioDebugMenu->addMenu("Audio Filter Options");
addDisabledActionAndSeparator(audioFilterMenu, "Filter Response");
{
QAction *flat = addCheckableActionToQMenuAndActionHash(audioFilterMenu, MenuOption::AudioFilterFlat,
0,
true,
appInstance->getAudio(),
SLOT(selectAudioFilterFlat()));
QAction *trebleCut = addCheckableActionToQMenuAndActionHash(audioFilterMenu, MenuOption::AudioFilterTrebleCut,
0,
false,
appInstance->getAudio(),
SLOT(selectAudioFilterTrebleCut()));
QAction *bassCut = addCheckableActionToQMenuAndActionHash(audioFilterMenu, MenuOption::AudioFilterBassCut,
0,
false,
appInstance->getAudio(),
SLOT(selectAudioFilterBassCut()));
QAction *smiley = addCheckableActionToQMenuAndActionHash(audioFilterMenu, MenuOption::AudioFilterSmiley,
0,
false,
appInstance->getAudio(),
SLOT(selectAudioFilterSmiley()));
QActionGroup* audioFilterGroup = new QActionGroup(audioFilterMenu);
audioFilterGroup->addAction(flat);
audioFilterGroup->addAction(trebleCut);
audioFilterGroup->addAction(bassCut);
audioFilterGroup->addAction(smiley);
}
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio);
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio);
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::StereoAudio, 0, false,

View file

@ -308,6 +308,11 @@ namespace MenuOption {
const QString Animations = "Animations...";
const QString Atmosphere = "Atmosphere";
const QString Attachments = "Attachments...";
const QString AudioFilter = "Audio Filter Bank";
const QString AudioFilterFlat = "Flat Response";
const QString AudioFilterTrebleCut= "Treble Cut";
const QString AudioFilterBassCut = "Bass Cut";
const QString AudioFilterSmiley = "Smiley Curve";
const QString AudioNoiseReduction = "Audio Noise Reduction";
const QString AudioScope = "Audio Scope";
const QString AudioScopeFiftyFrames = "Fifty";

View file

@ -118,6 +118,73 @@ void MetavoxelSystem::render() {
guideToAugmented(renderVisitor);
}
class HeightfieldCursorRenderVisitor : public MetavoxelVisitor {
public:
HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds);
virtual int visit(MetavoxelInfo& info);
private:
Box _bounds;
};
HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) :
MetavoxelVisitor(QVector<AttributePointer>() <<
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>(), lod),
_bounds(bounds) {
}
int HeightfieldCursorRenderVisitor::visit(MetavoxelInfo& info) {
if (!info.getBounds().intersects(_bounds)) {
return STOP_RECURSION;
}
if (!info.isLeaf) {
return DEFAULT_ORDER;
}
BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>();
if (buffer) {
buffer->render(true);
}
return STOP_RECURSION;
}
void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float radius) {
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().bind();
glActiveTexture(GL_TEXTURE4);
float scale = 1.0f / radius;
glm::vec4 sCoefficients(scale, 0.0f, 0.0f, -scale * position.x);
glm::vec4 tCoefficients(0.0f, 0.0f, scale, -scale * position.z);
glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&sCoefficients);
glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&tCoefficients);
glActiveTexture(GL_TEXTURE0);
glm::vec3 extents(radius, radius, radius);
HeightfieldCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents));
guideToAugmented(visitor);
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_CULL_FACE);
glDepthFunc(GL_LESS);
}
void MetavoxelSystem::deleteTextures(int heightID, int colorID) {
glDeleteTextures(1, (GLuint*)&heightID);
glDeleteTextures(1, (GLuint*)&colorID);
@ -239,7 +306,7 @@ PointBuffer::PointBuffer(const BufferPointVector& points) :
_points(points) {
}
void PointBuffer::render() {
void PointBuffer::render(bool cursor) {
// initialize buffer, etc. on first render
if (!_buffer.isCreated()) {
_buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
@ -294,7 +361,7 @@ public:
glm::vec3 vertex;
};
void HeightfieldBuffer::render() {
void HeightfieldBuffer::render(bool cursor) {
// initialize textures, etc. on first render
if (_heightTextureID == 0) {
glGenTextures(1, &_heightTextureID);
@ -385,17 +452,24 @@ void HeightfieldBuffer::render() {
glBindTexture(GL_TEXTURE_2D, _heightTextureID);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
int heightScaleLocation;
if (cursor) {
heightScaleLocation = DefaultMetavoxelRendererImplementation::getCursorHeightScaleLocation();
} else {
heightScaleLocation = DefaultMetavoxelRendererImplementation::getHeightScaleLocation();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
}
DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getHeightScaleLocation(), 1.0f / _heightSize);
DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(heightScaleLocation, 1.0f / _heightSize);
glDrawRangeElements(GL_QUADS, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
if (!cursor) {
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
@ -475,6 +549,17 @@ void DefaultMetavoxelRendererImplementation::init() {
_heightfieldProgram.setUniformValue("diffuseMap", 1);
_heightScaleLocation = _heightfieldProgram.uniformLocation("heightScale");
_heightfieldProgram.release();
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield_cursor.vert");
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_heightfield_cursor.frag");
_heightfieldCursorProgram.link();
_heightfieldCursorProgram.bind();
_heightfieldCursorProgram.setUniformValue("heightMap", 0);
_cursorHeightScaleLocation = _heightfieldCursorProgram.uniformLocation("heightScale");
_heightfieldCursorProgram.release();
}
}
@ -771,6 +856,8 @@ ProgramObject DefaultMetavoxelRendererImplementation::_pointProgram;
int DefaultMetavoxelRendererImplementation::_pointScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldProgram;
int DefaultMetavoxelRendererImplementation::_heightScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram;
int DefaultMetavoxelRendererImplementation::_cursorHeightScaleLocation;
static void enableClipPlane(GLenum plane, float x, float y, float z, float w) {
GLdouble coefficients[] = { x, y, z, w };

View file

@ -43,6 +43,8 @@ public:
void simulate(float deltaTime);
void render();
void renderHeightfieldCursor(const glm::vec3& position, float radius);
Q_INVOKABLE void deleteTextures(int heightID, int colorID);
protected:
@ -105,7 +107,7 @@ public:
virtual ~BufferData();
virtual void render() = 0;
virtual void render(bool cursor = false) = 0;
};
typedef QExplicitlySharedDataPointer<BufferData> BufferDataPointer;
@ -116,7 +118,7 @@ public:
PointBuffer(const BufferPointVector& points);
virtual void render();
virtual void render(bool cursor = false);
private:
@ -140,7 +142,7 @@ public:
const QByteArray& getHeight() const { return _height; }
const QByteArray& getColor() const { return _color; }
virtual void render();
virtual void render(bool cursor = false);
private:
@ -193,6 +195,9 @@ public:
static ProgramObject& getHeightfieldProgram() { return _heightfieldProgram; }
static int getHeightScaleLocation() { return _heightScaleLocation; }
static ProgramObject& getHeightfieldCursorProgram() { return _heightfieldCursorProgram; }
static int getCursorHeightScaleLocation() { return _cursorHeightScaleLocation; }
Q_INVOKABLE DefaultMetavoxelRendererImplementation();
virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod);
@ -206,6 +211,9 @@ private:
static ProgramObject _heightfieldProgram;
static int _heightScaleLocation;
static ProgramObject _heightfieldCursorProgram;
static int _cursorHeightScaleLocation;
};
/// Base class for spanner renderers; provides clipping.

View file

@ -163,9 +163,6 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
}
_eyePosition = calculateAverageEyePosition();
float velocityFilter = glm::clamp(1.0f - glm::length(_filteredEyePosition - _eyePosition), 0.0f, 1.0f);
_filteredEyePosition = velocityFilter * _filteredEyePosition + (1.0f - velocityFilter) * _eyePosition;
}
void Head::relaxLean(float deltaTime) {

View file

@ -88,7 +88,6 @@ public:
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
float getAverageLoudness() const { return _averageLoudness; }
glm::vec3 getFilteredEyePosition() const { return _filteredEyePosition; }
/// \return the point about which scaling occurs.
glm::vec3 getScalePivot() const;
@ -121,7 +120,6 @@ private:
glm::vec3 _leftEyePosition;
glm::vec3 _rightEyePosition;
glm::vec3 _eyePosition;
glm::vec3 _filteredEyePosition; // velocity filtered world space eye position
float _scale;
float _lastLoudness;

View file

@ -85,13 +85,13 @@ MyAvatar::MyAvatar() :
}
_skeletonModel.setEnableShapes(true);
// The skeleton is both a PhysicsEntity and Ragdoll, so we add it to the simulation once for each type.
_physicsSimulation.addEntity(&_skeletonModel);
_physicsSimulation.addRagdoll(&_skeletonModel);
_physicsSimulation.setEntity(&_skeletonModel);
_physicsSimulation.setRagdoll(&_skeletonModel);
}
MyAvatar::~MyAvatar() {
_physicsSimulation.removeEntity(&_skeletonModel);
_physicsSimulation.removeRagdoll(&_skeletonModel);
_physicsSimulation.setRagdoll(NULL);
_physicsSimulation.setEntity(NULL);
_lookAtTargetAvatar.clear();
}
@ -206,9 +206,10 @@ void MyAvatar::simulate(float deltaTime) {
{
PerformanceTimer perfTimer("ragdoll");
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) {
const int minError = 0.01f;
const float minError = 0.01f;
const float maxIterations = 10;
const quint64 maxUsec = 2000;
_physicsSimulation.setTranslation(_position);
_physicsSimulation.stepForward(deltaTime, minError, maxIterations, maxUsec);
} else {
_skeletonModel.moveShapesTowardJoints(1.0f);
@ -235,12 +236,10 @@ void MyAvatar::simulate(float deltaTime) {
} else {
_trapDuration = 0.0f;
}
/* TODO: Andrew to make this work
if (_collisionGroups & COLLISION_GROUP_AVATARS) {
PerformanceTimer perfTimer("avatars");
updateCollisionWithAvatars(deltaTime);
}
*/
}
// consider updating our billboard
@ -256,6 +255,12 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
estimatedRotation.x *= -1.0f;
estimatedRotation.z *= -1.0f;
} else if (OculusManager::isConnected()) {
estimatedPosition = OculusManager::getRelativePosition();
estimatedPosition.x *= -1.0f;
const float OCULUS_LEAN_SCALE = 0.05f;
estimatedPosition /= OCULUS_LEAN_SCALE;
} else {
FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker();
if (tracker) {
@ -1551,8 +1556,6 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float
return false;
}
const float BODY_COLLISION_RESOLUTION_TIMESCALE = 0.5f; // seconds
void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
// Reset detector for nearest avatar
_distanceToNearestAvatar = std::numeric_limits<float>::max();
@ -1563,41 +1566,51 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
}
float myBoundingRadius = getBoundingRadius();
const float BODY_COLLISION_RESOLUTION_FACTOR = glm::max(1.0f, deltaTime / BODY_COLLISION_RESOLUTION_TIMESCALE);
// find nearest avatar
float nearestDistance2 = std::numeric_limits<float>::max();
Avatar* nearestAvatar = NULL;
foreach (const AvatarSharedPointer& avatarPointer, avatars) {
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
if (static_cast<Avatar*>(this) == avatar) {
// don't collide with ourselves
continue;
}
float distance = glm::length(_position - avatar->getPosition());
if (_distanceToNearestAvatar > distance) {
_distanceToNearestAvatar = distance;
float distance2 = glm::distance2(_position, avatar->getPosition());
if (nearestDistance2 > distance2) {
nearestDistance2 = distance2;
nearestAvatar = avatar;
}
float theirBoundingRadius = avatar->getBoundingRadius();
if (distance < myBoundingRadius + theirBoundingRadius) {
// collide our body against theirs
QVector<const Shape*> myShapes;
_skeletonModel.getBodyShapes(myShapes);
QVector<const Shape*> theirShapes;
avatar->getSkeletonModel().getBodyShapes(theirShapes);
}
_distanceToNearestAvatar = glm::sqrt(nearestDistance2);
CollisionInfo collision;
if (ShapeCollider::collideShapesCoarse(myShapes, theirShapes, collision)) {
float penetrationDepth = glm::length(collision._penetration);
if (penetrationDepth > myBoundingRadius) {
qDebug() << "WARNING: ignoring avatar-avatar penetration depth " << penetrationDepth;
}
else if (penetrationDepth > EPSILON) {
setPosition(getPosition() - BODY_COLLISION_RESOLUTION_FACTOR * collision._penetration);
_lastBodyPenetration += collision._penetration;
emit collisionWithAvatar(getSessionUUID(), avatar->getSessionUUID(), collision);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) {
if (nearestAvatar != NULL) {
if (_distanceToNearestAvatar > myBoundingRadius + nearestAvatar->getBoundingRadius()) {
// they aren't close enough to put into the _physicsSimulation
// so we clear the pointer
nearestAvatar = NULL;
}
}
foreach (const AvatarSharedPointer& avatarPointer, avatars) {
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
if (static_cast<Avatar*>(this) == avatar) {
// don't collide with ourselves
continue;
}
SkeletonModel* skeleton = &(avatar->getSkeletonModel());
PhysicsSimulation* simulation = skeleton->getSimulation();
if (avatar == nearestAvatar) {
if (simulation != &(_physicsSimulation)) {
skeleton->setEnableShapes(true);
_physicsSimulation.addEntity(skeleton);
_physicsSimulation.addRagdoll(skeleton);
}
} else if (simulation == &(_physicsSimulation)) {
_physicsSimulation.removeRagdoll(skeleton);
_physicsSimulation.removeEntity(skeleton);
skeleton->setEnableShapes(false);
}
// collide their hands against us
avatar->getHand()->collideAgainstAvatar(this, false);
}
}
}

View file

@ -490,11 +490,13 @@ void SkeletonModel::renderRagdoll() {
float alpha = 0.3f;
float radius1 = 0.008f;
float radius2 = 0.01f;
glm::vec3 simulationTranslation = getTranslationInSimulationFrame();
for (int i = 0; i < numPoints; ++i) {
glPushMatrix();
// draw each point as a yellow hexagon with black border
glm::vec3 position = _rotation * _ragdollPoints[i]._position;
// NOTE: ragdollPoints are in simulation-frame but we want them to be model-relative
glm::vec3 position = _ragdollPoints[i]._position - simulationTranslation;
glTranslatef(position.x, position.y, position.z);
// draw each point as a yellow hexagon with black border
glColor4f(0.0f, 0.0f, 0.0f, alpha);
glutSolidSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
glColor4f(1.0f, 1.0f, 0.0f, alpha);
@ -511,13 +513,14 @@ void SkeletonModel::initRagdollPoints() {
clearRagdollConstraintsAndPoints();
_muscleConstraints.clear();
initRagdollTransform();
// one point for each joint
int numJoints = _jointStates.size();
_ragdollPoints.fill(VerletPoint(), numJoints);
for (int i = 0; i < numJoints; ++i) {
int numStates = _jointStates.size();
_ragdollPoints.fill(VerletPoint(), numStates);
for (int i = 0; i < numStates; ++i) {
const JointState& state = _jointStates.at(i);
glm::vec3 position = state.getPosition();
_ragdollPoints[i].initPosition(position);
// _ragdollPoints start in model-frame
_ragdollPoints[i].initPosition(state.getPosition());
}
}
@ -534,12 +537,12 @@ void SkeletonModel::buildRagdollConstraints() {
const JointState& state = _jointStates.at(i);
int parentIndex = state.getParentIndex();
if (parentIndex == -1) {
FixedConstraint* anchor = new FixedConstraint(&(_ragdollPoints[i]), glm::vec3(0.0f));
_ragdollConstraints.push_back(anchor);
FixedConstraint* anchor = new FixedConstraint(&_translationInSimulationFrame, &(_ragdollPoints[i]));
_fixedConstraints.push_back(anchor);
} else {
DistanceConstraint* bone = new DistanceConstraint(&(_ragdollPoints[i]), &(_ragdollPoints[parentIndex]));
bone->setDistance(state.getDistanceToParent());
_ragdollConstraints.push_back(bone);
_boneConstraints.push_back(bone);
families.insert(parentIndex, i);
}
float boneLength = glm::length(state.getPositionInParentFrame());
@ -558,11 +561,11 @@ void SkeletonModel::buildRagdollConstraints() {
if (numChildren > 1) {
for (int i = 1; i < numChildren; ++i) {
DistanceConstraint* bone = new DistanceConstraint(&(_ragdollPoints[children[i-1]]), &(_ragdollPoints[children[i]]));
_ragdollConstraints.push_back(bone);
_boneConstraints.push_back(bone);
}
if (numChildren > 2) {
DistanceConstraint* bone = new DistanceConstraint(&(_ragdollPoints[children[numChildren-1]]), &(_ragdollPoints[children[0]]));
_ragdollConstraints.push_back(bone);
_boneConstraints.push_back(bone);
}
}
++itr;
@ -604,6 +607,7 @@ void SkeletonModel::updateVisibleJointStates() {
}
QVector<glm::vec3> points;
points.reserve(_jointStates.size());
glm::quat invRotation = glm::inverse(_rotation);
for (int i = 0; i < _jointStates.size(); i++) {
JointState& state = _jointStates[i];
points.push_back(_ragdollPoints[i]._position);
@ -628,8 +632,9 @@ void SkeletonModel::updateVisibleJointStates() {
// we're looking for the rotation that moves visible bone parallel to ragdoll bone
// rotationBetween(jointTip - jointPivot, shapeTip - shapePivot)
// NOTE: points are in simulation-frame so rotate line segment into model-frame
glm::quat delta = rotationBetween(state.getVisiblePosition() - extractTranslation(parentTransform),
points[i] - points[parentIndex]);
invRotation * (points[i] - points[parentIndex]));
// apply
parentState.mixVisibleRotationDelta(delta, 0.01f);
@ -641,6 +646,7 @@ void SkeletonModel::updateVisibleJointStates() {
// virtual
void SkeletonModel::stepRagdollForward(float deltaTime) {
setRagdollTransform(_translation, _rotation);
Ragdoll::stepRagdollForward(deltaTime);
updateMuscles();
int numConstraints = _muscleConstraints.size();
@ -665,6 +671,7 @@ void SkeletonModel::buildShapes() {
}
initRagdollPoints();
float massScale = getMassScale();
float uniformScale = extractUniformScale(_scale);
const int numStates = _jointStates.size();
@ -678,25 +685,30 @@ void SkeletonModel::buildShapes() {
// this shape is forced to be a sphere
type = Shape::SPHERE_SHAPE;
}
if (radius < EPSILON) {
type = Shape::UNKNOWN_SHAPE;
}
Shape* shape = NULL;
int parentIndex = joint.parentIndex;
if (type == Shape::SPHERE_SHAPE) {
shape = new VerletSphereShape(radius, &(_ragdollPoints[i]));
shape->setEntity(this);
_ragdollPoints[i]._mass = glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume());
_ragdollPoints[i].setMass(massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume()));
} else if (type == Shape::CAPSULE_SHAPE) {
assert(parentIndex != -1);
shape = new VerletCapsuleShape(radius, &(_ragdollPoints[parentIndex]), &(_ragdollPoints[i]));
shape->setEntity(this);
_ragdollPoints[i]._mass = glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume());
_ragdollPoints[i].setMass(massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume()));
}
if (parentIndex != -1) {
// always disable collisions between joint and its parent
disableCollisions(i, parentIndex);
if (shape) {
disableCollisions(i, parentIndex);
}
} else {
// give the base joint a very large mass since it doesn't actually move
// in the local-frame simulation (it defines the origin)
_ragdollPoints[i]._mass = VERY_BIG_MASS;
_ragdollPoints[i].setMass(VERY_BIG_MASS);
}
_shapes.push_back(shape);
}
@ -712,8 +724,9 @@ void SkeletonModel::buildShapes() {
// ... then move shapes back to current joint positions
if (_ragdollPoints.size() == numStates) {
int numJoints = _jointStates.size();
for (int i = 0; i < numJoints; ++i) {
int numStates = _jointStates.size();
for (int i = 0; i < numStates; ++i) {
// ragdollPoints start in model-frame
_ragdollPoints[i].initPosition(_jointStates.at(i).getPosition());
}
}
@ -735,9 +748,11 @@ void SkeletonModel::moveShapesTowardJoints(float deltaTime) {
float fraction = glm::clamp(deltaTime / RAGDOLL_FOLLOWS_JOINTS_TIMESCALE, 0.0f, 1.0f);
float oneMinusFraction = 1.0f - fraction;
glm::vec3 simulationTranslation = getTranslationInSimulationFrame();
for (int i = 0; i < numStates; ++i) {
// ragdollPoints are in simulation-frame but jointStates are in model-frame
_ragdollPoints[i].initPosition(oneMinusFraction * _ragdollPoints[i]._position +
fraction * _jointStates.at(i).getPosition());
fraction * (simulationTranslation + _rotation * (_jointStates.at(i).getPosition())));
}
}
@ -748,23 +763,22 @@ void SkeletonModel::updateMuscles() {
int j = constraint->getParentIndex();
int k = constraint->getChildIndex();
assert(j != -1 && k != -1);
constraint->setChildOffset(_jointStates.at(k).getPosition() - _jointStates.at(j).getPosition());
// ragdollPoints are in simulation-frame but jointStates are in model-frame
constraint->setChildOffset(_rotation * (_jointStates.at(k).getPosition() - _jointStates.at(j).getPosition()));
}
}
void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
// compute default joint transforms
int numJoints = geometry.joints.size();
if (numJoints != _ragdollPoints.size()) {
return;
}
int numStates = _jointStates.size();
QVector<glm::mat4> transforms;
transforms.fill(glm::mat4(), numJoints);
transforms.fill(glm::mat4(), numStates);
// compute the default transforms and slam the ragdoll positions accordingly
// (which puts the shapes where we want them)
for (int i = 0; i < numJoints; i++) {
const FBXJoint& joint = geometry.joints.at(i);
for (int i = 0; i < numStates; i++) {
JointState& state = _jointStates[i];
const FBXJoint& joint = state.getFBXJoint();
int parentIndex = joint.parentIndex;
if (parentIndex == -1) {
transforms[i] = _jointStates[i].getTransform();
@ -836,7 +850,7 @@ void SkeletonModel::resetShapePositionsToDefaultPose() {
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
if (geometry.joints.isEmpty() || _shapes.size() != geometry.joints.size()) {
if (geometry.joints.isEmpty()) {
return;
}
@ -891,3 +905,54 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) {
glPopMatrix();
}
const int BALL_SUBDIVISIONS = 10;
// virtual
void SkeletonModel::renderJointCollisionShapes(float alpha) {
glPushMatrix();
Application::getInstance()->loadTranslatedViewMatrix(_translation);
glm::vec3 simulationTranslation = getTranslationInSimulationFrame();
for (int i = 0; i < _shapes.size(); i++) {
Shape* shape = _shapes[i];
if (!shape) {
continue;
}
glPushMatrix();
// shapes are stored in simulation-frame but we want position to be model-relative
if (shape->getType() == Shape::SPHERE_SHAPE) {
glm::vec3 position = shape->getTranslation() - simulationTranslation;
glTranslatef(position.x, position.y, position.z);
// draw a grey sphere at shape position
glColor4f(0.75f, 0.75f, 0.75f, alpha);
glutSolidSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
} else if (shape->getType() == Shape::CAPSULE_SHAPE) {
CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
// draw a blue sphere at the capsule endpoint
glm::vec3 endPoint;
capsule->getEndPoint(endPoint);
endPoint = endPoint - simulationTranslation;
glTranslatef(endPoint.x, endPoint.y, endPoint.z);
glColor4f(0.6f, 0.6f, 0.8f, alpha);
glutSolidSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
// draw a yellow sphere at the capsule startpoint
glm::vec3 startPoint;
capsule->getStartPoint(startPoint);
startPoint = startPoint - simulationTranslation;
glm::vec3 axis = endPoint - startPoint;
glTranslatef(-axis.x, -axis.y, -axis.z);
glColor4f(0.8f, 0.8f, 0.6f, alpha);
glutSolidSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
// draw a green cylinder between the two points
glm::vec3 origin(0.0f);
glColor4f(0.6f, 0.8f, 0.6f, alpha);
Avatar::renderJointConnectingCone( origin, axis, capsule->getRadius(), capsule->getRadius());
}
glPopMatrix();
}
glPopMatrix();
}

View file

@ -105,6 +105,7 @@ public:
void computeBoundingShape(const FBXGeometry& geometry);
void renderBoundingCollisionShapes(float alpha);
void renderJointCollisionShapes(float alpha);
float getBoundingShapeRadius() const { return _boundingShape.getRadius(); }
const CapsuleShape& getBoundingShape() const { return _boundingShape; }

View file

@ -10,7 +10,7 @@
//
#include "CaraFaceTracker.h"
#include <SharedUtil.h>
#include <GLMHelpers.h>
//qt
#include <QJsonDocument>

View file

@ -178,6 +178,31 @@ float rescaleCoef(float ddeCoef) {
return (ddeCoef - DDE_MIN_RANGE) / (DDE_MAX_RANGE - DDE_MIN_RANGE);
}
const int MIN = 0;
const int AVG = 1;
const int MAX = 2;
const float LONG_TERM_AVERAGE = 0.999f;
void resetCoefficient(float * coefficient, float currentValue) {
coefficient[MIN] = coefficient[MAX] = coefficient[AVG] = currentValue;
}
float updateAndGetCoefficient(float * coefficient, float currentValue, bool scaleToRange = false) {
coefficient[MIN] = (currentValue < coefficient[MIN]) ? currentValue : coefficient[MIN];
coefficient[MAX] = (currentValue > coefficient[MAX]) ? currentValue : coefficient[MAX];
coefficient[AVG] = LONG_TERM_AVERAGE * coefficient[AVG] + (1.f - LONG_TERM_AVERAGE) * currentValue;
if (coefficient[MAX] > coefficient[MIN]) {
if (scaleToRange) {
return glm::clamp((currentValue - coefficient[AVG]) / (coefficient[MAX] - coefficient[MIN]), 0.f, 1.f);
} else {
return glm::clamp(currentValue - coefficient[AVG], 0.f, 1.f);
}
} else {
return 0.f;
}
}
void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
if(buffer.size() > MIN_PACKET_SIZE) {
Packet packet;
@ -189,14 +214,17 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
memcpy(&translation, packet.translation, sizeof(packet.translation));
glm::quat rotation;
memcpy(&rotation, &packet.rotation, sizeof(packet.rotation));
if (_reset) {
if (_reset || (_lastReceiveTimestamp == 0)) {
memcpy(&_referenceTranslation, &translation, sizeof(glm::vec3));
memcpy(&_referenceRotation, &rotation, sizeof(glm::quat));
resetCoefficient(_rightEye, packet.expressions[0]);
resetCoefficient(_leftEye, packet.expressions[1]);
_reset = false;
}
// Compute relative translation
float LEAN_DAMPING_FACTOR = 40;
float LEAN_DAMPING_FACTOR = 200.0f;
translation -= _referenceTranslation;
translation /= LEAN_DAMPING_FACTOR;
translation.x *= -1;
@ -208,10 +236,19 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
_headTranslation = translation;
_headRotation = rotation;
if (_lastReceiveTimestamp == 0) {
// On first packet, reset coefficients
}
// Set blendshapes
float BLINK_MAGNIFIER = 2.0f;
_blendshapeCoefficients[_leftBlinkIndex] = rescaleCoef(packet.expressions[1]) * BLINK_MAGNIFIER;
_blendshapeCoefficients[_rightBlinkIndex] = rescaleCoef(packet.expressions[0]) * BLINK_MAGNIFIER;
float EYE_MAGNIFIER = 4.0f;
float rightEye = (updateAndGetCoefficient(_rightEye, packet.expressions[0])) * EYE_MAGNIFIER;
_blendshapeCoefficients[_rightBlinkIndex] = rightEye;
float leftEye = (updateAndGetCoefficient(_leftEye, packet.expressions[1])) * EYE_MAGNIFIER;
_blendshapeCoefficients[_leftBlinkIndex] = leftEye;
// Right eye = packet.expressions[0];
float leftBrow = 1.0f - rescaleCoef(packet.expressions[14]);
if (leftBrow < 0.5f) {

View file

@ -84,6 +84,10 @@ private:
int _mouthSmileRightIndex;
int _jawOpenIndex;
float _leftEye[3];
float _rightEye[3];
};
#endif // hifi_DdeFaceTracker_h

View file

@ -44,7 +44,7 @@ ovrFovPort OculusManager::_eyeFov[ovrEye_Count];
ovrEyeRenderDesc OculusManager::_eyeRenderDesc[ovrEye_Count];
ovrSizei OculusManager::_renderTargetSize;
ovrVector2f OculusManager::_UVScaleOffset[ovrEye_Count][2];
GLuint OculusManager::_vertices[ovrEye_Count] = { 0, 0 };
GLuint OculusManager::_vertices[ovrEye_Count] = { 0, 0 };
GLuint OculusManager::_indices[ovrEye_Count] = { 0, 0 };
GLsizei OculusManager::_meshSize[ovrEye_Count] = { 0, 0 };
ovrFrameTiming OculusManager::_hmdFrameTiming;
@ -66,12 +66,14 @@ void OculusManager::connect() {
UserActivityLogger::getInstance().connectedDevice("hmd", "oculus");
}
_isConnected = true;
#if defined(__APPLE__) || defined(_WIN32)
_eyeFov[0] = _ovrHmd->DefaultEyeFov[0];
_eyeFov[1] = _ovrHmd->DefaultEyeFov[1];
#else
ovrHmd_GetDesc(_ovrHmd, &_ovrHmdDesc);
_eyeFov[0] = _ovrHmdDesc.DefaultEyeFov[0];
_eyeFov[1] = _ovrHmdDesc.DefaultEyeFov[1];
#endif
//Get texture size
ovrSizei recommendedTex0Size = ovrHmd_GetFovTextureSize(_ovrHmd, ovrEye_Left,
_eyeFov[0], 1.0f);
@ -86,11 +88,21 @@ void OculusManager::connect() {
_eyeRenderDesc[0] = ovrHmd_GetRenderDesc(_ovrHmd, ovrEye_Left, _eyeFov[0]);
_eyeRenderDesc[1] = ovrHmd_GetRenderDesc(_ovrHmd, ovrEye_Right, _eyeFov[1]);
#if defined(__APPLE__) || defined(_WIN32)
ovrHmd_SetEnabledCaps(_ovrHmd, ovrHmdCap_LowPersistence);
#else
ovrHmd_SetEnabledCaps(_ovrHmd, ovrHmdCap_LowPersistence | ovrHmdCap_LatencyTest);
#endif
#if defined(__APPLE__) || defined(_WIN32)
ovrHmd_ConfigureTracking(_ovrHmd, ovrTrackingCap_Orientation | ovrTrackingCap_Position |
ovrTrackingCap_MagYawCorrection,
ovrTrackingCap_Orientation);
#else
ovrHmd_StartSensor(_ovrHmd, ovrSensorCap_Orientation | ovrSensorCap_YawCorrection |
ovrSensorCap_Position,
ovrSensorCap_Orientation);
#endif
if (!_camera) {
_camera = new Camera;
@ -123,6 +135,10 @@ void OculusManager::connect() {
} else {
_isConnected = false;
// we're definitely not in "VR mode" so tell the menu that
Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(false);
ovrHmd_Destroy(_ovrHmd);
ovr_Shutdown();
}
@ -183,6 +199,16 @@ void OculusManager::generateDistortionMesh() {
DistortionVertex* v = pVBVerts;
ovrDistortionVertex* ov = meshData.pVertexData;
for (unsigned int vertNum = 0; vertNum < meshData.VertexCount; vertNum++) {
#if defined(__APPLE__) || defined(_WIN32)
v->pos.x = ov->ScreenPosNDC.x;
v->pos.y = ov->ScreenPosNDC.y;
v->texR.x = ov->TanEyeAnglesR.x;
v->texR.y = ov->TanEyeAnglesR.y;
v->texG.x = ov->TanEyeAnglesG.x;
v->texG.y = ov->TanEyeAnglesG.y;
v->texB.x = ov->TanEyeAnglesB.x;
v->texB.y = ov->TanEyeAnglesB.y;
#else
v->pos.x = ov->Pos.x;
v->pos.y = ov->Pos.y;
v->texR.x = ov->TexR.x;
@ -191,6 +217,7 @@ void OculusManager::generateDistortionMesh() {
v->texG.y = ov->TexG.y;
v->texB.x = ov->TexB.x;
v->texB.y = ov->TexB.y;
#endif
v->color.r = v->color.g = v->color.b = (GLubyte)(ov->VignetteFactor * 255.99f);
v->color.a = (GLubyte)(ov->TimeWarpFactor * 255.99f);
v++;
@ -291,12 +318,23 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
glPushMatrix();
glm::quat orientation;
glm::vec3 trackerPosition;
#if defined(__APPLE__) || defined(_WIN32)
ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position;
trackerPosition = glm::vec3(ovrHeadPosition.x, ovrHeadPosition.y, ovrHeadPosition.z);
trackerPosition = bodyOrientation * trackerPosition;
#endif
//Render each eye into an fbo
for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) {
#if defined(__APPLE__) || defined(_WIN32)
ovrEyeType eye = _ovrHmd->EyeRenderOrder[eyeIndex];
#else
ovrEyeType eye = _ovrHmdDesc.EyeRenderOrder[eyeIndex];
#endif
//Set the camera rotation for this eye
eyeRenderPose[eye] = ovrHmd_GetEyePose(_ovrHmd, eye);
orientation.x = eyeRenderPose[eye].Orientation.x;
@ -305,7 +343,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
orientation.w = eyeRenderPose[eye].Orientation.w;
_camera->setTargetRotation(bodyOrientation * orientation);
_camera->setTargetPosition(position);
_camera->setTargetPosition(position + trackerPosition);
_camera->update(1.0f / Application::getInstance()->getFps());
Matrix4f proj = ovrMatrix4f_Projection(_eyeRenderDesc[eye].Fov, whichCamera.getNearClip(), whichCamera.getFarClip(), true);
@ -425,19 +464,32 @@ void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) {
//Tries to reconnect to the sensors
void OculusManager::reset() {
#ifdef HAVE_LIBOVR
disconnect();
connect();
if (_isConnected) {
ovrHmd_RecenterPose(_ovrHmd);
}
#endif
}
//Gets the current predicted angles from the oculus sensors
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
#ifdef HAVE_LIBOVR
#if defined(__APPLE__) || defined(_WIN32)
ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
#else
ovrSensorState ss = ovrHmd_GetSensorState(_ovrHmd, _hmdFrameTiming.ScanoutMidpointSeconds);
#endif
#if defined(__APPLE__) || defined(_WIN32)
if (ts.StatusFlags & (ovrStatus_OrientationTracked | ovrStatus_PositionTracked)) {
#else
if (ss.StatusFlags & (ovrStatus_OrientationTracked | ovrStatus_PositionTracked)) {
ovrPosef pose = ss.Predicted.Pose;
Quatf orientation = Quatf(pose.Orientation);
#endif
#if defined(__APPLE__) || defined(_WIN32)
ovrPosef headPose = ts.HeadPose.ThePose;
#else
ovrPosef headPose = ss.Predicted.Pose;
#endif
Quatf orientation = Quatf(headPose.Orientation);
orientation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
} else {
yaw = 0.0f;
@ -450,6 +502,18 @@ void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
roll = 0.0f;
#endif
}
glm::vec3 OculusManager::getRelativePosition() {
#if defined(__APPLE__) || defined(_WIN32)
ovrTrackingState trackingState = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
ovrVector3f headPosition = trackingState.HeadPose.ThePose.Position;
return glm::vec3(headPosition.x, headPosition.y, headPosition.z);
#else
// no positional tracking in Linux yet
return glm::vec3(0.0f, 0.0f, 0.0f);
#endif
}
//Used to set the size of the glow framebuffers
QSize OculusManager::getRenderTargetSize() {

View file

@ -40,6 +40,7 @@ public:
/// param \pitch[out] pitch in radians
/// param \roll[out] roll in radians
static void getEulerAngles(float& yaw, float& pitch, float& roll);
static glm::vec3 getRelativePosition();
static QSize getRenderTargetSize();
private:

View file

@ -19,6 +19,7 @@
#include "UserActivityLogger.h"
#ifdef HAVE_SIXENSE
const int CALIBRATION_STATE_IDLE = 0;
const int CALIBRATION_STATE_X = 1;
const int CALIBRATION_STATE_Y = 2;
@ -41,8 +42,9 @@ SixenseManager::SixenseManager() {
// By default we assume the _neckBase (in orb frame) is as high above the orb
// as the "torso" is below it.
_neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z);
sixenseInit();
#endif
_hydrasConnected = false;
_triggerPressed[0] = false;

View file

@ -71,7 +71,7 @@ private:
glm::vec3 _reachUp;
glm::vec3 _reachForward;
float _lastDistance;
#endif
bool _hydrasConnected;
quint64 _lastMovement;

View file

@ -16,6 +16,7 @@
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/transform.hpp>
#include <GLMHelpers.h>
#include <FBXReader.h>
class AngularConstraint;

View file

@ -188,10 +188,12 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati
QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
QVector<JointState> jointStates;
foreach (const FBXJoint& joint, geometry.joints) {
// NOTE: the state keeps a pointer to an FBXJoint
for (int i = 0; i < geometry.joints.size(); ++i) {
const FBXJoint& joint = geometry.joints[i];
// store a pointer to the FBXJoint in the JointState
JointState state;
state.setFBXJoint(&joint);
jointStates.append(state);
}
return jointStates;
@ -199,8 +201,8 @@ QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
void Model::initJointTransforms() {
// compute model transforms
int numJoints = _jointStates.size();
for (int i = 0; i < numJoints; ++i) {
int numStates = _jointStates.size();
for (int i = 0; i < numStates; ++i) {
JointState& state = _jointStates[i];
const FBXJoint& joint = state.getFBXJoint();
int parentIndex = joint.parentIndex;
@ -538,9 +540,9 @@ void Model::setJointStates(QVector<JointState> states) {
_jointStates = states;
initJointTransforms();
int numJoints = _jointStates.size();
int numStates = _jointStates.size();
float radius = 0.0f;
for (int i = 0; i < numJoints; ++i) {
for (int i = 0; i < numStates; ++i) {
float distance = glm::length(_jointStates[i].getPosition());
if (distance > radius) {
radius = distance;
@ -1243,55 +1245,7 @@ float Model::getLimbLength(int jointIndex) const {
const int BALL_SUBDIVISIONS = 10;
void Model::renderJointCollisionShapes(float alpha) {
glPushMatrix();
Application::getInstance()->loadTranslatedViewMatrix(_translation);
for (int i = 0; i < _shapes.size(); i++) {
Shape* shape = _shapes[i];
if (!shape) {
continue;
}
glPushMatrix();
// NOTE: the shapes are in the avatar local-frame
if (shape->getType() == Shape::SPHERE_SHAPE) {
// shapes are stored in world-frame, so we have to transform into model frame
glm::vec3 position = _rotation * shape->getTranslation();
glTranslatef(position.x, position.y, position.z);
const glm::quat& rotation = shape->getRotation();
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
// draw a grey sphere at shape position
glColor4f(0.75f, 0.75f, 0.75f, alpha);
glutSolidSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
} else if (shape->getType() == Shape::CAPSULE_SHAPE) {
CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
// draw a blue sphere at the capsule endpoint
glm::vec3 endPoint;
capsule->getEndPoint(endPoint);
endPoint = _rotation * endPoint;
glTranslatef(endPoint.x, endPoint.y, endPoint.z);
glColor4f(0.6f, 0.6f, 0.8f, alpha);
glutSolidSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
// draw a yellow sphere at the capsule startpoint
glm::vec3 startPoint;
capsule->getStartPoint(startPoint);
startPoint = _rotation * startPoint;
glm::vec3 axis = endPoint - startPoint;
glTranslatef(-axis.x, -axis.y, -axis.z);
glColor4f(0.8f, 0.8f, 0.6f, alpha);
glutSolidSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
// draw a green cylinder between the two points
glm::vec3 origin(0.0f);
glColor4f(0.6f, 0.8f, 0.6f, alpha);
Avatar::renderJointConnectingCone( origin, axis, capsule->getRadius(), capsule->getRadius());
}
glPopMatrix();
}
glPopMatrix();
// implement this when we have shapes for regular models
}
void Model::setBlendedVertices(const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {

View file

@ -149,7 +149,7 @@ public:
virtual void buildShapes();
virtual void updateShapePositions();
void renderJointCollisionShapes(float alpha);
virtual void renderJointCollisionShapes(float alpha);
/// Sets blended vertices computed in a separate thread.
void setBlendedVertices(const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);

View file

@ -118,6 +118,8 @@ MetavoxelEditor::MetavoxelEditor() :
addTool(new SetSpannerTool(this));
addTool(new ImportHeightfieldTool(this));
addTool(new EraseHeightfieldTool(this));
addTool(new HeightfieldHeightBrushTool(this));
addTool(new HeightfieldColorBrushTool(this));
updateAttributes();
@ -1080,3 +1082,72 @@ void EraseHeightfieldTool::apply() {
message.edit = QVariant::fromValue(edit);
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
}
HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name) :
MetavoxelTool(editor, name, false) {
QWidget* widget = new QWidget();
widget->setLayout(_form = new QFormLayout());
layout()->addWidget(widget);
_form->addRow("Radius:", _radius = new QDoubleSpinBox());
_radius->setSingleStep(0.01);
_radius->setMaximum(FLT_MAX);
_radius->setValue(1.0);
}
void HeightfieldBrushTool::render() {
if (Application::getInstance()->isMouseHidden()) {
return;
}
// find the intersection with the heightfield
glm::vec3 origin = Application::getInstance()->getMouseRayOrigin();
glm::vec3 direction = Application::getInstance()->getMouseRayDirection();
float distance;
if (!Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection(origin, direction, distance)) {
return;
}
Application::getInstance()->getMetavoxels()->renderHeightfieldCursor(
_position = origin + distance * direction, _radius->value());
}
bool HeightfieldBrushTool::eventFilter(QObject* watched, QEvent* event) {
if (event->type() == QEvent::Wheel) {
float angle = static_cast<QWheelEvent*>(event)->angleDelta().y();
const float ANGLE_SCALE = 1.0f / 1000.0f;
_radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE));
return true;
} else if (event->type() == QEvent::MouseButtonPress) {
MetavoxelEditMessage message = { createEdit(static_cast<QMouseEvent*>(event)->button() == Qt::RightButton) };
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
return true;
}
return false;
}
HeightfieldHeightBrushTool::HeightfieldHeightBrushTool(MetavoxelEditor* editor) :
HeightfieldBrushTool(editor, "Height Brush") {
_form->addRow("Height:", _height = new QDoubleSpinBox());
_height->setMinimum(-FLT_MAX);
_height->setMaximum(FLT_MAX);
_height->setValue(1.0);
}
QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) {
return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(),
alternate ? -_height->value() : _height->value()));
}
HeightfieldColorBrushTool::HeightfieldColorBrushTool(MetavoxelEditor* editor) :
HeightfieldBrushTool(editor, "Color Brush") {
_form->addRow("Color:", _color = new QColorEditor(this));
}
QVariant HeightfieldColorBrushTool::createEdit(bool alternate) {
return QVariant::fromValue(PaintHeightfieldColorEdit(_position, _radius->value(), _color->getColor()));
}

View file

@ -18,6 +18,7 @@
#include "MetavoxelSystem.h"
#include "renderer/ProgramObject.h"
class QColorEditor;
class QComboBox;
class QDoubleSpinBox;
class QGroupBox;
@ -282,7 +283,7 @@ private:
HeightfieldPreview _preview;
};
// Allows clearing heighfield blocks.
/// Allows clearing heighfield blocks.
class EraseHeightfieldTool : public HeightfieldTool {
Q_OBJECT
@ -302,4 +303,60 @@ private:
QSpinBox* _length;
};
/// Base class for tools that allow painting on heightfields.
class HeightfieldBrushTool : public MetavoxelTool {
Q_OBJECT
public:
HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name);
virtual void render();
virtual bool eventFilter(QObject* watched, QEvent* event);
protected:
virtual QVariant createEdit(bool alternate) = 0;
QFormLayout* _form;
QDoubleSpinBox* _radius;
glm::vec3 _position;
};
/// Allows raising or lowering parts of the heightfield.
class HeightfieldHeightBrushTool : public HeightfieldBrushTool {
Q_OBJECT
public:
HeightfieldHeightBrushTool(MetavoxelEditor* editor);
protected:
virtual QVariant createEdit(bool alternate);
private:
QDoubleSpinBox* _height;
};
/// Allows coloring parts of the heightfield.
class HeightfieldColorBrushTool : public HeightfieldBrushTool {
Q_OBJECT
public:
HeightfieldColorBrushTool(MetavoxelEditor* editor);
protected:
virtual QVariant createEdit(bool alternate);
private:
QColorEditor* _color;
};
#endif // hifi_MetavoxelEditor_h

View file

@ -11,6 +11,8 @@
#ifndef hifi_Base3DOverlay_h
#define hifi_Base3DOverlay_h
#include <glm/glm.hpp>
#include "Overlay.h"
class Base3DOverlay : public Overlay {

View file

@ -26,7 +26,7 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode,
if (packetsToProcessCount() > WAY_BEHIND && Application::getInstance()->getLogger()->extraDebugging()) {
qDebug("OctreePacketProcessor::processPacket() packets to process=%d", packetsToProcessCount());
}
ssize_t messageLength = mutablePacket.size();
int messageLength = mutablePacket.size();
Application* app = Application::getInstance();
bool wasStatsPacket = false;

View file

@ -1,29 +1,9 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME animation)
find_package(Qt5Widgets REQUIRED)
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(Network Script)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
link_hifi_libraries(shared fbx)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(fbx ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -1,26 +1,11 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME audio)
find_package(Qt5 COMPONENTS Script)
include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(Network)
# set up the external glm library
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
include_glm()
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
link_hifi_libraries(networking shared)
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -0,0 +1,26 @@
//
// AudioFilter.cpp
// hifi
//
// Created by Craig Hansen-Sturm on 8/10/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <math.h>
#include <vector>
#include <SharedUtil.h>
#include "AudioRingBuffer.h"
#include "AudioFilter.h"
template<>
AudioFilterPEQ3::FilterParameter AudioFilterPEQ3::_profiles[ AudioFilterPEQ3::_profileCount ][ AudioFilterPEQ3::_filterCount ] = {
// Freq Gain Q Freq Gain Q Freq Gain Q
{ { 300.0f, 1.0f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 1.0f, 1.0f } }, // flat response (default)
{ { 300.0f, 1.0f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 0.1f, 1.0f } }, // treble cut
{ { 300.0f, 0.1f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 1.0f, 1.0f } }, // bass cut
{ { 300.0f, 1.5f, 0.71f }, { 1000.0f, 0.5f, 1.0f }, { 4000.0f, 1.50f, 0.71f } } // smiley curve
};

View file

@ -0,0 +1,298 @@
//
// AudioFilter.h
// hifi
//
// Created by Craig Hansen-Sturm on 8/9/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AudioFilter_h
#define hifi_AudioFilter_h
////////////////////////////////////////////////////////////////////////////////////////////
// Implements a standard biquad filter in "Direct Form 1"
// Reference http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
//
class AudioBiquad {
//
// private data
//
float _a0; // gain
float _a1; // feedforward 1
float _a2; // feedforward 2
float _b1; // feedback 1
float _b2; // feedback 2
float _xm1;
float _xm2;
float _ym1;
float _ym2;
public:
//
// ctor/dtor
//
AudioBiquad()
: _xm1(0.)
, _xm2(0.)
, _ym1(0.)
, _ym2(0.) {
setParameters(0.,0.,0.,0.,0.);
}
~AudioBiquad() {
}
//
// public interface
//
void setParameters( const float a0, const float a1, const float a2, const float b1, const float b2 ) {
_a0 = a0; _a1 = a1; _a2 = a2; _b1 = b1; _b2 = b2;
}
void getParameters( float& a0, float& a1, float& a2, float& b1, float& b2 ) {
a0 = _a0; a1 = _a1; a2 = _a2; b1 = _b1; b2 = _b2;
}
void render( const float* in, float* out, const int frames) {
float x;
float y;
for (int i = 0; i < frames; ++i) {
x = *in++;
// biquad
y = (_a0 * x)
+ (_a1 * _xm1)
+ (_a2 * _xm2)
- (_b1 * _ym1)
- (_b2 * _ym2);
// update delay line
_xm2 = _xm1;
_xm1 = x;
_ym2 = _ym1;
_ym1 = y;
*out++ = y;
}
}
void reset() {
_xm1 = _xm2 = _ym1 = _ym2 = 0.;
}
};
////////////////////////////////////////////////////////////////////////////////////////////
// Implements a single-band parametric EQ using a biquad "peaking EQ" configuration
//
// gain > 1.0 boosts the center frequency
// gain < 1.0 cuts the center frequency
//
class AudioParametricEQ {
//
// private data
//
AudioBiquad _kernel;
float _sampleRate;
float _frequency;
float _gain;
float _slope;
// helpers
void updateKernel() {
/*
a0 = 1 + alpha*A
a1 = -2*cos(w0)
a2 = 1 - alpha*A
b1 = -2*cos(w0)
b2 = 1 - alpha/A
*/
const float a = _gain;
const float omega = TWO_PI * _frequency / _sampleRate;
const float alpha = 0.5f * sinf(omega) / _slope;
const float gamma = 1.0f / ( 1.0f + (alpha/a) );
const float a0 = 1.0f + (alpha*a);
const float a1 = -2.0f * cosf(omega);
const float a2 = 1.0f - (alpha*a);
const float b1 = a1;
const float b2 = 1.0f - (alpha/a);
_kernel.setParameters( a0*gamma,a1*gamma,a2*gamma,b1*gamma,b2*gamma );
}
public:
//
// ctor/dtor
//
AudioParametricEQ() {
setParameters(0.,0.,0.,0.);
updateKernel();
}
~AudioParametricEQ() {
}
//
// public interface
//
void setParameters( const float sampleRate, const float frequency, const float gain, const float slope ) {
_sampleRate = std::max(sampleRate,1.0f);
_frequency = std::max(frequency,2.0f);
_gain = std::max(gain,0.0f);
_slope = std::max(slope,0.00001f);
updateKernel();
}
void getParameters( float& sampleRate, float& frequency, float& gain, float& slope ) {
sampleRate = _sampleRate; frequency = _frequency; gain = _gain; slope = _slope;
}
void render(const float* in, float* out, const int frames ) {
_kernel.render(in,out,frames);
}
void reset() {
_kernel.reset();
}
};
////////////////////////////////////////////////////////////////////////////////////////////
// Helper/convenience class that implements a bank of EQ objects
//
template< typename T, const int N>
class AudioFilterBank {
//
// types
//
struct FilterParameter {
float _p1;
float _p2;
float _p3;
};
//
// private static data
//
static const int _filterCount = N;
static const int _profileCount = 4;
static FilterParameter _profiles[_profileCount][_filterCount];
//
// private data
//
T _filters[ _filterCount ];
float* _buffer;
float _sampleRate;
uint16_t _frameCount;
public:
//
// ctor/dtor
//
AudioFilterBank()
: _buffer(NULL)
, _sampleRate(0.)
, _frameCount(0) {
}
~AudioFilterBank() {
finalize();
}
//
// public interface
//
void initialize( const float sampleRate, const int frameCount ) {
finalize();
_buffer = (float*)malloc( frameCount * sizeof(float) );
if(!_buffer) {
return;
}
_sampleRate = sampleRate;
_frameCount = frameCount;
reset();
loadProfile(0); // load default profile "flat response" into the bank (see AudioFilter.cpp)
}
void finalize() {
if (_buffer ) {
free (_buffer);
_buffer = NULL;
}
}
void loadProfile( int profileIndex ) {
if (profileIndex >= 0 && profileIndex < _profileCount) {
for (int i = 0; i < _filterCount; ++i) {
FilterParameter p = _profiles[profileIndex][i];
_filters[i].setParameters(_sampleRate,p._p1,p._p2,p._p3);
}
}
}
void render( const float* in, float* out, const int frameCount ) {
for (int i = 0; i < _filterCount; ++i) {
_filters[i].render( in, out, frameCount );
}
}
void render( const int16_t* in, int16_t* out, const int frameCount ) {
if (!_buffer || ( frameCount > _frameCount ))
return;
const int scale = (2 << ((8*sizeof(int16_t))-1));
// convert int16_t to float32 (normalized to -1. ... 1.)
for (int i = 0; i < frameCount; ++i) {
_buffer[i] = ((float)(*in++)) / scale;
}
// for this filter, we share input/output buffers at each stage, but our design does not mandate this
render( _buffer, _buffer, frameCount );
// convert float32 to int16_t
for (int i = 0; i < frameCount; ++i) {
*out++ = (int16_t)(_buffer[i] * scale);
}
}
void reset() {
for (int i = 0; i < _filterCount; ++i ) {
_filters[i].reset();
}
}
};
////////////////////////////////////////////////////////////////////////////////////////////
// Specializations of AudioFilterBank
//
typedef AudioFilterBank< AudioParametricEQ, 1> AudioFilterPEQ1; // bank with one band of PEQ
typedef AudioFilterBank< AudioParametricEQ, 2> AudioFilterPEQ2; // bank with two bands of PEQ
typedef AudioFilterBank< AudioParametricEQ, 3> AudioFilterPEQ3; // bank with three bands of PEQ
// etc....
#endif // hifi_AudioFilter_h

View file

@ -15,9 +15,9 @@
#include <QtCore/QDebug>
#include "PacketHeaders.h"
#include "AudioRingBuffer.h"
#include <PacketHeaders.h>
#include "AudioRingBuffer.h"
AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode, int numFramesCapacity) :
_frameCapacity(numFramesCapacity),

View file

@ -15,12 +15,10 @@
#include <limits>
#include <stdint.h>
#include <glm/glm.hpp>
#include <QtCore/QIODevice>
#include "NodeData.h"
#include "SharedUtil.h"
#include <SharedUtil.h>
#include <NodeData.h>
const int SAMPLE_RATE = 24000;
@ -199,4 +197,4 @@ public:
int writeSamplesWithFade(ConstIterator source, int maxSamples, float fade);
};
#endif // hifi_AudioRingBuffer_h
#endif // hifi_AudioRingBuffer_h

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <glm/glm.hpp>
#include "InboundAudioStream.h"
#include "PacketHeaders.h"

View file

@ -1,30 +1,12 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME avatars)
find_package(Qt5Script REQUIRED)
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(Network Script)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
include_glm()
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
link_hifi_libraries(shared octree voxels networking)
include_hifi_library_headers(fbx)
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
# link in the hifi voxels library
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
target_link_libraries(${TARGET_NAME} Qt5::Script)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -22,7 +22,7 @@
#include <NetworkAccessManager.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <SharedUtil.h>
#include <GLMHelpers.h>
#include <StreamUtils.h>
#include <UUID.h>
#include <VoxelConstants.h>

View file

@ -290,7 +290,7 @@ public slots:
void sendBillboardPacket();
void setBillboardFromNetworkReply();
void setJointMappingsFromNetworkReply();
void setSessionUUID(const QUuid& id) { _sessionUUID = id; }
void setSessionUUID(const QUuid& sessionUUID) { _sessionUUID = sessionUUID; }
bool hasReferential();
protected:

View file

@ -9,19 +9,21 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <NodeList.h>
#include <PacketHeaders.h>
#include "AvatarHashMap.h"
AvatarHashMap::AvatarHashMap() :
_avatarHash()
_avatarHash(),
_lastOwnerSessionUUID()
{
connect(NodeList::getInstance(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
}
void AvatarHashMap::insert(const QUuid& id, AvatarSharedPointer avatar) {
_avatarHash.insert(id, avatar);
avatar->setSessionUUID(id);
void AvatarHashMap::insert(const QUuid& sessionUUID, AvatarSharedPointer avatar) {
_avatarHash.insert(sessionUUID, avatar);
avatar->setSessionUUID(sessionUUID);
}
AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) {
@ -110,10 +112,16 @@ void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QW
QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID));
bytesRead += NUM_BYTES_RFC4122_UUID;
AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
// have the matching (or new) avatar parse the data from the packet
bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
if (sessionUUID != _lastOwnerSessionUUID) {
AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
// have the matching (or new) avatar parse the data from the packet
bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
} else {
// create a dummy AvatarData class to throw this data on the ground
AvatarData dummyData;
bytesRead += dummyData.parseDataAtOffset(datagram, bytesRead);
}
}
}
@ -177,3 +185,7 @@ void AvatarHashMap::processKillAvatar(const QByteArray& datagram) {
erase(matchedAvatar);
}
}
void AvatarHashMap::sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID) {
_lastOwnerSessionUUID = oldUUID;
}

View file

@ -31,12 +31,15 @@ public:
const AvatarHash& getAvatarHash() { return _avatarHash; }
int size() const { return _avatarHash.size(); }
virtual void insert(const QUuid& id, AvatarSharedPointer avatar);
virtual void insert(const QUuid& sessionUUID, AvatarSharedPointer avatar);
public slots:
void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer);
bool containsAvatarWithDisplayName(const QString& displayName);
private slots:
void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID);
protected:
virtual AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
@ -51,6 +54,7 @@ protected:
void processKillAvatar(const QByteArray& datagram);
AvatarHash _avatarHash;
QUuid _lastOwnerSessionUUID;
};
#endif // hifi_AvatarHashMap_h

View file

@ -11,13 +11,13 @@
#include <glm/gtx/quaternion.hpp>
#include <FBXReader.h>
#include <GLMHelpers.h>
#include <OctreeConstants.h>
#include "AvatarData.h"
#include "HeadData.h"
#include "../fbx/src/FBXReader.h"
HeadData::HeadData(AvatarData* owningAvatar) :
_baseYaw(0.0f),
_basePitch(0.0f),

View file

@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <SharedUtil.h>
#include <GLMHelpers.h>
#include "AvatarData.h"
#include "Referential.h"

View file

@ -1,14 +1,7 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME embedded-webserver)
find_package(Qt5Network REQUIRED)
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(Network)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
target_link_libraries(${TARGET_NAME} Qt5::Network)
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -1,30 +1,15 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME fbx)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library()
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
include_glm()
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
link_hifi_libraries(shared networking octree voxels)
find_package(ZLIB REQUIRED)
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${ZLIB_LIBRARIES}")
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -23,9 +23,9 @@
#include <glm/gtx/transform.hpp>
#include <GeometryUtil.h>
#include <GLMHelpers.h>
#include <OctalCode.h>
#include <Shape.h>
#include <SharedUtil.h>
#include <VoxelTree.h>

View file

@ -1,29 +1,14 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME metavoxels)
find_package(Qt5 COMPONENTS Network Script Widgets)
auto_mtc()
include(${MACRO_DIR}/AutoMTC.cmake)
auto_mtc(${TARGET_NAME} "${ROOT_DIR}")
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME} "${AUTOMTC_SRC}")
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(Network Script Widgets)
# link in the networking library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_libraries(shared networking)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
include_glm()
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -61,6 +61,180 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons
return closestSpanner;
}
class RayHeightfieldIntersectionVisitor : public RayIntersectionVisitor {
public:
float intersectionDistance;
RayHeightfieldIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod);
virtual int visit(MetavoxelInfo& info, float distance);
};
RayHeightfieldIntersectionVisitor::RayHeightfieldIntersectionVisitor(const glm::vec3& origin,
const glm::vec3& direction, const MetavoxelLOD& lod) :
RayIntersectionVisitor(origin, direction, QVector<AttributePointer>() <<
AttributeRegistry::getInstance()->getHeightfieldAttribute(), QVector<AttributePointer>(), lod),
intersectionDistance(FLT_MAX) {
}
static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / 255.0f;
int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance) {
if (!info.isLeaf) {
return _order;
}
HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
if (!pointer) {
return STOP_RECURSION;
}
const QByteArray& contents = pointer->getContents();
const uchar* src = (const uchar*)contents.constData();
int size = glm::sqrt((float)contents.size());
int highest = size - 1;
float heightScale = highest * EIGHT_BIT_MAXIMUM_RECIPROCAL;
// find the initial location in heightfield coordinates
glm::vec3 entry = (_origin + distance * _direction - info.minimum) * (float)highest / info.size;
glm::vec3 floors = glm::floor(entry);
glm::vec3 ceils = glm::ceil(entry);
if (floors.x == ceils.x) {
if (_direction.x > 0.0f) {
ceils.x += 1.0f;
} else {
floors.x -= 1.0f;
}
}
if (floors.z == ceils.z) {
if (_direction.z > 0.0f) {
ceils.z += 1.0f;
} else {
floors.z -= 1.0f;
}
}
bool withinBounds = true;
float accumulatedDistance = 0.0f;
while (withinBounds) {
// find the heights at the corners of the current cell
int floorX = qMin(qMax((int)floors.x, 0), highest);
int floorZ = qMin(qMax((int)floors.z, 0), highest);
int ceilX = qMin(qMax((int)ceils.x, 0), highest);
int ceilZ = qMin(qMax((int)ceils.z, 0), highest);
float upperLeft = src[floorZ * size + floorX] * heightScale;
float upperRight = src[floorZ * size + ceilX] * heightScale;
float lowerLeft = src[ceilZ * size + floorX] * heightScale;
float lowerRight = src[ceilZ * size + ceilX] * heightScale;
// find the distance to the next x coordinate
float xDistance = FLT_MAX;
if (_direction.x > 0.0f) {
xDistance = (ceils.x - entry.x) / _direction.x;
} else if (_direction.x < 0.0f) {
xDistance = (floors.x - entry.x) / _direction.x;
}
// and the distance to the next z coordinate
float zDistance = FLT_MAX;
if (_direction.z > 0.0f) {
zDistance = (ceils.z - entry.z) / _direction.z;
} else if (_direction.z < 0.0f) {
zDistance = (floors.z - entry.z) / _direction.z;
}
// the exit distance is the lower of those two
float exitDistance = qMin(xDistance, zDistance);
glm::vec3 exit, nextFloors = floors, nextCeils = ceils;
if (exitDistance == FLT_MAX) {
if (_direction.y > 0.0f) {
return SHORT_CIRCUIT; // line points upwards; no collisions possible
}
withinBounds = false; // line points downwards; check this cell only
} else {
// find the exit point and the next cell, and determine whether it's still within the bounds
exit = entry + exitDistance * _direction;
withinBounds = (exit.y >= 0.0f && exit.y <= highest);
if (exitDistance == xDistance) {
if (_direction.x > 0.0f) {
nextFloors.x += 1.0f;
withinBounds &= (nextCeils.x += 1.0f) <= highest;
} else {
withinBounds &= (nextFloors.x -= 1.0f) >= 0.0f;
nextCeils.x -= 1.0f;
}
}
if (exitDistance == zDistance) {
if (_direction.z > 0.0f) {
nextFloors.z += 1.0f;
withinBounds &= (nextCeils.z += 1.0f) <= highest;
} else {
withinBounds &= (nextFloors.z -= 1.0f) >= 0.0f;
nextCeils.z -= 1.0f;
}
}
// check the vertical range of the ray against the ranges of the cell heights
if (qMin(entry.y, exit.y) > qMax(qMax(upperLeft, upperRight), qMax(lowerLeft, lowerRight)) ||
qMax(entry.y, exit.y) < qMin(qMin(upperLeft, upperRight), qMin(lowerLeft, lowerRight))) {
entry = exit;
floors = nextFloors;
ceils = nextCeils;
accumulatedDistance += exitDistance;
continue;
}
}
// having passed the bounds check, we must check against the planes
glm::vec3 relativeEntry = entry - glm::vec3(floors.x, upperLeft, floors.z);
// first check the triangle including the Z+ segment
glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft);
float lowerProduct = glm::dot(lowerNormal, _direction);
if (lowerProduct < 0.0f) {
float planeDistance = -glm::dot(lowerNormal, relativeEntry) / lowerProduct;
glm::vec3 intersection = relativeEntry + planeDistance * _direction;
if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f &&
intersection.z >= intersection.x) {
intersectionDistance = qMin(intersectionDistance, distance +
(accumulatedDistance + planeDistance) * (info.size / highest));
return SHORT_CIRCUIT;
}
}
// then the one with the X+ segment
glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight);
float upperProduct = glm::dot(upperNormal, _direction);
if (upperProduct < 0.0f) {
float planeDistance = -glm::dot(upperNormal, relativeEntry) / upperProduct;
glm::vec3 intersection = relativeEntry + planeDistance * _direction;
if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f &&
intersection.x >= intersection.z) {
intersectionDistance = qMin(intersectionDistance, distance +
(accumulatedDistance + planeDistance) * (info.size / highest));
return SHORT_CIRCUIT;
}
}
// no joy; continue on our way
entry = exit;
floors = nextFloors;
ceils = nextCeils;
accumulatedDistance += exitDistance;
}
return STOP_RECURSION;
}
bool MetavoxelClientManager::findFirstRayHeightfieldIntersection(const glm::vec3& origin,
const glm::vec3& direction, float& distance) {
RayHeightfieldIntersectionVisitor visitor(origin, direction, getLOD());
guide(visitor);
if (visitor.intersectionDistance == FLT_MAX) {
return false;
}
distance = visitor.intersectionDistance;
return true;
}
void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, const QColor& color) {
Sphere* sphere = new Sphere();
sphere->setTranslation(center);
@ -78,6 +252,84 @@ void MetavoxelClientManager::applyEdit(const MetavoxelEditMessage& edit, bool re
QMetaObject::invokeMethod(_updater, "applyEdit", Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, reliable));
}
class HeightfieldHeightVisitor : public MetavoxelVisitor {
public:
float height;
HeightfieldHeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location);
virtual int visit(MetavoxelInfo& info);
private:
glm::vec3 _location;
};
HeightfieldHeightVisitor::HeightfieldHeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location) :
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute(),
QVector<AttributePointer>(), lod),
height(-FLT_MAX),
_location(location) {
}
static const int REVERSE_ORDER = MetavoxelVisitor::encodeOrder(7, 6, 5, 4, 3, 2, 1, 0);
int HeightfieldHeightVisitor::visit(MetavoxelInfo& info) {
glm::vec3 relative = _location - info.minimum;
if (relative.x < 0.0f || relative.z < 0.0f || relative.x > info.size || relative.z > info.size ||
height >= info.minimum.y + info.size) {
return STOP_RECURSION;
}
if (!info.isLeaf) {
return REVERSE_ORDER;
}
HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
if (!pointer) {
return STOP_RECURSION;
}
const QByteArray& contents = pointer->getContents();
const uchar* src = (const uchar*)contents.constData();
int size = glm::sqrt((float)contents.size());
int highest = size - 1;
relative *= highest / info.size;
// find the bounds of the cell containing the point and the shared vertex heights
glm::vec3 floors = glm::floor(relative);
glm::vec3 ceils = glm::ceil(relative);
glm::vec3 fracts = glm::fract(relative);
int floorX = qMin(qMax((int)floors.x, 0), highest);
int floorZ = qMin(qMax((int)floors.z, 0), highest);
int ceilX = qMin(qMax((int)ceils.x, 0), highest);
int ceilZ = qMin(qMax((int)ceils.z, 0), highest);
float upperLeft = src[floorZ * size + floorX];
float lowerRight = src[ceilZ * size + ceilX];
float interpolatedHeight;
// the final vertex (and thus which triangle we check) depends on which half we're on
if (fracts.x > fracts.z) {
float upperRight = src[floorZ * size + ceilX];
interpolatedHeight = glm::mix(glm::mix(upperLeft, upperRight, fracts.x), lowerRight, fracts.z);
} else {
float lowerLeft = src[ceilZ * size + floorX];
interpolatedHeight = glm::mix(upperLeft, glm::mix(lowerLeft, lowerRight, fracts.x), fracts.z);
}
if (interpolatedHeight == 0.0f) {
return STOP_RECURSION; // ignore zero values
}
// convert the interpolated height into world space
height = qMax(height, info.minimum.y + interpolatedHeight * info.size * EIGHT_BIT_MAXIMUM_RECIPROCAL);
return SHORT_CIRCUIT;
}
float MetavoxelClientManager::getHeightfieldHeight(const glm::vec3& location) {
HeightfieldHeightVisitor visitor(getLOD(), location);
guide(visitor);
return visitor.height;
}
MetavoxelLOD MetavoxelClientManager::getLOD() {
return MetavoxelLOD();
}

View file

@ -37,12 +37,16 @@ public:
SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction,
const AttributePointer& attribute, float& distance);
bool findFirstRayHeightfieldIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance);
Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, const QColor& color = QColor(Qt::gray));
Q_INVOKABLE void setSpanner(const SharedObjectPointer& object, bool reliable = false);
Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false);
Q_INVOKABLE float getHeightfieldHeight(const glm::vec3& location);
/// Returns the current LOD. This must be thread-safe, as it will be called from the updater thread.
virtual MetavoxelLOD getLOD();

View file

@ -318,3 +318,169 @@ SetDataEdit::SetDataEdit(const glm::vec3& minimum, const MetavoxelData& data, bo
void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
data.set(minimum, this->data, blend);
}
PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius, float height) :
position(position),
radius(radius),
height(height) {
}
class PaintHeightfieldHeightEditVisitor : public MetavoxelVisitor {
public:
PaintHeightfieldHeightEditVisitor(const PaintHeightfieldHeightEdit& edit);
virtual int visit(MetavoxelInfo& info);
private:
PaintHeightfieldHeightEdit _edit;
Box _bounds;
};
PaintHeightfieldHeightEditVisitor::PaintHeightfieldHeightEditVisitor(const PaintHeightfieldHeightEdit& edit) :
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute(),
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute()),
_edit(edit) {
glm::vec3 extents(_edit.radius, _edit.radius, _edit.radius);
_bounds = Box(_edit.position - extents, _edit.position + extents);
}
int PaintHeightfieldHeightEditVisitor::visit(MetavoxelInfo& info) {
if (!info.getBounds().intersects(_bounds)) {
return STOP_RECURSION;
}
if (!info.isLeaf) {
return DEFAULT_ORDER;
}
HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
if (!pointer) {
return STOP_RECURSION;
}
QByteArray contents(pointer->getContents());
int size = glm::sqrt((float)contents.size());
int highest = size - 1;
float heightScale = highest / info.size;
glm::vec3 center = (_edit.position - info.minimum) * heightScale;
float scaledRadius = _edit.radius * heightScale;
glm::vec3 extents(scaledRadius, scaledRadius, scaledRadius);
glm::vec3 start = glm::floor(center - extents);
glm::vec3 end = glm::ceil(center + extents);
// raise/lower all points within the radius
float z = qMax(start.z, 0.0f);
float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highest);
uchar* lineDest = (uchar*)contents.data() + (int)z * size + (int)startX;
float squaredRadius = scaledRadius * scaledRadius;
float squaredRadiusReciprocal = 1.0f / squaredRadius;
const int EIGHT_BIT_MAXIMUM = 255;
float scaledHeight = _edit.height * EIGHT_BIT_MAXIMUM / info.size;
for (float endZ = qMin(end.z, (float)highest); z <= endZ; z += 1.0f) {
uchar* dest = lineDest;
for (float x = startX; x <= endX; x += 1.0f, dest++) {
float dx = x - center.x, dz = z - center.z;
float distanceSquared = dx * dx + dz * dz;
if (distanceSquared <= squaredRadius) {
// height falls off towards edges
int value = *dest + scaledHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal;
*dest = qMin(qMax(value, 0), EIGHT_BIT_MAXIMUM);
}
}
lineDest += size;
}
HeightfieldDataPointer newPointer(new HeightfieldData(contents));
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldDataPointer>(newPointer));
return STOP_RECURSION;
}
void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
PaintHeightfieldHeightEditVisitor visitor(*this);
data.guide(visitor);
}
PaintHeightfieldColorEdit::PaintHeightfieldColorEdit(const glm::vec3& position, float radius, const QColor& color) :
position(position),
radius(radius),
color(color) {
}
class PaintHeightfieldColorEditVisitor : public MetavoxelVisitor {
public:
PaintHeightfieldColorEditVisitor(const PaintHeightfieldColorEdit& edit);
virtual int visit(MetavoxelInfo& info);
private:
PaintHeightfieldColorEdit _edit;
Box _bounds;
};
PaintHeightfieldColorEditVisitor::PaintHeightfieldColorEditVisitor(const PaintHeightfieldColorEdit& edit) :
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute(),
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute()),
_edit(edit) {
glm::vec3 extents(_edit.radius, _edit.radius, _edit.radius);
_bounds = Box(_edit.position - extents, _edit.position + extents);
}
int PaintHeightfieldColorEditVisitor::visit(MetavoxelInfo& info) {
if (!info.getBounds().intersects(_bounds)) {
return STOP_RECURSION;
}
if (!info.isLeaf) {
return DEFAULT_ORDER;
}
HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
if (!pointer) {
return STOP_RECURSION;
}
QByteArray contents(pointer->getContents());
const int BYTES_PER_PIXEL = 3;
int size = glm::sqrt((float)contents.size() / BYTES_PER_PIXEL);
int highest = size - 1;
float heightScale = highest / info.size;
glm::vec3 center = (_edit.position - info.minimum) * heightScale;
float scaledRadius = _edit.radius * heightScale;
glm::vec3 extents(scaledRadius, scaledRadius, scaledRadius);
glm::vec3 start = glm::floor(center - extents);
glm::vec3 end = glm::ceil(center + extents);
// paint all points within the radius
float z = qMax(start.z, 0.0f);
float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highest);
int stride = size * BYTES_PER_PIXEL;
char* lineDest = contents.data() + (int)z * stride + (int)startX * BYTES_PER_PIXEL;
float squaredRadius = scaledRadius * scaledRadius;
char red = _edit.color.red(), green = _edit.color.green(), blue = _edit.color.blue();
for (float endZ = qMin(end.z, (float)highest); z <= endZ; z += 1.0f) {
char* dest = lineDest;
for (float x = startX; x <= endX; x += 1.0f, dest += BYTES_PER_PIXEL) {
float dx = x - center.x, dz = z - center.z;
if (dx * dx + dz * dz <= squaredRadius) {
dest[0] = red;
dest[1] = green;
dest[2] = blue;
}
}
lineDest += stride;
}
HeightfieldDataPointer newPointer(new HeightfieldData(contents));
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldDataPointer>(newPointer));
return STOP_RECURSION;
}
void PaintHeightfieldColorEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
PaintHeightfieldColorEditVisitor visitor(*this);
data.guide(visitor);
}

View file

@ -207,4 +207,38 @@ public:
DECLARE_STREAMABLE_METATYPE(SetDataEdit)
/// An edit that sets a region of a heightfield height.
class PaintHeightfieldHeightEdit : public MetavoxelEdit {
STREAMABLE
public:
STREAM glm::vec3 position;
STREAM float radius;
STREAM float height;
PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, float height = 0.0f);
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};
DECLARE_STREAMABLE_METATYPE(PaintHeightfieldHeightEdit)
/// An edit that sets a region of a heightfield color.
class PaintHeightfieldColorEdit : public MetavoxelEdit {
STREAMABLE
public:
STREAM glm::vec3 position;
STREAM float radius;
STREAM QColor color;
PaintHeightfieldColorEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, const QColor& color = QColor());
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};
DECLARE_STREAMABLE_METATYPE(PaintHeightfieldColorEdit)
#endif // hifi_MetavoxelMessages_h

View file

@ -24,6 +24,8 @@
#include <QVBoxLayout>
#include <QtDebug>
#include <GLMHelpers.h>
#include "MetavoxelUtil.h"
#include "ScriptCache.h"
#include "StreamUtils.h"

View file

@ -138,6 +138,8 @@ public:
QColorEditor(QWidget* parent);
const QColor& getColor() const { return _color; }
signals:
void colorChanged(const QColor& color);

View file

@ -1,39 +1,11 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME models)
find_package(Qt5Widgets REQUIRED)
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(Network Script)
include(${MACRO_DIR}/AutoMTC.cmake)
auto_mtc(${TARGET_NAME} "${ROOT_DIR}")
include_glm()
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME} "${AUTOMTC_SRC}")
link_hifi_libraries(shared octree fbx networking animation)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(fbx ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(animation ${TARGET_NAME} "${ROOT_DIR}")
# for streamable
link_hifi_library(metavoxels ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -38,7 +38,7 @@ void ModelEditPacketSender::sendEditModelMessage(PacketType type, ModelItemID mo
}
}
void ModelEditPacketSender::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew) {
void ModelEditPacketSender::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew) {
ModelItem::adjustEditPacketForClockSkew(codeColorBuffer, length, clockSkew);
}

View file

@ -32,6 +32,6 @@ public:
// My server type is the model server
virtual char getMyNodeType() const { return NodeType::ModelServer; }
virtual void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);
virtual void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew);
};
#endif // hifi_ModelEditPacketSender_h

View file

@ -11,19 +11,12 @@
#include <QtCore/QObject>
#include <GLMHelpers.h>
#include <Octree.h>
#include <RegisteredMetaTypes.h>
#include <SharedUtil.h> // usecTimestampNow()
#include <VoxelsScriptingInterface.h>
#include <VoxelDetail.h>
// This is not ideal, but adding script-engine as a linked library, will cause a circular reference
// I'm open to other potential solutions. Could we change cmake to allow libraries to reference each others
// headers, but not link to each other, this is essentially what this construct is doing, but would be
// better to add includes to the include path, but not link
#include "../../script-engine/src/ScriptEngine.h"
#include "ModelsScriptingInterface.h"
#include "ModelItem.h"
#include "ModelTree.h"
@ -641,7 +634,7 @@ bool ModelItem::encodeModelEditMessageDetails(PacketType command, ModelItemID id
}
// adjust any internal timestamps to fix clock skew for this server
void ModelItem::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew) {
void ModelItem::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew) {
unsigned char* dataAt = codeColorBuffer;
int octets = numberOfThreeBitSectionsInCode(dataAt);
int lengthOfOctcode = bytesRequiredForCodeLength(octets);

View file

@ -270,7 +270,7 @@ public:
static bool encodeModelEditMessageDetails(PacketType command, ModelItemID id, const ModelItemProperties& details,
unsigned char* bufferOut, int sizeIn, int& sizeOut);
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew);
void update(const quint64& now);

View file

@ -1,21 +1,14 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
set(TARGET_NAME networking)
project(${TARGET_NAME})
find_package(Qt5 COMPONENTS Network)
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(Network)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
link_hifi_libraries(shared)
# include GLM
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
target_link_libraries(${TARGET_NAME} Qt5::Network)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# we need ws2_32.lib on windows, but it's static so we don't bubble it up
target_link_libraries(${TARGET_NAME} ws2_32.lib)
endif ()
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

View file

@ -95,7 +95,7 @@ void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) {
if (sessionUUID != oldUUID) {
qDebug() << "NodeList UUID changed from" << uuidStringWithoutCurlyBraces(oldUUID)
<< "to" << uuidStringWithoutCurlyBraces(_sessionUUID);
emit uuidChanged(sessionUUID);
emit uuidChanged(sessionUUID, oldUUID);
}
}

View file

@ -107,7 +107,7 @@ public slots:
void killNodeWithUUID(const QUuid& nodeUUID);
signals:
void uuidChanged(const QUuid& ownerUUID);
void uuidChanged(const QUuid& ownerUUID, const QUuid& oldUUID);
void nodeAdded(SharedNodePointer);
void nodeKilled(SharedNodePointer);
protected:

View file

@ -81,6 +81,8 @@ PacketVersion versionForPacketType(PacketType type) {
return 1;
case PacketTypeAudioStreamStats:
return 1;
case PacketTypeMetavoxelData:
return 1;
default:
return 0;
}

View file

@ -39,10 +39,6 @@ public:
~PacketSender();
/// Add packet to outbound queue.
/// \param HifiSockAddr& address the destination address
/// \param packetData pointer to data
/// \param ssize_t packetLength size of data
/// \thread any thread, typically the application thread
void queuePacketForSending(const SharedNodePointer& destinationNode, const QByteArray& packet);
void setPacketsPerSecond(int packetsPerSecond);

View file

@ -24,10 +24,6 @@ public:
ReceivedPacketProcessor() { }
/// Add packet from network receive thread to the processing queue.
/// \param sockaddr& senderAddress the address of the sender
/// \param packetData pointer to received data
/// \param ssize_t packetLength size of received data
/// \thread network receive thread
void queueReceivedPacket(const SharedNodePointer& sendingNode, const QByteArray& packet);
/// Are there received packets waiting to be processed

View file

@ -253,14 +253,19 @@ PacketStreamStats SequenceNumberStats::getStatsForHistoryWindow() const {
}
// calculate difference between newest stats and oldest stats to get window stats
PacketStreamStats windowStats;
windowStats._received = newestStats->_received - oldestStats->_received;
windowStats._unreasonable = newestStats->_unreasonable - oldestStats->_unreasonable;
windowStats._early = newestStats->_early - oldestStats->_early;
windowStats._late = newestStats->_late - oldestStats->_late;
windowStats._lost = newestStats->_lost - oldestStats->_lost;
windowStats._recovered = newestStats->_recovered - oldestStats->_recovered;
windowStats._expectedReceived = newestStats->_expectedReceived - oldestStats->_expectedReceived;
return windowStats;
return *newestStats - *oldestStats;
}
PacketStreamStats SequenceNumberStats::getStatsForLastHistoryInterval() const {
const PacketStreamStats* newestStats = _statsHistory.getNewestEntry();
const PacketStreamStats* secondNewestStats = _statsHistory.get(1);
// this catches cases where history is length 1 or 0 (both are NULL in case of 0)
if (newestStats == NULL || secondNewestStats == NULL) {
return PacketStreamStats();
}
return *newestStats - *secondNewestStats;
}

View file

@ -31,6 +31,18 @@ public:
_expectedReceived(0)
{}
PacketStreamStats operator-(const PacketStreamStats& rhs) const {
PacketStreamStats diff;
diff._received = _received - rhs._received;
diff._unreasonable = _unreasonable - rhs._unreasonable;
diff._early = _early - rhs._early;
diff._late = _late - rhs._late;
diff._lost = _lost - rhs._lost;
diff._recovered = _recovered - rhs._recovered;
diff._expectedReceived = _expectedReceived - rhs._expectedReceived;
return diff;
}
float getLostRate() const { return (float)_lost / _expectedReceived; }
quint32 _received;
@ -76,6 +88,7 @@ public:
const PacketStreamStats& getStats() const { return _stats; }
PacketStreamStats getStatsForHistoryWindow() const;
PacketStreamStats getStatsForLastHistoryInterval() const;
const QSet<quint16>& getMissingSet() const { return _missingSet; }
private:

View file

@ -1,30 +1,19 @@
set(ROOT_DIR ../..)
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
set(TARGET_NAME octree)
find_package(Qt5Widgets REQUIRED)
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library()
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
include_glm()
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
link_hifi_libraries(shared networking)
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
# find ZLIB
find_package(ZLIB REQUIRED)
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
# append ZLIB and OpenSSL to our list of libraries to link
list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${ZLIB_LIBRARIES}")
# call macro to link our dependencies and bubble them up via a property on our target
link_shared_dependencies()

Some files were not shown because too many files have changed in this diff Show more