mirror of
https://github.com/overte-org/overte.git
synced 2025-04-24 05:53:29 +02:00
Merge branch 'master' of github.com:Atlante45/hifi
This commit is contained in:
commit
b37fa6f403
45 changed files with 1268 additions and 414 deletions
|
@ -185,22 +185,8 @@ set(EXTERNAL_PROJECT_PREFIX "project")
|
|||
set_property(DIRECTORY PROPERTY EP_PREFIX ${EXTERNAL_PROJECT_PREFIX})
|
||||
setup_externals_binary_dir()
|
||||
|
||||
# setup options to grab external project dependencies
|
||||
option(GET_BULLET "Get Bullet library automatically as external project" 1)
|
||||
option(GET_GLM "Get GLM library automatically as external project" 1)
|
||||
option(GET_GVERB "Get Gverb library automatically as external project" 1)
|
||||
option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1)
|
||||
option(GET_LIBOVR "Get LibOVR library automatically as external project" 1)
|
||||
option(GET_VHACD "Get V-HACD library automatically as external project" 1)
|
||||
option(GET_POLYVOX "Get polyvox library automatically as external project" 1)
|
||||
option(GET_OPENVR "Get OpenVR library automatically as external project" 1)
|
||||
option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1)
|
||||
option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1)
|
||||
option(GET_GLEW "Get GLEW library automatically as external project" 1)
|
||||
|
||||
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
|
||||
|
||||
option(GET_SDL2 "Get SDL2 library automatically as external project" 0)
|
||||
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs("${QT_DIR}/bin")
|
||||
|
|
|
@ -254,10 +254,10 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
// potentially update the max full rate distance for this frame
|
||||
maxAvatarDistanceThisFrame = std::max(maxAvatarDistanceThisFrame, distanceToAvatar);
|
||||
|
||||
if (distanceToAvatar != 0.0f
|
||||
if (distanceToAvatar != 0.0f
|
||||
&& distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID());
|
||||
AvatarDataSequenceNumber lastSeqFromSender = otherNodeData->getLastReceivedSequenceNumber();
|
||||
|
|
30
cmake/externals/faceshift/CMakeLists.txt
vendored
Normal file
30
cmake/externals/faceshift/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
set(EXTERNAL_NAME faceshift)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://hifi-public.s3.amazonaws.com/dependencies/faceshift.zip
|
||||
CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
# URL_MD5 1bdcb8a0b8d5b1ede434cc41efade41d
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Faceshift include directory")
|
||||
|
||||
if (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/Debug/faceshift.lib CACHE FILEPATH "Faceshift libraries")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/Release/faceshift.lib CACHE FILEPATH "Faceshift libraries")
|
||||
elseif (APPLE)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/Debug/libfaceshift.a CACHE FILEPATH "Faceshift libraries")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/Release/libfaceshift.a CACHE FILEPATH "Faceshift libraries")
|
||||
endif()
|
30
cmake/externals/sdl2/CMakeLists.txt
vendored
30
cmake/externals/sdl2/CMakeLists.txt
vendored
|
@ -47,25 +47,13 @@ if (APPLE)
|
|||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/SDL2.framework/Headers CACHE PATH "Location of SDL2 include directory")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${SOURCE_DIR}/SDL2.framework/SDL2 CACHE STRING "Path to SDL2 library")
|
||||
elseif (WIN32)
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/include CACHE PATH "Location of SDL2 include directory")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${SOURCE_DIR}/lib/x86/SDL2.lib CACHE FILEPATH "Path to SDL2 library")
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/lib/x86 CACHE PATH "Location of SDL2 DLL")
|
||||
else ()
|
||||
if (WIN32)
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
set(_ROOT_DIR ${SOURCE_DIR})
|
||||
set(_INCLUDE_DIR ${_ROOT_DIR}/include)
|
||||
set(_LIB_DIR "${SOURCE_DIR}/lib/x86")
|
||||
set(_LIB_EXT "lib")
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of SDL2 DLL")
|
||||
else ()
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
set(_ROOT_DIR ${INSTALL_DIR})
|
||||
set(_INCLUDE_DIR ${_ROOT_DIR}/include/SDL2)
|
||||
|
||||
set(_LIB_DIR ${INSTALL_DIR}/lib)
|
||||
set(_LIB_EXT "so")
|
||||
set(_LIB_PREFIX "lib")
|
||||
endif ()
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${_INCLUDE_DIR} CACHE PATH "Location of SDL2 include directory")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${_LIB_DIR}/${_LIB_PREFIX}SDL2.${_LIB_EXT} CACHE FILEPATH "Path to SDL2 library")
|
||||
endif ()
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/SDL2 CACHE PATH "Location of SDL2 include directory")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${INSTALL_DIR}/lib/libSDL2.so CACHE FILEPATH "Path to SDL2 library")
|
||||
endif ()
|
||||
|
|
36
cmake/externals/sixense/CMakeLists.txt
vendored
36
cmake/externals/sixense/CMakeLists.txt
vendored
|
@ -1,30 +1,20 @@
|
|||
include(ExternalProject)
|
||||
include(SelectLibraryConfigurations)
|
||||
|
||||
set(EXTERNAL_NAME Sixense)
|
||||
set(EXTERNAL_NAME sixense)
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL ./SixenseSDK_062612.zip
|
||||
URL_MD5 10cc8dc470d2ac1244a88cf04bc549cc
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip
|
||||
URL_MD5 752a3901f334124e9cffc2ba4136ef7d
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
find_library(SIXENSE_LIBRARY_RELEASE lib/osx_x64/release_dll/libsixense_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
find_library(SIXENSE_LIBRARY_DEBUG lib/osx_x64/debug_dll/libsixensed_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
elseif (UNIX)
|
||||
find_library(SIXENSE_LIBRARY_RELEASE lib/linux_x64/release/libsixense_x64.so HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
# find_library(SIXENSE_LIBRARY_DEBUG lib/linux_x64/debug/libsixensed_x64.so HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
elseif (WIN32)
|
||||
endif ()
|
||||
|
||||
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
|
@ -39,22 +29,18 @@ if (WIN32)
|
|||
set(ARCH_DIR "Win32")
|
||||
set(ARCH_SUFFIX "")
|
||||
endif()
|
||||
|
||||
# FIXME need to account for different architectures
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${SOURCE_DIR}/lib/${ARCH_DIR}/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL)
|
||||
add_paths_to_fixup_libs(${SOURCE_DIR}/bin/win32)
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${SOURCE_DIR}/lib/${ARCH_DIR}/VS2013/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL)
|
||||
add_paths_to_fixup_libs("${SOURCE_DIR}/bin/${ARCH_DIR}/VS2013/release_dll")
|
||||
|
||||
elseif(APPLE)
|
||||
|
||||
# FIXME need to account for different architectures
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx_x64/release_dll/libsixense_x64.dylib CACHE TYPE INTERNAL)
|
||||
add_paths_to_fixup_libs(${SOURCE_DIR}/bin/osx32)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx_x64/release_dll/libsixense_x64.dylib CACHE TYPE INTERNAL)
|
||||
|
||||
elseif(NOT ANDROID)
|
||||
|
||||
# FIXME need to account for different architectures
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux_x64/release/libsixense_x64.so CACHE TYPE INTERNAL)
|
||||
add_paths_to_fixup_libs(${SOURCE_DIR}/bin/linux32)
|
||||
|
||||
# FIXME need to account for different architectures
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux_x64/release/libsixense_x64.so CACHE TYPE INTERNAL)
|
||||
|
||||
endif()
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS)
|
|||
string(TOUPPER ${_PROJ_NAME} _PROJ_NAME_UPPER)
|
||||
|
||||
# has the user told us they specific don't want this as an external project?
|
||||
if (GET_${_PROJ_NAME_UPPER})
|
||||
if (NOT USE_LOCAL_${_PROJ_NAME_UPPER})
|
||||
# have we already detected we can't have this as external project on this OS?
|
||||
if (NOT DEFINED ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT OR ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT)
|
||||
# have we already setup the target?
|
||||
|
|
14
cmake/macros/TargetFaceshift.cmake
Normal file
14
cmake/macros/TargetFaceshift.cmake
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Created by Bradley Austin Davis on 2015/10/10
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_FACESHIFT)
|
||||
add_dependency_external_projects(faceshift)
|
||||
find_package(Faceshift REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${FACESHIFT_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${FACESHIFT_LIBRARIES})
|
||||
add_definitions(-DHAVE_FACESHIFT)
|
||||
endmacro()
|
14
cmake/macros/TargetSDL2.cmake
Normal file
14
cmake/macros/TargetSDL2.cmake
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Created by Bradley Austin Davis on 2015/10/10
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_SDL2)
|
||||
add_dependency_external_projects(sdl2)
|
||||
find_package(SDL2 REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SDL2_INCLUDE_DIR})
|
||||
target_link_libraries(${TARGET_NAME} ${SDL2_LIBRARY})
|
||||
add_definitions(-DHAVE_SDL2)
|
||||
endmacro()
|
14
cmake/macros/TargetSixense.cmake
Normal file
14
cmake/macros/TargetSixense.cmake
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Created by Bradley Austin Davis on 2015/10/10
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_SIXENSE)
|
||||
add_dependency_external_projects(sixense)
|
||||
find_package(Sixense REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES})
|
||||
add_definitions(-DHAVE_SIXENSE)
|
||||
endmacro()
|
|
@ -18,32 +18,9 @@
|
|||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("faceshift")
|
||||
|
||||
find_path(FACESHIFT_INCLUDE_DIRS fsbinarystream.h PATH_SUFFIXES include HINTS ${FACESHIFT_SEARCH_DIRS})
|
||||
|
||||
if (APPLE)
|
||||
set(ARCH_DIR "MacOS")
|
||||
elseif (UNIX)
|
||||
set(ARCH_DIR "UNIX")
|
||||
elseif (WIN32)
|
||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(ARCH_DIR "x64")
|
||||
else()
|
||||
set(ARCH_DIR "Win32")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
find_library(FACESHIFT_LIBRARY_RELEASE NAME faceshift PATH_SUFFIXES lib/${ARCH_DIR} HINTS ${FACESHIFT_SEARCH_DIRS})
|
||||
find_library(FACESHIFT_LIBRARY_DEBUG NAME faceshiftd PATH_SUFFIXES lib/${ARCH_DIR} HINTS ${FACESHIFT_SEARCH_DIRS})
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
select_library_configurations(FACESHIFT)
|
||||
|
||||
set(FACESHIFT_LIBRARIES ${FACESHIFT_LIBRARY})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Faceshift DEFAULT_MSG FACESHIFT_INCLUDE_DIRS FACESHIFT_LIBRARIES)
|
||||
|
||||
mark_as_advanced(FACESHIFT_INCLUDE_DIRS FACESHIFT_LIBRARIES FACESHIFT_SEARCH_DIRS)
|
|
@ -18,49 +18,6 @@
|
|||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("sixense")
|
||||
|
||||
find_path(SIXENSE_INCLUDE_DIRS sixense.h PATH_SUFFIXES include HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
|
||||
if (APPLE)
|
||||
find_library(SIXENSE_LIBRARY_RELEASE lib/osx_x64/release_dll/libsixense_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
find_library(SIXENSE_LIBRARY_DEBUG lib/osx_x64/debug_dll/libsixensed_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
elseif (UNIX)
|
||||
find_library(SIXENSE_LIBRARY_RELEASE lib/linux_x64/release/libsixense_x64.so HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
# find_library(SIXENSE_LIBRARY_DEBUG lib/linux_x64/debug/libsixensed_x64.so HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
elseif (WIN32)
|
||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(ARCH_DIR "x64")
|
||||
set(ARCH_SUFFIX "_x64")
|
||||
else()
|
||||
set(ARCH_DIR "Win32")
|
||||
set(ARCH_SUFFIX "")
|
||||
endif()
|
||||
|
||||
find_library(SIXENSE_LIBRARY_RELEASE "lib/${ARCH_DIR}/release_dll/sixense${ARCH_SUFFIX}.lib" HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
find_library(SIXENSE_LIBRARY_DEBUG "lib/${ARCH_DIR}/debug_dll/sixensed.lib" HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
|
||||
find_path(SIXENSE_DEBUG_DLL_PATH "sixensed${ARCH_SUFFIX}.dll" PATH_SUFFIXES bin/${ARCH_DIR}/debug_dll HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
find_path(SIXENSE_RELEASE_DLL_PATH "sixense${ARCH_SUFFIX}.dll" PATH_SUFFIXES bin/${ARCH_DIR}/release_dll HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
find_path(SIXENSE_DEVICE_DLL_PATH DeviceDLL.dll PATH_SUFFIXES samples/${ARCH_DIR}/sixense_simple3d HINTS ${SIXENSE_SEARCH_DIRS})
|
||||
endif ()
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
select_library_configurations(SIXENSE)
|
||||
|
||||
set(SIXENSE_REQUIREMENTS SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES)
|
||||
if (WIN32)
|
||||
list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH SIXENSE_DEVICE_DLL_PATH)
|
||||
endif ()
|
||||
|
||||
set(SIXENSE_LIBRARIES "${SIXENSE_LIBRARY}")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Sixense DEFAULT_MSG ${SIXENSE_REQUIREMENTS})
|
||||
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs(${SIXENSE_DEBUG_DLL_PATH} ${SIXENSE_RELEASE_DLL_PATH} ${SIXENSE_DEVICE_DLL_PATH})
|
||||
endif ()
|
||||
|
||||
find_package_handle_standard_args(Sixense DEFAULT_MSG SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES)
|
||||
mark_as_advanced(SIXENSE_LIBRARIES SIXENSE_INCLUDE_DIRS SIXENSE_SEARCH_DIRS)
|
||||
|
|
23
examples/baseball/audio/assets.txt
Normal file
23
examples/baseball/audio/assets.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
crowd-boos.wav
|
||||
atp:c632c92b166ade60aa16b23ff1dfdf712856caeb83bd9311980b2d5edac821af.wav
|
||||
|
||||
crowd-cheers-organ.wav
|
||||
atp:b8044401a846ed29f881a0b9b80cf1ba41f26327180c28fc9c70d144f9b70045.wav
|
||||
|
||||
crowd-medium.wav
|
||||
atp:0821bf2ac60dd2f356dfdd948e8bb89c23984dc3584612f6c815765154f02cae.wav
|
||||
|
||||
baseball-hitting-bat-1.wav
|
||||
atp:6f0b691a0c9c9ece6557d97fe242b1faec4020fe26efc9c17327993b513c5fe5.wav
|
||||
|
||||
baseball-hitting-bat-set-1.wav
|
||||
atp:5be5806205158ebdc5c3623ceb7ae73315028b51ffeae24292aff7042e3fa6a9.wav
|
||||
|
||||
baseball-hitting-bat-set-2.wav
|
||||
atp:e68661374e2145c480809c26134782aad11e0de456c7802170c7abccc4028873.wav
|
||||
|
||||
baseball-hitting-bat-set-3.wav
|
||||
atp:787e3c9af17dd3929527787176ede83d6806260e63ddd5a4cef48cd22e32c6f7.wav
|
||||
|
||||
baseball-hitting-bat-set-4.wav
|
||||
atp:fc65383431a6238c7a4749f0f6f061f75a604ed5e17d775ab1b2955609e67ebb.wav
|
8
examples/baseball/audio/attribution.txt
Normal file
8
examples/baseball/audio/attribution.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Baseball bat hitting sounds
|
||||
https://www.freesound.org/people/SocializedArtist45/sounds/266595/
|
||||
https://www.freesound.org/people/CGEffex/sounds/93136/
|
||||
|
||||
Crowd Sounds
|
||||
http://freesound.org/people/AshFox/sounds/191925/
|
||||
http://freesound.org/people/AshFox/sounds/191928/
|
||||
http://freesound.org/people/AshFox/sounds/191929/
|
165
examples/baseball/line.js
Normal file
165
examples/baseball/line.js
Normal file
|
@ -0,0 +1,165 @@
|
|||
function info(message) {
|
||||
print("[INFO] " + message);
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
print("[ERROR] " + message);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PolyLine
|
||||
*****************************************************************************/
|
||||
var LINE_DIMENSIONS = { x: 2000, y: 2000, z: 2000 };
|
||||
var MAX_LINE_LENGTH = 40; // This must be 2 or greater;
|
||||
var PolyLine = function(position, color, defaultStrokeWidth) {
|
||||
//info("Creating polyline");
|
||||
//Vec3.print("New line at", position);
|
||||
this.position = position;
|
||||
this.color = color;
|
||||
this.defaultStrokeWidth = 0.10;
|
||||
this.points = [
|
||||
{ x: 0, y: 0, z: 0 },
|
||||
];
|
||||
this.strokeWidths = [
|
||||
this.defaultStrokeWidth,
|
||||
]
|
||||
this.normals = [
|
||||
{ x: 1, y: 0, z: 0 },
|
||||
]
|
||||
this.entityID = Entities.addEntity({
|
||||
type: "PolyLine",
|
||||
position: position,
|
||||
linePoints: this.points,
|
||||
normals: this.normals,
|
||||
strokeWidths: this.strokeWidths,
|
||||
dimensions: LINE_DIMENSIONS,
|
||||
color: color,
|
||||
lifetime: 20,
|
||||
});
|
||||
};
|
||||
|
||||
PolyLine.prototype.enqueuePoint = function(position) {
|
||||
if (this.isFull()) {
|
||||
error("Hit max PolyLine size");
|
||||
return;
|
||||
}
|
||||
|
||||
//Vec3.print("pos", position);
|
||||
//info("Number of points: " + this.points.length);
|
||||
|
||||
position = Vec3.subtract(position, this.position);
|
||||
this.points.push(position);
|
||||
this.normals.push({ x: 1, y: 0, z: 0 });
|
||||
this.strokeWidths.push(this.defaultStrokeWidth);
|
||||
Entities.editEntity(this.entityID, {
|
||||
linePoints: this.points,
|
||||
normals: this.normals,
|
||||
strokeWidths: this.strokeWidths,
|
||||
});
|
||||
};
|
||||
|
||||
PolyLine.prototype.dequeuePoint = function() {
|
||||
if (this.points.length == 0) {
|
||||
error("Hit min PolyLine size");
|
||||
return;
|
||||
}
|
||||
|
||||
this.points = this.points.slice(1);
|
||||
this.normals = this.normals.slice(1);
|
||||
this.strokeWidths = this.strokeWidths.slice(1);
|
||||
|
||||
Entities.editEntity(this.entityID, {
|
||||
linePoints: this.points,
|
||||
normals: this.normals,
|
||||
strokeWidths: this.strokeWidths,
|
||||
});
|
||||
};
|
||||
|
||||
PolyLine.prototype.getFirstPoint = function() {
|
||||
return Vec3.sum(this.position, this.points[0]);
|
||||
};
|
||||
|
||||
PolyLine.prototype.getLastPoint = function() {
|
||||
return Vec3.sum(this.position, this.points[this.points.length - 1]);
|
||||
};
|
||||
|
||||
PolyLine.prototype.getSize = function() {
|
||||
return this.points.length;
|
||||
}
|
||||
|
||||
PolyLine.prototype.isFull = function() {
|
||||
return this.points.length >= MAX_LINE_LENGTH;
|
||||
};
|
||||
|
||||
PolyLine.prototype.destroy = function() {
|
||||
Entities.deleteEntity(this.entityID);
|
||||
this.points = [];
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* InfiniteLine
|
||||
*****************************************************************************/
|
||||
InfiniteLine = function(position, color) {
|
||||
this.position = position;
|
||||
this.color = color;
|
||||
this.lines = [new PolyLine(position, color)];
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.enqueuePoint = function(position) {
|
||||
var currentLine;
|
||||
|
||||
if (this.lines.length == 0) {
|
||||
currentLine = new PolyLine(position, this.color);
|
||||
this.lines.push(currentLine);
|
||||
} else {
|
||||
currentLine = this.lines[this.lines.length - 1];
|
||||
}
|
||||
|
||||
if (currentLine.isFull()) {
|
||||
//info("Current line is full, creating new line");
|
||||
//Vec3.print("Last line is", currentLine.getLastPoint());
|
||||
//Vec3.print("New line is", position);
|
||||
var newLine = new PolyLine(currentLine.getLastPoint(), this.color);
|
||||
this.lines.push(newLine);
|
||||
currentLine = newLine;
|
||||
}
|
||||
|
||||
currentLine.enqueuePoint(position);
|
||||
|
||||
++this.size;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.dequeuePoint = function() {
|
||||
if (this.lines.length == 0) {
|
||||
error("Trying to dequeue from InfiniteLine when no points are left");
|
||||
return;
|
||||
}
|
||||
|
||||
var lastLine = this.lines[0];
|
||||
lastLine.dequeuePoint();
|
||||
|
||||
if (lastLine.getSize() <= 1) {
|
||||
this.lines = this.lines.slice(1);
|
||||
}
|
||||
|
||||
--this.size;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.getFirstPoint = function() {
|
||||
return this.lines.length > 0 ? this.lines[0].getFirstPoint() : null;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.getLastPoint = function() {
|
||||
return this.lines.length > 0 ? this.lines[lines.length - 1].getLastPoint() : null;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.destroy = function() {
|
||||
for (var i = 0; i < this.lines.length; ++i) {
|
||||
this.lines[i].destroy();
|
||||
}
|
||||
|
||||
this.size = 0;
|
||||
};
|
313
examples/baseball/pitching.js
Normal file
313
examples/baseball/pitching.js
Normal file
|
@ -0,0 +1,313 @@
|
|||
Script.include("line.js");
|
||||
|
||||
var AUDIO = {
|
||||
crowdBoos: [
|
||||
SoundCache.getSound("atp:c632c92b166ade60aa16b23ff1dfdf712856caeb83bd9311980b2d5edac821af.wav", false)
|
||||
],
|
||||
crowdCheers: [
|
||||
SoundCache.getSound("atp:0821bf2ac60dd2f356dfdd948e8bb89c23984dc3584612f6c815765154f02cae.wav", false),
|
||||
SoundCache.getSound("atp:b8044401a846ed29f881a0b9b80cf1ba41f26327180c28fc9c70d144f9b70045.wav", false),
|
||||
],
|
||||
batHit: [
|
||||
SoundCache.getSound("atp:6f0b691a0c9c9ece6557d97fe242b1faec4020fe26efc9c17327993b513c5fe5.wav", false),
|
||||
SoundCache.getSound("atp:5be5806205158ebdc5c3623ceb7ae73315028b51ffeae24292aff7042e3fa6a9.wav", false),
|
||||
SoundCache.getSound("atp:e68661374e2145c480809c26134782aad11e0de456c7802170c7abccc4028873.wav", false),
|
||||
SoundCache.getSound("atp:787e3c9af17dd3929527787176ede83d6806260e63ddd5a4cef48cd22e32c6f7.wav", false),
|
||||
SoundCache.getSound("atp:fc65383431a6238c7a4749f0f6f061f75a604ed5e17d775ab1b2955609e67ebb.wav", false),
|
||||
]
|
||||
}
|
||||
|
||||
var PITCH_THUNK_SOUND_URL = "http://hifi-public.s3.amazonaws.com/sounds/ping_pong_gun/pong_sound.wav";
|
||||
var pitchSound = SoundCache.getSound(PITCH_THUNK_SOUND_URL, false);
|
||||
|
||||
var PITCHING_MACHINE_URL = "atp:87d4879530b698741ecc45f6f31789aac11f7865a2c3bec5fe9b061a182c80d4.fbx";
|
||||
var PITCHING_MACHINE_OUTPUT_OFFSET_PCT = {
|
||||
x: 0.0,
|
||||
y: 0.25,
|
||||
z: -1.05,
|
||||
};
|
||||
var PITCHING_MACHINE_PROPERTIES = {
|
||||
name: "Pitching Machine",
|
||||
type: "Model",
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0.8,
|
||||
z: -18.3,
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
},
|
||||
gravity: {
|
||||
x: 0.0,
|
||||
y: -9.8,
|
||||
z: 0.0
|
||||
},
|
||||
registrationPoint: {
|
||||
x: 0.5,
|
||||
y: 0.5,
|
||||
z: 0.5,
|
||||
},
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 180, 0),
|
||||
modelURL: PITCHING_MACHINE_URL,
|
||||
dimensions: {
|
||||
x: 0.4,
|
||||
y: 0.61,
|
||||
z: 0.39
|
||||
},
|
||||
collisionsWillMove: false,
|
||||
shapeType: "Box",
|
||||
};
|
||||
PITCHING_MACHINE_PROPERTIES.dimensions = Vec3.multiply(2.5, PITCHING_MACHINE_PROPERTIES.dimensions);
|
||||
var DISTANCE_FROM_PLATE = PITCHING_MACHINE_PROPERTIES.position.z;
|
||||
|
||||
var PITCH_RATE = 5000;
|
||||
|
||||
var BASEBALL_MODEL_URL = "atp:7185099f1f650600ca187222573a88200aeb835454bd2f578f12c7fb4fd190fa.fbx";
|
||||
var BASEBALL_MIN_SPEED = 2.7;
|
||||
var BASEBALL_MAX_SPEED = 5.7;
|
||||
var BASEBALL_RADIUS = 0.07468;
|
||||
var BASEBALL_PROPERTIES = {
|
||||
name: "Baseball",
|
||||
type: "Model",
|
||||
modelURL: BASEBALL_MODEL_URL,
|
||||
shapeType: "Sphere",
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
dimensions: {
|
||||
x: BASEBALL_RADIUS,
|
||||
y: BASEBALL_RADIUS,
|
||||
z: BASEBALL_RADIUS
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
angularVelocity: {
|
||||
x: 17.0,
|
||||
y: 0,
|
||||
z: -8.0,
|
||||
|
||||
x: 0.0,
|
||||
y: 0,
|
||||
z: 0.0,
|
||||
},
|
||||
angularDamping: 0.0,
|
||||
damping: 0.0,
|
||||
restitution: 0.5,
|
||||
friction: 0.0,
|
||||
lifetime: 20,
|
||||
//collisionSoundURL: PITCH_THUNK_SOUND_URL,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: 0,//-9.8,
|
||||
z: 0
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var pitchingMachineID = Entities.addEntity(PITCHING_MACHINE_PROPERTIES);
|
||||
|
||||
var pitchFromPosition = { x: 0, y: 1.0, z: 0 };
|
||||
var pitchDirection = { x: 0, y: 0, z: 1 };
|
||||
|
||||
function shallowCopy(obj) {
|
||||
var copy = {}
|
||||
for (var key in obj) {
|
||||
copy[key] = obj[key];
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
function randomInt(low, high) {
|
||||
return Math.floor(randomFloat(low, high));
|
||||
}
|
||||
|
||||
function randomFloat(low, high) {
|
||||
if (high === undefined) {
|
||||
high = low;
|
||||
low = 0;
|
||||
}
|
||||
return low + Math.random() * (high - low);
|
||||
}
|
||||
|
||||
var ACCELERATION_SPREAD = 10.15;
|
||||
|
||||
function Baseball(position, velocity, ballScale) {
|
||||
var self = this;
|
||||
|
||||
// Setup entity properties
|
||||
var properties = shallowCopy(BASEBALL_PROPERTIES);
|
||||
properties.position = position;
|
||||
properties.velocity = velocity;
|
||||
/*
|
||||
properties.gravity = {
|
||||
x: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
y: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
z: 0.0,
|
||||
};
|
||||
*/
|
||||
properties.dimensions = Vec3.multiply(ballScale, properties.dimensions);
|
||||
|
||||
// Create entity
|
||||
this.entityID = Entities.addEntity(properties);
|
||||
this.trail = null;
|
||||
this.onHit = function() { return true; };
|
||||
this.hasBeenHit = false;
|
||||
|
||||
this.boundCollisionCallback = function(a, b, c) { self.collisionCallback.call(self, a, b, c); };
|
||||
Script.addEventHandler(this.entityID, "collisionWithEntity", this.boundCollisionCallback);
|
||||
/*
|
||||
if (false && Math.random() < 0.5) {
|
||||
for (var i = 0; i < 50; i++) {
|
||||
Script.setTimeout(function() {
|
||||
Entities.editEntity(entityID, {
|
||||
gravity: {
|
||||
x: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
y: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
z: 0.0,
|
||||
}
|
||||
})
|
||||
}, i * 100);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Baseball.prototype = {
|
||||
collisionCallback: function(entityA, entityB, collision) {
|
||||
var self = this;
|
||||
|
||||
this.hasBeenHit = true;
|
||||
var properties = Entities.getEntityProperties(this.entityID, ['position', 'velocity']);
|
||||
this.trail = new InfiniteLine(properties.position, { red: 255, green: 128, blue: 89 });
|
||||
var lastPosition = properties.position;
|
||||
//Vec3.print("Velocity", properties.velocity);
|
||||
//Vec3.print("VelocityChange", collision.velocityChange);
|
||||
var speed = Vec3.length(properties.velocity);
|
||||
playRandomSound(AUDIO.batHit, {
|
||||
position: properties.position,
|
||||
volume: 2.0
|
||||
});
|
||||
var sounds = null;
|
||||
if (speed < 5.0) {
|
||||
sounds = AUDIO.crowdBoos;
|
||||
} else {
|
||||
sounds = AUDIO.crowdCheers;
|
||||
}
|
||||
var self = this;
|
||||
this.trailInterval = Script.setInterval(function() {
|
||||
var properties = Entities.getEntityProperties(self.entityID, ['position']);
|
||||
if (Vec3.distance(properties.position, lastPosition)) {
|
||||
self.trail.enqueuePoint(properties.position);
|
||||
lastPosition = properties.position;
|
||||
}
|
||||
}, 50);
|
||||
Entities.editEntity(self.entityID, {
|
||||
velocity: Vec3.multiply(2, properties.velocity),
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -9.8,
|
||||
z: 0
|
||||
}
|
||||
});
|
||||
|
||||
var removeHandler = this.onHit(entityB, collision);
|
||||
if (removeHandler) {
|
||||
Script.removeEventHandler(self.entityID, "collisionWithEntity", self.boundCollisionCallback);
|
||||
}
|
||||
},
|
||||
cleanupTrail: function() {
|
||||
if (this.trail) {
|
||||
Script.clearInterval(this.trailInterval);
|
||||
this.trailInterval = null;
|
||||
|
||||
this.trail.destroy();
|
||||
this.trail = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function playRandomSound(sounds, options) {
|
||||
if (options === undefined) {
|
||||
options = {
|
||||
volume: 1.0,
|
||||
position: MyAvatar.position,
|
||||
}
|
||||
}
|
||||
Audio.playSound(sounds[randomInt(sounds.length)], options);
|
||||
}
|
||||
|
||||
var lastTrail = null;
|
||||
|
||||
|
||||
function vec3Mult(a, b) {
|
||||
return {
|
||||
x: a.x * b.x,
|
||||
y: a.y * b.y,
|
||||
z: a.z * b.z,
|
||||
};
|
||||
}
|
||||
|
||||
var lastBall = null;
|
||||
var injector = null;
|
||||
|
||||
function pitchBall() {
|
||||
if (lastBall) {
|
||||
lastBall.cleanupTrail();
|
||||
}
|
||||
|
||||
var machineProperties = Entities.getEntityProperties(pitchingMachineID, ["dimensions", "position", "rotation"]);
|
||||
var pitchFromPositionBase = machineProperties.position;
|
||||
var pitchFromOffset = vec3Mult(machineProperties.dimensions, PITCHING_MACHINE_OUTPUT_OFFSET_PCT);
|
||||
pitchFromOffset = Vec3.multiplyQbyV(machineProperties.rotation, pitchFromOffset);
|
||||
var pitchFromPosition = Vec3.sum(pitchFromPositionBase, pitchFromOffset);
|
||||
var pitchDirection = Quat.getFront(machineProperties.rotation);
|
||||
var ballScale = machineProperties.dimensions.x / PITCHING_MACHINE_PROPERTIES.dimensions.x;
|
||||
print("Creating baseball");
|
||||
|
||||
var speed = randomFloat(BASEBALL_MIN_SPEED, BASEBALL_MAX_SPEED)
|
||||
var timeToPassPlate = (DISTANCE_FROM_PLATE + 1.0) / speed;
|
||||
|
||||
var baseball = new Baseball(pitchFromPosition, Vec3.multiply(speed, pitchDirection), ballScale);
|
||||
lastBall = baseball;
|
||||
|
||||
baseball.onHit = function(entityB, collision) {
|
||||
var properties = Entities.getEntityProperties(entityB, ["name"]);
|
||||
var name = properties.name;
|
||||
print("Hit: " + name);
|
||||
if (name == "backstop") {
|
||||
print("STRIKE");
|
||||
} else if (name == "bat") {
|
||||
print("HIT");
|
||||
Script.setTimeout(function() {
|
||||
playRandomSound(sounds, {
|
||||
position: { x: 0 ,y: 0, z: 0 },
|
||||
volume: 1.0,
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
//Script.clearTimeout(strikeTimeout);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!injector) {
|
||||
injector = Audio.playSound(pitchSound, {
|
||||
position: pitchFromPosition,
|
||||
volume: 1.0
|
||||
});
|
||||
} else {
|
||||
injector.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
Entities.deleteEntity(pitchingMachineID);
|
||||
})
|
||||
|
||||
Script.setInterval(pitchBall, PITCH_RATE);
|
||||
|
||||
|
||||
|
||||
|
0
examples/baseballEntityScript.js
Normal file
0
examples/baseballEntityScript.js
Normal file
|
@ -55,6 +55,7 @@ var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held
|
|||
var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected
|
||||
var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things
|
||||
var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object
|
||||
var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -404,8 +405,9 @@ function MyController(hand, triggerAction) {
|
|||
|
||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation",
|
||||
"gravity", "ignoreForCollisions"]);
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity",
|
||||
"ignoreForCollisions",
|
||||
"collisionsWillMove"]);
|
||||
var now = Date.now();
|
||||
|
||||
// add the action and initialize some variables
|
||||
|
@ -549,8 +551,14 @@ function MyController(hand, triggerAction) {
|
|||
this.lineOff();
|
||||
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity,
|
||||
["position", "rotation", "gravity", "ignoreForCollisions"]);
|
||||
["position", "rotation", "gravity",
|
||||
"ignoreForCollisions", "collisionsWillMove"]);
|
||||
this.activateEntity(this.grabbedEntity, grabbedProperties);
|
||||
if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) {
|
||||
Entities.editEntity(this.grabbedEntity, {
|
||||
collisionsWillMove: false
|
||||
});
|
||||
}
|
||||
|
||||
var handRotation = this.getHandRotation();
|
||||
var handPosition = this.getHandPosition();
|
||||
|
@ -579,7 +587,8 @@ function MyController(hand, triggerAction) {
|
|||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||
relativePosition: this.offsetPosition,
|
||||
relativeRotation: this.offsetRotation,
|
||||
ttl: ACTION_TTL
|
||||
ttl: ACTION_TTL,
|
||||
kinematic: NEAR_GRABBING_KINEMATIC
|
||||
});
|
||||
if (this.actionID === NULL_ACTION_ID) {
|
||||
this.actionID = null;
|
||||
|
@ -631,7 +640,8 @@ function MyController(hand, triggerAction) {
|
|||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||
relativePosition: this.offsetPosition,
|
||||
relativeRotation: this.offsetRotation,
|
||||
ttl: ACTION_TTL
|
||||
ttl: ACTION_TTL,
|
||||
kinematic: NEAR_GRABBING_KINEMATIC
|
||||
});
|
||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||
}
|
||||
|
@ -828,6 +838,7 @@ function MyController(hand, triggerAction) {
|
|||
if (data["refCount"] == 1) {
|
||||
data["gravity"] = grabbedProperties.gravity;
|
||||
data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions;
|
||||
data["collisionsWillMove"] = grabbedProperties.collisionsWillMove;
|
||||
var whileHeldProperties = {gravity: {x:0, y:0, z:0}};
|
||||
if (invertSolidWhileHeld) {
|
||||
whileHeldProperties["ignoreForCollisions"] = ! grabbedProperties.ignoreForCollisions;
|
||||
|
@ -845,7 +856,8 @@ function MyController(hand, triggerAction) {
|
|||
if (data["refCount"] < 1) {
|
||||
Entities.editEntity(entityID, {
|
||||
gravity: data["gravity"],
|
||||
ignoreForCollisions: data["ignoreForCollisions"]
|
||||
ignoreForCollisions: data["ignoreForCollisions"],
|
||||
collisionsWillMove: data["collisionsWillMove"]
|
||||
});
|
||||
data = null;
|
||||
}
|
||||
|
|
323
examples/map.js~
Normal file
323
examples/map.js~
Normal file
|
@ -0,0 +1,323 @@
|
|||
Script.include("entityManager.js");
|
||||
Script.include("overlayManager.js");
|
||||
|
||||
|
||||
// Poll for nearby map data
|
||||
|
||||
var entityManager = new EntityManager();
|
||||
|
||||
// From http://evanw.github.io/lightgl.js/docs/raytracer.html
|
||||
function raySphereIntersection(origin, ray, center, radius) {
|
||||
var offset = Vec3.subtract(origin, center);
|
||||
var a = Vec3.dot(ray, ray);
|
||||
// var a = ray.dot(ray);
|
||||
var b = 2 * Vec3.dot(ray, offset);
|
||||
// var b = 2 * ray.dot(offset);
|
||||
var c = Vec3.dot(offset, offset) - radius * radius;
|
||||
// var c = offset.dot(offset) - radius * radius;
|
||||
var discriminant = b * b - 4 * a * c;
|
||||
|
||||
if (discriminant > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
Map = function(data) {
|
||||
var visible = false;
|
||||
|
||||
var ROOT_OFFSET = Vec3.multiply(0.3, Quat.getFront(MyAvatar.orientation));
|
||||
var ROOT_POSITION = Vec3.sum(MyAvatar.position, ROOT_OFFSET);
|
||||
|
||||
var ROOT_SCALE = 0.0005;
|
||||
|
||||
// Create object in objectManager
|
||||
var rootObject = entityManager.addBare();
|
||||
var position = ROOT_POSITION;
|
||||
rootObject.position = ROOT_POSITION;
|
||||
rootObject.scale = ROOT_SCALE
|
||||
Vec3.print("Position:", position);
|
||||
|
||||
// Search for all nearby objects that have the userData "mapped"
|
||||
// TODO Update to use the zone's bounds
|
||||
var entities = Entities.findEntities(MyAvatar.position, 32000);
|
||||
var mappedEntities = [];
|
||||
var minCorner = {
|
||||
x: 4294967295,
|
||||
y: 4294967295,
|
||||
z: 4294967295,
|
||||
};
|
||||
var maxCorner = {
|
||||
x: -4294967295,
|
||||
y: -4294967295,
|
||||
z: -4294967295,
|
||||
};
|
||||
|
||||
for (var i = 0; i < entities.length; ++i) {
|
||||
var entityID = entities[i];
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
if (properties.userData == "mapped" || properties.userData == "tracked") {
|
||||
|
||||
print("Found: ", properties.name);
|
||||
|
||||
minCorner.x = Math.min(minCorner.x, properties.position.x - (properties.dimensions.x / 2));
|
||||
minCorner.y = Math.min(minCorner.y, properties.position.y - (properties.dimensions.y / 2));
|
||||
minCorner.z = Math.min(minCorner.z, properties.position.z - (properties.dimensions.z / 2));
|
||||
|
||||
maxCorner.x = Math.max(maxCorner.x, properties.position.x - (properties.dimensions.x / 2));
|
||||
maxCorner.y = Math.max(maxCorner.y, properties.position.y - (properties.dimensions.y / 2));
|
||||
maxCorner.z = Math.max(maxCorner.z, properties.position.z - (properties.dimensions.z / 2));
|
||||
|
||||
}
|
||||
// if (properties.userData == "mapped") {
|
||||
// properties.visible = false;
|
||||
// var entity = entityManager.add(properties.type, properties);
|
||||
// mappedEntities.push(entity);
|
||||
// } else if (properties.userData == "tracked") {
|
||||
// // TODO implement tracking of objects
|
||||
// }
|
||||
}
|
||||
|
||||
var dimensions = {
|
||||
x: maxCorner.x - minCorner.x,
|
||||
y: maxCorner.y - minCorner.y,
|
||||
z: maxCorner.z - minCorner.z,
|
||||
};
|
||||
Vec3.print("dims", dimensions);
|
||||
|
||||
var center = {
|
||||
x: minCorner.x + (dimensions.x / 2),
|
||||
y: minCorner.y + (dimensions.y / 2),
|
||||
z: minCorner.z + (dimensions.z / 2),
|
||||
};
|
||||
Vec3.print("center", center);
|
||||
|
||||
var trackedEntities = [];
|
||||
var waypointEntities = [];
|
||||
for (var i = 0; i < entities.length; ++i) {
|
||||
var entityID = entities[i];
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
var mapData = null;
|
||||
try {
|
||||
var data = JSON.parse(properties.userData.replace(/(\r\n|\n|\r)/gm,""));
|
||||
mapData = data.mapData;
|
||||
} catch (e) {
|
||||
print("Caught: ", properties.name);
|
||||
}
|
||||
|
||||
if (mapData) {
|
||||
print("Creating copy of", properties.name);
|
||||
properties.name += " (COPY)";
|
||||
properties.userData = "";
|
||||
properties.visible = true;
|
||||
var position = properties.position;
|
||||
properties.position = Vec3.subtract(properties.position, center);
|
||||
properties.position = Vec3.multiply(properties.position, ROOT_SCALE);
|
||||
var extra = { };
|
||||
|
||||
if (mapData.track) {
|
||||
extra.trackingEntityID= entityID;
|
||||
trackedEntities.push(entity);
|
||||
rootObject.addChild(entity);
|
||||
}
|
||||
if (mapData.waypoint) {
|
||||
print("Waypoint: ", mapData.waypoint.name);
|
||||
// properties.type = "Model";
|
||||
// properties.modelURL = "atp:ca49a13938376b3eb68d7b2b9189afb3f580c07b6950ea9e65b5260787204145.fbx";
|
||||
extra.waypoint = mapData.waypoint;
|
||||
extra.waypoint.position = position;
|
||||
}
|
||||
|
||||
var entity = entityManager.add(properties.type, properties);
|
||||
entity.__extra__ = extra;
|
||||
if (mapData.waypoint) {
|
||||
waypointEntities.push(entity);
|
||||
}
|
||||
mappedEntities.push(entity);
|
||||
|
||||
rootObject.addChild(entity);
|
||||
|
||||
} else {
|
||||
// print("Not creating copy of", properties.name);
|
||||
}
|
||||
}
|
||||
|
||||
var avatarArrowEntity = entityManager.add("Model", {
|
||||
name: "You Are Here",
|
||||
modelURL: "atp:ce4f0c4e491e40b73d28f2646da4f676fe9ea364cf5f1bf5615522ef6acfd80e.fbx",
|
||||
position: Vec3.multiply(Vec3.subtract(MyAvatar.position, center), ROOT_SCALE),
|
||||
dimensions: { x: 30, y: 100, z: 100 },
|
||||
});
|
||||
rootObject.addChild(avatarArrowEntity);
|
||||
|
||||
this.isVisible = function() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
function mousePressEvent(event) {
|
||||
// Entities.setZonesArePickable(false);
|
||||
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
for (var i = 0; i < waypointEntities.length; ++i) {
|
||||
var entity = waypointEntities[i];
|
||||
print("Checkit for hit", entity.__extra__.waypoint.name);
|
||||
var result = raySphereIntersection(pickRay.origin, pickRay.direction, entity.worldPosition, 0.1);//entity.worldScale);
|
||||
if (result) {
|
||||
print("Pressed entity: ", entity.id);
|
||||
print("Pressed waypoint: ", entity.__extra__.waypoint.name);
|
||||
print("Teleporting...");
|
||||
MyAvatar.position = entity.__extra__.waypoint.position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// var result = Entities.findRayIntersection(pickRay, false);
|
||||
// if (result.intersects) {
|
||||
// var entity = entityManager.get(result.entityID);
|
||||
// if (entity) {
|
||||
// print("Pressed entity: ", entity.id);
|
||||
// }
|
||||
// if (entity && entity.__extra__.waypoint) {
|
||||
// print("Pressed waypoint: ", entity.__extra__.waypoint.name);
|
||||
// print("Teleporting...");
|
||||
// MyAvatar.position = entity.__extra__.waypoint.position;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Entities.setZonesArePickable(true);
|
||||
};
|
||||
|
||||
var time = 0;
|
||||
Script.update.connect(function(dt) {
|
||||
time += dt;
|
||||
// Update tracked entities
|
||||
for (var i = 0; i < trackedEntities.length; ++i) {
|
||||
entity = trackedEntities[i];
|
||||
var entityID = entity.__extra__.trackingEntityID;
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
properties.position = Vec3.subtract(properties.position, center);
|
||||
properties.position = Vec3.multiply(properties.position, ROOT_SCALE);
|
||||
entity.position = properties.position;
|
||||
}
|
||||
|
||||
|
||||
var position = Vec3.subtract(MyAvatar.position, center)
|
||||
position.y += 60 + (Math.sin(time) * 10);
|
||||
position = Vec3.multiply(position, ROOT_SCALE);
|
||||
avatarArrowEntity.position = position;
|
||||
// Vec3.print("Position:", avatarArrowEntity.position);
|
||||
|
||||
// rootObject.position = Vec3.sum(position, { x: 0, y: Math.sin(time) / 30, z: 0 });
|
||||
//var ROOT_OFFSET = Vec3.multiply(0.3, Quat.getFront(MyAvatar.orientation));
|
||||
//var ROOT_POSITION = Vec3.sum(MyAvatar.position, ROOT_OFFSET);
|
||||
// position = ROOT_POSITION;
|
||||
rootObject.position = ROOT_POSITION;
|
||||
entityManager.update();
|
||||
|
||||
// Update waypoint highlights
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
for (var i = 0; i < waypointEntities.length; ++i) {
|
||||
var entity = waypointEntities[i];
|
||||
print("Checkit for hit", entity.__extra__.waypoint.name);
|
||||
var result = raySphereIntersection(pickRay.origin, pickRay.direction, entity.worldPosition, 0.1);//entity.worldScale);
|
||||
if (result) {
|
||||
print("Pressed entity: ", entity.id);
|
||||
print("Pressed waypoint: ", entity.__extra__.waypoint.name);
|
||||
print("Teleporting...");
|
||||
MyAvatar.position = entity.__extra__.waypoint.position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function setVisible(newValue) {
|
||||
if (visible != newValue) {
|
||||
visible = newValue;
|
||||
|
||||
if (visible) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.show = function() {
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
this.hide = function() {
|
||||
setVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
var map = null;
|
||||
map = Map(mapData);
|
||||
|
||||
// On press key
|
||||
Controller.keyPressEvent.connect(function(event) {
|
||||
if (event.text == "m") {
|
||||
if (!map) {
|
||||
map = Map(mapData);
|
||||
}
|
||||
|
||||
map.show();
|
||||
print("MAP!");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var mapData = {
|
||||
config: {
|
||||
// World dimensions that the minimap maps to
|
||||
worldDimensions: {
|
||||
x: 10.0,
|
||||
y: 10.0,
|
||||
z: 10.0,
|
||||
},
|
||||
// The center of the map should map to this location in the center of the area
|
||||
worldCenter: {
|
||||
x: 5.0,
|
||||
y: 5.0,
|
||||
z: 5.0,
|
||||
},
|
||||
// Map dimensions
|
||||
mapDimensions: {
|
||||
x: 10.0,
|
||||
y: 10.0,
|
||||
z: 10.0,
|
||||
},
|
||||
|
||||
// Can this be automated? Tag entities that should be included? Store in UserData?
|
||||
objects: [
|
||||
{
|
||||
type: "Model",
|
||||
modelURL: "https://hifi-public.s3.amazonaws.com/ozan/sets/huffman_set/huffman_set.fbx",
|
||||
},
|
||||
],
|
||||
},
|
||||
waypoints: [
|
||||
{
|
||||
name: "Forest's Edge",
|
||||
position: {
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
// entityManager = new OverlayManager();
|
||||
// entityManager = new EntityManager();
|
||||
//
|
||||
// var rootEntity = entityManager.addBare();
|
||||
//
|
||||
// var time = 0;
|
||||
//
|
||||
//
|
||||
// rootEntity.scale = 0.1;
|
||||
// Script.include("sfData.js");
|
||||
// rootEntity.addChild(entity);
|
||||
entityManager.update();
|
|
@ -47,6 +47,7 @@
|
|||
if (this.painting) {
|
||||
return;
|
||||
}
|
||||
this.whichHand = this.hand;
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
this.getHandPosition = MyAvatar.getRightPalmPosition;
|
||||
this.getHandRotation = MyAvatar.getRightPalmRotation;
|
||||
|
@ -183,6 +184,9 @@
|
|||
},
|
||||
|
||||
releaseGrab: function() {
|
||||
if(this.hand !== this.whichHand) {
|
||||
return;
|
||||
}
|
||||
this.stopPainting();
|
||||
|
||||
},
|
||||
|
@ -241,10 +245,8 @@
|
|||
Overlays.deleteOverlay(this.laserPointer);
|
||||
// this.eraseBoard();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new Whiteboard();
|
||||
});
|
|
@ -16,186 +16,199 @@
|
|||
|
||||
Script.include("../../libraries/utils.js");
|
||||
var scriptURL = Script.resolvePath("whiteboardEntityScript.js");
|
||||
var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/whiteboard.fbx";
|
||||
|
||||
var colorIndicatorBorderModelURL = "https://s3.amazonaws.com/hifi-public/eric/models/colorIndicatorBorder.fbx";
|
||||
var eraserModelURL = "https://s3.amazonaws.com/hifi-public/eric/models/eraser.fbx";
|
||||
var surfaceModelURL = "https://s3.amazonaws.com/hifi-public/eric/models/boardSurface.fbx";
|
||||
var rotation = Quat.safeEulerAngles(Camera.getOrientation());
|
||||
rotation = Quat.fromPitchYawRollDegrees(0, rotation.y, 0);
|
||||
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(rotation)));
|
||||
center.y += 0.4;
|
||||
|
||||
var whiteboardDimensions, colorIndicatorBoxDimensions, colorIndicatorBox, eraser, blocker;
|
||||
var colorBoxes = [];
|
||||
|
||||
var colors = [
|
||||
hexToRgb("#2F8E84"),
|
||||
hexToRgb("#66CCB3"),
|
||||
hexToRgb("#A43C37"),
|
||||
hexToRgb("#491849"),
|
||||
hexToRgb("#6AB03B"),
|
||||
hexToRgb("#993369"),
|
||||
hexToRgb("#9B47C2")
|
||||
hexToRgb("#000000")
|
||||
];
|
||||
|
||||
//WHITEBOARD
|
||||
var whiteboardDimensions = {
|
||||
x: 2,
|
||||
y: 1.5,
|
||||
z: 0.08
|
||||
};
|
||||
var whiteboard = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: "https://hifi-public.s3.amazonaws.com/ozan/support/for_eric/whiteboard/whiteboard.fbx",
|
||||
name: "whiteboard",
|
||||
shapeType: "box",
|
||||
modelURL: modelURL,
|
||||
name: "whiteboard base",
|
||||
position: center,
|
||||
rotation: rotation,
|
||||
script: scriptURL,
|
||||
dimensions: whiteboardDimensions,
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// COLOR INDICATOR BOX
|
||||
var colorIndicatorDimensions = {
|
||||
x: whiteboardDimensions.x,
|
||||
y: 0.05,
|
||||
z: 0.02
|
||||
var colorIndicatorPosition = {
|
||||
x: center.x,
|
||||
y: center.y,
|
||||
z: center.z
|
||||
};
|
||||
scriptURL = Script.resolvePath("colorIndicatorEntityScript.js");
|
||||
var colorIndicatorPosition = Vec3.sum(center, {
|
||||
x: 0,
|
||||
y: whiteboardDimensions.y / 2 + colorIndicatorDimensions.y / 2,
|
||||
z: 0
|
||||
});
|
||||
var colorIndicatorBox = Entities.addEntity({
|
||||
type: "Box",
|
||||
name: "Color Indicator",
|
||||
color: colors[0],
|
||||
rotation: rotation,
|
||||
colorIndicatorPosition.y += 1.55;
|
||||
colorIndicatorPosition = Vec3.sum(colorIndicatorPosition, Vec3.multiply(-0.1, Quat.getFront(rotation)));
|
||||
var colorIndicatorBorder = Entities.addEntity({
|
||||
type: "Model",
|
||||
position: colorIndicatorPosition,
|
||||
dimensions: colorIndicatorDimensions,
|
||||
script: scriptURL,
|
||||
userData: JSON.stringify({
|
||||
whiteboard: whiteboard
|
||||
})
|
||||
modelURL: colorIndicatorBorderModelURL,
|
||||
rotation: rotation,
|
||||
shapeType: "box"
|
||||
});
|
||||
|
||||
Entities.editEntity(whiteboard, {
|
||||
var surfaceCenter = Vec3.sum(center, Vec3.multiply(-0.1, Quat.getFront(rotation)));
|
||||
surfaceCenter.y += 0.6;
|
||||
var drawingSurface = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: surfaceModelURL,
|
||||
shapeType: "box",
|
||||
name: "whiteboard surface",
|
||||
position: surfaceCenter,
|
||||
script: scriptURL,
|
||||
rotation: rotation,
|
||||
userData: JSON.stringify({
|
||||
color: {
|
||||
currentColor: colors[0]
|
||||
},
|
||||
colorIndicator: colorIndicatorBox
|
||||
})
|
||||
});
|
||||
|
||||
//COLOR BOXES
|
||||
var direction = Quat.getRight(rotation);
|
||||
var colorBoxPosition = Vec3.subtract(center, Vec3.multiply(direction, whiteboardDimensions.x / 2));
|
||||
var colorBoxes = [];
|
||||
var colorSquareDimensions = {
|
||||
x: (whiteboardDimensions.x / 2) / (colors.length - 1),
|
||||
y: 0.1,
|
||||
z: 0.05
|
||||
};
|
||||
colorBoxPosition.y += whiteboardDimensions.y / 2 + colorIndicatorDimensions.y + colorSquareDimensions.y / 2;
|
||||
var spaceBetweenColorBoxes = Vec3.multiply(direction, colorSquareDimensions.x * 2);
|
||||
var scriptURL = Script.resolvePath("colorSelectorEntityScript.js");
|
||||
for (var i = 0; i < colors.length; i++) {
|
||||
var colorBox = Entities.addEntity({
|
||||
type: "Box",
|
||||
name: "Color Selector",
|
||||
position: colorBoxPosition,
|
||||
dimensions: colorSquareDimensions,
|
||||
rotation: rotation,
|
||||
color: colors[i],
|
||||
script: scriptURL,
|
||||
userData: JSON.stringify({
|
||||
whiteboard: whiteboard,
|
||||
colorIndicator: colorIndicatorBox
|
||||
})
|
||||
});
|
||||
colorBoxes.push(colorBox);
|
||||
colorBoxPosition = Vec3.sum(colorBoxPosition, spaceBetweenColorBoxes);
|
||||
}
|
||||
|
||||
|
||||
// BLACK BOX
|
||||
var blackBoxDimensions = {
|
||||
x: 0.3,
|
||||
y: 0.3,
|
||||
z: 0.01
|
||||
};
|
||||
|
||||
colorBoxPosition = Vec3.subtract(center, Vec3.multiply(direction, whiteboardDimensions.x / 2 + blackBoxDimensions.x / 2 - 0.01));
|
||||
colorBoxPosition.y += 0.3;
|
||||
var fragShaderURL = Script.resolvePath('blackInk.fs?v1' + Math.random());
|
||||
var blackBox = Entities.addEntity({
|
||||
type: 'Box',
|
||||
name: "Black Color",
|
||||
position: colorBoxPosition,
|
||||
dimensions: blackBoxDimensions,
|
||||
rotation: rotation,
|
||||
color: {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 0
|
||||
},
|
||||
script: scriptURL,
|
||||
userData: JSON.stringify({
|
||||
whiteboard: whiteboard,
|
||||
version: 2,
|
||||
ProceduralEntity: {
|
||||
shaderUrl: fragShaderURL
|
||||
}
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
var lightPosition = Vec3.sum(center, Vec3.multiply(-3, Quat.getFront(rotation)));
|
||||
var light = Entities.addEntity({
|
||||
type: 'Light',
|
||||
name: 'whiteboard light',
|
||||
position: lightPosition,
|
||||
dimensions: {x: 10, y: 10, z: 10},
|
||||
intensity: 2,
|
||||
color: {red: 255, green: 255, blue: 255}
|
||||
});
|
||||
|
||||
var eraseBoxDimensions = {
|
||||
x: 0.5,
|
||||
y: 0.1,
|
||||
z: 0.01
|
||||
};
|
||||
|
||||
|
||||
var eraseBoxPosition = Vec3.sum(center, Vec3.multiply(direction, whiteboardDimensions.x / 2 + eraseBoxDimensions.x / 2 + 0.01));
|
||||
eraseBoxPosition.y += 0.3;
|
||||
var eraserPosition = Vec3.sum(center, {x: 0, y: 2.05, z: 0 });
|
||||
eraserPosition = Vec3.sum(eraserPosition, Vec3.multiply(-0.1, rotation));
|
||||
scriptURL = Script.resolvePath("eraseBoardEntityScript.js");
|
||||
var eraseAllText = Entities.addEntity({
|
||||
type: "Text",
|
||||
position: eraseBoxPosition,
|
||||
var eraser = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: eraserModelURL,
|
||||
position: eraserPosition,
|
||||
name: "Eraser",
|
||||
script: scriptURL,
|
||||
rotation: rotation,
|
||||
dimensions: eraseBoxDimensions,
|
||||
backgroundColor: {
|
||||
red: 0,
|
||||
green: 60,
|
||||
blue: 0
|
||||
},
|
||||
textColor: {
|
||||
red: 255,
|
||||
green: 10,
|
||||
blue: 10
|
||||
},
|
||||
text: "ERASE BOARD",
|
||||
lineHeight: 0.07,
|
||||
userData: JSON.stringify({
|
||||
whiteboard: whiteboard
|
||||
whiteboard: drawingSurface
|
||||
})
|
||||
});
|
||||
|
||||
Script.setTimeout(function() {
|
||||
whiteboardDimensions = Entities.getEntityProperties(whiteboard, "naturalDimensions").naturalDimensions;
|
||||
colorIndicatorBorderDimensions = Entities.getEntityProperties(colorIndicatorBorder, "naturalDimensions").naturalDimensions;
|
||||
setUp();
|
||||
}, 2000)
|
||||
|
||||
|
||||
function setUp() {
|
||||
var blockerPosition = Vec3.sum(center, {x: 0, y: -1, z: 0 });
|
||||
blockerPosition = Vec3.sum(blockerPosition, Vec3.multiply(-1, Quat.getFront(rotation)));
|
||||
blocker = Entities.addEntity({
|
||||
type: "Box",
|
||||
rotation: rotation,
|
||||
position: blockerPosition,
|
||||
dimensions: {x: whiteboardDimensions.x, y: 1, z: 0.1},
|
||||
shapeType: "box",
|
||||
visible: false
|
||||
});
|
||||
|
||||
var eraseModelDimensions = Entities.getEntityProperties(eraser, "naturalDimensions").naturalDimensions;
|
||||
Entities.editEntity(eraser, {dimensions: eraseModelDimensions});
|
||||
Entities.editEntity(colorIndicatorBorder, {dimensions: colorIndicatorBorderDimensions});
|
||||
|
||||
scriptURL = Script.resolvePath("colorIndicatorEntityScript.js");
|
||||
var colorIndicatorPosition = Vec3.sum(center, {
|
||||
x: 0,
|
||||
y: whiteboardDimensions.y / 2 + colorIndicatorBorderDimensions.y / 2,
|
||||
z: 0
|
||||
});
|
||||
colorIndicatorPosition = Vec3.sum(colorIndicatorPosition, Vec3.multiply(-.1, Quat.getFront(rotation)));
|
||||
var colorIndicatorBoxDimensions = Vec3.multiply(colorIndicatorBorderDimensions, 0.9);
|
||||
colorIndicatorBox = Entities.addEntity({
|
||||
type: "Box",
|
||||
name: "Color Indicator",
|
||||
color: colors[0],
|
||||
rotation: rotation,
|
||||
position: colorIndicatorPosition,
|
||||
dimensions: colorIndicatorBoxDimensions,
|
||||
script: scriptURL,
|
||||
userData: JSON.stringify({
|
||||
whiteboard: drawingSurface
|
||||
})
|
||||
});
|
||||
|
||||
Entities.editEntity(drawingSurface, {
|
||||
userData: JSON.stringify({
|
||||
color: {
|
||||
currentColor: colors[0]
|
||||
},
|
||||
colorIndicator: colorIndicatorBox
|
||||
})
|
||||
});
|
||||
|
||||
//COLOR BOXES
|
||||
var direction = Quat.getRight(rotation);
|
||||
var colorBoxPosition = Vec3.subtract(center, Vec3.multiply(direction, whiteboardDimensions.x / 2));
|
||||
var colorSquareDimensions = {
|
||||
x: 0.13,
|
||||
y: 0.13,
|
||||
z: 0.002
|
||||
};
|
||||
|
||||
var palleteDepthOffset = -0.07;
|
||||
var palleteHeightOffset = -0.28;
|
||||
|
||||
colorBoxPosition = Vec3.sum(colorBoxPosition, Vec3.multiply(palleteDepthOffset, Quat.getFront(rotation)));
|
||||
colorBoxPosition.y += palleteHeightOffset;
|
||||
var spaceBetweenColorBoxes = Vec3.multiply(direction, colorSquareDimensions.x * 1.76);
|
||||
var palleteXOffset = Vec3.multiply(direction, 0.43);
|
||||
colorBoxPosition = Vec3.sum(colorBoxPosition, palleteXOffset);
|
||||
var scriptURL = Script.resolvePath("colorSelectorEntityScript.js");
|
||||
for (var i = 0; i < colors.length; i++) {
|
||||
var colorBox = Entities.addEntity({
|
||||
type: "Box",
|
||||
name: "Color Selector",
|
||||
position: colorBoxPosition,
|
||||
dimensions: colorSquareDimensions,
|
||||
rotation: rotation,
|
||||
color: colors[i],
|
||||
script: scriptURL,
|
||||
userData: JSON.stringify({
|
||||
whiteboard: drawingSurface,
|
||||
colorIndicator: colorIndicatorBox
|
||||
})
|
||||
});
|
||||
colorBoxes.push(colorBox);
|
||||
colorBoxPosition = Vec3.sum(colorBoxPosition, spaceBetweenColorBoxes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
Entities.deleteEntity(whiteboard);
|
||||
Entities.deleteEntity(eraseAllText);
|
||||
Entities.deleteEntity(blackBox);
|
||||
Entities.deleteEntity(drawingSurface);
|
||||
Entities.deleteEntity(colorIndicatorBorder);
|
||||
Entities.deleteEntity(eraser);
|
||||
Entities.deleteEntity(colorIndicatorBox);
|
||||
Entities.deleteEntity(blocker);
|
||||
Entities.deleteEntity(light);
|
||||
colorBoxes.forEach(function(colorBox) {
|
||||
Entities.deleteEntity(colorBox);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Uncomment this line to delete whiteboard and all associated entity on script close
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
// Script.scriptEnding.connect(cleanup);
|
|
@ -266,4 +266,4 @@
|
|||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new Flashlight();
|
||||
});
|
||||
});
|
|
@ -2,7 +2,12 @@ set(TARGET_NAME interface)
|
|||
project(${TARGET_NAME})
|
||||
|
||||
# set a default root dir for each of our optional externals if it was not passed
|
||||
set(OPTIONAL_EXTERNALS "Faceshift" "LeapMotion" "RtMidi" "RSSDK" "3DConnexionClient" "iViewHMD")
|
||||
set(OPTIONAL_EXTERNALS "LeapMotion" "RtMidi" "RSSDK" "iViewHMD")
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND OPTIONAL_EXTERNALS "3DConnexionClient")
|
||||
endif()
|
||||
|
||||
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
|
||||
string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE)
|
||||
if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR)
|
||||
|
@ -102,12 +107,14 @@ link_hifi_libraries(shared octree environment gpu gl procedural model render
|
|||
render-utils entities-renderer ui auto-updater
|
||||
plugins display-plugins input-plugins)
|
||||
|
||||
#fixme find a way to express faceshift as a plugin
|
||||
target_bullet()
|
||||
target_glew()
|
||||
target_opengl()
|
||||
|
||||
|
||||
add_dependency_external_projects(sdl2)
|
||||
if (WIN32 OR APPLE)
|
||||
target_faceshift()
|
||||
endif()
|
||||
|
||||
# perform standard include and linking for found externals
|
||||
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
|
||||
|
|
26
interface/external/faceshift/readme.txt
vendored
26
interface/external/faceshift/readme.txt
vendored
|
@ -1,26 +0,0 @@
|
|||
|
||||
Instructions for adding the Faceshift library to Interface
|
||||
Stephen Birarda, July 18th, 2014
|
||||
|
||||
OS X users: You can also use homebrew to get the Faceshift library by tapping our repo - highfidelity/homebrew-formulas
|
||||
and then calling 'brew install highfidelity/formulas/faceshift'.
|
||||
|
||||
You can download the Faceshift SDK from http://download.faceshift.com/faceshift-network.zip.
|
||||
|
||||
Create a ‘faceshift’ folder under interface/externals.
|
||||
|
||||
You may optionally choose to place this folder in a location outside the repository (so you can re-use with different checkouts and different projects).
|
||||
|
||||
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder ‘faceshift’ that contains the lib and include folders.
|
||||
|
||||
1. Build a Faceshift static library from the fsbinarystream.cpp file.
|
||||
Windows: Win32 console application; no precompiled header or SDL checks; no ATL or MFC headers; Project Properties, Configuration Type = Static Library (.lib).
|
||||
|
||||
2. Copy the library files to the ‘lib’ folder in your Faceshift folder.
|
||||
OSX: If you build a release version call it libfaceshift.a. The debug version should be called libfaceshiftd.a.
|
||||
Windows: The release and debug versions should be called faceshift.lib and faceshiftd.lib, respectively. Copy them into a ‘Win32’ folder in your ‘lib’ folder.
|
||||
|
||||
3. Copy the fsbinarystream.h header file from the Faceshift SDK into the ‘include’ folder in your Faceshift folder.
|
||||
|
||||
4. Clear your build directory, run cmake and build, and you should be all set.
|
||||
|
13
interface/external/sdl2/readme.txt
vendored
13
interface/external/sdl2/readme.txt
vendored
|
@ -1,13 +0,0 @@
|
|||
|
||||
Instructions for adding the SDL library (SDL2) to Interface
|
||||
David Rowe, 11 Jan 2015
|
||||
|
||||
You can download the SDL development library from https://www.libsdl.org/. Interface has been tested with version 2.0.3.
|
||||
|
||||
1. Copy the include and lib folders into the interface/externals/sdl2 folder.
|
||||
This readme.txt should be there as well.
|
||||
|
||||
You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects).
|
||||
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'sdl2' that contains the two folders mentioned above.
|
||||
|
||||
2. Clear your build directory, run cmake and build, and you should be all set.
|
10
interface/external/sixense/readme.txt
vendored
10
interface/external/sixense/readme.txt
vendored
|
@ -1,10 +0,0 @@
|
|||
|
||||
Instructions for adding the Sixense driver to Interface
|
||||
Andrzej Kapolka, November 18, 2013
|
||||
|
||||
1. Copy the Sixense sdk folders (bin, include, lib, and samples) into the interface/external/Sixense folder. This readme.txt should be there as well.
|
||||
|
||||
You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects).
|
||||
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'sixense' that contains the folders mentioned above.
|
||||
|
||||
3. Delete your build directory, run cmake and build, and you should be all set.
|
|
@ -197,7 +197,7 @@
|
|||
"id": "rightHandOpen",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx",
|
||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_right.fbx",
|
||||
"startFrame": 0.0,
|
||||
"endFrame": 0.0,
|
||||
"timeScale": 1.0,
|
||||
|
@ -209,9 +209,9 @@
|
|||
"id": "rightHandClose",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/right_hand_anim.fbx",
|
||||
"startFrame": 15.0,
|
||||
"endFrame": 15.0,
|
||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_right.fbx",
|
||||
"startFrame": 10.0,
|
||||
"endFrame": 10.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
},
|
||||
|
@ -346,7 +346,7 @@
|
|||
"id": "leftHandOpen",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx",
|
||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_left.fbx",
|
||||
"startFrame": 0.0,
|
||||
"endFrame": 0.0,
|
||||
"timeScale": 1.0,
|
||||
|
@ -358,9 +358,9 @@
|
|||
"id": "leftHandClose",
|
||||
"type": "clip",
|
||||
"data": {
|
||||
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx",
|
||||
"startFrame": 15.0,
|
||||
"endFrame": 15.0,
|
||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_left.fbx",
|
||||
"startFrame": 10.0,
|
||||
"endFrame": 10.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
},
|
||||
|
|
|
@ -950,8 +950,8 @@ void Application::initializeGL() {
|
|||
checkFPStimer.start(1000);
|
||||
|
||||
// call our idle function whenever we can
|
||||
connect(&idleTimer, &QTimer::timeout, this, &Application::idle);
|
||||
idleTimer.start(TARGET_SIM_FRAME_PERIOD_MS);
|
||||
// connect(&idleTimer, &QTimer::timeout, this, &Application::idle);
|
||||
// idleTimer.start(TARGET_SIM_FRAME_PERIOD_MS);
|
||||
_idleLoopStdev.reset();
|
||||
|
||||
// update before the first render
|
||||
|
@ -1023,6 +1023,10 @@ void Application::paintGL() {
|
|||
if (_inPaint) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this is a good idea
|
||||
idle();
|
||||
|
||||
_inPaint = true;
|
||||
Finally clearFlagLambda([this] { _inPaint = false; });
|
||||
|
||||
|
@ -2070,7 +2074,7 @@ void Application::idle() {
|
|||
float secondsSinceLastUpdate = timeSinceLastUpdateUs / USECS_PER_SECOND;
|
||||
|
||||
if (isThrottled && (timeSinceLastUpdateUs / USECS_PER_MSEC) < THROTTLED_SIM_FRAME_PERIOD_MS) {
|
||||
return; // bail early, we're throttled and not enough time has elapsed
|
||||
//return; // bail early, we're throttled and not enough time has elapsed
|
||||
}
|
||||
|
||||
_lastTimeUpdated.start();
|
||||
|
|
|
@ -35,7 +35,8 @@ AvatarActionHold::~AvatarActionHold() {
|
|||
qDebug() << "AvatarActionHold::~AvatarActionHold";
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <plugins/PluginManager.h>
|
||||
#include <input-plugins/ViveControllerManager.h>
|
||||
void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
|
||||
bool gotLock = false;
|
||||
glm::quat rotation;
|
||||
|
@ -51,7 +52,24 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
|
|||
glm::vec3 offset;
|
||||
glm::vec3 palmPosition;
|
||||
glm::quat palmRotation;
|
||||
if (_hand == "right") {
|
||||
|
||||
const auto& plugins = PluginManager::getInstance()->getInputPlugins();
|
||||
auto it = std::find_if(std::begin(plugins), std::end(plugins), [](const InputPluginPointer& plugin) {
|
||||
return plugin->getName() == ViveControllerManager::NAME;
|
||||
});
|
||||
|
||||
if (it != std::end(plugins)) {
|
||||
const auto& vive = it->dynamicCast<ViveControllerManager>();
|
||||
auto index = (_hand == "right") ? 0 : 1; auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
auto translation = extractTranslation(userInputMapper->getSensorToWorldMat());
|
||||
auto rotation = glm::quat_cast(userInputMapper->getSensorToWorldMat());
|
||||
|
||||
|
||||
const glm::quat quarterX = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
const glm::quat yFlip = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
palmPosition = translation + rotation * vive->getPosition(index);
|
||||
palmRotation = rotation * vive->getRotation(index) * yFlip * quarterX;
|
||||
} else if (_hand == "right") {
|
||||
palmPosition = holdingAvatar->getRightPalmPosition();
|
||||
palmRotation = holdingAvatar->getRightPalmRotation();
|
||||
} else {
|
||||
|
@ -119,6 +137,9 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) {
|
|||
worldTrans.setRotation(glmToBullet(_rotationalTarget));
|
||||
rigidBody->setWorldTransform(worldTrans);
|
||||
|
||||
ownerEntity->setPosition(_positionalTarget);
|
||||
ownerEntity->setRotation(_rotationalTarget);
|
||||
|
||||
_previousPositionalTarget = _positionalTarget;
|
||||
_previousRotationalTarget = _rotationalTarget;
|
||||
_previousSet = true;
|
||||
|
@ -224,6 +245,8 @@ QVariantMap AvatarActionHold::getArguments() {
|
|||
arguments["relativeRotation"] = glmToQMap(_relativeRotation);
|
||||
arguments["timeScale"] = _linearTimeScale;
|
||||
arguments["hand"] = _hand;
|
||||
arguments["kinematic"] = _kinematic;
|
||||
arguments["kinematicSetVelocity"] = _kinematicSetVelocity;
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe
|
|||
avatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||
QWriteLocker locker(&_hashLock);
|
||||
_avatarHash.insert(sessionUUID, avatar);
|
||||
|
||||
emit avatarAddedEvent(sessionUUID);
|
||||
return avatar;
|
||||
}
|
||||
|
||||
|
@ -137,13 +137,16 @@ void AvatarHashMap::processKillAvatar(QSharedPointer<NLPacket> packet, SharedNod
|
|||
// read the node id
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
removeAvatar(sessionUUID);
|
||||
|
||||
}
|
||||
|
||||
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) {
|
||||
QWriteLocker locker(&_hashLock);
|
||||
_avatarHash.remove(sessionUUID);
|
||||
emit avatarRemovedEvent(sessionUUID);
|
||||
}
|
||||
|
||||
void AvatarHashMap::sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID) {
|
||||
_lastOwnerSessionUUID = oldUUID;
|
||||
emit avatarSessionChangedEvent(sessionUUID, oldUUID);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,11 @@ public:
|
|||
void withAvatarHash(std::function<void(const AvatarHash& hash)>);
|
||||
int size() { return _avatarHash.size(); }
|
||||
|
||||
signals:
|
||||
void avatarAddedEvent(const QUuid& sessionUUID);
|
||||
void avatarRemovedEvent(const QUuid& sessionUUID);
|
||||
void avatarSessionChangedEvent(const QUuid& sessionUUID,const QUuid& oldUUID);
|
||||
|
||||
public slots:
|
||||
bool isAvatarInRange(const glm::vec3 & position, const float range);
|
||||
|
||||
|
|
|
@ -44,8 +44,7 @@ bool GlWindow::makeCurrent() {
|
|||
qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||
});
|
||||
|
||||
QOpenGLContext * currentContext = QOpenGLContext::currentContext();
|
||||
Q_ASSERT(_context == currentContext);
|
||||
Q_ASSERT(_context == QOpenGLContext::currentContext());
|
||||
|
||||
return makeCurrentResult;
|
||||
}
|
||||
|
|
|
@ -11,55 +11,5 @@ if (WIN32)
|
|||
target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES})
|
||||
endif()
|
||||
|
||||
#add_dependency_external_projects(Sixense)
|
||||
#find_package(Sixense REQUIRED)
|
||||
#target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS})
|
||||
#target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES})
|
||||
|
||||
# set a default root dir for each of our optional externals if it was not passed
|
||||
set(OPTIONAL_EXTERNALS "SDL2" "Sixense")
|
||||
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
|
||||
string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE)
|
||||
if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR)
|
||||
string(TOLOWER ${EXTERNAL} ${EXTERNAL}_LOWERCASE)
|
||||
set(${${EXTERNAL}_UPPERCASE}_ROOT_DIR "${CMAKE_SOURCE_DIR}/interface/external/${${EXTERNAL}_LOWERCASE}")
|
||||
endif ()
|
||||
endforeach()
|
||||
|
||||
# perform standard include and linking for found externals
|
||||
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
|
||||
|
||||
if (${${EXTERNAL}_UPPERCASE}_REQUIRED)
|
||||
find_package(${EXTERNAL} REQUIRED)
|
||||
else ()
|
||||
find_package(${EXTERNAL})
|
||||
endif ()
|
||||
|
||||
if (${${EXTERNAL}_UPPERCASE}_FOUND AND NOT DISABLE_${${EXTERNAL}_UPPERCASE})
|
||||
add_definitions(-DHAVE_${${EXTERNAL}_UPPERCASE})
|
||||
|
||||
# include the library directories (ignoring warnings)
|
||||
if (NOT ${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS)
|
||||
set(${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIR})
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS})
|
||||
|
||||
# perform the system include hack for OS X to ignore warnings
|
||||
if (APPLE)
|
||||
foreach(EXTERNAL_INCLUDE_DIR ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${EXTERNAL_INCLUDE_DIR}")
|
||||
endforeach()
|
||||
endif ()
|
||||
|
||||
if (NOT ${${EXTERNAL}_UPPERCASE}_LIBRARIES)
|
||||
set(${${EXTERNAL}_UPPERCASE}_LIBRARIES ${${${EXTERNAL}_UPPERCASE}_LIBRARY})
|
||||
endif ()
|
||||
|
||||
if (NOT APPLE OR NOT ${${EXTERNAL}_UPPERCASE} MATCHES "SIXENSE")
|
||||
target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES})
|
||||
elseif (APPLE AND NOT INSTALLER_BUILD)
|
||||
add_definitions(-DSIXENSE_LIB_FILENAME=\"${${${EXTERNAL}_UPPERCASE}_LIBRARY_RELEASE}\")
|
||||
endif ()
|
||||
endif ()
|
||||
endforeach()
|
||||
target_sdl2()
|
||||
target_sixense()
|
||||
|
|
|
@ -217,6 +217,15 @@ void ViveControllerManager::renderHand(UserInputMapper::PoseValue pose, gpu::Bat
|
|||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
||||
}
|
||||
|
||||
glm::vec3 ViveControllerManager::getPosition(int hand) const {
|
||||
const mat4& mat = _trackedDevicePoseMat4[hand ? 3 : 4];
|
||||
return extractTranslation(mat);
|
||||
}
|
||||
glm::quat ViveControllerManager::getRotation(int hand) const {
|
||||
const mat4& mat = _trackedDevicePoseMat4[hand ? 3 : 4];
|
||||
return glm::quat_cast(mat);
|
||||
}
|
||||
|
||||
void ViveControllerManager::update(float deltaTime, bool jointsCaptured) {
|
||||
#ifdef Q_OS_WIN
|
||||
_poseStateMap.clear();
|
||||
|
@ -250,7 +259,7 @@ void ViveControllerManager::update(float deltaTime, bool jointsCaptured) {
|
|||
numTrackedControllers++;
|
||||
|
||||
const mat4& mat = _trackedDevicePoseMat4[device];
|
||||
|
||||
|
||||
if (!jointsCaptured) {
|
||||
handlePoseEvent(mat, numTrackedControllers - 1);
|
||||
}
|
||||
|
@ -372,16 +381,23 @@ void ViveControllerManager::handlePoseEvent(const mat4& mat, int index) {
|
|||
// Q = (deltaQ * QOffset) * (yFlip * quarterTurnAboutX)
|
||||
//
|
||||
// Q = (deltaQ * inverse(deltaQForAlignedHand)) * (yFlip * quarterTurnAboutX)
|
||||
|
||||
|
||||
float sign = (index == LEFT_HAND) ? -1.0f : 1.0f;
|
||||
|
||||
const glm::quat quarterX = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
const glm::quat yFlip = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
float sign = (index == LEFT_HAND) ? -1.0f : 1.0f;
|
||||
const glm::quat signedQuaterZ = glm::angleAxis(sign * PI / 2.0f, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
const glm::quat eighthX = glm::angleAxis(PI / 4.0f, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
const glm::quat offset = glm::inverse(signedQuaterZ * eighthX);
|
||||
rotation = rotation * offset * yFlip * quarterX;
|
||||
|
||||
|
||||
const glm::quat rotationOffset = glm::inverse(signedQuaterZ * eighthX) * yFlip * quarterX;
|
||||
const glm::vec3 translationOffset = glm::vec3(sign * CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||
CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||
2.0f * CONTROLLER_LENGTH_OFFSET);
|
||||
|
||||
position += rotation * glm::vec3(0, 0, -CONTROLLER_LENGTH_OFFSET);
|
||||
position += rotation * translationOffset;
|
||||
rotation = rotation * rotationOffset;
|
||||
//{quat, x = 0.653281, y = -0.270598, z = 0.653281, w = 0.270598}{vec3, x = 0.0381, y = -0.0381, z = -0.1524}
|
||||
|
||||
_poseStateMap[makeInput(JointChannel(index)).getChannel()] = UserInputMapper::PoseValue(position, rotation);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
class ViveControllerManager : public InputPlugin, public InputDevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static const QString NAME;
|
||||
|
||||
enum JoystickAxisChannel {
|
||||
AXIS_Y_POS = 1U << 1,
|
||||
AXIS_Y_NEG = 1U << 2,
|
||||
|
@ -74,6 +76,10 @@ public:
|
|||
UserInputMapper::Input makeInput(unsigned int button, int index);
|
||||
UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index);
|
||||
UserInputMapper::Input makeInput(JointChannel joint);
|
||||
|
||||
int getNumDevices() const;
|
||||
glm::vec3 getPosition(int device) const;
|
||||
glm::quat getRotation(int device) const;
|
||||
|
||||
private:
|
||||
void renderHand(UserInputMapper::PoseValue pose, gpu::Batch& batch, int index);
|
||||
|
@ -92,8 +98,6 @@ private:
|
|||
int _rightHandRenderID;
|
||||
|
||||
bool _renderControllers;
|
||||
|
||||
static const QString NAME;
|
||||
};
|
||||
|
||||
#endif // hifi__ViveControllerManager
|
||||
|
|
|
@ -89,7 +89,6 @@ AssetRequest* AssetClient::createRequest(const QString& hash, const QString& ext
|
|||
|
||||
// Move to the AssetClient thread in case we are not currently on that thread (which will usually be the case)
|
||||
request->moveToThread(thread());
|
||||
request->setParent(this);
|
||||
|
||||
return request;
|
||||
} else {
|
||||
|
@ -105,7 +104,6 @@ AssetUpload* AssetClient::createUpload(const QString& filename) {
|
|||
auto upload = new AssetUpload(filename);
|
||||
|
||||
upload->moveToThread(thread());
|
||||
upload->setParent(this);
|
||||
|
||||
return upload;
|
||||
} else {
|
||||
|
@ -118,7 +116,6 @@ AssetUpload* AssetClient::createUpload(const QByteArray& data, const QString& ex
|
|||
auto upload = new AssetUpload(data, extension);
|
||||
|
||||
upload->moveToThread(thread());
|
||||
upload->setParent(this);
|
||||
|
||||
return upload;
|
||||
} else {
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#include "PhysicsCollisionGroups.h"
|
||||
|
||||
bool CharacterController::needsRemoval() const {
|
||||
return (bool)(_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION);
|
||||
return ((_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION) == PENDING_FLAG_REMOVE_FROM_SIMULATION);
|
||||
}
|
||||
|
||||
bool CharacterController::needsAddition() const {
|
||||
return (bool)(_pendingFlags & PENDING_FLAG_ADD_TO_SIMULATION);
|
||||
return ((_pendingFlags & PENDING_FLAG_ADD_TO_SIMULATION) == PENDING_FLAG_ADD_TO_SIMULATION);
|
||||
}
|
||||
|
||||
void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
|
||||
|
|
|
@ -35,7 +35,9 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta
|
|||
if (ownerEntityExpired) {
|
||||
qDebug() << "warning -- action with no entity removing self from btCollisionWorld.";
|
||||
btDynamicsWorld* dynamicsWorld = static_cast<btDynamicsWorld*>(collisionWorld);
|
||||
dynamicsWorld->removeAction(this);
|
||||
if (dynamicsWorld) {
|
||||
dynamicsWorld->removeAction(this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -120,6 +122,17 @@ QVariantMap ObjectAction::getArguments() {
|
|||
arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND;
|
||||
}
|
||||
arguments["tag"] = _tag;
|
||||
|
||||
EntityItemPointer entity = _ownerEntity.lock();
|
||||
if (entity) {
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState) {
|
||||
arguments["::active"] = motionState->isActive();
|
||||
arguments["::motion-type"] = motionTypeToString(motionState->getMotionType());
|
||||
} else {
|
||||
arguments["::no-motion-state"] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,21 @@ void ObjectMotionState::setMotionType(MotionType motionType) {
|
|||
_motionType = motionType;
|
||||
}
|
||||
|
||||
void ObjectMotionState::updateCCDConfiguration() {
|
||||
if (_body) {
|
||||
if (_shape) {
|
||||
btVector3 center;
|
||||
btScalar radius;
|
||||
_shape->getBoundingSphere(center, radius);
|
||||
_body->setCcdMotionThreshold(radius * 2.0f);
|
||||
_body->setCcdSweptSphereRadius(radius);
|
||||
} else {
|
||||
// Disable CCD
|
||||
_body->setCcdMotionThreshold(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMotionState::setRigidBody(btRigidBody* body) {
|
||||
// give the body a (void*) back-pointer to this ObjectMotionState
|
||||
if (_body != body) {
|
||||
|
@ -125,6 +140,7 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) {
|
|||
if (_body) {
|
||||
_body->setUserPointer(this);
|
||||
}
|
||||
updateCCDConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +203,8 @@ bool ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
if (_shape != newShape) {
|
||||
_shape = newShape;
|
||||
_body->setCollisionShape(_shape);
|
||||
|
||||
updateCCDConfiguration();
|
||||
} else {
|
||||
// huh... the shape didn't actually change, so we clear the DIRTY_SHAPE flag
|
||||
flags &= ~Simulation::DIRTY_SHAPE;
|
||||
|
|
|
@ -29,6 +29,15 @@ enum MotionType {
|
|||
MOTION_TYPE_KINEMATIC // keyframed motion
|
||||
};
|
||||
|
||||
inline QString motionTypeToString(MotionType motionType) {
|
||||
switch(motionType) {
|
||||
case MOTION_TYPE_STATIC: return QString("static");
|
||||
case MOTION_TYPE_DYNAMIC: return QString("dynamic");
|
||||
case MOTION_TYPE_KINEMATIC: return QString("kinematic");
|
||||
}
|
||||
return QString("unknown");
|
||||
}
|
||||
|
||||
enum MotionStateType {
|
||||
MOTIONSTATE_TYPE_INVALID,
|
||||
MOTIONSTATE_TYPE_ENTITY,
|
||||
|
@ -137,6 +146,7 @@ protected:
|
|||
virtual bool isReadyToComputeShape() = 0;
|
||||
virtual btCollisionShape* computeNewShape() = 0;
|
||||
void setMotionType(MotionType motionType);
|
||||
void updateCCDConfiguration();
|
||||
|
||||
// clearObjectBackPointer() overrrides should call the base method, then actually clear the object back pointer.
|
||||
virtual void clearObjectBackPointer() { _type = MOTIONSTATE_TYPE_INVALID; }
|
||||
|
|
|
@ -241,7 +241,7 @@ void PhysicsEngine::stepSimulation() {
|
|||
float timeStep = btMin(dt, MAX_TIMESTEP);
|
||||
|
||||
if (_myAvatarController) {
|
||||
// ADEBUG TODO: move this stuff outside and in front of stepSimulation, because
|
||||
// ADEBUG TODO: move this stuff outside and in front of stepSimulation, because
|
||||
// the updateShapeIfNecessary() call needs info from MyAvatar and should
|
||||
// be done on the main thread during the pre-simulation stuff
|
||||
if (_myAvatarController->needsRemoval()) {
|
||||
|
@ -263,7 +263,8 @@ void PhysicsEngine::stepSimulation() {
|
|||
updateContactMap();
|
||||
};
|
||||
|
||||
int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, PHYSICS_ENGINE_MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP, onSubStep);
|
||||
int numSubsteps = _dynamicsWorld->stepSimulationWithSubstepCallback(timeStep, PHYSICS_ENGINE_MAX_NUM_SUBSTEPS,
|
||||
PHYSICS_ENGINE_FIXED_SUBSTEP, onSubStep);
|
||||
if (numSubsteps > 0) {
|
||||
BT_PROFILE("postSimulation");
|
||||
_numSubsteps += (uint32_t)numSubsteps;
|
||||
|
|
|
@ -27,8 +27,9 @@ ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(
|
|||
: btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration) {
|
||||
}
|
||||
|
||||
int ThreadSafeDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep, SubStepCallback onSubStep) {
|
||||
BT_PROFILE("stepSimulation");
|
||||
int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep, int maxSubSteps,
|
||||
btScalar fixedTimeStep, SubStepCallback onSubStep) {
|
||||
BT_PROFILE("stepSimulationWithSubstepCallback");
|
||||
int subSteps = 0;
|
||||
if (maxSubSteps) {
|
||||
//fixed timestep with interpolation
|
||||
|
|
|
@ -37,8 +37,9 @@ public:
|
|||
btConstraintSolver* constraintSolver,
|
||||
btCollisionConfiguration* collisionConfiguration);
|
||||
|
||||
// virtual overrides from btDiscreteDynamicsWorld
|
||||
int stepSimulation( btScalar timeStep, int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.), SubStepCallback onSubStep = []() { });
|
||||
int stepSimulationWithSubstepCallback(btScalar timeStep, int maxSubSteps = 1,
|
||||
btScalar fixedTimeStep = btScalar(1.)/btScalar(60.),
|
||||
SubStepCallback onSubStep = []() { });
|
||||
void synchronizeMotionStates();
|
||||
|
||||
// btDiscreteDynamicsWorld::m_localTime is the portion of real-time that has not yet been simulated
|
||||
|
|
|
@ -23,6 +23,25 @@
|
|||
/// Scriptable interface a Vec3ernion helper class object. Used exclusively in the JavaScript API
|
||||
class Vec3 : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(glm::vec3 UNIT_X READ UNIT_X CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_Y READ UNIT_Y CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_Z READ UNIT_Z CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_NEG_X READ UNIT_NEG_X CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_NEG_Y READ UNIT_NEG_Y CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_NEG_Z READ UNIT_NEG_Z CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_XY READ UNIT_XY CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_XZ READ UNIT_XZ CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_YZ READ UNIT_YZ CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UNIT_XYZ READ UNIT_XYZ CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 FLOAT_MAX READ FLOAT_MAX CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 FLOAT_MIN READ FLOAT_MIN CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 ZERO READ ZERO CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 ONE READ ONE CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 TWO READ TWO CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 HALF READ HALF CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 RIGHT READ RIGHT CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 UP READ UP CONSTANT)
|
||||
Q_PROPERTY(glm::vec3 FRONT READ FRONT CONSTANT)
|
||||
|
||||
public slots:
|
||||
glm::vec3 reflect(const glm::vec3& v1, const glm::vec3& v2) { return glm::reflect(v1, v2); }
|
||||
|
@ -30,6 +49,7 @@ public slots:
|
|||
float dot(const glm::vec3& v1, const glm::vec3& v2) { return glm::dot(v1, v2); }
|
||||
glm::vec3 multiply(const glm::vec3& v1, float f) { return v1 * f; }
|
||||
glm::vec3 multiply(float f, const glm::vec3& v1) { return v1 * f; }
|
||||
glm::vec3 multiplyVbyV(const glm::vec3& v1, const glm::vec3& v2) { return v1 * v2; }
|
||||
glm::vec3 multiplyQbyV(const glm::quat& q, const glm::vec3& v) { return q * v; }
|
||||
glm::vec3 sum(const glm::vec3& v1, const glm::vec3& v2) { return v1 + v2; }
|
||||
glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2) { return v1 - v2; }
|
||||
|
@ -45,6 +65,8 @@ public slots:
|
|||
glm::vec3 toPolar(const glm::vec3& v);
|
||||
glm::vec3 fromPolar(const glm::vec3& polar);
|
||||
glm::vec3 fromPolar(float elevation, float azimuth);
|
||||
|
||||
private:
|
||||
const glm::vec3& UNIT_X() { return Vectors::UNIT_X; }
|
||||
const glm::vec3& UNIT_Y() { return Vectors::UNIT_Y; }
|
||||
const glm::vec3& UNIT_Z() { return Vectors::UNIT_Z; }
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
const int PHYSICS_ENGINE_MAX_NUM_SUBSTEPS = 6; // Bullet will start to "lose time" at 10 FPS.
|
||||
const float PHYSICS_ENGINE_FIXED_SUBSTEP = 1.0f / 60.0f;
|
||||
const float PHYSICS_ENGINE_FIXED_SUBSTEP = 1.0f / 90.0f;
|
||||
|
||||
// return incremental rotation (Bullet-style) caused by angularVelocity over timeStep
|
||||
glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float timeStep);
|
||||
|
|
|
@ -113,6 +113,7 @@ void VrMenu::addMenu(QMenu* menu) {
|
|||
Q_ARG(QVariant, QVariant::fromValue(qmlParent)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(menu->title())));
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
QObject* result = returnedValue.value<QObject*>();
|
||||
Q_ASSERT(result);
|
||||
|
||||
|
@ -153,6 +154,7 @@ void VrMenu::addAction(QMenu* menu, QAction* action) {
|
|||
Q_ARG(QVariant, QVariant::fromValue(menuQml)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(action->text())));
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
QObject* result = returnedValue.value<QObject*>();
|
||||
Q_ASSERT(result);
|
||||
// Bind the QML and Widget together
|
||||
|
@ -174,6 +176,7 @@ void VrMenu::insertAction(QAction* before, QAction* action) {
|
|||
Q_ARG(QVariant, QVariant::fromValue(beforeQml)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(action->text())));
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
QObject* result = returnedValue.value<QObject*>();
|
||||
Q_ASSERT(result);
|
||||
bindActionToQmlAction(result, action);
|
||||
|
@ -192,4 +195,5 @@ void VrMenu::removeAction(QAction* action) {
|
|||
Q_ARG(QVariant, QVariant::fromValue(menu)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(item)));
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue