mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 06:32:57 +02:00
Merge branch 'master' into plugins_pt3
This commit is contained in:
commit
8bad80324f
34 changed files with 1240 additions and 133 deletions
|
@ -179,6 +179,7 @@ option(GET_SOXR "Get Soxr 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)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
# OSXTBBInstallNameChange.cmake
|
||||
# cmake/externals/tbb
|
||||
# OSXInstallNameChange.cmake
|
||||
# cmake/macros
|
||||
#
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Created by Stephen Birarda on February 20, 2014
|
||||
|
@ -10,36 +10,33 @@
|
|||
#
|
||||
|
||||
# first find the so files in the source dir
|
||||
set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||
file(GLOB_RECURSE _TBB_LIBRARIES "${_TBB_LIBRARY_DIR}/*.dylib")
|
||||
message("INSTALL_NAME_LIBRARY_DIR ${INSTALL_NAME_LIBRARY_DIR}")
|
||||
|
||||
# raise an error if we found none
|
||||
if (NOT _TBB_LIBRARIES)
|
||||
message(FATAL_ERROR "Did not find any TBB libraries")
|
||||
file(GLOB_RECURSE _LIBRARIES "${INSTALL_NAME_LIBRARY_DIR}/*.dylib")
|
||||
|
||||
if (NOT _LIBRARIES)
|
||||
message(FATAL_ERROR "OSXInstallNameChange -- no libraries found: ${INSTALL_NAME_LIBRARY_DIR}")
|
||||
endif ()
|
||||
|
||||
# find the install_name_tool command
|
||||
find_program(INSTALL_NAME_TOOL_COMMAND NAMES install_name_tool DOC "Path to the install_name_tool command")
|
||||
|
||||
# find the lipo command
|
||||
find_program(LIPO_COMMAND NAMES lipo DOC "Path to the lipo command")
|
||||
|
||||
# enumerate the libraries
|
||||
foreach(_TBB_LIBRARY ${_TBB_LIBRARIES})
|
||||
get_filename_component(_TBB_LIBRARY_FILENAME ${_TBB_LIBRARY} NAME)
|
||||
foreach(_LIBRARY ${_LIBRARIES})
|
||||
get_filename_component(_LIBRARY_FILENAME ${_LIBRARY} NAME)
|
||||
|
||||
set(_INSTALL_NAME_ARGS ${INSTALL_NAME_TOOL_COMMAND} -id ${_TBB_LIBRARY} ${_TBB_LIBRARY_FILENAME})
|
||||
set(_INSTALL_NAME_ARGS ${INSTALL_NAME_TOOL_COMMAND} -id ${_LIBRARY} ${_LIBRARY_FILENAME})
|
||||
|
||||
message(STATUS "${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS}
|
||||
WORKING_DIRECTORY ${_TBB_LIBRARY_DIR}
|
||||
WORKING_DIRECTORY ${INSTALL_NAME_LIBRARY_DIR}
|
||||
ERROR_VARIABLE _INSTALL_NAME_ERROR
|
||||
)
|
||||
|
||||
if (_INSTALL_NAME_ERROR)
|
||||
message(FATAL_ERROR "There was an error changing install name for ${_TBB_LIBRARY_FILENAME} - ${_INSTALL_NAME_ERROR}")
|
||||
message(FATAL_ERROR "There was an error changing install name for ${_LIBRARY_FILENAME} - ${_INSTALL_NAME_ERROR}")
|
||||
endif ()
|
||||
endforeach()
|
||||
|
57
cmake/externals/polyvox/CMakeLists.txt
vendored
Normal file
57
cmake/externals/polyvox/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
set(EXTERNAL_NAME polyvox)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/polyvox-master-2015-5-27.zip
|
||||
URL_MD5 e3dd09a24df4db29ba370e3bea753388
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
|
||||
if (APPLE)
|
||||
set(INSTALL_NAME_LIBRARY_DIR ${INSTALL_DIR}/lib)
|
||||
message(STATUS "in polyvox INSTALL_NAME_LIBRARY_DIR ${INSTALL_NAME_LIBRARY_DIR}")
|
||||
ExternalProject_Add_Step(
|
||||
${EXTERNAL_NAME}
|
||||
change-install-name
|
||||
COMMENT "Calling install_name_tool on libraries to fix install name for dylib linking"
|
||||
COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${INSTALL_NAME_LIBRARY_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake
|
||||
DEPENDEES install
|
||||
WORKING_DIRECTORY <SOURCE_DIR>
|
||||
LOG 1
|
||||
)
|
||||
endif ()
|
||||
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
if (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_CORE_INCLUDE_DIRS ${INSTALL_DIR}/PolyVoxCore/include CACHE FILEPATH
|
||||
"Path to polyvox core include directory")
|
||||
set(${EXTERNAL_NAME_UPPER}_UTIL_INCLUDE_DIRS ${INSTALL_DIR}/PolyVoxUtil/include CACHE FILEPATH
|
||||
"Path to polyvox util include directory")
|
||||
else ()
|
||||
set(${EXTERNAL_NAME_UPPER}_CORE_INCLUDE_DIRS ${INSTALL_DIR}/include/PolyVoxCore CACHE FILEPATH
|
||||
"Path to polyvox core include directory")
|
||||
set(${EXTERNAL_NAME_UPPER}_UTIL_INCLUDE_DIRS ${INSTALL_DIR}/include/PolyVoxUtil CACHE FILEPATH
|
||||
"Path to polyvox util include directory")
|
||||
endif ()
|
||||
|
||||
|
||||
if (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_CORE_LIBRARY ${INSTALL_DIR}/PolyVoxCore/lib/PolyVoxCore.lib CACHE FILEPATH "polyvox core library")
|
||||
# set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY ${INSTALL_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib CACHE FILEPATH "polyvox util library")
|
||||
elseif (APPLE)
|
||||
set(${EXTERNAL_NAME_UPPER}_CORE_LIBRARY ${INSTALL_DIR}/lib/libPolyVoxCore.dylib CACHE FILEPATH "polyvox core library")
|
||||
# set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY ${INSTALL_DIR}/lib/libPolyVoxUtil.dylib CACHE FILEPATH "polyvox util library")
|
||||
else ()
|
||||
set(${EXTERNAL_NAME_UPPER}_CORE_LIBRARY ${INSTALL_DIR}/lib/libPolyVoxCore.so CACHE FILEPATH "polyvox core library")
|
||||
# set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY ${INSTALL_DIR}/lib/libPolyVoxUtil.so CACHE FILEPATH "polyvox util library")
|
||||
endif ()
|
4
cmake/externals/tbb/CMakeLists.txt
vendored
4
cmake/externals/tbb/CMakeLists.txt
vendored
|
@ -66,7 +66,7 @@ if (APPLE)
|
|||
${EXTERNAL_NAME}
|
||||
change-install-name
|
||||
COMMENT "Calling install_name_tool on TBB libraries to fix install name for dylib linking"
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/OSXTBBInstallNameChange.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_TBB_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake
|
||||
DEPENDEES install
|
||||
WORKING_DIRECTORY <SOURCE_DIR>
|
||||
LOG 1
|
||||
|
@ -115,4 +115,4 @@ endif ()
|
|||
|
||||
if (DEFINED ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories")
|
||||
endif ()
|
||||
endif ()
|
||||
|
|
54
cmake/modules/FindPolyVox.cmake
Normal file
54
cmake/modules/FindPolyVox.cmake
Normal file
|
@ -0,0 +1,54 @@
|
|||
#
|
||||
# FindPolyvox.cmake
|
||||
#
|
||||
# Try to find the libpolyvox resampling library
|
||||
#
|
||||
# You can provide a LIBPOLYVOX_ROOT_DIR which contains lib and include directories
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# POLYVOX_FOUND - system found libpolyvox
|
||||
# POLYVOX_INCLUDE_DIRS - the libpolyvox include directory
|
||||
# POLYVOX_LIBRARIES - link to this to use libpolyvox
|
||||
#
|
||||
# Created on 1/22/2015 by Stephen Birarda
|
||||
# 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
|
||||
#
|
||||
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("polyvox")
|
||||
|
||||
find_path(POLYVOX_CORE_INCLUDE_DIRS PolyVoxCore/SimpleVolume.h PATH_SUFFIXES include include/PolyVoxCore HINTS ${POLYVOX_SEARCH_DIRS})
|
||||
# find_path(POLYVOX_UTIL_INCLUDE_DIRS PolyVoxUtil/Serialization.h PATH_SUFFIXES include include/PolyVoxUtil HINTS ${POLYVOX_SEARCH_DIRS})
|
||||
|
||||
find_library(POLYVOX_CORE_LIBRARY NAMES PolyVoxCore PATH_SUFFIXES lib HINTS ${POLYVOX_SEARCH_DIRS})
|
||||
# find_library(POLYVOX_UTIL_LIBRARY NAMES PolyVoxUtil PATH_SUFFIXES lib HINTS ${POLYVOX_SEARCH_DIRS})
|
||||
|
||||
|
||||
# if (WIN32)
|
||||
# find_path(POLYVOX_DLL_PATH polyvox.dll PATH_SUFFIXES bin HINTS ${POLYVOX_SEARCH_DIRS})
|
||||
# endif()
|
||||
|
||||
# set(POLYVOX_REQUIREMENTS POLYVOX_CORE_INCLUDE_DIRS POLYVOX_UTIL_INCLUDE_DIRS POLYVOX_CORE_LIBRARY POLYVOX_UTIL_LIBRARY)
|
||||
set(POLYVOX_REQUIREMENTS POLYVOX_CORE_INCLUDE_DIRS POLYVOX_CORE_LIBRARY)
|
||||
# if (WIN32)
|
||||
# list(APPEND POLYVOX_REQUIREMENTS POLYVOX_DLL_PATH)
|
||||
# endif ()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Polyvox DEFAULT_MSG ${POLYVOX_REQUIREMENTS})
|
||||
|
||||
# if (WIN32)
|
||||
# add_paths_to_fixup_libs(${POLYVOX_DLL_PATH})
|
||||
# endif ()
|
||||
|
||||
# set(POLYVOX_INCLUDE_DIRS ${POLYVOX_CORE_INCLUDE_DIRS} ${POLYVOX_UTIL_INCLUDE_DIRS})
|
||||
# set(POLYVOX_LIBRARIES ${POLYVOX_CORE_LIBRARY} ${POLYVOX_UTIL_LIBRARY})
|
||||
|
||||
set(POLYVOX_INCLUDE_DIRS ${POLYVOX_CORE_INCLUDE_DIRS})
|
||||
set(POLYVOX_LIBRARIES ${POLYVOX_CORE_LIBRARY})
|
||||
|
||||
mark_as_advanced(POLYVOX_INCLUDE_DIRS POLYVOX_LIBRARIES POLYVOX_SEARCH_DIRS)
|
|
@ -0,0 +1,201 @@
|
|||
// blockWorld.js
|
||||
// examples
|
||||
//
|
||||
// Created by Eric Levin on May 26, 2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Creates a floor of tiles and then drops planky blocks at random points above the tile floor
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var TILE_SIZE = 7
|
||||
var GENERATE_INTERVAL = 50;
|
||||
var NUM_ROWS = 10;
|
||||
var angVelRange = 4;
|
||||
|
||||
var floorTiles = [];
|
||||
var blocks = [];
|
||||
var blockSpawner;
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
|
||||
|
||||
var floorPos = Vec3.sum(MyAvatar.position, {
|
||||
x: 0,
|
||||
y: -2,
|
||||
z: 0
|
||||
});
|
||||
var x = floorPos.x;
|
||||
|
||||
var currentRowIndex = 0;
|
||||
var currentColumnIndex = 0;
|
||||
|
||||
var DROP_HEIGHT = floorPos.y + 5;
|
||||
var BLOCK_GRAVITY = {
|
||||
x: 0,
|
||||
y: -9,
|
||||
z: 0
|
||||
};
|
||||
var BLOCK_SIZE = {
|
||||
x: 0.2,
|
||||
y: 0.1,
|
||||
z: 0.8
|
||||
};
|
||||
|
||||
var bounds = {
|
||||
xMin: floorPos.x,
|
||||
xMax: floorPos.x + (TILE_SIZE * NUM_ROWS) - TILE_SIZE,
|
||||
zMin: floorPos.z,
|
||||
zMax: floorPos.z + (TILE_SIZE * NUM_ROWS) - TILE_SIZE
|
||||
};
|
||||
|
||||
var screenSize = Controller.getViewportDimensions();
|
||||
|
||||
var BUTTON_SIZE = 32;
|
||||
var PADDING = 3;
|
||||
|
||||
var offButton = Overlays.addOverlay("image", {
|
||||
x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING,
|
||||
y: screenSize.y - (BUTTON_SIZE + PADDING),
|
||||
width: BUTTON_SIZE,
|
||||
height: BUTTON_SIZE,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/close.png",
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
var deleteButton = Overlays.addOverlay("image", {
|
||||
x: screenSize.x / 2 - BUTTON_SIZE,
|
||||
y: screenSize.y - (BUTTON_SIZE + PADDING),
|
||||
width: BUTTON_SIZE,
|
||||
height: BUTTON_SIZE,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png",
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
|
||||
function generateFloor() {
|
||||
for (var z = floorPos.z; currentColumnIndex < NUM_ROWS; z += TILE_SIZE, currentColumnIndex++) {
|
||||
floorTiles.push(Entities.addEntity({
|
||||
type: 'Box',
|
||||
position: {
|
||||
x: x,
|
||||
y: floorPos.y,
|
||||
z: z
|
||||
},
|
||||
dimensions: {
|
||||
x: TILE_SIZE,
|
||||
y: 2,
|
||||
z: TILE_SIZE
|
||||
},
|
||||
color: {
|
||||
red: randFloat(70, 120),
|
||||
green: randFloat(70, 71),
|
||||
blue: randFloat(70, 80)
|
||||
},
|
||||
// collisionsWillMove: true
|
||||
}));
|
||||
}
|
||||
|
||||
currentRowIndex++;
|
||||
if (currentRowIndex < NUM_ROWS) {
|
||||
currentColumnIndex = 0;
|
||||
x += TILE_SIZE;
|
||||
Script.setTimeout(generateFloor, GENERATE_INTERVAL);
|
||||
} else {
|
||||
//Once we're done generating floor, drop planky blocks at random points on floor
|
||||
blockSpawner = Script.setInterval(function() {
|
||||
dropBlock();
|
||||
}, GENERATE_INTERVAL)
|
||||
}
|
||||
}
|
||||
|
||||
function dropBlock() {
|
||||
var dropPos = floorPos;
|
||||
dropPos.y = DROP_HEIGHT;
|
||||
dropPos.x = randFloat(bounds.xMin, bounds.xMax);
|
||||
dropPos.z = randFloat(bounds.zMin, bounds.zMax);
|
||||
blocks.push(Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: 'http://s3.amazonaws.com/hifi-public/marketplace/hificontent/Games/blocks/block.fbx',
|
||||
shapeType: 'box',
|
||||
position: dropPos,
|
||||
dimensions: BLOCK_SIZE,
|
||||
collisionsWillMove: true,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -9,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: .1,
|
||||
z: 0
|
||||
},
|
||||
angularVelocity: {
|
||||
x: randFloat(-angVelRange, angVelRange),
|
||||
y: randFloat(-angVelRange, angVelRange),
|
||||
z: randFloat(-angVelRange, angVelRange),
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||
x: event.x,
|
||||
y: event.y
|
||||
});
|
||||
if (clickedOverlay == offButton) {
|
||||
Script.clearInterval(blockSpawner);
|
||||
}
|
||||
if(clickedOverlay == deleteButton){
|
||||
destroyStuff();
|
||||
}
|
||||
}
|
||||
|
||||
generateFloor();
|
||||
|
||||
function cleanup() {
|
||||
// for (var i = 0; i < floorTiles.length; i++) {
|
||||
// Entities.deleteEntity(floorTiles[i]);
|
||||
// }
|
||||
// for (var i = 0; i < blocks.length; i++) {
|
||||
// Entities.deleteEntity(blocks[i]);
|
||||
// }
|
||||
Overlays.deleteOverlay(offButton);
|
||||
Overlays.deleteOverlay(deleteButton)
|
||||
Script.clearInterval(blockSpawner);
|
||||
}
|
||||
|
||||
function destroyStuff() {
|
||||
for (var i = 0; i < floorTiles.length; i++) {
|
||||
Entities.deleteEntity(floorTiles[i]);
|
||||
}
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
Entities.deleteEntity(blocks[i]);
|
||||
}
|
||||
Script.clearInterval(blockSpawner);
|
||||
|
||||
}
|
||||
|
||||
function randFloat(low, high) {
|
||||
return Math.floor(low + Math.random() * (high - low));
|
||||
}
|
||||
|
||||
function map(value, min1, max1, min2, max2) {
|
||||
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
|
@ -67,20 +67,6 @@ var pointerButton = Overlays.addOverlay("image", {
|
|||
|
||||
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2.0, Quat.getFront(Camera.getOrientation())));
|
||||
center.y += 0.5;
|
||||
var whiteBoard = Entities.addEntity({
|
||||
type: "Box",
|
||||
position: center,
|
||||
dimensions: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
z: .001
|
||||
},
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
}
|
||||
});
|
||||
|
||||
function calculateNearLinePosition(targetPosition) {
|
||||
var handPosition = MyAvatar.getRightPalmPosition();
|
||||
|
@ -243,7 +229,6 @@ function keyReleaseEvent(event) {
|
|||
}
|
||||
|
||||
function cleanup() {
|
||||
Entities.deleteEntity(whiteBoard);
|
||||
for (var i = 0; i < strokes.length; i++) {
|
||||
Entities.deleteEntity(strokes[i]);
|
||||
}
|
||||
|
|
43
examples/voxels.js
Normal file
43
examples/voxels.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
var controlHeld = false;
|
||||
|
||||
|
||||
function mousePressEvent(event) {
|
||||
if (!event.isLeftButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||
// var props = Entities.getEntityProperties(intersection.entityID);
|
||||
if (intersection.intersects) {
|
||||
var ids = Entities.findEntities(intersection.intersection, 10);
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
var id = ids[i];
|
||||
if (controlHeld) {
|
||||
Entities.setVoxelSphere(id, intersection.intersection, 1.2, 0);
|
||||
} else {
|
||||
Entities.setVoxelSphere(id, intersection.intersection, 1.2, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function keyPressEvent(event) {
|
||||
if (event.text == "CONTROL") {
|
||||
controlHeld = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function keyReleaseEvent(event) {
|
||||
if (event.text == "CONTROL") {
|
||||
controlHeld = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
|
@ -1948,7 +1948,9 @@ FaceTracker* Application::getSelectedFaceTracker() {
|
|||
}
|
||||
|
||||
void Application::setActiveFaceTracker() {
|
||||
#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)
|
||||
bool isMuted = Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking);
|
||||
#endif
|
||||
#ifdef HAVE_FACESHIFT
|
||||
auto faceshiftTracker = DependencyManager::get<Faceshift>();
|
||||
faceshiftTracker->setIsMuted(isMuted);
|
||||
|
|
|
@ -356,7 +356,7 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) {
|
|||
});
|
||||
|
||||
if (!Application::getInstance()->isMouseHidden()) {
|
||||
renderPointersOculus(myAvatar->getDefaultEyePosition());
|
||||
renderPointersOculus();
|
||||
}
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
@ -486,49 +486,40 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi
|
|||
direction = glm::normalize(intersectionWithUi - origin);
|
||||
}
|
||||
|
||||
glm::vec2 getPolarCoordinates(const PalmData& palm) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
auto avatarOrientation = myAvatar->getOrientation();
|
||||
auto eyePos = myAvatar->getDefaultEyePosition();
|
||||
glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm);
|
||||
// Direction of the tip relative to the eye
|
||||
glm::vec3 tipDirection = tip - eyePos;
|
||||
// orient into avatar space
|
||||
tipDirection = glm::inverse(avatarOrientation) * tipDirection;
|
||||
// Normalize for trig functions
|
||||
tipDirection = glm::normalize(tipDirection);
|
||||
// Convert to polar coordinates
|
||||
glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y));
|
||||
return polar;
|
||||
}
|
||||
|
||||
//Caculate the click location using one of the sixense controllers. Scale is not applied
|
||||
QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm);
|
||||
glm::vec3 eyePos = myAvatar->getHead()->getEyePosition();
|
||||
glm::quat invOrientation = glm::inverse(myAvatar->getOrientation());
|
||||
//direction of ray goes towards camera
|
||||
glm::vec3 dir = invOrientation * glm::normalize(qApp->getCamera()->getPosition() - tip);
|
||||
glm::vec3 tipPos = invOrientation * (tip - eyePos);
|
||||
|
||||
QPoint rv;
|
||||
auto canvasSize = qApp->getCanvasSize();
|
||||
if (qApp->isHMDMode()) {
|
||||
float t;
|
||||
|
||||
//We back the ray up by dir to ensure that it will not start inside the UI.
|
||||
glm::vec3 adjustedPos = tipPos - dir;
|
||||
//Find intersection of crosshair ray.
|
||||
if (raySphereIntersect(dir, adjustedPos, _oculusUIRadius * myAvatar->getScale(), &t)){
|
||||
glm::vec3 collisionPos = adjustedPos + dir * t;
|
||||
//Normalize it in case its not a radius of 1
|
||||
collisionPos = glm::normalize(collisionPos);
|
||||
//If we hit the back hemisphere, mark it as not a collision
|
||||
if (collisionPos.z > 0) {
|
||||
rv.setX(INT_MAX);
|
||||
rv.setY(INT_MAX);
|
||||
} else {
|
||||
|
||||
float u = asin(collisionPos.x) / (_textureFov)+0.5f;
|
||||
float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f);
|
||||
|
||||
rv.setX(u * canvasSize.x);
|
||||
rv.setY(v * canvasSize.y);
|
||||
}
|
||||
} else {
|
||||
//if they did not click on the overlay, just set the coords to INT_MAX
|
||||
rv.setX(INT_MAX);
|
||||
rv.setY(INT_MAX);
|
||||
}
|
||||
glm::vec2 polar = getPolarCoordinates(*palm);
|
||||
glm::vec2 point = sphericalToScreen(-polar);
|
||||
rv.rx() = point.x;
|
||||
rv.ry() = point.y;
|
||||
} else {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
glm::dmat4 projection;
|
||||
qApp->getProjectionMatrix(&projection);
|
||||
glm::quat invOrientation = glm::inverse(myAvatar->getOrientation());
|
||||
glm::vec3 eyePos = myAvatar->getDefaultEyePosition();
|
||||
glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm);
|
||||
glm::vec3 tipPos = invOrientation * (tip - eyePos);
|
||||
|
||||
glm::vec4 clipSpacePos = glm::vec4(projection * glm::dvec4(tipPos, 1.0));
|
||||
glm::vec3 ndcSpacePos;
|
||||
|
@ -729,7 +720,7 @@ void ApplicationOverlay::renderControllerPointers() {
|
|||
}
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
|
||||
void ApplicationOverlay::renderPointersOculus() {
|
||||
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
@ -737,16 +728,12 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
|
|||
//Controller Pointers
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
|
||||
|
||||
PalmData& palm = myAvatar->getHand()->getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm);
|
||||
glm::vec3 tipDirection = glm::normalize(glm::inverse(myAvatar->getOrientation()) * (tip - eyePos));
|
||||
float pitch = -glm::asin(tipDirection.y);
|
||||
float yawSign = glm::sign(-tipDirection.x);
|
||||
float yaw = glm::acos(-tipDirection.z) *
|
||||
((yawSign == 0.0f) ? 1.0f : yawSign);
|
||||
glm::quat orientation = glm::quat(glm::vec3(pitch, yaw, 0.0f));
|
||||
glm::vec2 polar = getPolarCoordinates(palm);
|
||||
// Convert to quaternion
|
||||
glm::quat orientation = glm::quat(glm::vec3(polar.y, -polar.x, 0.0f));
|
||||
// Render reticle at location
|
||||
renderReticle(orientation, _alpha);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ private:
|
|||
void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder);
|
||||
|
||||
void renderControllerPointers();
|
||||
void renderPointersOculus(const glm::vec3& eyePos);
|
||||
void renderPointersOculus();
|
||||
|
||||
void renderAudioMeter();
|
||||
void renderCameraToggle();
|
||||
|
|
|
@ -12,4 +12,9 @@ find_package(Bullet REQUIRED)
|
|||
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
|
||||
|
||||
add_dependency_external_projects(polyvox)
|
||||
find_package(PolyVox REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${POLYVOX_LIBRARIES})
|
||||
|
||||
link_hifi_libraries(shared gpu script-engine render-utils)
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "RenderableWebEntityItem.h"
|
||||
#include "RenderableZoneEntityItem.h"
|
||||
#include "RenderableLineEntityItem.h"
|
||||
#include "RenderablePolyVoxEntityItem.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
|
||||
EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
||||
|
@ -65,6 +66,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Zone, RenderableZoneEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Line, RenderableLineEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(PolyVox, RenderablePolyVoxEntityItem::factory)
|
||||
|
||||
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
||||
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
||||
|
|
336
libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp
Normal file
336
libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp
Normal file
|
@ -0,0 +1,336 @@
|
|||
//
|
||||
// RenderablePolyVoxEntityItem.cpp
|
||||
// libraries/entities-renderer/src/
|
||||
//
|
||||
// Created by Seth Alves on 5/19/15.
|
||||
// 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
|
||||
//
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#include <gpu/GPUConfig.h>
|
||||
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <Model.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include <PolyVoxCore/CubicSurfaceExtractorWithNormals.h>
|
||||
#include <PolyVoxCore/MarchingCubesSurfaceExtractor.h>
|
||||
#include <PolyVoxCore/SurfaceMesh.h>
|
||||
#include <PolyVoxCore/SimpleVolume.h>
|
||||
#include <PolyVoxCore/Raycast.h>
|
||||
#include <PolyVoxCore/Material.h>
|
||||
|
||||
#include "model/Geometry.h"
|
||||
#include "gpu/GLBackend.h"
|
||||
#include "EntityTreeRenderer.h"
|
||||
#include "RenderablePolyVoxEntityItem.h"
|
||||
|
||||
|
||||
EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return EntityItemPointer(new RenderablePolyVoxEntityItem(entityID, properties));
|
||||
}
|
||||
|
||||
RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() {
|
||||
delete _volData;
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) {
|
||||
|
||||
if (_volData && voxelVolumeSize == _voxelVolumeSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "resetting voxel-space size";
|
||||
|
||||
PolyVoxEntityItem::setVoxelVolumeSize(voxelVolumeSize);
|
||||
|
||||
if (_volData) {
|
||||
delete _volData;
|
||||
}
|
||||
|
||||
PolyVox::Vector3DInt32 lowCorner(0, 0, 0);
|
||||
PolyVox::Vector3DInt32 highCorner(_voxelVolumeSize[0] - 1, // -1 because these corners are inclusive
|
||||
_voxelVolumeSize[1] - 1,
|
||||
_voxelVolumeSize[2] - 1);
|
||||
|
||||
_volData = new PolyVox::SimpleVolume<uint8_t>(PolyVox::Region(lowCorner, highCorner));
|
||||
}
|
||||
|
||||
|
||||
void RenderablePolyVoxEntityItem::setVoxelData(QByteArray voxelData) {
|
||||
if (voxelData == _voxelData) {
|
||||
return;
|
||||
}
|
||||
PolyVoxEntityItem::setVoxelData(voxelData);
|
||||
decompressVolumeData();
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const {
|
||||
glm::vec3 scale = _dimensions / _voxelVolumeSize; // meters / voxel-units
|
||||
glm::mat4 scaled = glm::scale(glm::mat4(), scale);
|
||||
glm::mat4 centerToCorner = glm::translate(scaled, _voxelVolumeSize / -2.0f);
|
||||
glm::mat4 rotation = glm::mat4_cast(_rotation);
|
||||
glm::mat4 translation = glm::translate(getCenter());
|
||||
return translation * rotation * centerToCorner;
|
||||
}
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::worldToVoxelMatrix() const {
|
||||
glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix());
|
||||
return worldToModelMatrix;
|
||||
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {
|
||||
// This three-level for loop iterates over every voxel in the volume
|
||||
for (int z = 0; z < _volData->getDepth(); z++) {
|
||||
for (int y = 0; y < _volData->getHeight(); y++) {
|
||||
for (int x = 0; x < _volData->getWidth(); x++) {
|
||||
// Store our current position as a vector...
|
||||
glm::vec3 pos(x, y, z);
|
||||
// And compute how far the current position is from the center of the volume
|
||||
float fDistToCenter = glm::distance(pos, center);
|
||||
// If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||
if (fDistToCenter <= radius) {
|
||||
_volData->setVoxelAt(x, y, z, toValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
compressVolumeData();
|
||||
_needsModelReload = true;
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) {
|
||||
// glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords);
|
||||
glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f);
|
||||
glm::vec3 scale = _dimensions / _voxelVolumeSize; // meters / voxel-units
|
||||
float scaleY = scale[0];
|
||||
float radiusVoxelCoords = radiusWorldCoords / scaleY;
|
||||
setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue);
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::getModel() {
|
||||
if (!_volData) {
|
||||
// this will cause the allocation of _volData
|
||||
setVoxelVolumeSize(_voxelVolumeSize);
|
||||
}
|
||||
|
||||
// A mesh object to hold the result of surface extraction
|
||||
PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal> polyVoxMesh;
|
||||
|
||||
switch (_voxelSurfaceStyle) {
|
||||
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: {
|
||||
PolyVox::MarchingCubesSurfaceExtractor<PolyVox::SimpleVolume<uint8_t>> surfaceExtractor
|
||||
(_volData, _volData->getEnclosingRegion(), &polyVoxMesh);
|
||||
surfaceExtractor.execute();
|
||||
break;
|
||||
}
|
||||
case PolyVoxEntityItem::SURFACE_CUBIC: {
|
||||
PolyVox::CubicSurfaceExtractorWithNormals<PolyVox::SimpleVolume<uint8_t>> surfaceExtractor
|
||||
(_volData, _volData->getEnclosingRegion(), &polyVoxMesh);
|
||||
surfaceExtractor.execute();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// convert PolyVox mesh to a Sam mesh
|
||||
model::Mesh* mesh = new model::Mesh();
|
||||
model::MeshPointer meshPtr(mesh);
|
||||
|
||||
const std::vector<uint32_t>& vecIndices = polyVoxMesh.getIndices();
|
||||
auto indexBuffer = new gpu::Buffer(vecIndices.size() * sizeof(uint32_t), (gpu::Byte*)vecIndices.data());
|
||||
auto indexBufferPtr = gpu::BufferPointer(indexBuffer);
|
||||
mesh->setIndexBuffer(gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW)));
|
||||
|
||||
|
||||
const std::vector<PolyVox::PositionMaterialNormal>& vecVertices = polyVoxMesh.getVertices();
|
||||
auto vertexBuffer = new gpu::Buffer(vecVertices.size() * sizeof(PolyVox::PositionMaterialNormal),
|
||||
(gpu::Byte*)vecVertices.data());
|
||||
auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer);
|
||||
mesh->setVertexBuffer(gpu::BufferView(vertexBufferPtr,
|
||||
0,
|
||||
vertexBufferPtr->getSize() - sizeof(float) * 3,
|
||||
sizeof(PolyVox::PositionMaterialNormal),
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
|
||||
mesh->addAttribute(gpu::Stream::NORMAL,
|
||||
gpu::BufferView(vertexBufferPtr,
|
||||
sizeof(float) * 3,
|
||||
vertexBufferPtr->getSize() - sizeof(float) * 3,
|
||||
sizeof(PolyVox::PositionMaterialNormal),
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
|
||||
|
||||
// auto normalAttrib = mesh->getAttributeBuffer(gpu::Stream::NORMAL);
|
||||
// for (auto normal = normalAttrib.begin<glm::vec3>(); normal != normalAttrib.end<glm::vec3>(); normal++) {
|
||||
// (*normal) = -(*normal);
|
||||
// }
|
||||
|
||||
qDebug() << "---- vecIndices.size() =" << vecIndices.size();
|
||||
qDebug() << "---- vecVertices.size() =" << vecVertices.size();
|
||||
|
||||
_modelGeometry.setMesh(meshPtr);
|
||||
_needsModelReload = false;
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render");
|
||||
assert(getType() == EntityTypes::PolyVox);
|
||||
|
||||
if (_needsModelReload) {
|
||||
getModel();
|
||||
}
|
||||
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
glm::vec3 scale = dimensions / _voxelVolumeSize;
|
||||
glm::vec3 center = getCenter();
|
||||
glm::quat rotation = getRotation();
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
glm::vec3 positionToCenter = center - position;
|
||||
// make the rendered voxel volume be centered on the entity's position
|
||||
positionToCenter -= _dimensions * glm::vec3(0.5f,0.5f,0.5f);
|
||||
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
|
||||
glScalef(scale.x, scale.y, scale.z);
|
||||
|
||||
auto mesh = _modelGeometry.getMesh();
|
||||
gpu::Batch batch;
|
||||
batch.setInputFormat(mesh->getVertexFormat());
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, mesh->getVertexBuffer());
|
||||
batch.setInputBuffer(gpu::Stream::NORMAL,
|
||||
mesh->getVertexBuffer()._buffer,
|
||||
sizeof(float) * 3,
|
||||
mesh->getVertexBuffer()._stride);
|
||||
batch.setIndexBuffer(gpu::UINT32, mesh->getIndexBuffer()._buffer, 0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
glPopMatrix();
|
||||
RenderableDebugableEntityItem::render(this, args);
|
||||
}
|
||||
|
||||
class RaycastFunctor
|
||||
{
|
||||
public:
|
||||
RaycastFunctor() : _result(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) { }
|
||||
bool operator()(PolyVox::SimpleVolume<unsigned char>::Sampler& sampler)
|
||||
{
|
||||
if (sampler.getVoxel() == 0) {
|
||||
return true; // keep raycasting
|
||||
}
|
||||
PolyVox::Vector3DInt32 positionIndex = sampler.getPosition();
|
||||
_result = glm::vec4(positionIndex.getX(), positionIndex.getY(), positionIndex.getZ(), 1.0f);
|
||||
return false;
|
||||
}
|
||||
glm::vec4 _result;
|
||||
};
|
||||
|
||||
bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin,
|
||||
const glm::vec3& direction,
|
||||
bool& keepSearching,
|
||||
OctreeElement*& element,
|
||||
float& distance, BoxFace& face,
|
||||
void** intersectedObject,
|
||||
bool precisionPicking) const
|
||||
{
|
||||
if (_needsModelReload || !precisionPicking) {
|
||||
// just intersect with bounding box
|
||||
return true;
|
||||
}
|
||||
|
||||
glm::mat4 wtvMatrix = worldToVoxelMatrix();
|
||||
glm::vec3 farPoint = origin + direction;
|
||||
glm::vec4 originInVoxel = wtvMatrix * glm::vec4(origin, 1.0f);
|
||||
glm::vec4 farInVoxel = wtvMatrix * glm::vec4(farPoint, 1.0f);
|
||||
glm::vec4 directionInVoxel = farInVoxel - originInVoxel;
|
||||
|
||||
PolyVox::Vector3DFloat start(originInVoxel[0], originInVoxel[1], originInVoxel[2]);
|
||||
PolyVox::Vector3DFloat pvDirection(directionInVoxel[0], directionInVoxel[1], directionInVoxel[2]);
|
||||
pvDirection.normalise();
|
||||
|
||||
// the PolyVox ray intersection code requires a near and far point.
|
||||
glm::vec3 scale = _dimensions / _voxelVolumeSize; // meters / voxel-units
|
||||
float distanceToEntity = glm::distance(origin, _position);
|
||||
float largestDimension = glm::max(_dimensions[0], _dimensions[1], _dimensions[2]);
|
||||
// set ray cast length to long enough to cover all of the voxel space
|
||||
pvDirection *= (distanceToEntity + largestDimension) / glm::min(scale[0], scale[1], scale[2]);
|
||||
|
||||
PolyVox::RaycastResult raycastResult;
|
||||
RaycastFunctor callback;
|
||||
raycastResult = PolyVox::raycastWithDirection(_volData, start, pvDirection, callback);
|
||||
|
||||
if (raycastResult == PolyVox::RaycastResults::Completed) {
|
||||
// the ray completed its path -- nothing was hit.
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * callback._result;
|
||||
|
||||
distance = glm::distance(glm::vec3(intersectedWorldPosition), origin);
|
||||
|
||||
face = BoxFace::MIN_X_FACE; // XXX
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// compress the data in _volData and save the results. The compressed form is used during
|
||||
// saves to disk and for transmission over the wire
|
||||
void RenderablePolyVoxEntityItem::compressVolumeData() {
|
||||
int rawSize = _volData->getDepth() * _volData->getHeight() * _volData->getWidth();
|
||||
QByteArray uncompressedData = QByteArray(rawSize, '\0');
|
||||
|
||||
for (int z = 0; z < _volData->getDepth(); z++) {
|
||||
for (int y = 0; y < _volData->getHeight(); y++) {
|
||||
for (int x = 0; x < _volData->getWidth(); x++) {
|
||||
uint8_t uVoxelValue = _volData->getVoxelAt(x, y, z);
|
||||
int uncompressedIndex = z * _volData->getHeight() * _volData->getWidth() + y * _volData->getWidth() + x;
|
||||
uncompressedData[uncompressedIndex] = uVoxelValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray newVoxelData = qCompress(uncompressedData, 9);
|
||||
// HACK -- until we have a way to allow for properties larger than MTU, don't update.
|
||||
if (newVoxelData.length() < 1200) {
|
||||
_voxelData = newVoxelData;
|
||||
qDebug() << "-------------- voxel compresss --------------";
|
||||
qDebug() << "raw-size =" << rawSize << " compressed-size =" << newVoxelData.size();
|
||||
} else {
|
||||
qDebug() << "voxel data too large, reverting change.";
|
||||
// revert
|
||||
decompressVolumeData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// take compressed data and decompreess it into _volData.
|
||||
void RenderablePolyVoxEntityItem::decompressVolumeData() {
|
||||
int rawSize = _volData->getDepth() * _volData->getHeight() * _volData->getWidth();
|
||||
QByteArray uncompressedData = QByteArray(rawSize, '\0');
|
||||
|
||||
uncompressedData = qUncompress(_voxelData);
|
||||
|
||||
for (int z = 0; z < _volData->getDepth(); z++) {
|
||||
for (int y = 0; y < _volData->getHeight(); y++) {
|
||||
for (int x = 0; x < _volData->getWidth(); x++) {
|
||||
int uncompressedIndex = z * _volData->getHeight() * _volData->getWidth() + y * _volData->getWidth() + x;
|
||||
_volData->setVoxelAt(x, y, z, uncompressedData[uncompressedIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_needsModelReload = true;
|
||||
|
||||
qDebug() << "--------------- voxel decompress ---------------";
|
||||
qDebug() << "raw-size =" << rawSize << " compressed-size =" << _voxelData.size();
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// RenderablePolyVoxEntityItem.h
|
||||
// libraries/entities-renderer/src/
|
||||
//
|
||||
// Created by Seth Alves on 5/19/15.
|
||||
// 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_RenderablePolyVoxEntityItem_h
|
||||
#define hifi_RenderablePolyVoxEntityItem_h
|
||||
|
||||
#include <PolyVoxCore/SimpleVolume.h>
|
||||
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
|
||||
class RenderablePolyVoxEntityItem : public PolyVoxEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderablePolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
PolyVoxEntityItem(entityItemID, properties) { }
|
||||
|
||||
virtual ~RenderablePolyVoxEntityItem();
|
||||
|
||||
virtual void somethingChangedNotification() {
|
||||
// This gets called from EnityItem::readEntityDataFromBuffer every time a packet describing
|
||||
// this entity comes from the entity-server. It gets called even if nothing has actually changed
|
||||
// (see the comment in EntityItem.cpp). If that gets fixed, this could be used to know if we
|
||||
// need to redo the voxel data.
|
||||
// _needsModelReload = true;
|
||||
}
|
||||
|
||||
|
||||
void render(RenderArgs* args);
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||
void** intersectedObject, bool precisionPicking) const;
|
||||
|
||||
void getModel();
|
||||
|
||||
virtual void setVoxelData(QByteArray voxelData);
|
||||
|
||||
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
|
||||
glm::mat4 voxelToWorldMatrix() const;
|
||||
glm::mat4 worldToVoxelMatrix() const;
|
||||
|
||||
// coords are in voxel-volume space
|
||||
virtual void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue);
|
||||
|
||||
// coords are in world-space
|
||||
virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue);
|
||||
|
||||
private:
|
||||
void compressVolumeData();
|
||||
void decompressVolumeData();
|
||||
|
||||
PolyVox::SimpleVolume<uint8_t>* _volData = nullptr;
|
||||
model::Geometry _modelGeometry;
|
||||
bool _needsModelReload = true;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_RenderablePolyVoxEntityItem_h
|
|
@ -183,9 +183,9 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
QByteArray encodedPropertyFlags;
|
||||
int propertyCount = 0;
|
||||
|
||||
successIDFits = packetData->appendValue(encodedID);
|
||||
successIDFits = packetData->appendRawData(encodedID);
|
||||
if (successIDFits) {
|
||||
successTypeFits = packetData->appendValue(encodedType);
|
||||
successTypeFits = packetData->appendRawData(encodedType);
|
||||
}
|
||||
if (successTypeFits) {
|
||||
successCreatedFits = packetData->appendValue(_created);
|
||||
|
@ -194,17 +194,17 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
successLastEditedFits = packetData->appendValue(lastEdited);
|
||||
}
|
||||
if (successLastEditedFits) {
|
||||
successLastUpdatedFits = packetData->appendValue(encodedUpdateDelta);
|
||||
successLastUpdatedFits = packetData->appendRawData(encodedUpdateDelta);
|
||||
}
|
||||
if (successLastUpdatedFits) {
|
||||
successLastSimulatedFits = packetData->appendValue(encodedSimulatedDelta);
|
||||
successLastSimulatedFits = packetData->appendRawData(encodedSimulatedDelta);
|
||||
}
|
||||
|
||||
if (successLastSimulatedFits) {
|
||||
propertyFlagsOffset = packetData->getUncompressedByteOffset();
|
||||
encodedPropertyFlags = propertyFlags;
|
||||
oldPropertyFlagsLength = encodedPropertyFlags.length();
|
||||
successPropertyFlagsFits = packetData->appendValue(encodedPropertyFlags);
|
||||
successPropertyFlagsFits = packetData->appendRawData(encodedPropertyFlags);
|
||||
}
|
||||
|
||||
bool headerFits = successIDFits && successTypeFits && successCreatedFits && successLastEditedFits
|
||||
|
@ -652,6 +652,7 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s
|
|||
// lastEdited
|
||||
quint64 lastEditedInLocalTime;
|
||||
memcpy(&lastEditedInLocalTime, dataAt, sizeof(lastEditedInLocalTime));
|
||||
assert(lastEditedInLocalTime > 0);
|
||||
quint64 lastEditedInServerTime = lastEditedInLocalTime + clockSkew;
|
||||
memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime));
|
||||
#ifdef WANT_DEBUG
|
||||
|
@ -956,9 +957,6 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
#endif
|
||||
setLastEdited(now);
|
||||
somethingChangedNotification(); // notify derived classes that something has changed
|
||||
if (_created == UNKNOWN_CREATED_TIME) {
|
||||
_created = now;
|
||||
}
|
||||
if (getDirtyFlags() & (EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES)) {
|
||||
// anything that sets the transform or velocity must update _lastSimulated which is used
|
||||
// for kinematic extrapolation (e.g. we want to extrapolate forward from this moment
|
||||
|
@ -967,6 +965,16 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
// timestamps
|
||||
quint64 timestamp = properties.getCreated();
|
||||
if (_created == UNKNOWN_CREATED_TIME && timestamp != UNKNOWN_CREATED_TIME) {
|
||||
quint64 now = usecTimestampNow();
|
||||
if (timestamp > now) {
|
||||
timestamp = now;
|
||||
}
|
||||
_created = timestamp;
|
||||
}
|
||||
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "ParticleEffectEntityItem.h"
|
||||
#include "TextEntityItem.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
#include "PolyVoxEntityItem.h"
|
||||
|
||||
AtmospherePropertyGroup EntityItemProperties::_staticAtmosphere;
|
||||
SkyboxPropertyGroup EntityItemProperties::_staticSkybox;
|
||||
|
@ -87,10 +88,14 @@ CONSTRUCT_PROPERTY(keyLightColor, ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR),
|
|||
CONSTRUCT_PROPERTY(keyLightIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY),
|
||||
CONSTRUCT_PROPERTY(keyLightAmbientIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY),
|
||||
CONSTRUCT_PROPERTY(keyLightDirection, ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION),
|
||||
CONSTRUCT_PROPERTY(voxelVolumeSize, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE),
|
||||
CONSTRUCT_PROPERTY(voxelData, PolyVoxEntityItem::DEFAULT_VOXEL_DATA),
|
||||
CONSTRUCT_PROPERTY(voxelSurfaceStyle, PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE),
|
||||
CONSTRUCT_PROPERTY(name, ENTITY_ITEM_DEFAULT_NAME),
|
||||
CONSTRUCT_PROPERTY(backgroundMode, BACKGROUND_MODE_INHERIT),
|
||||
CONSTRUCT_PROPERTY(sourceUrl, ""),
|
||||
|
||||
|
||||
_id(UNKNOWN_ENTITY_ID),
|
||||
_idSet(false),
|
||||
_lastEdited(0),
|
||||
|
@ -336,6 +341,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, keyLightDirection);
|
||||
CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_MODE, backgroundMode);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl);
|
||||
CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize);
|
||||
CHECK_PROPERTY_CHANGE(PROP_VOXEL_DATA, voxelData);
|
||||
CHECK_PROPERTY_CHANGE(PROP_VOXEL_SURFACE_STYLE, voxelSurfaceStyle);
|
||||
|
||||
changedProperties += _stage.getChangedProperties();
|
||||
changedProperties += _atmosphere.getChangedProperties();
|
||||
|
@ -418,6 +426,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightDirection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(backgroundMode, getBackgroundModeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(sourceUrl);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(voxelVolumeSize);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(voxelData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(voxelSurfaceStyle);
|
||||
|
||||
// Sitting properties support
|
||||
if (!skipDefaults) {
|
||||
|
@ -523,7 +535,11 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightDirection, glmVec3, setKeyLightDirection);
|
||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(backgroundMode, BackgroundMode);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl);
|
||||
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, glmVec3, setVoxelVolumeSize);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelData, QByteArray, setVoxelData);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelSurfaceStyle, uint16_t, setVoxelSurfaceStyle);
|
||||
|
||||
_stage.copyFromScriptValue(object, _defaultSettings);
|
||||
_atmosphere.copyFromScriptValue(object, _defaultSettings);
|
||||
_skybox.copyFromScriptValue(object, _defaultSettings);
|
||||
|
@ -619,23 +635,23 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
quint64 lastEdited = properties.getLastEdited();
|
||||
bool successLastEditedFits = packetData->appendValue(lastEdited);
|
||||
|
||||
bool successIDFits = packetData->appendValue(encodedID);
|
||||
bool successIDFits = packetData->appendRawData(encodedID);
|
||||
if (successIDFits) {
|
||||
successIDFits = packetData->appendValue(encodedToken);
|
||||
successIDFits = packetData->appendRawData(encodedToken);
|
||||
}
|
||||
bool successTypeFits = packetData->appendValue(encodedType);
|
||||
bool successTypeFits = packetData->appendRawData(encodedType);
|
||||
|
||||
// NOTE: We intentionally do not send "created" times in edit messages. This is because:
|
||||
// 1) if the edit is to an existing entity, the created time can not be changed
|
||||
// 2) if the edit is to a new entity, the created time is the last edited time
|
||||
|
||||
// TODO: Should we get rid of this in this in edit packets, since this has to always be 0?
|
||||
bool successLastUpdatedFits = packetData->appendValue(encodedUpdateDelta);
|
||||
bool successLastUpdatedFits = packetData->appendRawData(encodedUpdateDelta);
|
||||
|
||||
int propertyFlagsOffset = packetData->getUncompressedByteOffset();
|
||||
QByteArray encodedPropertyFlags = propertyFlags;
|
||||
int oldPropertyFlagsLength = encodedPropertyFlags.length();
|
||||
bool successPropertyFlagsFits = packetData->appendValue(encodedPropertyFlags);
|
||||
bool successPropertyFlagsFits = packetData->appendRawData(encodedPropertyFlags);
|
||||
int propertyCount = 0;
|
||||
|
||||
bool headerFits = successIDFits && successTypeFits && successLastEditedFits
|
||||
|
@ -740,6 +756,12 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
_staticSkybox.setProperties(properties);
|
||||
_staticSkybox.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::PolyVox) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_VOLUME_SIZE, properties.getVoxelVolumeSize());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_DATA, properties.getVoxelData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_SURFACE_STYLE, properties.getVoxelSurfaceStyle());
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, properties.getMarketplaceID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
|
||||
|
@ -974,11 +996,17 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
properties.getAtmosphere().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
|
||||
properties.getSkybox().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::PolyVox) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VOXEL_VOLUME_SIZE, glm::vec3, setVoxelVolumeSize);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VOXEL_DATA, QByteArray, setVoxelData);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VOXEL_SURFACE_STYLE, uint16_t, setVoxelSurfaceStyle);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
@ -1079,6 +1107,10 @@ void EntityItemProperties::markAllChanged() {
|
|||
_skybox.markAllChanged();
|
||||
|
||||
_sourceUrlChanged = true;
|
||||
|
||||
_voxelVolumeSizeChanged = true;
|
||||
_voxelDataChanged = true;
|
||||
_voxelSurfaceStyleChanged = true;
|
||||
}
|
||||
|
||||
/// The maximum bounding cube for the entity, independent of it's rotation.
|
||||
|
|
|
@ -54,6 +54,7 @@ class EntityItemProperties {
|
|||
friend class ZoneEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class WebEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class LineEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class PolyVoxEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
public:
|
||||
EntityItemProperties();
|
||||
virtual ~EntityItemProperties();
|
||||
|
@ -135,6 +136,9 @@ public:
|
|||
DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float);
|
||||
DEFINE_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float);
|
||||
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t);
|
||||
DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode);
|
||||
DEFINE_PROPERTY_GROUP(Stage, stage, StagePropertyGroup);
|
||||
|
@ -189,6 +193,8 @@ public:
|
|||
|
||||
QString getSimulatorIDAsString() const { return _simulatorID.toString().mid(1,36).toUpper(); }
|
||||
|
||||
void setVoxelDataDirty() { _voxelDataChanged = true; }
|
||||
|
||||
private:
|
||||
QUuid _id;
|
||||
bool _idSet;
|
||||
|
@ -219,7 +225,6 @@ void EntityItemPropertiesFromScriptValue(const QScriptValue &object, EntityItemP
|
|||
inline void EntityItemProperties::setPosition(const glm::vec3& value)
|
||||
{ _position = glm::clamp(value, 0.0f, (float)TREE_SCALE); _positionChanged = true; }
|
||||
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||
debug << "EntityItemProperties[" << "\n";
|
||||
|
||||
|
@ -281,6 +286,9 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
|||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundMode, backgroundMode, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, VoxelVolumeSize, voxelVolumeSize, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, VoxelData, voxelData, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, VoxelSurfaceStyle, voxelSurfaceStyle, "");
|
||||
|
||||
properties.getStage().debugDump();
|
||||
properties.getAtmosphere().debugDump();
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define READ_ENTITY_PROPERTY(P,T,S) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
int bytes = OctreePacketData::uppackDataFromBytes(dataAt, fromBuffer); \
|
||||
int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
bytesRead += bytes; \
|
||||
if (overwriteLocalData) { \
|
||||
|
@ -49,7 +49,7 @@
|
|||
#define READ_ENTITY_PROPERTY_TO_PROPERTIES(P,T,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
int bytes = OctreePacketData::uppackDataFromBytes(dataAt, fromBuffer); \
|
||||
int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
processedBytes += bytes; \
|
||||
properties.O(fromBuffer); \
|
||||
|
@ -91,10 +91,18 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScri
|
|||
inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, quint32 v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const QString& v) { return QScriptValue(v); }
|
||||
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const xColor& v) { return xColorToScriptValue(e, v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::quat& v) { return quatToScriptValue(e, v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const QScriptValue& v) { return v; }
|
||||
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) {
|
||||
QByteArray b64 = v.toBase64();
|
||||
return QScriptValue(QString(b64));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,g,P,p) \
|
||||
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P()) { \
|
||||
QScriptValue groupProperties = properties.property(#g); \
|
||||
|
@ -129,6 +137,16 @@ inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { re
|
|||
inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); }
|
||||
inline QString QString_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toString().trimmed(); }
|
||||
inline QUuid QUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); }
|
||||
|
||||
|
||||
inline QByteArray QByteArray_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = true;
|
||||
QString b64 = v.toVariant().toString().trimmed();
|
||||
return QByteArray::fromBase64(b64.toUtf8());
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
|
|
|
@ -110,6 +110,10 @@ enum EntityPropertyList {
|
|||
PROP_RESTITUTION,
|
||||
PROP_FRICTION,
|
||||
|
||||
PROP_VOXEL_VOLUME_SIZE,
|
||||
PROP_VOXEL_DATA,
|
||||
PROP_VOXEL_SURFACE_STYLE,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties ABOVE this line
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "ModelEntityItem.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
#include "EntitiesLogging.h"
|
||||
#include "PolyVoxEntityItem.h"
|
||||
|
||||
|
||||
EntityScriptingInterface::EntityScriptingInterface() :
|
||||
|
@ -382,3 +383,40 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
|
|||
vec3FromScriptValue(intersection, value.intersection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) {
|
||||
if (!_entityTree) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::setVoxelSphere no entity with ID" << entityID;
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityTypes::EntityType entityType = entity->getType();
|
||||
if (entityType != EntityTypes::PolyVox) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto now = usecTimestampNow();
|
||||
|
||||
PolyVoxEntityItem* polyVoxEntity = static_cast<PolyVoxEntityItem*>(entity.get());
|
||||
_entityTree->lockForWrite();
|
||||
polyVoxEntity->setSphere(center, radius, value);
|
||||
entity->setLastEdited(now);
|
||||
entity->setLastBroadcast(now);
|
||||
_entityTree->unlock();
|
||||
|
||||
_entityTree->lockForRead();
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
_entityTree->unlock();
|
||||
|
||||
properties.setVoxelDataDirty();
|
||||
properties.setLastEdited(now);
|
||||
|
||||
queueEntityMessage(PacketTypeEntityEdit, entityID, properties);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -117,6 +117,8 @@ public slots:
|
|||
Q_INVOKABLE void setSendPhysicsUpdates(bool value);
|
||||
Q_INVOKABLE bool getSendPhysicsUpdates() const;
|
||||
|
||||
Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value);
|
||||
|
||||
Q_INVOKABLE void dumpTree() const;
|
||||
|
||||
signals:
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "WebEntityItem.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
#include "LineEntityItem.h"
|
||||
#include "PolyVoxEntityItem.h"
|
||||
|
||||
QMap<EntityTypes::EntityType, QString> EntityTypes::_typeToNameMap;
|
||||
QMap<QString, EntityTypes::EntityType> EntityTypes::_nameToTypeMap;
|
||||
|
@ -45,6 +46,7 @@ REGISTER_ENTITY_TYPE(Text)
|
|||
REGISTER_ENTITY_TYPE(ParticleEffect)
|
||||
REGISTER_ENTITY_TYPE(Zone)
|
||||
REGISTER_ENTITY_TYPE(Line)
|
||||
REGISTER_ENTITY_TYPE(PolyVox)
|
||||
|
||||
const QString& EntityTypes::getEntityTypeName(EntityType entityType) {
|
||||
QMap<EntityType, QString>::iterator matchedTypeName = _typeToNameMap.find(entityType);
|
||||
|
|
|
@ -45,7 +45,8 @@ public:
|
|||
Zone,
|
||||
Web,
|
||||
Line,
|
||||
LAST = Line
|
||||
PolyVox,
|
||||
LAST = PolyVox
|
||||
} EntityType;
|
||||
|
||||
static const QString& getEntityTypeName(EntityType entityType);
|
||||
|
|
117
libraries/entities/src/PolyVoxEntityItem.cpp
Normal file
117
libraries/entities/src/PolyVoxEntityItem.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
//
|
||||
// PolyVoxEntityItem.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 5/11/15.
|
||||
// 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
|
||||
//
|
||||
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityTreeElement.h"
|
||||
|
||||
|
||||
const glm::vec3 PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE = glm::vec3(32, 32, 32);
|
||||
const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(qCompress(QByteArray(0), 9));
|
||||
const PolyVoxEntityItem::PolyVoxSurfaceStyle PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE =
|
||||
PolyVoxEntityItem::SURFACE_MARCHING_CUBES;
|
||||
|
||||
EntityItemPointer PolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return EntityItemPointer(new PolyVoxEntityItem(entityID, properties));
|
||||
}
|
||||
|
||||
PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID),
|
||||
_voxelVolumeSize(PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE),
|
||||
_voxelData(PolyVoxEntityItem::DEFAULT_VOXEL_DATA),
|
||||
_voxelSurfaceStyle(PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE)
|
||||
{
|
||||
_type = EntityTypes::PolyVox;
|
||||
_created = properties.getCreated();
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
EntityItemProperties PolyVoxEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelVolumeSize, getVoxelVolumeSize);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelData, getVoxelData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelSurfaceStyle, getVoxelSurfaceStyle);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(voxelVolumeSize, setVoxelVolumeSize);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(voxelData, setVoxelData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(voxelSurfaceStyle, setVoxelSurfaceStyle);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - getLastEdited();
|
||||
qCDebug(entities) << "PolyVoxEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties._lastEdited);
|
||||
}
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
|
||||
|
||||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_VOXEL_VOLUME_SIZE, glm::vec3, setVoxelVolumeSize);
|
||||
READ_ENTITY_PROPERTY(PROP_VOXEL_DATA, QByteArray, setVoxelData);
|
||||
READ_ENTITY_PROPERTY(PROP_VOXEL_SURFACE_STYLE, uint16_t, setVoxelSurfaceStyle);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_VOXEL_VOLUME_SIZE;
|
||||
requestedProperties += PROP_VOXEL_DATA;
|
||||
requestedProperties += PROP_VOXEL_SURFACE_STYLE;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
void PolyVoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_VOLUME_SIZE, getVoxelVolumeSize());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_DATA, getVoxelData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_SURFACE_STYLE, (uint16_t) getVoxelSurfaceStyle());
|
||||
}
|
||||
|
||||
void PolyVoxEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(entities) << " POLYVOX EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " position:" << debugTreeVector(_position);
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(_dimensions);
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
98
libraries/entities/src/PolyVoxEntityItem.h
Normal file
98
libraries/entities/src/PolyVoxEntityItem.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
//
|
||||
// PolyVoxEntityItem.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 5/11/15.
|
||||
// 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_PolyVoxEntityItem_h
|
||||
#define hifi_PolyVoxEntityItem_h
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
class PolyVoxEntityItem : public EntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
PolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
||||
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const;
|
||||
|
||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
||||
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
|
||||
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
|
||||
void setXColor(const xColor& value) {
|
||||
_color[RED_INDEX] = value.red;
|
||||
_color[GREEN_INDEX] = value.green;
|
||||
_color[BLUE_INDEX] = value.blue;
|
||||
}
|
||||
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_POLYVOX; }
|
||||
|
||||
// never have a ray intersection pick a PolyVoxEntityItem.
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||
void** intersectedObject, bool precisionPicking) const { return false; }
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize) { _voxelVolumeSize = voxelVolumeSize; }
|
||||
virtual const glm::vec3& getVoxelVolumeSize() const { return _voxelVolumeSize; }
|
||||
|
||||
virtual void setVoxelData(QByteArray voxelData) { _voxelData = voxelData; }
|
||||
virtual const QByteArray& getVoxelData() const { return _voxelData; }
|
||||
|
||||
enum PolyVoxSurfaceStyle {
|
||||
SURFACE_MARCHING_CUBES,
|
||||
SURFACE_CUBIC
|
||||
};
|
||||
|
||||
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) { _voxelSurfaceStyle = voxelSurfaceStyle; }
|
||||
virtual void setVoxelSurfaceStyle(uint16_t voxelSurfaceStyle) {
|
||||
_voxelSurfaceStyle = (PolyVoxSurfaceStyle) voxelSurfaceStyle;
|
||||
}
|
||||
virtual PolyVoxSurfaceStyle getVoxelSurfaceStyle() const { return _voxelSurfaceStyle; }
|
||||
|
||||
static const glm::vec3 DEFAULT_VOXEL_VOLUME_SIZE;
|
||||
static const QByteArray DEFAULT_VOXEL_DATA;
|
||||
static const PolyVoxSurfaceStyle DEFAULT_VOXEL_SURFACE_STYLE;
|
||||
|
||||
// coords are in voxel-volume space
|
||||
virtual void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {}
|
||||
|
||||
// coords are in world-space
|
||||
virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue) {}
|
||||
|
||||
protected:
|
||||
rgbColor _color;
|
||||
glm::vec3 _voxelVolumeSize; // this is always 3 bytes
|
||||
QByteArray _voxelData;
|
||||
PolyVoxSurfaceStyle _voxelSurfaceStyle;
|
||||
};
|
||||
|
||||
#endif // hifi_PolyVoxEntityItem_h
|
|
@ -228,13 +228,14 @@ public:
|
|||
{
|
||||
public:
|
||||
|
||||
Iterator(T* ptr = NULL) { _ptr = ptr; }
|
||||
Iterator(T* ptr = NULL, int stride = sizeof(T)): _ptr(ptr), _stride(stride) { }
|
||||
Iterator(const Iterator<T>& iterator) = default;
|
||||
~Iterator() {}
|
||||
|
||||
Iterator<T>& operator=(const Iterator<T>& iterator) = default;
|
||||
Iterator<T>& operator=(T* ptr) {
|
||||
_ptr = ptr;
|
||||
// stride is left unchanged
|
||||
return (*this);
|
||||
}
|
||||
|
||||
|
@ -249,42 +250,48 @@ public:
|
|||
bool operator==(const Iterator<T>& iterator) const { return (_ptr == iterator.getConstPtr()); }
|
||||
bool operator!=(const Iterator<T>& iterator) const { return (_ptr != iterator.getConstPtr()); }
|
||||
|
||||
void movePtr(const Index& movement) {
|
||||
auto byteptr = ((Byte*)_ptr);
|
||||
byteptr += _stride * movement;
|
||||
_ptr = (T*)byteptr;
|
||||
}
|
||||
|
||||
Iterator<T>& operator+=(const Index& movement) {
|
||||
_ptr += movement;
|
||||
movePtr(movement);
|
||||
return (*this);
|
||||
}
|
||||
Iterator<T>& operator-=(const Index& movement) {
|
||||
_ptr -= movement;
|
||||
movePtr(-movement);
|
||||
return (*this);
|
||||
}
|
||||
Iterator<T>& operator++() {
|
||||
++_ptr;
|
||||
movePtr(1);
|
||||
return (*this);
|
||||
}
|
||||
Iterator<T>& operator--() {
|
||||
--_ptr;
|
||||
movePtr(-1);
|
||||
return (*this);
|
||||
}
|
||||
Iterator<T> operator++(Index) {
|
||||
auto temp(*this);
|
||||
++_ptr;
|
||||
movePtr(1);
|
||||
return temp;
|
||||
}
|
||||
Iterator<T> operator--(Index) {
|
||||
auto temp(*this);
|
||||
--_ptr;
|
||||
movePtr(-1);
|
||||
return temp;
|
||||
}
|
||||
Iterator<T> operator+(const Index& movement) {
|
||||
auto oldPtr = _ptr;
|
||||
_ptr += movement;
|
||||
movePtr(movement);
|
||||
auto temp(*this);
|
||||
_ptr = oldPtr;
|
||||
return temp;
|
||||
}
|
||||
Iterator<T> operator-(const Index& movement) {
|
||||
auto oldPtr = _ptr;
|
||||
_ptr -= movement;
|
||||
movePtr(-movement);
|
||||
auto temp(*this);
|
||||
_ptr = oldPtr;
|
||||
return temp;
|
||||
|
@ -302,16 +309,17 @@ public:
|
|||
protected:
|
||||
|
||||
T* _ptr;
|
||||
int _stride;
|
||||
};
|
||||
|
||||
template <typename T> Iterator<T> begin() { return Iterator<T>(&edit<T>(0)); }
|
||||
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>())); }
|
||||
template <typename T> Iterator<const T> cbegin() const { return Iterator<const T>(&get<T>(0)); }
|
||||
template <typename T> Iterator<const T> cend() const { return Iterator<const T>(&get<T>(getNum<T>())); }
|
||||
template <typename T> Iterator<T> begin() { return Iterator<T>(&edit<T>(0), _stride); }
|
||||
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
|
||||
template <typename T> Iterator<const T> cbegin() const { return Iterator<const T>(&get<T>(0), _stride); }
|
||||
template <typename T> Iterator<const T> cend() const { return Iterator<const T>(&get<T>(getNum<T>()), _stride); }
|
||||
|
||||
// the number of elements of the specified type fitting in the view size
|
||||
template <typename T> Index getNum() const {
|
||||
return Index(_size / sizeof(T));
|
||||
return Index(_size / _stride);
|
||||
}
|
||||
|
||||
template <typename T> const T& get() const {
|
||||
|
@ -347,7 +355,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename T> const T& get(const Index index) const {
|
||||
Resource::Size elementOffset = index * sizeof(T) + _offset;
|
||||
Resource::Size elementOffset = index * _stride + _offset;
|
||||
#if _DEBUG
|
||||
if (!_buffer) {
|
||||
qDebug() << "Accessing null gpu::buffer!";
|
||||
|
@ -363,7 +371,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename T> T& edit(const Index index) const {
|
||||
Resource::Size elementOffset = index * sizeof(T) + _offset;
|
||||
Resource::Size elementOffset = index * _stride + _offset;
|
||||
#if _DEBUG
|
||||
if (!_buffer) {
|
||||
qDebug() << "Accessing null gpu::buffer!";
|
||||
|
|
|
@ -42,6 +42,15 @@ void Mesh::addAttribute(Slot slot, const BufferView& buffer) {
|
|||
evalVertexFormat();
|
||||
}
|
||||
|
||||
const BufferView Mesh::getAttributeBuffer(int attrib) const {
|
||||
auto attribBuffer = _attributeBuffers.find(attrib);
|
||||
if (attribBuffer != _attributeBuffers.end()) {
|
||||
return attribBuffer->second;
|
||||
} else {
|
||||
return BufferView();
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::evalVertexFormat() {
|
||||
auto vf = new VertexFormat();
|
||||
int channelNum = 0;
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
// Attribute Buffers
|
||||
int getNumAttributes() const { return _attributeBuffers.size(); }
|
||||
void addAttribute(Slot slot, const BufferView& buffer);
|
||||
const BufferView getAttributeBuffer(int attrib) const;
|
||||
|
||||
// Stream format
|
||||
const gpu::Stream::FormatPointer getVertexFormat() const { return _vertexFormat; }
|
||||
|
|
|
@ -107,7 +107,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
} else {
|
||||
// skybox has no cubemap, just clear the color buffer
|
||||
auto color = skybox.getColor();
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(skybox.getColor(),1.0f), 0.f, 0);
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 1.0f), 0.f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -426,7 +426,12 @@ bool OctreePacketData::appendValue(const QUuid& uuid) {
|
|||
}
|
||||
|
||||
bool OctreePacketData::appendValue(const QByteArray& bytes) {
|
||||
bool success = appendRawData((const unsigned char*)bytes.constData(), bytes.size());
|
||||
// TODO: make this a ByteCountCoded leading byte
|
||||
uint16_t length = bytes.size();
|
||||
bool success = appendValue(length);
|
||||
if (success) {
|
||||
success = appendRawData((const unsigned char*)bytes.constData(), bytes.size());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -451,6 +456,12 @@ bool OctreePacketData::appendRawData(const unsigned char* data, int length) {
|
|||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool OctreePacketData::appendRawData(QByteArray data) {
|
||||
return appendRawData((unsigned char *)data.data(), data.size());
|
||||
}
|
||||
|
||||
|
||||
quint64 OctreePacketData::_compressContentTime = 0;
|
||||
quint64 OctreePacketData::_compressContentCalls = 0;
|
||||
|
||||
|
@ -545,7 +556,7 @@ void OctreePacketData::debugContent() {
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, QString& result) {
|
||||
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QString& result) {
|
||||
uint16_t length;
|
||||
memcpy(&length, dataBytes, sizeof(length));
|
||||
dataBytes += sizeof(length);
|
||||
|
@ -554,7 +565,7 @@ int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, QStrin
|
|||
return sizeof(length) + length;
|
||||
}
|
||||
|
||||
int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, QUuid& result) {
|
||||
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QUuid& result) {
|
||||
uint16_t length;
|
||||
memcpy(&length, dataBytes, sizeof(length));
|
||||
dataBytes += sizeof(length);
|
||||
|
@ -567,9 +578,18 @@ int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, QUuid&
|
|||
return sizeof(length) + length;
|
||||
}
|
||||
|
||||
int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, xColor& result) {
|
||||
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, xColor& result) {
|
||||
result.red = dataBytes[RED_INDEX];
|
||||
result.green = dataBytes[GREEN_INDEX];
|
||||
result.blue = dataBytes[BLUE_INDEX];
|
||||
return sizeof(rgbColor);
|
||||
}
|
||||
|
||||
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) {
|
||||
uint16_t length;
|
||||
memcpy(&length, dataBytes, sizeof(length));
|
||||
dataBytes += sizeof(length);
|
||||
QByteArray value((const char*)dataBytes, length);
|
||||
result = value;
|
||||
return sizeof(length) + length;
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@ public:
|
|||
|
||||
/// appends raw bytes, might fail if byte would cause packet to be too large
|
||||
bool appendRawData(const unsigned char* data, int length);
|
||||
bool appendRawData(QByteArray data);
|
||||
|
||||
/// returns a byte offset from beginning of the uncompressed stream based on offset from end.
|
||||
/// Positive offsetFromEnd returns that many bytes before the end of uncompressed stream
|
||||
|
@ -226,20 +227,21 @@ public:
|
|||
static quint64 getTotalBytesOfBitMasks() { return _totalBytesOfBitMasks; } /// total bytes of bitmasks
|
||||
static quint64 getTotalBytesOfColor() { return _totalBytesOfColor; } /// total bytes of color
|
||||
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, float& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, bool& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, quint64& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, uint32_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, uint16_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, uint8_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, rgbColor& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, glm::quat& result) { int bytes = unpackOrientationQuatFromBytes(dataBytes, result); return bytes; }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, ShapeType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, BackgroundMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, QString& result);
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, QUuid& result);
|
||||
static int uppackDataFromBytes(const unsigned char* dataBytes, xColor& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, float& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, bool& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, quint64& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, uint32_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, uint16_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, uint8_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, rgbColor& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::quat& result) { int bytes = unpackOrientationQuatFromBytes(dataBytes, result); return bytes; }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, ShapeType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, BackgroundMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QString& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QUuid& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, xColor& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
|
||||
|
||||
private:
|
||||
/// appends raw bytes, might fail if byte would cause packet to be too large
|
||||
|
|
|
@ -35,7 +35,8 @@ enum ShapeType {
|
|||
SHAPE_TYPE_CYLINDER_X,
|
||||
SHAPE_TYPE_CYLINDER_Y,
|
||||
SHAPE_TYPE_CYLINDER_Z,
|
||||
SHAPE_TYPE_LINE
|
||||
SHAPE_TYPE_LINE,
|
||||
SHAPE_TYPE_POLYVOX
|
||||
};
|
||||
|
||||
class ShapeInfo {
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace MeshMassPropertiesTests{
|
|||
void testParallelAxisTheorem();
|
||||
void testTetrahedron();
|
||||
void testOpenTetrahedonMesh();
|
||||
void testClosedTetrahedronMesh();
|
||||
void testClosedTetrahedronMesh();
|
||||
void testBoxAsMesh();
|
||||
void runAllTests();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue