Merge branch 'master' into plugins_pt3

This commit is contained in:
Brad Davis 2015-05-29 09:05:01 -07:00
commit 8bad80324f
34 changed files with 1240 additions and 133 deletions

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -45,7 +45,8 @@ public:
Zone,
Web,
Line,
LAST = Line
PolyVox,
LAST = PolyVox
} EntityType;
static const QString& getEntityTypeName(EntityType entityType);

View 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);
}

View 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,7 +15,7 @@ namespace MeshMassPropertiesTests{
void testParallelAxisTheorem();
void testTetrahedron();
void testOpenTetrahedonMesh();
void testClosedTetrahedronMesh();
void testClosedTetrahedronMesh();
void testBoxAsMesh();
void runAllTests();
}