Merge branch 'master' of https://github.com/highfidelity/hifi into avatarUI

This commit is contained in:
ZappoMan 2015-04-01 09:09:50 -07:00
commit 827e37b920
45 changed files with 379 additions and 224 deletions

View file

@ -26,6 +26,7 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
project(hifi) project(hifi)
add_definitions(-DGLM_FORCE_RADIANS) add_definitions(-DGLM_FORCE_RADIANS)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
if (WIN32) if (WIN32)
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS) add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)

View file

@ -45,7 +45,7 @@ Agent::Agent(const QByteArray& packet) :
DependencyManager::get<EntityScriptingInterface>()->setPacketSender(&_entityEditSender); DependencyManager::get<EntityScriptingInterface>()->setPacketSender(&_entityEditSender);
DependencyManager::set<ResouceCacheSharedItems>(); DependencyManager::set<ResourceCacheSharedItems>();
DependencyManager::set<SoundCache>(); DependencyManager::set<SoundCache>();
} }

View file

@ -180,7 +180,7 @@ void AssignmentClientMonitor::readPendingDatagrams() {
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
if (!packetUUID.isNull()) { if (!packetUUID.isNull()) {
matchingNode = DependencyManager::get<LimitedNodeList>()->addOrUpdateNode matchingNode = DependencyManager::get<LimitedNodeList>()->addOrUpdateNode
(packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false, false);
AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); AssignmentClientChildData *childData = new AssignmentClientChildData("unknown");
matchingNode->setLinkedData(childData); matchingNode->setLinkedData(childData);
} else { } else {

View file

@ -20,6 +20,7 @@
#include <AccountManager.h> #include <AccountManager.h>
#include <HTTPConnection.h> #include <HTTPConnection.h>
#include <LogHandler.h> #include <LogHandler.h>
#include <NetworkingConstants.h>
#include <UUID.h> #include <UUID.h>
#include "../AssignmentClient.h" #include "../AssignmentClient.h"
@ -252,7 +253,7 @@ OctreeServer::OctreeServer(const QByteArray& packet) :
// make sure the AccountManager has an Auth URL for payment redemptions // make sure the AccountManager has an Auth URL for payment redemptions
AccountManager::getInstance().setAuthURL(DEFAULT_NODE_AUTH_URL); AccountManager::getInstance().setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
} }
OctreeServer::~OctreeServer() { OctreeServer::~OctreeServer() {

View file

@ -19,7 +19,7 @@ if (WIN32)
${EXTERNAL_NAME} ${EXTERNAL_NAME}
URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip
URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 URL_MD5 f5e8914fc9064ad32e0d62d19d33d977
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 -DUSE_DX11=0
LOG_DOWNLOAD 1 LOG_DOWNLOAD 1
LOG_CONFIGURE 1 LOG_CONFIGURE 1
LOG_BUILD 1 LOG_BUILD 1

View file

@ -13,16 +13,28 @@ if (ANDROID)
BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm
BUILD_IN_SOURCE 1 BUILD_IN_SOURCE 1
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/AndroidTBBLibCopy.cmake INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=so -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
)
elseif (APPLE)
find_program(MAKE_COMMAND NAMES make DOC "Path to the make command")
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_src.tgz
URL_MD5 bf090eaa86cf89ea014b7b462786a440
BUILD_COMMAND ${MAKE_COMMAND} tbb_os=macos
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=dylib -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake
LOG_DOWNLOAD 1 LOG_DOWNLOAD 1
LOG_CONFIGURE 1 LOG_CONFIGURE 1
LOG_BUILD 1 LOG_BUILD 1
) )
else () else ()
if (APPLE) if (WIN32)
set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_osx.tgz)
set(DOWNLOAD_MD5 25a36ebff070ff801760ec658079f6aa)
elseif (WIN32)
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_win.zip) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_win.zip)
set(DOWNLOAD_MD5 d250d40bb93b255f75bcbb19e976a440) set(DOWNLOAD_MD5 d250d40bb93b255f75bcbb19e976a440)
else () else ()
@ -46,7 +58,7 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
if (APPLE) if (APPLE)
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/libc++") set(_TBB_LIB_DIR "${SOURCE_DIR}/lib")
set(_LIB_PREFIX "lib") set(_LIB_PREFIX "lib")
set(_LIB_EXT "dylib") set(_LIB_EXT "dylib")
@ -95,14 +107,8 @@ elseif (UNIX)
endif () endif ()
if (DEFINED _TBB_LIB_DIR) if (DEFINED _TBB_LIB_DIR)
if (NOT APPLE) set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location") set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc_debug.${_LIB_EXT} CACHE FILEPATH "TBB malloc debug library location")
set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc_debug.${_LIB_EXT} CACHE FILEPATH "TBB malloc debug library location")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "TBB debug library location")
set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG "" CACHE FILEPATH "TBB malloc debug library location")
endif ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb.${_LIB_EXT} CACHE FILEPATH "TBB release library location") set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb.${_LIB_EXT} CACHE FILEPATH "TBB release library location")
set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc.${_LIB_EXT} CACHE FILEPATH "TBB malloc release library location") set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc.${_LIB_EXT} CACHE FILEPATH "TBB malloc release library location")
endif () endif ()

View file

@ -10,9 +10,11 @@
# #
# first find the so files in the source dir # first find the so files in the source dir
set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/libc++) set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib)
file(GLOB_RECURSE _TBB_LIBRARIES "${_TBB_LIBRARY_DIR}/*.dylib") file(GLOB_RECURSE _TBB_LIBRARIES "${_TBB_LIBRARY_DIR}/*.dylib")
message(${_TBB_LIBRARIES})
# raise an error if we found none # raise an error if we found none
if (NOT _TBB_LIBRARIES) if (NOT _TBB_LIBRARIES)
message(FATAL_ERROR "Did not find any TBB libraries") message(FATAL_ERROR "Did not find any TBB libraries")
@ -28,20 +30,6 @@ find_program(LIPO_COMMAND NAMES lipo DOC "Path to the lipo command")
foreach(_TBB_LIBRARY ${_TBB_LIBRARIES}) foreach(_TBB_LIBRARY ${_TBB_LIBRARIES})
get_filename_component(_TBB_LIBRARY_FILENAME ${_TBB_LIBRARY} NAME) get_filename_component(_TBB_LIBRARY_FILENAME ${_TBB_LIBRARY} NAME)
set(_LIPO_ARGS -remove i386 ${_TBB_LIBRARY_FILENAME} -output ${_TBB_LIBRARY_FILENAME})
message(STATUS "${LIPO_COMMAND} ${_LIPO_ARGS}")
# first we use lipo to remove i386 from each dylib
execute_process(
COMMAND ${LIPO_COMMAND} ${_LIPO_ARGS}
WORKING_DIRECTORY ${_TBB_LIBRARY_DIR}
ERROR_VARIABLE _LIPO_ERROR
)
if (_LIPO_ERROR)
message(FATAL_ERROR "There was an error removing i386 for ${_TBB_LIBRARY_FILENAME} - ${_LIPO_ERROR}")
endif ()
set(_INSTALL_NAME_ARGS ${INSTALL_NAME_TOOL_COMMAND} -id ${_TBB_LIBRARY} ${_TBB_LIBRARY_FILENAME}) set(_INSTALL_NAME_ARGS ${INSTALL_NAME_TOOL_COMMAND} -id ${_TBB_LIBRARY} ${_TBB_LIBRARY_FILENAME})
message(STATUS "${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS}") message(STATUS "${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS}")

View file

@ -1,5 +1,5 @@
# #
# AndroidTBBLibCopy.cmake # TBBLibCopy.cmake
# cmake/externals/tbb # cmake/externals/tbb
# #
# Copyright 2015 High Fidelity, Inc. # Copyright 2015 High Fidelity, Inc.
@ -10,7 +10,7 @@
# #
# first find the so files in the source dir # first find the so files in the source dir
file(GLOB_RECURSE _TBB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/build/*.so") file(GLOB_RECURSE _TBB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/build/*.${TBB_LIBS_SUFFIX}")
# raise an error if we found none # raise an error if we found none
if (NOT _TBB_LIBRARIES) if (NOT _TBB_LIBRARIES)

View file

@ -95,6 +95,13 @@
"can_set": true "can_set": true
} }
] ]
},
{
"name": "editors_are_rezzers",
"type": "checkbox",
"label": "Only editors can create new entities",
"help": "When checked, only those who can edit the domain can create new entites.",
"default": false
} }
] ]
}, },

View file

@ -27,6 +27,7 @@
#include <HifiConfigVariantMap.h> #include <HifiConfigVariantMap.h>
#include <HTTPConnection.h> #include <HTTPConnection.h>
#include <LogUtils.h> #include <LogUtils.h>
#include <NetworkingConstants.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <SettingHandle.h> #include <SettingHandle.h>
#include <SharedUtil.h> #include <SharedUtil.h>
@ -46,6 +47,7 @@ const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io";
const QString ALLOWED_USERS_SETTINGS_KEYPATH = "security.allowed_users"; const QString ALLOWED_USERS_SETTINGS_KEYPATH = "security.allowed_users";
const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity"; const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity";
const QString ALLOWED_EDITORS_SETTINGS_KEYPATH = "security.allowed_editors"; const QString ALLOWED_EDITORS_SETTINGS_KEYPATH = "security.allowed_editors";
const QString EDITORS_ARE_REZZERS_KEYPATH = "security.editors_are_rezzers";
DomainServer::DomainServer(int argc, char* argv[]) : DomainServer::DomainServer(int argc, char* argv[]) :
@ -181,7 +183,7 @@ bool DomainServer::optionallySetupOAuth() {
// if we don't have an oauth provider URL then we default to the default node auth url // if we don't have an oauth provider URL then we default to the default node auth url
if (_oauthProviderURL.isEmpty()) { if (_oauthProviderURL.isEmpty()) {
_oauthProviderURL = DEFAULT_NODE_AUTH_URL; _oauthProviderURL = NetworkingConstants::METAVERSE_SERVER_URL;
} }
AccountManager& accountManager = AccountManager::getInstance(); AccountManager& accountManager = AccountManager::getInstance();
@ -645,9 +647,23 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock
QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList();
bool canAdjustLocks = allowedEditors.isEmpty() || allowedEditors.contains(username); bool canAdjustLocks = allowedEditors.isEmpty() || allowedEditors.contains(username);
const QVariant* editorsAreRezzersVariant =
valueForKeyPath(_settingsManager.getSettingsMap(), EDITORS_ARE_REZZERS_KEYPATH);
bool onlyEditorsAreRezzers = false;
if (editorsAreRezzersVariant) {
onlyEditorsAreRezzers = editorsAreRezzersVariant->toBool();
}
bool canRez = true;
if (onlyEditorsAreRezzers) {
canRez = canAdjustLocks;
}
SharedNodePointer newNode = SharedNodePointer newNode =
DependencyManager::get<LimitedNodeList>()->addOrUpdateNode(nodeUUID, nodeType, DependencyManager::get<LimitedNodeList>()->addOrUpdateNode(nodeUUID, nodeType,
publicSockAddr, localSockAddr, canAdjustLocks); publicSockAddr, localSockAddr,
canAdjustLocks, canRez);
// when the newNode is created the linked data is also created // when the newNode is created the linked data is also created
// if this was a static assignment set the UUID, set the sendingSockAddr // if this was a static assignment set the UUID, set the sendingSockAddr
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(newNode->getLinkedData()); DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(newNode->getLinkedData());
@ -902,6 +918,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append);
broadcastDataStream << node->getUUID(); broadcastDataStream << node->getUUID();
broadcastDataStream << node->getCanAdjustLocks(); broadcastDataStream << node->getCanAdjustLocks();
broadcastDataStream << node->getCanRez();
int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos(); int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos();

View file

@ -43,8 +43,8 @@ var floor = Entities.addEntity(
var edge1 = Entities.addEntity( var edge1 = Entities.addEntity(
{ type: "Box", { type: "Box",
position: Vec3.sum(center, { x: FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), position: Vec3.sum(center, { x: FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }),
dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE + EDGE_THICKESS },
color: { red: 128, green: 128, blue: 128 }, color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
visible: true, visible: true,
@ -54,8 +54,8 @@ var edge1 = Entities.addEntity(
var edge2 = Entities.addEntity( var edge2 = Entities.addEntity(
{ type: "Box", { type: "Box",
position: Vec3.sum(center, { x: -FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), position: Vec3.sum(center, { x: -FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }),
dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE + EDGE_THICKESS },
color: { red: 128, green: 128, blue: 128 }, color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
visible: true, visible: true,
@ -65,8 +65,8 @@ var edge2 = Entities.addEntity(
var edge3 = Entities.addEntity( var edge3 = Entities.addEntity(
{ type: "Box", { type: "Box",
position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: -FLOOR_SIZE / 2.0 }), position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: -FLOOR_SIZE / 2.0 }),
dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, dimensions: { x: FLOOR_SIZE + EDGE_THICKESS, y: EDGE_THICKESS, z: EDGE_THICKESS },
color: { red: 128, green: 128, blue: 128 }, color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
visible: true, visible: true,
@ -76,8 +76,8 @@ var edge3 = Entities.addEntity(
var edge4 = Entities.addEntity( var edge4 = Entities.addEntity(
{ type: "Box", { type: "Box",
position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: FLOOR_SIZE / 2.0 }), position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: FLOOR_SIZE / 2.0 }),
dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, dimensions: { x: FLOOR_SIZE + EDGE_THICKESS, y: EDGE_THICKESS, z: EDGE_THICKESS },
color: { red: 128, green: 128, blue: 128 }, color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
visible: true, visible: true,
@ -97,6 +97,7 @@ for (var i = 0; i < NUM_BLOCKS; i++) {
dimensions: { x: type.x * SCALE, y: type.y * SCALE, z: type.z * SCALE }, dimensions: { x: type.x * SCALE, y: type.y * SCALE, z: type.z * SCALE },
color: { red: type.red, green: type.green, blue: type.blue }, color: { red: type.red, green: type.green, blue: type.blue },
gravity: { x: 0, y: GRAVITY, z: 0 }, gravity: { x: 0, y: GRAVITY, z: 0 },
velocity: { x: 0, y: 0.05, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
damping: DAMPING, damping: DAMPING,
lifetime: LIFETIME, lifetime: LIFETIME,
@ -104,6 +105,11 @@ for (var i = 0; i < NUM_BLOCKS; i++) {
} }
function scriptEnding() { function scriptEnding() {
Entities.editEntity(edge1, { locked: false });
Entities.editEntity(edge2, { locked: false });
Entities.editEntity(edge3, { locked: false });
Entities.editEntity(edge4, { locked: false });
Entities.editEntity(floor, { locked: false });
Entities.deleteEntity(edge1); Entities.deleteEntity(edge1);
Entities.deleteEntity(edge2); Entities.deleteEntity(edge2);
Entities.deleteEntity(edge3); Entities.deleteEntity(edge3);

View file

@ -90,44 +90,49 @@ var score = 0;
var bulletID = false; var bulletID = false;
var targetID = false; var targetID = false;
// Create a reticle image in center of screen // Create overlay buttons and reticle
var BUTTON_SIZE = 32;
var PADDING = 3;
var NUM_BUTTONS = 3;
var screenSize = Controller.getViewportDimensions(); var screenSize = Controller.getViewportDimensions();
var startX = screenSize.x / 2 - (NUM_BUTTONS * (BUTTON_SIZE + PADDING)) / 2;
var reticle = Overlays.addOverlay("image", { var reticle = Overlays.addOverlay("image", {
x: screenSize.x / 2 - 16, x: screenSize.x / 2 - (BUTTON_SIZE / 2),
y: screenSize.y / 2 - 16, y: screenSize.y / 2 - (BUTTON_SIZE / 2),
width: 32, width: BUTTON_SIZE,
height: 32, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/billiardsReticle.png", imageURL: HIFI_PUBLIC_BUCKET + "images/billiardsReticle.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1 alpha: 1
}); });
var offButton = Overlays.addOverlay("image", { var offButton = Overlays.addOverlay("image", {
x: screenSize.x - 48, x: startX,
y: 96, y: screenSize.y - (BUTTON_SIZE + PADDING),
width: 32, width: BUTTON_SIZE,
height: 32, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/close.png", imageURL: HIFI_PUBLIC_BUCKET + "images/close.png",
color: { red: 255, green: 255, blue: 255}, alpha: 1
});
startX += BUTTON_SIZE + PADDING;
var platformButton = Overlays.addOverlay("image", {
x: startX,
y: screenSize.y - (BUTTON_SIZE + PADDING),
width: BUTTON_SIZE,
height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/city.png",
alpha: 1 alpha: 1
}); });
var platformButton = Overlays.addOverlay("image", { startX += BUTTON_SIZE + PADDING;
x: screenSize.x - 48,
y: 130,
width: 32,
height: 32,
imageURL: HIFI_PUBLIC_BUCKET + "images/city.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1
});
var gridButton = Overlays.addOverlay("image", { var gridButton = Overlays.addOverlay("image", {
x: screenSize.x - 48, x: startX,
y: 164, y: screenSize.y - (BUTTON_SIZE + PADDING),
width: 32, width: BUTTON_SIZE,
height: 32, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/blocks.png", imageURL: HIFI_PUBLIC_BUCKET + "images/blocks.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1 alpha: 1
}); });
@ -282,7 +287,7 @@ function makePlatform(gravity, scale, size) {
z: pos.z - (separation * size / 2.0) + z * separation }, z: pos.z - (separation * size / 2.0) + z * separation },
dimensions: dimensions, dimensions: dimensions,
color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 }, color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 },
velocity: { x: 0, y: 0, z: 0 }, velocity: { x: 0, y: 0.05, z: 0 },
gravity: { x: 0, y: gravity, z: 0 }, gravity: { x: 0, y: gravity, z: 0 },
lifetime: TARGET_LIFE, lifetime: TARGET_LIFE,
damping: 0.1, damping: 0.1,
@ -297,7 +302,7 @@ function makePlatform(gravity, scale, size) {
type: "Box", type: "Box",
position: { x: pos.x, y: pos.y - separation / 2.0, z: pos.z }, position: { x: pos.x, y: pos.y - separation / 2.0, z: pos.z },
dimensions: { x: 2.0 * separation * size, y: separation / 2.0, z: 2.0 * separation * size }, dimensions: { x: 2.0 * separation * size, y: separation / 2.0, z: 2.0 * separation * size },
color: { red: 128, green: 128, blue: 128 }, color: { red: 100, green: 100, blue: 100 },
lifetime: TARGET_LIFE lifetime: TARGET_LIFE
}); });

View file

@ -23,21 +23,27 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var rollSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/dice/diceRoll.wav"); var rollSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/dice/diceRoll.wav");
var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to create new objects."
var screenSize = Controller.getViewportDimensions(); var screenSize = Controller.getViewportDimensions();
var BUTTON_SIZE = 32;
var PADDING = 3;
var offButton = Overlays.addOverlay("image", { var offButton = Overlays.addOverlay("image", {
x: screenSize.x - 48, x: screenSize.x / 2 - BUTTON_SIZE,
y: 96, y: screenSize.y- (BUTTON_SIZE + PADDING),
width: 32, width: BUTTON_SIZE,
height: 32, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/close.png", imageURL: HIFI_PUBLIC_BUCKET + "images/close.png",
color: { red: 255, green: 255, blue: 255}, color: { red: 255, green: 255, blue: 255},
alpha: 1 alpha: 1
}); });
var diceButton = Overlays.addOverlay("image", { var diceButton = Overlays.addOverlay("image", {
x: screenSize.x - 48, x: screenSize.x / 2 + PADDING,
y: 130, y: screenSize.y - (BUTTON_SIZE + PADDING),
width: 32, width: BUTTON_SIZE,
height: 32, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/die.png", imageURL: HIFI_PUBLIC_BUCKET + "images/die.png",
color: { red: 255, green: 255, blue: 255}, color: { red: 255, green: 255, blue: 255},
alpha: 1 alpha: 1
@ -48,21 +54,28 @@ var LIFETIME = 300;
// NOTE: angularVelocity is in radians/sec // NOTE: angularVelocity is in radians/sec
var MAX_ANGULAR_SPEED = Math.PI; var MAX_ANGULAR_SPEED = Math.PI;
function shootDice(position, velocity) { function shootDice(position, velocity) {
for (var i = 0; i < NUMBER_OF_DICE; i++) { if (!Entities.canRez()) {
dice.push(Entities.addEntity( Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG);
{ type: "Model", } else {
modelURL: HIFI_PUBLIC_BUCKET + "models/props/Dice/goldDie.fbx", for (var i = 0; i < NUMBER_OF_DICE; i++) {
position: position, dice.push(Entities.addEntity(
velocity: velocity, { type: "Model",
rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), modelURL: HIFI_PUBLIC_BUCKET + "models/props/Dice/goldDie.fbx",
angularVelocity: { x: Math.random() * MAX_ANGULAR_SPEED, y: Math.random() * MAX_ANGULAR_SPEED, z: Math.random() * MAX_ANGULAR_SPEED }, position: position,
lifetime: LIFETIME, velocity: velocity,
gravity: { x: 0, y: GRAVITY, z: 0 }, rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360),
shapeType: "box", angularVelocity: { x: Math.random() * MAX_ANGULAR_SPEED,
collisionsWillMove: true y: Math.random() * MAX_ANGULAR_SPEED,
})); z: Math.random() * MAX_ANGULAR_SPEED },
position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); lifetime: LIFETIME,
gravity: { x: 0, y: GRAVITY, z: 0 },
shapeType: "box",
collisionsWillMove: true
}));
position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation()))));
}
} }
} }
@ -92,7 +105,7 @@ function mousePressEvent(event) {
var clickedText = false; var clickedText = false;
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
if (clickedOverlay == offButton) { if (clickedOverlay == offButton) {
deleteDice(); Script.stop();
} else if (clickedOverlay == diceButton) { } else if (clickedOverlay == diceButton) {
var HOW_HARD = 2.0; var HOW_HARD = 2.0;
var position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); var position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));

View file

@ -132,7 +132,7 @@
this.updateLightIDInUserData(); this.updateLightIDInUserData();
} else { } else {
var that = this; var that = this;
Script.setTimeout(function() { that.maybeUpdateLightIDInUserData() }, 500); Script.setTimeout(function() { that.maybeUpdateLightIDInUserData() }, 500);
} }
} }
@ -213,6 +213,10 @@
this.preload = function(entityID) { this.preload = function(entityID) {
this.preOperation(entityID); this.preOperation(entityID);
}; };
this.unload = function(){
Entities.deleteEntity(this.lightID);
}
this.clickReleaseOnEntity = function(entityID, mouseEvent) { this.clickReleaseOnEntity = function(entityID, mouseEvent) {
this.preOperation(entityID); this.preOperation(entityID);

View file

@ -68,6 +68,7 @@
#include <MainWindow.h> #include <MainWindow.h>
#include <ModelEntityItem.h> #include <ModelEntityItem.h>
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <OctalCode.h> #include <OctalCode.h>
#include <OctreeSceneStats.h> #include <OctreeSceneStats.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
@ -136,6 +137,13 @@
#include "ui/StandAloneJSConsole.h" #include "ui/StandAloneJSConsole.h"
#include "ui/Stats.h" #include "ui/Stats.h"
// ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
#if defined(Q_OS_WIN)
extern "C" {
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
#endif
using namespace std; using namespace std;
// Starfield information // Starfield information
@ -241,7 +249,7 @@ bool setupEssentials(int& argc, char** argv) {
auto jsConsole = DependencyManager::set<StandAloneJSConsole>(); auto jsConsole = DependencyManager::set<StandAloneJSConsole>();
auto dialogsManager = DependencyManager::set<DialogsManager>(); auto dialogsManager = DependencyManager::set<DialogsManager>();
auto bandwidthRecorder = DependencyManager::set<BandwidthRecorder>(); auto bandwidthRecorder = DependencyManager::set<BandwidthRecorder>();
auto resouceCacheSharedItems = DependencyManager::set<ResouceCacheSharedItems>(); auto resourceCacheSharedItems = DependencyManager::set<ResourceCacheSharedItems>();
auto entityScriptingInterface = DependencyManager::set<EntityScriptingInterface>(); auto entityScriptingInterface = DependencyManager::set<EntityScriptingInterface>();
auto windowScriptingInterface = DependencyManager::set<WindowScriptingInterface>(); auto windowScriptingInterface = DependencyManager::set<WindowScriptingInterface>();
#if defined(Q_OS_MAC) || defined(Q_OS_WIN) #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
@ -418,7 +426,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
// set the account manager's root URL and trigger a login request if we don't have the access token // set the account manager's root URL and trigger a login request if we don't have the access token
accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL); accountManager.setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
UserActivityLogger::getInstance().launch(applicationVersion()); UserActivityLogger::getInstance().launch(applicationVersion());
// once the event loop has started, check and signal for an access token // once the event loop has started, check and signal for an access token
@ -646,6 +654,11 @@ void Application::initializeGL() {
} }
#endif #endif
qDebug() << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
qDebug() << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
qDebug() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
#ifdef WIN32 #ifdef WIN32
GLenum err = glewInit(); GLenum err = glewInit();
if (GLEW_OK != err) { if (GLEW_OK != err) {

View file

@ -685,6 +685,10 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
* joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform; * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
} }
// Each joint contributes its point to the bounding box
glm::vec3 jointPosition = extractTranslation(transforms[i]);
totalExtents.addPoint(jointPosition);
Shape* shape = _shapes[i]; Shape* shape = _shapes[i];
if (!shape) { if (!shape) {
continue; continue;
@ -694,8 +698,6 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
// that contains the sphere centered at the end of the joint with radius of the bone. // that contains the sphere centered at the end of the joint with radius of the bone.
// TODO: skip hand and arm shapes for bounding box calculation // TODO: skip hand and arm shapes for bounding box calculation
glm::vec3 jointPosition = extractTranslation(transforms[i]);
int type = shape->getType(); int type = shape->getType();
if (type == CAPSULE_SHAPE) { if (type == CAPSULE_SHAPE) {
// add the two furthest surface points of the capsule // add the two furthest surface points of the capsule

View file

@ -13,7 +13,7 @@
#include <qwebview.h> #include <qwebview.h>
#include <AccountManager.h> #include <AccountManager.h>
#include <LimitedNodeList.h> #include <NetworkingConstants.h>
#include "Application.h" #include "Application.h"
#include "DataWebPage.h" #include "DataWebPage.h"
@ -39,7 +39,7 @@ DataWebDialog* DataWebDialog::dialogForPath(const QString& path,
connect(dialogWebView->page()->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared, connect(dialogWebView->page()->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared,
dialogWebView, &DataWebDialog::addJavascriptObjectsToWindow); dialogWebView, &DataWebDialog::addJavascriptObjectsToWindow);
QUrl dataWebUrl(DEFAULT_NODE_AUTH_URL); QUrl dataWebUrl(NetworkingConstants::METAVERSE_SERVER_URL);
dataWebUrl.setPath(path); dataWebUrl.setPath(path);
qDebug() << "Opening a data web dialog for" << dataWebUrl.toString(); qDebug() << "Opening a data web dialog for" << dataWebUrl.toString();

View file

@ -14,6 +14,7 @@
#include <QPushButton> #include <QPushButton>
#include <QPixmap> #include <QPixmap>
#include <NetworkingConstants.h>
#include <PathUtils.h> #include <PathUtils.h>
#include "Application.h" #include "Application.h"
@ -23,7 +24,8 @@
#include "LoginDialog.h" #include "LoginDialog.h"
#include "UIUtil.h" #include "UIUtil.h"
const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.com/users/password/new"; const QString CREATE_ACCOUNT_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/create";
const QString FORGOT_PASSWORD_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/users/password/new";
LoginDialog::LoginDialog(QWidget* parent) : LoginDialog::LoginDialog(QWidget* parent) :
FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP), FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP),
@ -44,6 +46,7 @@ LoginDialog::LoginDialog(QWidget* parent) :
this, &LoginDialog::close); this, &LoginDialog::close);
UIUtil::scaleWidgetFontSizes(this); UIUtil::scaleWidgetFontSizes(this);
_ui->accountLabel->setText(_ui->accountLabel->text().arg(CREATE_ACCOUNT_URL, FORGOT_PASSWORD_URL));
// Initialize toggle connection // Initialize toggle connection
toggleQAction(); toggleQAction();

View file

@ -447,7 +447,7 @@ border-radius: 4px; padding-top: 1px;</string>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="accountLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Helvetica,Arial,sans-serif</family> <family>Helvetica,Arial,sans-serif</family>
@ -456,9 +456,12 @@ border-radius: 4px; padding-top: 1px;</string>
</property> </property>
<property name="text"> <property name="text">
<string>&lt;style type=&quot;text/css&quot;&gt; <string>&lt;style type=&quot;text/css&quot;&gt;
a { text-decoration: none; color: #267077;} a { text-decoration: none; color: #267077; margin:0;padding:0;}
#create {font-weight:bold;}
p {margin:5px 0;}
&lt;/style&gt; &lt;/style&gt;
&lt;a href=&quot;https://metaverse.highfidelity.com/password/new&quot;&gt;Recover password?&lt;/a&gt;</string> &lt;p&gt;&lt;a id=&quot;create&quot; href=&quot;%1&quot;&gt;Create account&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;%2&quot;&gt;Recover password&lt;/a&gt;&lt;/p&gt;</string>
</property> </property>
<property name="openExternalLinks"> <property name="openExternalLinks">
<bool>true</bool> <bool>true</bool>

View file

@ -61,7 +61,7 @@ void RenderableModelEntityItem::remapTextures() {
} }
if (!_model->isLoadedWithTextures()) { if (!_model->isLoadedWithTextures()) {
return; // nothing to do if the model has not yet loaded it's default textures return; // nothing to do if the model has not yet loaded its default textures
} }
if (!_originalTexturesRead && _model->isLoadedWithTextures()) { if (!_originalTexturesRead && _model->isLoadedWithTextures()) {
@ -220,7 +220,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
// if we have a URL, then we will want to end up returning a model... // if we have a URL, then we will want to end up returning a model...
if (!getModelURL().isEmpty()) { if (!getModelURL().isEmpty()) {
// if we have a previously allocated model, but it's URL doesn't match // if we have a previously allocated model, but its URL doesn't match
// then we need to let our renderer update our model for us. // then we need to let our renderer update our model for us.
if (_model && QUrl(getModelURL()) != _model->getURL()) { if (_model && QUrl(getModelURL()) != _model->getURL()) {
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL()); result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL());
@ -293,7 +293,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
} }
if (_model->getCollisionURL().isEmpty()) { if (_model->getCollisionURL().isEmpty()) {
// no model url, so we're ready to compute a shape. // no collision-model url, so we're ready to compute a shape (of type None).
return true; return true;
} }
@ -312,35 +312,30 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
info.setParams(getShapeType(), 0.5f * getDimensions()); info.setParams(getShapeType(), 0.5f * getDimensions());
} else { } else {
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry(); const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry(); const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry();
const QSharedPointer<NetworkGeometry> renderNetworkGeometry = _model->getGeometry();
const FBXGeometry& renderGeometry = renderNetworkGeometry->getFBXGeometry();
AABox aaBox;
_points.clear(); _points.clear();
unsigned int i = 0; unsigned int i = 0;
// the way OBJ files get read, each section under a "g" line is its own meshPart. We only expect // the way OBJ files get read, each section under a "g" line is its own meshPart. We only expect
// to find one actual "mesh" (with one or more meshParts in it), but we loop over the meshes, just in case. // to find one actual "mesh" (with one or more meshParts in it), but we loop over the meshes, just in case.
foreach (const FBXMesh& mesh, fbxGeometry.meshes) { foreach (const FBXMesh& mesh, collisionGeometry.meshes) {
// each meshPart is a convex hull // each meshPart is a convex hull
foreach (const FBXMeshPart &meshPart, mesh.parts) { foreach (const FBXMeshPart &meshPart, mesh.parts) {
QVector<glm::vec3> pointsInPart; QVector<glm::vec3> pointsInPart;
// run through all the triangles and (uniquely) add each point to the hull // run through all the triangles and (uniquely) add each point to the hull
unsigned int triangleCount = meshPart.triangleIndices.size() / 3; unsigned int triangleCount = meshPart.triangleIndices.size() / 3;
assert((unsigned int)meshPart.triangleIndices.size() == triangleCount*3);
for (unsigned int j = 0; j < triangleCount; j++) { for (unsigned int j = 0; j < triangleCount; j++) {
unsigned int p0Index = meshPart.triangleIndices[j*3]; unsigned int p0Index = meshPart.triangleIndices[j*3];
unsigned int p1Index = meshPart.triangleIndices[j*3+1]; unsigned int p1Index = meshPart.triangleIndices[j*3+1];
unsigned int p2Index = meshPart.triangleIndices[j*3+2]; unsigned int p2Index = meshPart.triangleIndices[j*3+2];
assert(p0Index < (unsigned int)mesh.vertices.size());
assert(p1Index < (unsigned int)mesh.vertices.size());
assert(p2Index < (unsigned int)mesh.vertices.size());
glm::vec3 p0 = mesh.vertices[p0Index]; glm::vec3 p0 = mesh.vertices[p0Index];
glm::vec3 p1 = mesh.vertices[p1Index]; glm::vec3 p1 = mesh.vertices[p1Index];
glm::vec3 p2 = mesh.vertices[p2Index]; glm::vec3 p2 = mesh.vertices[p2Index];
aaBox += p0;
aaBox += p1;
aaBox += p2;
if (!pointsInPart.contains(p0)) { if (!pointsInPart.contains(p0)) {
pointsInPart << p0; pointsInPart << p0;
} }
@ -360,18 +355,10 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
unsigned int p1Index = meshPart.quadIndices[j*4+1]; unsigned int p1Index = meshPart.quadIndices[j*4+1];
unsigned int p2Index = meshPart.quadIndices[j*4+2]; unsigned int p2Index = meshPart.quadIndices[j*4+2];
unsigned int p3Index = meshPart.quadIndices[j*4+3]; unsigned int p3Index = meshPart.quadIndices[j*4+3];
assert(p0Index < (unsigned int)mesh.vertices.size());
assert(p1Index < (unsigned int)mesh.vertices.size());
assert(p2Index < (unsigned int)mesh.vertices.size());
assert(p3Index < (unsigned int)mesh.vertices.size());
glm::vec3 p0 = mesh.vertices[p0Index]; glm::vec3 p0 = mesh.vertices[p0Index];
glm::vec3 p1 = mesh.vertices[p1Index]; glm::vec3 p1 = mesh.vertices[p1Index];
glm::vec3 p2 = mesh.vertices[p2Index]; glm::vec3 p2 = mesh.vertices[p2Index];
glm::vec3 p3 = mesh.vertices[p3Index]; glm::vec3 p3 = mesh.vertices[p3Index];
aaBox += p0;
aaBox += p1;
aaBox += p2;
aaBox += p3;
if (!pointsInPart.contains(p0)) { if (!pointsInPart.contains(p0)) {
pointsInPart << p0; pointsInPart << p0;
} }
@ -386,6 +373,11 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
} }
} }
if (pointsInPart.size() == 0) {
qDebug() << "Warning -- meshPart has no faces";
continue;
}
// add next convex hull // add next convex hull
QVector<glm::vec3> newMeshPoints; QVector<glm::vec3> newMeshPoints;
_points << newMeshPoints; _points << newMeshPoints;
@ -394,11 +386,14 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
} }
} }
// make sure we aren't about to divide by zero // We expect that the collision model will have the same units and will be displaced
glm::vec3 aaBoxDim = aaBox.getDimensions(); // from its origin in the same way the visual model is. The visual model has
aaBoxDim = glm::clamp(aaBoxDim, glm::vec3(FLT_EPSILON), aaBoxDim); // been centered and probably scaled. We take the scaling and offset which were applied
// to the visual model and apply them to the collision model (without regard for the
// collision model's extents).
glm::vec3 scale = _dimensions / renderGeometry.getUnscaledMeshExtents().size();
glm::vec3 scale = _dimensions / aaBoxDim;
// multiply each point by scale before handing the point-set off to the physics engine // multiply each point by scale before handing the point-set off to the physics engine
for (int i = 0; i < _points.size(); i++) { for (int i = 0; i < _points.size(); i++) {
for (int j = 0; j < _points[i].size(); j++) { for (int j = 0; j < _points[i].size(); j++) {

View file

@ -23,6 +23,7 @@ EntityScriptingInterface::EntityScriptingInterface() :
{ {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
connect(nodeList.data(), &NodeList::canAdjustLocksChanged, this, &EntityScriptingInterface::canAdjustLocksChanged); connect(nodeList.data(), &NodeList::canAdjustLocksChanged, this, &EntityScriptingInterface::canAdjustLocksChanged);
connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged);
} }
void EntityScriptingInterface::queueEntityMessage(PacketType packetType, void EntityScriptingInterface::queueEntityMessage(PacketType packetType,
@ -30,12 +31,15 @@ void EntityScriptingInterface::queueEntityMessage(PacketType packetType,
getEntityPacketSender()->queueEditEntityMessage(packetType, entityID, properties); getEntityPacketSender()->queueEditEntityMessage(packetType, entityID, properties);
} }
bool EntityScriptingInterface::canAdjustLocks() { bool EntityScriptingInterface::canAdjustLocks() {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
return nodeList->getThisNodeCanAdjustLocks(); return nodeList->getThisNodeCanAdjustLocks();
} }
bool EntityScriptingInterface::canRez() {
auto nodeList = DependencyManager::get<NodeList>();
return nodeList->getThisNodeCanRez();
}
void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) { void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) {
if (_entityTree) { if (_entityTree) {

View file

@ -66,6 +66,9 @@ public slots:
// returns true if the DomainServer will allow this Node/Avatar to make changes // returns true if the DomainServer will allow this Node/Avatar to make changes
Q_INVOKABLE bool canAdjustLocks(); Q_INVOKABLE bool canAdjustLocks();
// returns true if the DomainServer will allow this Node/Avatar to rez new entities
Q_INVOKABLE bool canRez();
/// adds a model with the specific properties /// adds a model with the specific properties
Q_INVOKABLE EntityItemID addEntity(const EntityItemProperties& properties); Q_INVOKABLE EntityItemID addEntity(const EntityItemProperties& properties);
@ -117,6 +120,7 @@ signals:
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
void canAdjustLocksChanged(bool canAdjustLocks); void canAdjustLocksChanged(bool canAdjustLocks);
void canRezChanged(bool canRez);
void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);

View file

@ -659,12 +659,14 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
qDebug() << "User attempted to edit an unknown entity. ID:" << entityItemID; qDebug() << "User attempted to edit an unknown entity. ID:" << entityItemID;
} }
} else { } else {
// this is a new entity... assign a new entityID if (senderNode->getCanRez()) {
entityItemID = assignEntityID(entityItemID); // this is a new entity... assign a new entityID
EntityItem* newEntity = addEntity(entityItemID, properties); entityItemID = assignEntityID(entityItemID);
if (newEntity) { EntityItem* newEntity = addEntity(entityItemID, properties);
newEntity->markAsChangedOnServer(); if (newEntity) {
notifyNewlyCreatedEntity(*newEntity, senderNode); newEntity->markAsChangedOnServer();
notifyNewlyCreatedEntity(*newEntity, senderNode);
}
} }
} }
} }

View file

@ -27,7 +27,8 @@ public:
enum SpecialToken { enum SpecialToken {
NO_TOKEN = -1, NO_TOKEN = -1,
NO_PUSHBACKED_TOKEN = -1, NO_PUSHBACKED_TOKEN = -1,
DATUM_TOKEN = 0x100 DATUM_TOKEN = 0x100,
COMMENT_TOKEN = 0x101
}; };
int nextToken(); int nextToken();
const QByteArray& getDatum() const { return _datum; } const QByteArray& getDatum() const { return _datum; }
@ -35,11 +36,13 @@ public:
void skipLine() { _device->readLine(); } void skipLine() { _device->readLine(); }
void pushBackToken(int token) { _pushedBackToken = token; } void pushBackToken(int token) { _pushedBackToken = token; }
void ungetChar(char ch) { _device->ungetChar(ch); } void ungetChar(char ch) { _device->ungetChar(ch); }
const QString getComment() const { return _comment; }
private: private:
QIODevice* _device; QIODevice* _device;
QByteArray _datum; QByteArray _datum;
int _pushedBackToken; int _pushedBackToken;
QString _comment;
}; };
@ -56,9 +59,11 @@ int OBJTokenizer::nextToken() {
continue; // skip whitespace continue; // skip whitespace
} }
switch (ch) { switch (ch) {
case '#': case '#': {
_device->readLine(); // skip the comment _comment = _device->readLine(); // skip the comment
break; qDebug() << "COMMENT:" << _comment;
return COMMENT_TOKEN;
}
case '\"': case '\"':
_datum = ""; _datum = "";
@ -104,7 +109,8 @@ bool OBJTokenizer::isNextTokenFloat() {
} }
bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
FBXGeometry &geometry, QVector<glm::vec3>& faceNormals, QVector<int>& faceNormalIndexes) { FBXGeometry &geometry, QVector<glm::vec3>& faceNormals, QVector<int>& faceNormalIndexes,
float& scaleGuess) {
FBXMesh &mesh = geometry.meshes[0]; FBXMesh &mesh = geometry.meshes[0];
mesh.parts.append(FBXMeshPart()); mesh.parts.append(FBXMeshPart());
FBXMeshPart &meshPart = mesh.parts.last(); FBXMeshPart &meshPart = mesh.parts.last();
@ -128,7 +134,17 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0)); meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0));
while (true) { while (true) {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { int tokenType = tokenizer.nextToken();
if (tokenType == OBJTokenizer::COMMENT_TOKEN) {
if (tokenizer.getComment().contains("This file uses centimeters as units")) {
scaleGuess = 1.0f / 100.0f;
}
if (tokenizer.getComment().contains("This file uses millimeters as units")) {
scaleGuess = 1.0f / 1000.0f;
}
continue;
}
if (tokenType != OBJTokenizer::DATUM_TOKEN) {
result = false; result = false;
break; break;
} }
@ -192,6 +208,7 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
while (true) { while (true) {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
if (indices.count() == 0) { if (indices.count() == 0) {
// nonsense, bail out.
goto done; goto done;
} }
break; break;
@ -266,22 +283,22 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
} }
} else { } else {
// something we don't (yet) care about // something we don't (yet) care about
qDebug() << "OBJ parser is skipping a line with" << token; // qDebug() << "OBJ parser is skipping a line with" << token;
tokenizer.skipLine(); tokenizer.skipLine();
} }
} }
done: done:
if (meshPart.triangleIndices.size() == 0 && meshPart.quadIndices.size() == 0) {
// empty mesh?
mesh.parts.pop_back();
}
return result; return result;
} }
FBXGeometry extractOBJGeometry(const FBXNode& node, const QVariantHash& mapping) {
FBXGeometry geometry;
return geometry;
}
FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) { FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) {
QBuffer buffer(const_cast<QByteArray*>(&model)); QBuffer buffer(const_cast<QByteArray*>(&model));
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
@ -294,24 +311,30 @@ FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) {
OBJTokenizer tokenizer(device); OBJTokenizer tokenizer(device);
QVector<int> faceNormalIndexes; QVector<int> faceNormalIndexes;
QVector<glm::vec3> faceNormals; QVector<glm::vec3> faceNormals;
float scaleGuess = 1.0f;
faceNormalIndexes.clear(); faceNormalIndexes.clear();
geometry.meshExtents.reset(); geometry.meshExtents.reset();
geometry.meshes.append(FBXMesh()); geometry.meshes.append(FBXMesh());
try { try {
// call parseOBJGroup as long as it's returning true. Each successful call will // call parseOBJGroup as long as it's returning true. Each successful call will
// add a new meshPart to the geometry's single mesh. // add a new meshPart to the geometry's single mesh.
bool success = true; bool success = true;
while (success) { while (success) {
success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes); success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes, scaleGuess);
} }
FBXMesh &mesh = geometry.meshes[0]; FBXMesh &mesh = geometry.meshes[0];
// if we got a hint about units, scale all the points
if (scaleGuess != 1.0f) {
for (int i = 0; i < mesh.vertices.size(); i++) {
mesh.vertices[i] *= scaleGuess;
}
}
mesh.meshExtents.reset(); mesh.meshExtents.reset();
foreach (const glm::vec3& vertex, mesh.vertices) { foreach (const glm::vec3& vertex, mesh.vertices) {
mesh.meshExtents.addPoint(vertex); mesh.meshExtents.addPoint(vertex);

View file

@ -33,8 +33,7 @@ AddressManager::AddressManager() :
_rootPlaceName(), _rootPlaceName(),
_rootPlaceID(), _rootPlaceID(),
_positionGetter(NULL), _positionGetter(NULL),
_orientationGetter(NULL), _orientationGetter(NULL)
_localDSPortSharedMem(NULL)
{ {
connect(qApp, &QCoreApplication::aboutToQuit, this, &AddressManager::storeCurrentAddress); connect(qApp, &QCoreApplication::aboutToQuit, this, &AddressManager::storeCurrentAddress);
} }
@ -331,13 +330,6 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
if (domainHostname == "localhost") {
auto nodeList = DependencyManager::get<NodeList>();
nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY,
_localDSPortSharedMem,
domainPort);
}
if (!hostnameRegex.cap(2).isEmpty()) { if (!hostnameRegex.cap(2).isEmpty()) {
domainPort = (qint16) hostnameRegex.cap(2).toInt(); domainPort = (qint16) hostnameRegex.cap(2).toInt();
} }

View file

@ -95,8 +95,6 @@ private:
QUuid _rootPlaceID; QUuid _rootPlaceID;
PositionGetter _positionGetter; PositionGetter _positionGetter;
OrientationGetter _orientationGetter; OrientationGetter _orientationGetter;
QSharedMemory* _localDSPortSharedMem; // memory shared with domain server
}; };
#endif // hifi_AddressManager_h #endif // hifi_AddressManager_h

View file

@ -47,6 +47,7 @@ public:
void setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname); void setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname);
unsigned short getPort() const { return _sockAddr.getPort(); } unsigned short getPort() const { return _sockAddr.getPort(); }
void setPort(quint16 port) { _sockAddr.setPort(port); }
const QUuid& getAssignmentUUID() const { return _assignmentUUID; } const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }

View file

@ -36,8 +36,6 @@ const char SOLO_NODE_TYPES[2] = {
NodeType::AudioMixer NodeType::AudioMixer
}; };
const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://metaverse.highfidelity.com");
LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) : LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) :
linkedDataCreateCallback(NULL), linkedDataCreateCallback(NULL),
_sessionUUID(), _sessionUUID(),
@ -49,7 +47,8 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short
_publicSockAddr(), _publicSockAddr(),
_stunSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT), _stunSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT),
_packetStatTimer(), _packetStatTimer(),
_thisNodeCanAdjustLocks(false) _thisNodeCanAdjustLocks(false),
_thisNodeCanRez(true)
{ {
static bool firstCall = true; static bool firstCall = true;
if (firstCall) { if (firstCall) {
@ -108,6 +107,13 @@ void LimitedNodeList::setThisNodeCanAdjustLocks(bool canAdjustLocks) {
} }
} }
void LimitedNodeList::setThisNodeCanRez(bool canRez) {
if (_thisNodeCanRez != canRez) {
_thisNodeCanRez = canRez;
emit canRezChanged(canRez);
}
}
QUdpSocket& LimitedNodeList::getDTLSSocket() { QUdpSocket& LimitedNodeList::getDTLSSocket() {
if (!_dtlsSocket) { if (!_dtlsSocket) {
// DTLS socket getter called but no DTLS socket exists, create it now // DTLS socket getter called but no DTLS socket exists, create it now
@ -392,8 +398,9 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) {
_nodeMutex.unlock(); _nodeMutex.unlock();
QWriteLocker writeLocker(&_nodeMutex); _nodeMutex.lockForWrite();
_nodeHash.unsafe_erase(it); _nodeHash.unsafe_erase(it);
_nodeMutex.unlock();
handleNodeKill(matchingNode); handleNodeKill(matchingNode);
} else { } else {
@ -416,7 +423,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) {
SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
bool canAdjustLocks) { bool canAdjustLocks, bool canRez) {
NodeHash::const_iterator it = _nodeHash.find(uuid); NodeHash::const_iterator it = _nodeHash.find(uuid);
if (it != _nodeHash.end()) { if (it != _nodeHash.end()) {
@ -425,11 +432,12 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
matchingNode->setPublicSocket(publicSocket); matchingNode->setPublicSocket(publicSocket);
matchingNode->setLocalSocket(localSocket); matchingNode->setLocalSocket(localSocket);
matchingNode->setCanAdjustLocks(canAdjustLocks); matchingNode->setCanAdjustLocks(canAdjustLocks);
matchingNode->setCanRez(canRez);
return matchingNode; return matchingNode;
} else { } else {
// we didn't have this node, so add them // we didn't have this node, so add them
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, canAdjustLocks); Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, canAdjustLocks, canRez);
SharedNodePointer newNodePointer(newNode); SharedNodePointer newNodePointer(newNode);
_nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer)); _nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer));

View file

@ -42,8 +42,6 @@ const quint64 NODE_SILENCE_THRESHOLD_MSECS = 2 * 1000;
extern const char SOLO_NODE_TYPES[2]; extern const char SOLO_NODE_TYPES[2];
extern const QUrl DEFAULT_NODE_AUTH_URL;
const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost";
const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
@ -86,6 +84,9 @@ public:
bool getThisNodeCanAdjustLocks() const { return _thisNodeCanAdjustLocks; } bool getThisNodeCanAdjustLocks() const { return _thisNodeCanAdjustLocks; }
void setThisNodeCanAdjustLocks(bool canAdjustLocks); void setThisNodeCanAdjustLocks(bool canAdjustLocks);
bool getThisNodeCanRez() const { return _thisNodeCanRez; }
void setThisNodeCanRez(bool canRez);
void rebindNodeSocket(); void rebindNodeSocket();
QUdpSocket& getNodeSocket() { return _nodeSocket; } QUdpSocket& getNodeSocket() { return _nodeSocket; }
@ -116,7 +117,8 @@ public:
SharedNodePointer sendingNodeForPacket(const QByteArray& packet); SharedNodePointer sendingNodeForPacket(const QByteArray& packet);
SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks); const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
bool canAdjustLocks, bool canRez);
const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; } const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; }
const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; } const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; }
@ -208,6 +210,7 @@ signals:
void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); void publicSockAddrChanged(const HifiSockAddr& publicSockAddr);
void canAdjustLocksChanged(bool canAdjustLocks); void canAdjustLocksChanged(bool canAdjustLocks);
void canRezChanged(bool canRez);
void dataSent(const quint8 channel_type, const int bytes); void dataSent(const quint8 channel_type, const int bytes);
void dataReceived(const quint8 channel_type, const int bytes); void dataReceived(const quint8 channel_type, const int bytes);
@ -243,6 +246,7 @@ protected:
QElapsedTimer _packetStatTimer; QElapsedTimer _packetStatTimer;
bool _thisNodeCanAdjustLocks; bool _thisNodeCanAdjustLocks;
bool _thisNodeCanRez;
template<typename IteratorLambda> template<typename IteratorLambda>
void eachNodeHashIterator(IteratorLambda functor) { void eachNodeHashIterator(IteratorLambda functor) {

View file

@ -0,0 +1,21 @@
//
// NetworkingConstants.h
// libraries/networking/src
//
// Created by Stephen Birarda on 2015-03-31.
// Copyright 2015 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_NetworkingConstants_h
#define hifi_NetworkingConstants_h
#include <QtCore/QUrl>
namespace NetworkingConstants {
const QUrl METAVERSE_SERVER_URL = QUrl("https://metaverse.highfidelity.com");
}
#endif // hifi_NetworkingConstants_h

View file

@ -41,7 +41,7 @@ const QString& NodeType::getNodeTypeName(NodeType_t nodeType) {
} }
Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
const HifiSockAddr& localSocket, bool canAdjustLocks) : const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez) :
NetworkPeer(uuid, publicSocket, localSocket), NetworkPeer(uuid, publicSocket, localSocket),
_type(type), _type(type),
_activeSocket(NULL), _activeSocket(NULL),
@ -53,7 +53,8 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
_clockSkewUsec(0), _clockSkewUsec(0),
_mutex(), _mutex(),
_clockSkewMovingPercentile(30, 0.8f), // moving 80th percentile of 30 samples _clockSkewMovingPercentile(30, 0.8f), // moving 80th percentile of 30 samples
_canAdjustLocks(canAdjustLocks) _canAdjustLocks(canAdjustLocks),
_canRez(canRez)
{ {
} }
@ -133,6 +134,7 @@ QDataStream& operator<<(QDataStream& out, const Node& node) {
out << node._publicSocket; out << node._publicSocket;
out << node._localSocket; out << node._localSocket;
out << node._canAdjustLocks; out << node._canAdjustLocks;
out << node._canRez;
return out; return out;
} }
@ -143,6 +145,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) {
in >> node._publicSocket; in >> node._publicSocket;
in >> node._localSocket; in >> node._localSocket;
in >> node._canAdjustLocks; in >> node._canAdjustLocks;
in >> node._canRez;
return in; return in;
} }

View file

@ -45,7 +45,7 @@ class Node : public NetworkPeer {
Q_OBJECT Q_OBJECT
public: public:
Node(const QUuid& uuid, NodeType_t type, Node(const QUuid& uuid, NodeType_t type,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks); const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez);
~Node(); ~Node();
bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; } bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; }
@ -79,6 +79,9 @@ public:
void setCanAdjustLocks(bool canAdjustLocks) { _canAdjustLocks = canAdjustLocks; } void setCanAdjustLocks(bool canAdjustLocks) { _canAdjustLocks = canAdjustLocks; }
bool getCanAdjustLocks() { return _canAdjustLocks; } bool getCanAdjustLocks() { return _canAdjustLocks; }
void setCanRez(bool canRez) { _canRez = canRez; }
bool getCanRez() { return _canRez; }
void activatePublicSocket(); void activatePublicSocket();
void activateLocalSocket(); void activateLocalSocket();
@ -105,6 +108,7 @@ private:
QMutex _mutex; QMutex _mutex;
MovingPercentile _clockSkewMovingPercentile; MovingPercentile _clockSkewMovingPercentile;
bool _canAdjustLocks; bool _canAdjustLocks;
bool _canRez;
}; };
QDebug operator<<(QDebug debug, const Node &message); QDebug operator<<(QDebug debug, const Node &message);

View file

@ -277,6 +277,23 @@ void NodeList::sendDomainServerCheckIn() {
if (!_domainHandler.isConnected()) { if (!_domainHandler.isConnected()) {
qDebug() << "Sending connect request to domain-server at" << _domainHandler.getHostname(); qDebug() << "Sending connect request to domain-server at" << _domainHandler.getHostname();
// is this our localhost domain-server?
// if so we need to make sure we have an up-to-date local port in case it restarted
if (_domainHandler.getSockAddr().getAddress() == QHostAddress::LocalHost
|| _domainHandler.getHostname() == "localhost") {
static QSharedMemory* localDSPortSharedMem = NULL;
quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY,
localDSPortSharedMem,
domainPort);
qDebug() << "Local domain-server port read from shared memory (or default) is" << domainPort;
_domainHandler.setPort(domainPort);
}
} }
// construct the DS check in packet // construct the DS check in packet
@ -386,6 +403,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
bool thisNodeCanAdjustLocks; bool thisNodeCanAdjustLocks;
packetStream >> thisNodeCanAdjustLocks; packetStream >> thisNodeCanAdjustLocks;
setThisNodeCanAdjustLocks(thisNodeCanAdjustLocks); setThisNodeCanAdjustLocks(thisNodeCanAdjustLocks);
bool thisNodeCanRez;
packetStream >> thisNodeCanRez;
setThisNodeCanRez(thisNodeCanRez);
// pull each node in the packet // pull each node in the packet
while(packetStream.device()->pos() < packet.size()) { while(packetStream.device()->pos() < packet.size()) {
@ -394,8 +415,9 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
QUuid nodeUUID, connectionUUID; QUuid nodeUUID, connectionUUID;
HifiSockAddr nodePublicSocket, nodeLocalSocket; HifiSockAddr nodePublicSocket, nodeLocalSocket;
bool canAdjustLocks; bool canAdjustLocks;
bool canRez;
packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> canAdjustLocks; packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> canAdjustLocks >> canRez;
// if the public socket address is 0 then it's reachable at the same IP // if the public socket address is 0 then it's reachable at the same IP
// as the domain server // as the domain server
@ -403,7 +425,8 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
nodePublicSocket.setAddress(_domainHandler.getIP()); nodePublicSocket.setAddress(_domainHandler.getIP());
} }
SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket, canAdjustLocks); SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket,
nodeLocalSocket, canAdjustLocks, canRez);
packetStream >> connectionUUID; packetStream >> connectionUUID;
node->setConnectionSecret(connectionUUID); node->setConnectionSecret(connectionUUID);

View file

@ -15,6 +15,7 @@
#include "AccountManager.h" #include "AccountManager.h"
#include "LimitedNodeList.h" #include "LimitedNodeList.h"
#include "NetworkingConstants.h"
#include "SharedUtil.h" #include "SharedUtil.h"
#include "OAuthNetworkAccessManager.h" #include "OAuthNetworkAccessManager.h"
@ -33,7 +34,8 @@ QNetworkReply* OAuthNetworkAccessManager::createRequest(QNetworkAccessManager::O
QIODevice* outgoingData) { QIODevice* outgoingData) {
AccountManager& accountManager = AccountManager::getInstance(); AccountManager& accountManager = AccountManager::getInstance();
if (accountManager.hasValidAccessToken() && req.url().host() == DEFAULT_NODE_AUTH_URL.host()) { if (accountManager.hasValidAccessToken()
&& req.url().host() == NetworkingConstants::METAVERSE_SERVER_URL.host()) {
QNetworkRequest authenticatedRequest(req); QNetworkRequest authenticatedRequest(req);
authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
authenticatedRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, authenticatedRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER,

View file

@ -64,7 +64,7 @@ PacketVersion versionForPacketType(PacketType type) {
return 2; return 2;
case PacketTypeDomainList: case PacketTypeDomainList:
case PacketTypeDomainListRequest: case PacketTypeDomainListRequest:
return 4; return 5;
case PacketTypeCreateAssignment: case PacketTypeCreateAssignment:
case PacketTypeRequestAssignment: case PacketTypeRequestAssignment:
return 2; return 2;

View file

@ -70,6 +70,7 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
bool delayLoad, void* extra) { bool delayLoad, void* extra) {
QSharedPointer<Resource> resource = _resources.value(url); QSharedPointer<Resource> resource = _resources.value(url);
if (!resource.isNull()) { if (!resource.isNull()) {
removeUnusedResource(resource);
return resource; return resource;
} }
@ -83,16 +84,14 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
return getResource(fallback, QUrl(), delayLoad); return getResource(fallback, QUrl(), delayLoad);
} }
if (resource.isNull()) { resource = createResource(url, fallback.isValid() ?
resource = createResource(url, fallback.isValid() ? getResource(fallback, QUrl(), true) : QSharedPointer<Resource>(), delayLoad, extra);
getResource(fallback, QUrl(), true) : QSharedPointer<Resource>(), delayLoad, extra); resource->setSelf(resource);
resource->setSelf(resource); resource->setCache(this);
resource->setCache(this); _resources.insert(url, resource);
_resources.insert(url, resource); removeUnusedResource(resource);
resource->ensureLoading();
} else {
removeUnusedResource(resource);
}
return resource; return resource;
} }
@ -134,7 +133,7 @@ void ResourceCache::reserveUnusedResource(qint64 resourceSize) {
} }
void ResourceCache::attemptRequest(Resource* resource) { void ResourceCache::attemptRequest(Resource* resource) {
auto sharedItems = DependencyManager::get<ResouceCacheSharedItems>(); auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
if (_requestLimit <= 0) { if (_requestLimit <= 0) {
// wait until a slot becomes available // wait until a slot becomes available
sharedItems->_pendingRequests.append(resource); sharedItems->_pendingRequests.append(resource);
@ -147,7 +146,7 @@ void ResourceCache::attemptRequest(Resource* resource) {
void ResourceCache::requestCompleted(Resource* resource) { void ResourceCache::requestCompleted(Resource* resource) {
auto sharedItems = DependencyManager::get<ResouceCacheSharedItems>(); auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
sharedItems->_loadingRequests.removeOne(resource); sharedItems->_loadingRequests.removeOne(resource);
_requestLimit++; _requestLimit++;

View file

@ -48,14 +48,14 @@ static const qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES;
// ResourceCache derived classes. Since we can't count on the ordering of // ResourceCache derived classes. Since we can't count on the ordering of
// static members destruction, we need to use this Dependency manager implemented // static members destruction, we need to use this Dependency manager implemented
// object instead // object instead
class ResouceCacheSharedItems : public Dependency { class ResourceCacheSharedItems : public Dependency {
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
public: public:
QList<QPointer<Resource> > _pendingRequests; QList<QPointer<Resource> > _pendingRequests;
QList<Resource*> _loadingRequests; QList<Resource*> _loadingRequests;
private: private:
ResouceCacheSharedItems() { } ResourceCacheSharedItems() { }
virtual ~ResouceCacheSharedItems() { } virtual ~ResourceCacheSharedItems() { }
}; };
@ -71,10 +71,10 @@ public:
qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; } qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; }
static const QList<Resource*>& getLoadingRequests() static const QList<Resource*>& getLoadingRequests()
{ return DependencyManager::get<ResouceCacheSharedItems>()->_loadingRequests; } { return DependencyManager::get<ResourceCacheSharedItems>()->_loadingRequests; }
static int getPendingRequestCount() static int getPendingRequestCount()
{ return DependencyManager::get<ResouceCacheSharedItems>()->_pendingRequests.size(); } { return DependencyManager::get<ResourceCacheSharedItems>()->_pendingRequests.size(); }
ResourceCache(QObject* parent = NULL); ResourceCache(QObject* parent = NULL);
virtual ~ResourceCache(); virtual ~ResourceCache();

View file

@ -212,6 +212,9 @@ btVector3 CharacterController::perpindicularComponent(const btVector3& direction
} }
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
const float DEFAULT_GRAVITY = 5.0f;
const float TERMINAL_VELOCITY = 55.0f;
const float JUMP_SPEED = 5.0f;
CharacterController::CharacterController(AvatarData* avatarData) { CharacterController::CharacterController(AvatarData* avatarData) {
assert(avatarData); assert(avatarData);
@ -226,9 +229,9 @@ CharacterController::CharacterController(AvatarData* avatarData) {
_velocityTimeInterval = 0.0f; _velocityTimeInterval = 0.0f;
_verticalVelocity = 0.0f; _verticalVelocity = 0.0f;
_verticalOffset = 0.0f; _verticalOffset = 0.0f;
_gravity = 5.0f; // slower than Earth's _gravity = DEFAULT_GRAVITY; // slower than Earth's
_maxFallSpeed = 55.0f; // Terminal velocity of a sky diver in m/s. _maxFallSpeed = TERMINAL_VELOCITY; // Terminal velocity of a sky diver in m/s.
_jumpSpeed = 5.0f; _jumpSpeed = JUMP_SPEED;
_isOnGround = false; _isOnGround = false;
_isJumping = false; _isJumping = false;
_isHovering = true; _isHovering = true;
@ -350,6 +353,7 @@ bool CharacterController::recoverFromPenetration(btCollisionWorld* collisionWorl
return penetration; return penetration;
} }
void CharacterController::scanDown(btCollisionWorld* world) { void CharacterController::scanDown(btCollisionWorld* world) {
// we test with downward raycast and if we don't find floor close enough then turn on "hover" // we test with downward raycast and if we don't find floor close enough then turn on "hover"
btKinematicClosestNotMeRayResultCallback callback(_ghostObject); btKinematicClosestNotMeRayResultCallback callback(_ghostObject);

View file

@ -535,10 +535,13 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit
} }
void DeferredLightingEffect::setAmbientLightMode(int preset) { void DeferredLightingEffect::setAmbientLightMode(int preset) {
if ((preset >= -1) && (preset < model::SphericalHarmonics::NUM_PRESET)) { if ((preset >= 0) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
_ambientLightMode = preset; _ambientLightMode = preset;
auto light = _allocatedLights.front(); auto light = _allocatedLights.front();
light->setAmbientSpherePreset(model::SphericalHarmonics::Preset(preset % model::SphericalHarmonics::NUM_PRESET)); light->setAmbientSpherePreset(model::SphericalHarmonics::Preset(preset % model::SphericalHarmonics::NUM_PRESET));
} else {
// force to preset 0
setAmbientLightMode(0);
} }
} }

View file

@ -1775,10 +1775,10 @@ QSharedPointer<NetworkGeometry> GeometryCache::getGeometry(const QUrl& url, cons
return getResource(url, fallback, delayLoad, NULL).staticCast<NetworkGeometry>(); return getResource(url, fallback, delayLoad, NULL).staticCast<NetworkGeometry>();
} }
QSharedPointer<Resource> GeometryCache::createResource(const QUrl& url, QSharedPointer<Resource> GeometryCache::createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
const QSharedPointer<Resource>& fallback, bool delayLoad, const void* extra) { bool delayLoad, const void* extra) {
QSharedPointer<NetworkGeometry> geometry(new NetworkGeometry(url, fallback.staticCast<NetworkGeometry>(), delayLoad), QSharedPointer<NetworkGeometry> geometry(new NetworkGeometry(url, fallback.staticCast<NetworkGeometry>(), delayLoad),
&Resource::allReferencesCleared); &Resource::allReferencesCleared);
geometry->setLODParent(geometry); geometry->setLODParent(geometry);
return geometry.staticCast<Resource>(); return geometry.staticCast<Resource>();
} }

View file

@ -2372,7 +2372,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
bool forceRenderSomeMeshes) { bool forceRenderMeshes) {
PROFILE_RANGE(__FUNCTION__); PROFILE_RANGE(__FUNCTION__);
int meshPartsRendered = 0; int meshPartsRendered = 0;
@ -2395,7 +2395,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned,
args, locations, skinLocations); args, locations, skinLocations);
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
args, locations, skinLocations, forceRenderSomeMeshes); args, locations, skinLocations, forceRenderMeshes);
GLBATCH(glUseProgram)(0); GLBATCH(glUseProgram)(0);
return meshPartsRendered; return meshPartsRendered;
@ -2403,7 +2403,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args,
Locations* locations, SkinLocations* skinLocations, bool forceRenderSomeMeshes) { Locations* locations, SkinLocations* skinLocations, bool forceRenderMeshes) {
PROFILE_RANGE(__FUNCTION__); PROFILE_RANGE(__FUNCTION__);
auto textureCache = DependencyManager::get<TextureCache>(); auto textureCache = DependencyManager::get<TextureCache>();
@ -2439,21 +2439,14 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
// if we got here, then check to see if this mesh is in view // if we got here, then check to see if this mesh is in view
if (args) { if (args) {
bool shouldRender = true; bool shouldRender = true;
bool forceRender = false;
args->_meshesConsidered++; args->_meshesConsidered++;
if (args->_viewFrustum) { if (args->_viewFrustum) {
// NOTE: This is a hack to address the fact that for avatar meshes, the _calculatedMeshBoxes can be wrong shouldRender = forceRenderMeshes ||
// for some meshes. Those meshes where the mesh's modelTransform is the identity matrix, and will have args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
// incorrectly calculated mesh boxes. In this case, we will ignore the box and assume it's visible.
if (forceRenderSomeMeshes && (geometry.meshes.at(i).modelTransform == glm::mat4())) {
forceRender = true;
}
shouldRender = forceRender || args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
if (shouldRender && !forceRender) { if (shouldRender && !forceRenderMeshes) {
float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter()); float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter());
shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(),
distance); distance);

View file

@ -460,14 +460,14 @@ private:
bool renderCore(float alpha, RenderMode mode, RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args);
int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL,
bool forceRenderSomeMeshes = false); bool forceRenderMeshes = false);
void setupBatchTransform(gpu::Batch& batch); void setupBatchTransform(gpu::Batch& batch);
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned);
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
RenderArgs* args, Locations* locations, SkinLocations* skinLocations, RenderArgs* args, Locations* locations, SkinLocations* skinLocations,
bool forceRenderSomeMeshes = false); bool forceRenderMeshes = false);
static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,

View file

@ -17,12 +17,13 @@
#include <qurlquery.h> #include <qurlquery.h>
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <AccountManager.h> #include <AccountManager.h>
#include "XMLHttpRequestClass.h" #include "XMLHttpRequestClass.h"
#include "ScriptEngine.h" #include "ScriptEngine.h"
const QString METAVERSE_API_URL = "https://metaverse.highfidelity.com/api/"; const QString METAVERSE_API_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/api/";
Q_DECLARE_METATYPE(QByteArray*) Q_DECLARE_METATYPE(QByteArray*)

View file

@ -48,7 +48,7 @@ public:
void rotate(const glm::quat& rotation); void rotate(const glm::quat& rotation);
glm::vec3 size() const { return maximum - minimum; } glm::vec3 size() const { return maximum - minimum; }
float largestDimension () const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); } float largestDimension() const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); }
/// \return new Extents which is original rotated around orign by rotation /// \return new Extents which is original rotated around orign by rotation
Extents getRotated(const glm::quat& rotation) const { Extents getRotated(const glm::quat& rotation) const {

View file

@ -66,7 +66,9 @@ QDataStream& operator>>(QDataStream& in, glm::quat& quaternion) {
} }
// less common utils can be enabled with DEBUG // less common utils can be enabled with DEBUG
#ifdef DEBUG // FIXME, remove the second defined clause once these compile, or remove the
// functions.
#if defined(DEBUG) && defined(FIXED_STREAMS)
std::ostream& operator<<(std::ostream& s, const CollisionInfo& c) { std::ostream& operator<<(std::ostream& s, const CollisionInfo& c) {
s << "{penetration=" << c._penetration s << "{penetration=" << c._penetration