This commit is contained in:
Sam Gateau 2015-05-05 12:03:45 -07:00
commit 13482575d2
33 changed files with 1326 additions and 392 deletions

View file

@ -10,21 +10,41 @@
#
macro(SYMLINK_OR_COPY_DIRECTORY_BESIDE_TARGET _SHOULD_SYMLINK _DIRECTORY _DESTINATION)
# remove the current directory
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E remove_directory $<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}
)
if (${_SHOULD_SYMLINK})
# the caller wants a symlink, so just add a command to symlink the DIR beside target
# first create the destination
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E create_symlink
"${_DIRECTORY}"
COMMAND "${CMAKE_COMMAND}" -E make_directory
$<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}
)
else ()
# remove the current directory
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E remove_directory $<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}
)
# the caller wants a symlink, so just add a command to symlink all contents of _DIRECTORY
# in the destination - we can't simply create a symlink for _DESTINATION
# because the remove_directory call above would delete the original files
file(GLOB _DIR_ITEMS ${_DIRECTORY}/*)
foreach(_ITEM ${_DIR_ITEMS})
# get the filename for this item
get_filename_component(_ITEM_FILENAME ${_ITEM} NAME)
# add the command to symlink this item
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E create_symlink
${_ITEM}
$<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}/${_ITEM_FILENAME}
)
endforeach()
else ()
# copy the directory
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD

View file

@ -0,0 +1,69 @@
//
// changingAtmosphereExample.js
// examples
//
// Created by Brad Hefta-Gaub on 4/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// This is an example script that demonstrates creating a zone using the atmosphere features that changes scatter properties
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var count = 0;
var stopAfter = 10000;
var zoneEntityA = Entities.addEntity({
type: "Zone",
position: { x: 1000, y: 1000, z: 1000},
dimensions: { x: 2000, y: 2000, z: 2000 },
keyLightColor: { red: 255, green: 0, blue: 0 },
stageSunModelEnabled: false,
shapeType: "sphere",
skyboxMode: "atmosphere",
atmosphere: {
center: { x: 1000, y: 0, z: 1000},
innerRadius: 1000.0,
outerRadius: 1025.0,
rayleighScattering: 0.0025, // Meaningful values 0 to ~0.01
mieScattering: 0.0010, // Meaningful values 0 to ~0.01
// First two, Meaningful values 0 to 1 each, blue, purple; third meaningful 0.3 to 1 - affects shape
scatteringWavelengths: { x: 0.650, y: 0.570, z: 0.475 },
hasStars: true
},
stageLatitude: 37.777,
stageLongitude: 122.407,
stageAltitude: 0.03,
stageDay: 183,
stageHour: 5,
stageSunModelEnabled: true
});
// register the call back so it fires before each data send
Script.update.connect(function(deltaTime) {
// stop it...
if (count >= stopAfter) {
print("calling Script.stop()");
Script.stop();
}
count++;
var rayleighScattering = (count / 100000) % 0.01;
var mieScattering = (count / 100000) % 0.01;
var waveX = (count / 2000) % 1;
var waveZ = ((count / 2000) % 0.7) + 0.3;
Entities.editEntity(zoneEntityA, {
atmosphere: {
rayleighScattering: rayleighScattering,
mieScattering: mieScattering,
scatteringWavelengths: { x: waveX, y: waveX, z: waveZ }
},
});
});

View file

@ -0,0 +1,63 @@
//
// zoneAtmosphereExample.js
// examples
//
// Created by Brad Hefta-Gaub on 4/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// This is an example script that demonstrates creating a zone using the atmosphere features
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var count = 0;
var stopAfter = 10000;
var zoneEntityA = Entities.addEntity({
type: "Zone",
position: { x: 1000, y: 1000, z: 1000},
dimensions: { x: 2000, y: 2000, z: 2000 },
keyLightColor: { red: 255, green: 0, blue: 0 },
stageSunModelEnabled: false,
shapeType: "sphere",
skyboxMode: "atmosphere",
atmosphere: {
center: { x: 1000, y: 0, z: 1000},
innerRadius: 1000.0,
outerRadius: 1025.0,
rayleighScattering: 0.0025,
mieScattering: 0.0010,
scatteringWavelengths: { x: 0.650, y: 0.570, z: 0.475 },
hasStars: false
},
stageLatitude: 37.777,
stageLongitude: 122.407,
stageAltitude: 0.03,
stageDay: 60,
stageHour: 0,
stageSunModelEnabled: true
});
// register the call back so it fires before each data send
Script.update.connect(function(deltaTime) {
// stop it...
if (count >= stopAfter) {
print("calling Script.stop()");
Script.stop();
}
count++;
var newHour = (count / 10) % 24;
var newIntensity = ((count / 10) % 24) / 24;
print("newHour:" + newHour);
print("newIntensity:" + newIntensity);
Entities.editEntity(zoneEntityA, {
stageHour: newHour,
keyLightIntensity: newIntensity
});
});

View file

@ -1,3 +1,16 @@
// grab.js
// examples
//
// Created by Eric Levin on May 1, 2015
// Copyright 2015 High Fidelity, Inc.
//
// Grab's physically moveable entities with the mouse, by applying a spring force.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var isGrabbing = false;
var grabbedEntity = null;
var prevMouse = {};
@ -5,10 +18,22 @@ var deltaMouse = {
z: 0
}
var entityProps;
var targetPosition;
var moveUpDown = false;
var currentPosition, currentVelocity;
var CLOSE_ENOUGH = 0.001;
var FULL_STRENGTH = 0.11;
var SPRING_RATE = 1.5;
var DAMPING_RATE = 0.80;
var ANGULAR_DAMPING_RATE = 0.40;
var SCREEN_TO_METERS = 0.001;
var currentPosition, currentVelocity, cameraEntityDistance, currentRotation;
var velocityTowardTarget, desiredVelocity, addedVelocity, newVelocity, dPosition, camYaw, distanceToTarget, targetPosition;
var shouldRotate = false;
var dQ, theta, axisAngle, dT;
var angularVelocity = {
x: 0,
y: 0,
z: 0
};
var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav");
var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav");
@ -23,16 +48,6 @@ var DROP_WIDTH = 2;
var dropLine = Overlays.addOverlay("line3d", {
start: {
x: 0,
y: 0,
z: 0
},
end: {
x: 0,
y: 0,
z: 0
},
color: DROP_COLOR,
alpha: 1,
visible: false,
@ -51,8 +66,8 @@ function mousePressEvent(event) {
var props = Entities.getEntityProperties(grabbedEntity)
isGrabbing = true;
targetPosition = props.position;
currentPosition = props.position;
currentVelocity = props.velocity;
currentPosition = props.position;
currentVelocity = props.velocity;
updateDropLine(targetPosition);
Audio.playSound(grabSound, {
position: props.position,
@ -61,16 +76,20 @@ function mousePressEvent(event) {
}
}
function updateDropLine(position) {
Overlays.editOverlay(dropLine, {
visible: true,
start: position,
end: Vec3.sum(position, {
x: 0,
y: -DROP_DISTANCE,
z: 0
})
})
function updateDropLine(position) {
Overlays.editOverlay(dropLine, {
visible: true,
start: {
x: position.x,
y: position.y + DROP_DISTANCE,
z: position.z
},
end: {
x: position.x,
y: position.y - DROP_DISTANCE,
z: position.z
}
})
}
@ -100,14 +119,26 @@ function mouseMoveEvent(event) {
deltaMouse.z = 0;
}
// Update the target position by the amount the mouse moved
var camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y;
var dPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse);
// Adjust target position for the object by the mouse move
var avatarEntityDistance = Vec3.distance(Camera.getPosition(), currentPosition);
camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y;
dPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse);
if (!shouldRotate) {
// Adjust target position for the object by the mouse move
cameraEntityDistance = Vec3.distance(Camera.getPosition(), currentPosition);
// Scale distance we want to move by the distance from the camera to the grabbed object
// TODO: Correct SCREEN_TO_METERS to be correct for the actual FOV, resolution
var SCREEN_TO_METERS = 0.001;
targetPosition = Vec3.sum(targetPosition, Vec3.multiply(dPosition, avatarEntityDistance * SCREEN_TO_METERS));
targetPosition = Vec3.sum(targetPosition, Vec3.multiply(dPosition, cameraEntityDistance * SCREEN_TO_METERS));
} else if (shouldRotate) {
var transformedDeltaMouse = {
x: deltaMouse.z,
y: deltaMouse.x,
z: deltaMouse.y
};
transformedDeltaMouse = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), transformedDeltaMouse);
dQ = Quat.fromVec3Degrees(transformedDeltaMouse);
theta = 2 * Math.acos(dQ.w);
axisAngle = Quat.axis(dQ);
angularVelocity = Vec3.multiply((theta / dT), axisAngle);
}
}
prevMouse.x = event.x;
prevMouse.y = event.y;
@ -119,41 +150,60 @@ function keyReleaseEvent(event) {
if (event.text === "SHIFT") {
moveUpDown = false;
}
if (event.text === "SPACE") {
shouldRotate = false;
}
}
function keyPressEvent(event) {
if (event.text === "SHIFT") {
moveUpDown = true;
}
if (event.text === "SPACE") {
shouldRotate = true;
}
}
function update(deltaTime) {
dT = deltaTime;
if (isGrabbing) {
entityProps = Entities.getEntityProperties(grabbedEntity);
currentPosition = entityProps.position;
currentVelocity = entityProps.velocity;
currentPosition = entityProps.position;
currentVelocity = entityProps.velocity;
currentRotation = entityProps.rotation;
var dPosition = Vec3.subtract(targetPosition, currentPosition);
var CLOSE_ENOUGH = 0.001;
if (Vec3.length(dPosition) > CLOSE_ENOUGH) {
distanceToTarget = Vec3.length(dPosition);
if (distanceToTarget > CLOSE_ENOUGH) {
// compute current velocity in the direction we want to move
var velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition));
velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition));
velocityTowardTarget = Vec3.multiply(dPosition, velocityTowardTarget);
// compute the speed we would like to be going toward the target position
var SPRING_RATE = 0.35;
var DAMPING_RATE = 0.55;
var desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
// compute how much we want to add to the existing velocity
var addedVelocity = Vec3.subtract(desiredVelocity, velocityTowardTarget);
var newVelocity = Vec3.sum(currentVelocity, addedVelocity);
addedVelocity = Vec3.subtract(desiredVelocity, velocityTowardTarget);
// If target is too far, roll off the force as inverse square of distance
if (distanceToTarget / cameraEntityDistance > FULL_STRENGTH) {
addedVelocity = Vec3.multiply(addedVelocity, Math.pow(FULL_STRENGTH / distanceToTarget, 2.0));
}
newVelocity = Vec3.sum(currentVelocity, addedVelocity);
// Add Damping
newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE));
// Update entity
Entities.editEntity(grabbedEntity, {
velocity: newVelocity
})
}
updateDropLine(currentPosition);
//add damping to angular velocity:
}
if (shouldRotate) {
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
}
Entities.editEntity(grabbedEntity, {
velocity: newVelocity,
angularVelocity: angularVelocity
})
updateDropLine(targetPosition);
}
}
@ -162,5 +212,4 @@ Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.keyPressEvent.connect(keyPressEvent);
Controller.keyReleaseEvent.connect(keyReleaseEvent);
Script.update.connect(update);
Script.update.connect(update);

View file

@ -107,6 +107,10 @@ Item {
}
MenuItem { action: animations }
}
Menu {
title: "Long menu name top menu"
MenuItem { action: aboutApp }
}
Menu {
title: "Help"
MenuItem { action: aboutApp }

View file

@ -5,6 +5,7 @@ import QtQuick.Controls.Styles 1.3
import "controls"
import "styles"
Hifi.VrMenu {
id: root
HifiConstants { id: hifi }
@ -12,15 +13,14 @@ Hifi.VrMenu {
anchors.fill: parent
objectName: "VrMenu"
enabled: false
opacity: 0.0
z: 10000
property int animationDuration: 200
property var models: []
property var columns: []
z: 10000
onEnabledChanged: {
if (enabled && columns.length == 0) {
@ -51,20 +51,22 @@ Hifi.VrMenu {
property var menuBuilder: Component {
Border {
HifiConstants { id: hifi }
property int menuDepth
Component.onCompleted: {
menuDepth = root.models.length - 1
if (menuDepth == 0) {
x = lastMousePosition.x - 20
y = lastMousePosition.y - 20
} else {
var lastColumn = root.columns[menuDepth - 1]
var lastColumn = root.columns[menuDepth - 1]
x = lastColumn.x + 64;
y = lastMousePosition.y - height / 2;
}
}
border.color: hifi.colors.hifiBlue
color: hifi.colors.window
property int menuDepth
implicitHeight: listView.implicitHeight + 16
implicitWidth: listView.implicitWidth + 16
@ -84,167 +86,27 @@ Hifi.VrMenu {
model: root.models[menuDepth]
delegate: Loader {
id: loader
sourceComponent: root.itemBuilder
source: "VrMenuItem.qml"
Binding {
target: loader.item
property: "root"
property: "menuContainer"
value: root
when: loader.status == Loader.Ready
}
}
Binding {
target: loader.item
property: "source"
value: modelData
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "border"
value: listView.parent
when: loader.status == Loader.Ready
}
}
Binding {
target: loader.item
property: "listView"
value: listView
when: loader.status == Loader.Ready
}
}
}
}
}
}
property var itemBuilder: Component {
Item {
property var source
property var root
property var listView
property var border
implicitHeight: row.implicitHeight + 4
implicitWidth: row.implicitWidth + label.height
// FIXME uncommenting this line results in menus that have blank spots
// rather than having the correct size
// visible: source.visible
Row {
id: row
spacing: 2
anchors {
top: parent.top
topMargin: 2
}
Spacer { size: 4 }
FontAwesome {
id: check
verticalAlignment: Text.AlignVCenter
y: 2
size: label.height
text: checkText()
color: label.color
function checkText() {
if (!source || source.type != 1 || !source.checkable) {
return "";
}
// FIXME this works for native QML menus but I don't think it will
// for proxied QML menus
if (source.exclusiveGroup) {
return source.checked ? "\uF05D" : "\uF10C"
}
return source.checked ? "\uF046" : "\uF096"
}
}
Text {
id: label
text: typedText()
color: source.enabled ? hifi.colors.text : hifi.colors.disabledText
enabled: source.enabled && source.visible
function typedText() {
if (source) {
switch(source.type) {
case 2:
return source.title;
case 1:
return source.text;
case 0:
return "-----"
}
}
return ""
}
}
} // row
FontAwesome {
anchors {
top: row.top
}
id: tag
size: label.height
width: implicitWidth
visible: source.type == 2
x: listView.width - width - 4
text: "\uF0DA"
color: label.color
}
MouseArea {
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
right: tag.right
rightMargin: -4
}
acceptedButtons: Qt.LeftButton
hoverEnabled: true
Rectangle {
id: highlight
visible: false
anchors.fill: parent
color: "#7f0e7077"
}
Timer {
id: timer
interval: 1000
onTriggered: parent.select();
}
onEntered: {
/*
* Uncomment below to have menus auto-popup
*
* FIXME if we enabled timer based menu popup, either the timer has
* to be very very short or after auto popup there has to be a small
* amount of time, or a test if the mouse has moved before a click
* will be accepted, otherwise it's too easy to accidently click on
* something immediately after the auto-popup appears underneath your
* cursor
*
*/
//if (source.type == 2 && enabled) {
// timer.start()
//}
highlight.visible = source.enabled
}
onExited: {
timer.stop()
highlight.visible = false
}
onClicked: {
select();
}
function select() {
//timer.stop();
var popped = false;
while (columns.length - 1 > listView.parent.menuDepth) {
popColumn();
popped = true;
}
if (!popped || source.type != 1) {
parent.root.selectItem(parent.source);
}
}
}
}
}
@ -259,7 +121,7 @@ Hifi.VrMenu {
var oldColumn = lastColumn();
//oldColumn.enabled = false
}
var newColumn = menuBuilder.createObject(root);
var newColumn = menuBuilder.createObject(root);
columns.push(newColumn);
newColumn.forceActiveFocus();
}
@ -292,11 +154,11 @@ Hifi.VrMenu {
source.trigger()
enabled = false
break;
case 0:
case 0:
break;
}
}
function reset() {
while (columns.length > 0) {
popColumn();

View file

@ -0,0 +1,130 @@
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import "controls"
import "styles"
Item {
id: root
HifiConstants {
id: hifi
}
property var source
property var menuContainer
property var listView
MouseArea {
anchors.left: parent.left
anchors.right: tag.right
anchors.rightMargin: -4
anchors.top: parent.top
anchors.bottom: parent.bottom
acceptedButtons: Qt.LeftButton
hoverEnabled: true
Rectangle {
id: highlight
visible: false
anchors.fill: parent
color: "#7f0e7077"
}
onEntered: {
//if (source.type == 2 && enabled) {
// timer.start()
//}
highlight.visible = source.enabled
}
onExited: {
timer.stop()
highlight.visible = false
}
onClicked: {
select()
}
}
implicitHeight: label.implicitHeight * 1.5
implicitWidth: label.implicitWidth + label.height * 2.5
Timer {
id: timer
interval: 1000
onTriggered: parent.select()
}
FontAwesome {
clip: true
id: check
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
anchors.verticalCenter: parent.verticalCenter
color: label.color
text: checkText()
size: label.height
font.pixelSize: size
function checkText() {
if (!source || source.type != 1 || !source.checkable) {
return ""
}
// FIXME this works for native QML menus but I don't think it will
// for proxied QML menus
if (source.exclusiveGroup) {
return source.checked ? "\uF05D" : "\uF10C"
}
return source.checked ? "\uF046" : "\uF096"
}
}
Text {
id: label
text: typedText()
anchors.left: check.right
anchors.leftMargin: 4
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
color: source.enabled ? hifi.colors.text : hifi.colors.disabledText
enabled: source.enabled && source.visible
function typedText() {
if (source) {
switch (source.type) {
case 2:
return source.title
case 1:
return source.text
case 0:
return "-----"
}
}
return ""
}
}
FontAwesome {
id: tag
x: listView.width - width - 4
size: label.height
width: implicitWidth
visible: source.type == 2
text: "\uF0DA"
anchors.verticalCenter: parent.verticalCenter
color: label.color
}
function select() {
//timer.stop();
var popped = false
while (columns.length - 1 > listView.parent.menuDepth) {
popColumn()
popped = true
}
if (!popped || source.type != 1) {
root.menuContainer.selectItem(source)
}
}
}

View file

@ -824,13 +824,18 @@ void Application::paintGL() {
glEnable(GL_LINE_SMOOTH);
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
// Always use the default eye position, not the actual head eye position.
// Using the latter will cause the camera to wobble with idle animations,
// or with changes from the face tracker
_myCamera.setPosition(_myAvatar->getDefaultEyePosition());
if (!OculusManager::isConnected()) {
// If there isn't an HMD, match exactly to avatar's head
_myCamera.setPosition(_myAvatar->getHead()->getEyePosition());
// If not using an HMD, grab the camera orientation directly
_myCamera.setRotation(_myAvatar->getHead()->getCameraOrientation());
} else {
// For an HMD, set the base position and orientation to that of the avatar body
_myCamera.setPosition(_myAvatar->getDefaultEyePosition());
// In an HMD, people can look up and down with their actual neck, and the
// per-eye HMD pose will be applied later. So set the camera orientation
// to only the yaw, excluding pitch and roll, i.e. an orientation that
// is orthongonal to the (body's) Y axis
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation());
}
@ -3071,11 +3076,11 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][2]);
}
// Render the stars and sky only if sky dome mode
// Background rendering decision
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) {
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) {
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
PerformanceTimer perfTimer("stars");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... stars...");
@ -3086,32 +3091,31 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
// compute starfield alpha based on distance from atmosphere
float alpha = 1.0f;
bool hasStars = true;
if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
// TODO: handle this correctly for zones
const EnvironmentData& closestData = _environment.getClosestData(theCamera.getPosition());
float height = glm::distance(theCamera.getPosition(),
closestData.getAtmosphereCenter(theCamera.getPosition()));
if (height < closestData.getAtmosphereInnerRadius()) {
alpha = 0.0f;
if (closestData.getHasStars()) {
float height = glm::distance(theCamera.getPosition(), closestData.getAtmosphereCenter());
if (height < closestData.getAtmosphereInnerRadius()) {
alpha = 0.0f;
} else if (height < closestData.getAtmosphereOuterRadius()) {
alpha = (height - closestData.getAtmosphereInnerRadius()) /
(closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius());
} else if (height < closestData.getAtmosphereOuterRadius()) {
alpha = (height - closestData.getAtmosphereInnerRadius()) /
(closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius());
}
} else {
hasStars = false;
}
}
// finally render the starfield
_stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha);
}
// draw the sky dome
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
PerformanceTimer perfTimer("atmosphere");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... atmosphere...");
_environment.renderAtmospheres(theCamera);
if (hasStars) {
_stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha);
}
}
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) {
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) {

View file

@ -282,6 +282,9 @@ public:
virtual int getBoundaryLevelAdjust() const;
virtual PickRay computePickRay(float x, float y);
virtual const glm::vec3& getAvatarPosition() const { return _myAvatar->getPosition(); }
virtual void overrideEnvironmentData(const EnvironmentData& newData) { _environment.override(newData); }
virtual void endOverrideEnvironmentData() { _environment.endOverride(); }
NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; }

View file

@ -71,15 +71,46 @@ void Environment::resetToDefault() {
void Environment::renderAtmospheres(Camera& camera) {
// get the lock for the duration of the call
QMutexLocker locker(&_mutex);
foreach (const ServerData& serverData, _data) {
// TODO: do something about EnvironmentData
foreach (const EnvironmentData& environmentData, serverData) {
renderAtmosphere(camera, environmentData);
if (_environmentIsOverridden) {
renderAtmosphere(camera, _overrideData);
} else {
foreach (const ServerData& serverData, _data) {
// TODO: do something about EnvironmentData
foreach (const EnvironmentData& environmentData, serverData) {
renderAtmosphere(camera, environmentData);
}
}
}
}
EnvironmentData Environment::getClosestData(const glm::vec3& position) {
if (_environmentIsOverridden) {
return _overrideData;
}
// get the lock for the duration of the call
QMutexLocker locker(&_mutex);
EnvironmentData closest;
float closestDistance = FLT_MAX;
foreach (const ServerData& serverData, _data) {
foreach (const EnvironmentData& environmentData, serverData) {
float distance = glm::distance(position, environmentData.getAtmosphereCenter(position)) -
environmentData.getAtmosphereOuterRadius();
if (distance < closestDistance) {
closest = environmentData;
closestDistance = distance;
}
}
}
return closest;
}
// NOTE: Deprecated - I'm leaving this in for now, but it's not actually used. I made it private
// so that if anyone wants to start using this in the future they will consider how to make it
// work with new physics systems.
glm::vec3 Environment::getGravity (const glm::vec3& position) {
//
// 'Default' gravity pulls you downward in Y when you are near the X/Z plane
@ -115,25 +146,6 @@ glm::vec3 Environment::getGravity (const glm::vec3& position) {
return gravity;
}
const EnvironmentData Environment::getClosestData(const glm::vec3& position) {
// get the lock for the duration of the call
QMutexLocker locker(&_mutex);
EnvironmentData closest;
float closestDistance = FLT_MAX;
foreach (const ServerData& serverData, _data) {
foreach (const EnvironmentData& environmentData, serverData) {
float distance = glm::distance(position, environmentData.getAtmosphereCenter(position)) -
environmentData.getAtmosphereOuterRadius();
if (distance < closestDistance) {
closest = environmentData;
closestDistance = distance;
}
}
}
return closest;
}
bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end,
float radius, glm::vec3& penetration) {
// collide with the "floor"
@ -217,14 +229,14 @@ ProgramObject* Environment::createSkyProgram(const char* from, int* locations) {
}
void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) {
glm::vec3 center = data.getAtmosphereCenter(camera.getPosition());
glm::vec3 center = data.getAtmosphereCenter();
glPushMatrix();
glTranslatef(center.x, center.y, center.z);
glm::vec3 relativeCameraPos = camera.getPosition() - center;
float height = glm::length(relativeCameraPos);
// use the appropriate shader depending on whether we're inside or outside
ProgramObject* program;
int* locations;

View file

@ -30,15 +30,19 @@ public:
void init();
void resetToDefault();
void renderAtmospheres(Camera& camera);
void override(const EnvironmentData& overrideData) { _overrideData = overrideData; _environmentIsOverridden = true; }
void endOverride() { _environmentIsOverridden = false; }
glm::vec3 getGravity (const glm::vec3& position);
const EnvironmentData getClosestData(const glm::vec3& position);
EnvironmentData getClosestData(const glm::vec3& position);
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration);
int parseData(const HifiSockAddr& senderSockAddr, const QByteArray& packet);
private:
glm::vec3 getGravity (const glm::vec3& position); // NOTE: Deprecated
bool findCapsulePenetration(const glm::vec3& start,
const glm::vec3& end, float radius, glm::vec3& penetration); // NOTE: Deprecated
ProgramObject* createSkyProgram(const char* from, int* locations);
@ -74,6 +78,8 @@ private:
typedef QHash<int, EnvironmentData> ServerData;
QHash<HifiSockAddr, ServerData> _data;
EnvironmentData _overrideData;
bool _environmentIsOverridden = false;
QMutex _mutex;
};

View file

@ -795,7 +795,6 @@ void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
glm::vec3 OculusManager::getRelativePosition() {
ovrTrackingState trackingState = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
ovrVector3f headPosition = trackingState.HeadPose.ThePose.Position;
return glm::vec3(headPosition.x, headPosition.y, headPosition.z);
}

View file

@ -427,6 +427,25 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
_bestZone->getStageAltitude());
scene->setStageDayTime(_bestZone->getStageHour());
scene->setStageYearTime(_bestZone->getStageDay());
if (_bestZone->getSkyboxMode() == SKYBOX_MODE_ATMOSPHERE) {
EnvironmentData data = _bestZone->getEnvironmentData();
glm::vec3 keyLightDirection = scene->getKeyLightDirection();
glm::vec3 inverseKeyLightDirection = keyLightDirection * -1.0f;
// NOTE: is this right? It seems like the "sun" should be based on the center of the
// atmosphere, not where the camera is.
glm::vec3 keyLightLocation = _viewState->getAvatarPosition()
+ (inverseKeyLightDirection * data.getAtmosphereOuterRadius());
data.setSunLocation(keyLightLocation);
const float KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO = 20.0f;
float sunBrightness = scene->getKeyLightIntensity() * KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO;
data.setSunBrightness(sunBrightness);
_viewState->overrideEnvironmentData(data);
}
} else {
if (_hasPreviousZone) {
scene->setKeyLightColor(_previousKeyLightColor);
@ -440,6 +459,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
scene->setStageYearTime(_previousStageDay);
_hasPreviousZone = false;
}
_viewState->endOverrideEnvironmentData();
}
// we must call endScene while we still have the tree locked so that no one deletes a model

View file

@ -13,4 +13,4 @@ find_package(Bullet REQUIRED)
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
link_hifi_libraries(avatars shared octree gpu model fbx networking animation)
link_hifi_libraries(avatars shared octree gpu model fbx networking animation environment)

View file

@ -0,0 +1,196 @@
//
// AtmospherePropertyGroup.cpp
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 12/4/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <OctreePacketData.h>
#include "AtmospherePropertyGroup.h"
#include "EntityItemProperties.h"
#include "EntityItemPropertiesMacros.h"
AtmospherePropertyGroup::AtmospherePropertyGroup() {
_center = glm::vec3(0.0f);
_innerRadius = 0.0f;
_outerRadius = 0.0f;
_mieScattering = 0.0f;
_rayleighScattering = 0.0f;
_scatteringWavelengths = glm::vec3(0.0f);
_hasStars = true;
}
void AtmospherePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, Center, center);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, InnerRadius, innerRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, OuterRadius, outerRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, MieScattering, mieScattering);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, RayleighScattering, rayleighScattering);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, ScatteringWavelengths, scatteringWavelengths);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, HasStars, hasStars);
}
void AtmospherePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_VEC3(atmosphere, center, setCenter);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(atmosphere, innerRadius, setInnerRadius);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(atmosphere, outerRadius, setOuterRadius);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(atmosphere, mieScattering, setMieScattering);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(atmosphere, rayleighScattering, setRayleighScattering);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_VEC3(atmosphere, scatteringWavelengths, setScatteringWavelengths);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(atmosphere, hasStars, setHasStars);
}
void AtmospherePropertyGroup::debugDump() const {
qDebug() << " AtmospherePropertyGroup: ---------------------------------------------";
qDebug() << " Center:" << getCenter() << " has changed:" << centerChanged();
qDebug() << " Inner Radius:" << getInnerRadius() << " has changed:" << innerRadiusChanged();
qDebug() << " Outer Radius:" << getOuterRadius() << " has changed:" << outerRadiusChanged();
qDebug() << " Mie Scattering:" << getMieScattering() << " has changed:" << mieScatteringChanged();
qDebug() << " Rayleigh Scattering:" << getRayleighScattering() << " has changed:" << rayleighScatteringChanged();
qDebug() << " Scattering Wavelengths:" << getScatteringWavelengths() << " has changed:" << scatteringWavelengthsChanged();
qDebug() << " Has Stars:" << getHasStars() << " has changed:" << hasStarsChanged();
}
bool AtmospherePropertyGroup::appentToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, appendValue, getCenter());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, appendValue, getInnerRadius());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, appendValue, getOuterRadius());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, appendValue, getMieScattering());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, appendValue, getRayleighScattering());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, appendValue, getScatteringWavelengths());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, appendValue, getHasStars());
return true;
}
bool AtmospherePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) {
int bytesRead = 0;
bool overwriteLocalData = true;
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, glm::vec3, _center);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, float, _innerRadius);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, float, _outerRadius);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, float, _mieScattering);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, float, _rayleighScattering);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, glm::vec3, _scatteringWavelengths);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, bool, _hasStars);
processedBytes += bytesRead;
return true;
}
void AtmospherePropertyGroup::markAllChanged() {
_centerChanged = true;
_innerRadiusChanged = true;
_outerRadiusChanged = true;
_mieScatteringChanged = true;
_rayleighScatteringChanged = true;
_scatteringWavelengthsChanged = true;
_hasStarsChanged = true;
}
EntityPropertyFlags AtmospherePropertyGroup::getChangedProperties() const {
EntityPropertyFlags changedProperties;
CHECK_PROPERTY_CHANGE(PROP_ATMOSPHERE_CENTER, center);
CHECK_PROPERTY_CHANGE(PROP_ATMOSPHERE_INNER_RADIUS, innerRadius);
CHECK_PROPERTY_CHANGE(PROP_ATMOSPHERE_OUTER_RADIUS, outerRadius);
CHECK_PROPERTY_CHANGE(PROP_ATMOSPHERE_MIE_SCATTERING, mieScattering);
CHECK_PROPERTY_CHANGE(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, rayleighScattering);
CHECK_PROPERTY_CHANGE(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, scatteringWavelengths);
CHECK_PROPERTY_CHANGE(PROP_ATMOSPHERE_HAS_STARS, hasStars);
return changedProperties;
}
void AtmospherePropertyGroup::getProperties(EntityItemProperties& properties) const {
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, Center, getCenter);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, InnerRadius, getInnerRadius);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, OuterRadius, getOuterRadius);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, MieScattering, getMieScattering);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, MieScattering, getMieScattering);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, RayleighScattering, getRayleighScattering);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, ScatteringWavelengths, getScatteringWavelengths);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Atmosphere, HasStars, getHasStars);
}
bool AtmospherePropertyGroup::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false;
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Atmosphere, Center, center, setCenter);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Atmosphere, InnerRadius, innerRadius, setInnerRadius);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Atmosphere, OuterRadius, outerRadius, setOuterRadius);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Atmosphere, MieScattering, mieScattering, setMieScattering);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Atmosphere, RayleighScattering, rayleighScattering, setRayleighScattering);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Atmosphere, ScatteringWavelengths, scatteringWavelengths, setScatteringWavelengths);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Atmosphere, HasStars, hasStars, setHasStars);
return somethingChanged;
}
EntityPropertyFlags AtmospherePropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties;
requestedProperties += PROP_ATMOSPHERE_CENTER;
requestedProperties += PROP_ATMOSPHERE_INNER_RADIUS;
requestedProperties += PROP_ATMOSPHERE_OUTER_RADIUS;
requestedProperties += PROP_ATMOSPHERE_MIE_SCATTERING;
requestedProperties += PROP_ATMOSPHERE_RAYLEIGH_SCATTERING;
requestedProperties += PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS;
requestedProperties += PROP_ATMOSPHERE_HAS_STARS;
return requestedProperties;
}
void AtmospherePropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, appendValue, getCenter());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, appendValue, getInnerRadius());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, appendValue, getOuterRadius());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, appendValue, getMieScattering());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, appendValue, getRayleighScattering());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, appendValue, getScatteringWavelengths());
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, appendValue, getHasStars());
}
int AtmospherePropertyGroup::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_ATMOSPHERE_CENTER, glm::vec3, _center);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, float, _innerRadius);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, float, _outerRadius);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, float, _mieScattering);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, float, _rayleighScattering);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, glm::vec3, _scatteringWavelengths);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, bool, _hasStars);
return bytesRead;
}

View file

@ -0,0 +1,102 @@
//
// AtmospherePropertyGroup.h
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 12/4/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AtmospherePropertyGroup_h
#define hifi_AtmospherePropertyGroup_h
#include <QtScript/QScriptEngine>
#include "PropertyGroup.h"
#include "EntityItemPropertiesMacros.h"
class EntityItemProperties;
class EncodeBitstreamParams;
class OctreePacketData;
class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
#include <stdint.h>
#include <glm/glm.hpp>
/*
#include <glm/gtx/extented_min_max.hpp>
#include <QtCore/QObject>
#include <QVector>
#include <QString>
#include <AACube.h>
#include <FBXReader.h> // for SittingPoint
#include <PropertyFlags.h>
#include <OctreeConstants.h>
#include <ShapeInfo.h>
#include "EntityItemID.h"
#include "AtmospherePropertyGroupMacros.h"
#include "EntityTypes.h"
*/
class AtmospherePropertyGroup : public PropertyGroup {
public:
AtmospherePropertyGroup();
virtual ~AtmospherePropertyGroup() {}
// EntityItemProperty related helpers
virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const;
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings);
virtual void debugDump() const;
virtual bool appentToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const;
virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes);
virtual void markAllChanged();
virtual EntityPropertyFlags getChangedProperties() const;
// EntityItem related helpers
// methods for getting/setting all properties of an entity
virtual void getProperties(EntityItemProperties& propertiesOut) const;
/// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties);
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
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);
DEFINE_PROPERTY_REF(PROP_ATMOSPHERE_CENTER, Center, center, glm::vec3);
DEFINE_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, InnerRadius, innerRadius, float);
DEFINE_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, OuterRadius, outerRadius, float);
DEFINE_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, MieScattering, mieScattering, float);
DEFINE_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, RayleighScattering, rayleighScattering, float);
DEFINE_PROPERTY_REF(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, ScatteringWavelengths, scatteringWavelengths, glm::vec3);
DEFINE_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, HasStars, hasStars, bool);
};
#endif // hifi_AtmospherePropertyGroup_h

View file

@ -27,6 +27,8 @@
#include "TextEntityItem.h"
#include "ZoneEntityItem.h"
AtmospherePropertyGroup EntityItemProperties::_staticAtmosphere;
EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1);
EntityItemProperties::EntityItemProperties() :
@ -87,6 +89,7 @@ EntityItemProperties::EntityItemProperties() :
CONSTRUCT_PROPERTY(stageDay, ZoneEntityItem::DEFAULT_STAGE_DAY),
CONSTRUCT_PROPERTY(stageHour, ZoneEntityItem::DEFAULT_STAGE_HOUR),
CONSTRUCT_PROPERTY(name, ENTITY_ITEM_DEFAULT_NAME),
CONSTRUCT_PROPERTY(skyboxMode, SKYBOX_MODE_INHERIT),
_id(UNKNOWN_ENTITY_ID),
_idSet(false),
@ -234,6 +237,43 @@ void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) {
}
}
const char* skyboxModeNames[] = {"inherit", "atmosphere", "texture" };
QHash<QString, SkyboxMode> stringToSkyboxModeLookup;
void addSkyboxMode(SkyboxMode type) {
stringToSkyboxModeLookup[skyboxModeNames[type]] = type;
}
void buildStringToSkyboxModeLookup() {
addSkyboxMode(SKYBOX_MODE_INHERIT);
addSkyboxMode(SKYBOX_MODE_ATMOSPHERE);
addSkyboxMode(SKYBOX_MODE_TEXTURE);
}
QString EntityItemProperties::getSkyboxModeAsString() const {
if (_skyboxMode < sizeof(skyboxModeNames) / sizeof(char *))
return QString(skyboxModeNames[_skyboxMode]);
return QString(skyboxModeNames[SKYBOX_MODE_INHERIT]);
}
QString EntityItemProperties::getSkyboxModeString(SkyboxMode mode) {
if (mode < sizeof(skyboxModeNames) / sizeof(char *))
return QString(skyboxModeNames[mode]);
return QString(skyboxModeNames[SKYBOX_MODE_INHERIT]);
}
void EntityItemProperties::setSkyboxModeFromString(const QString& skyboxMode) {
if (stringToSkyboxModeLookup.empty()) {
buildStringToSkyboxModeLookup();
}
auto skyboxModeItr = stringToSkyboxModeLookup.find(skyboxMode.toLower());
if (skyboxModeItr != stringToSkyboxModeLookup.end()) {
_skyboxMode = skyboxModeItr.value();
_skyboxModeChanged = true;
}
}
EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
EntityPropertyFlags changedProperties;
@ -294,6 +334,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_STAGE_DAY, stageDay);
CHECK_PROPERTY_CHANGE(PROP_STAGE_HOUR, stageHour);
CHECK_PROPERTY_CHANGE(PROP_SKYBOX_MODE, skyboxMode);
changedProperties += _atmosphere.getChangedProperties();
return changedProperties;
}
@ -375,6 +419,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(stageAltitude);
COPY_PROPERTY_TO_QSCRIPTVALUE(stageDay);
COPY_PROPERTY_TO_QSCRIPTVALUE(stageHour);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(skyboxMode, getSkyboxModeAsString());
// Sitting properties support
if (!skipDefaults) {
@ -408,6 +453,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
if (!skipDefaults) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesList); // gettable, but not settable
}
_atmosphere.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
return properties;
}
@ -477,7 +524,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageAltitude, setStageAltitude);
COPY_PROPERTY_FROM_QSCRIPTVALUE_INT(stageDay, setStageDay);
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageHour, setStageHour);
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(skyboxMode, SkyboxMode);
_atmosphere.copyFromScriptValue(object, _defaultSettings);
_lastEdited = usecTimestampNow();
}
@ -682,6 +730,11 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)properties.getShapeType());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, appendValue, (uint32_t)properties.getSkyboxMode());
_staticAtmosphere.setProperties(properties);
_staticAtmosphere.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
}
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID());
@ -931,6 +984,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_HOUR, float, setStageHour);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SKYBOX_MODE, SkyboxMode, setSkyboxMode);
properties.getAtmosphere().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
}
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID);
@ -1032,6 +1087,10 @@ void EntityItemProperties::markAllChanged() {
_stageAltitudeChanged = true;
_stageDayChanged = true;
_stageHourChanged = true;
_skyboxModeChanged = true;
_atmosphere.markAllChanged();
}
/// The maximum bounding cube for the entity, independent of it's rotation.

View file

@ -29,115 +29,11 @@
#include <OctreeConstants.h>
#include <ShapeInfo.h>
#include "AtmospherePropertyGroup.h"
#include "EntityItemID.h"
#include "EntityItemPropertiesMacros.h"
#include "EntityTypes.h"
enum EntityPropertyList {
PROP_PAGED_PROPERTY,
PROP_CUSTOM_PROPERTIES_INCLUDED,
// these properties are supported by the EntityItem base class
PROP_VISIBLE,
PROP_POSITION,
PROP_RADIUS, // NOTE: PROP_RADIUS is obsolete and only included in old format streams
PROP_DIMENSIONS = PROP_RADIUS,
PROP_ROTATION,
PROP_DENSITY,
PROP_VELOCITY,
PROP_GRAVITY,
PROP_DAMPING,
PROP_LIFETIME,
PROP_SCRIPT,
// these properties are supported by some derived classes
PROP_COLOR,
PROP_MODEL_URL,
PROP_ANIMATION_URL,
PROP_ANIMATION_FPS,
PROP_ANIMATION_FRAME_INDEX,
PROP_ANIMATION_PLAYING,
// these properties are supported by the EntityItem base class
PROP_REGISTRATION_POINT,
PROP_ANGULAR_VELOCITY,
PROP_ANGULAR_DAMPING,
PROP_IGNORE_FOR_COLLISIONS,
PROP_COLLISIONS_WILL_MOVE,
// property used by Light entity
PROP_IS_SPOTLIGHT,
PROP_DIFFUSE_COLOR_UNUSED,
PROP_AMBIENT_COLOR_UNUSED,
PROP_SPECULAR_COLOR_UNUSED,
PROP_INTENSITY, // Previously PROP_CONSTANT_ATTENUATION
PROP_LINEAR_ATTENUATION_UNUSED,
PROP_QUADRATIC_ATTENUATION_UNUSED,
PROP_EXPONENT,
PROP_CUTOFF,
// available to all entities
PROP_LOCKED,
// used by Model entities
PROP_TEXTURES,
PROP_ANIMATION_SETTINGS,
PROP_USER_DATA,
PROP_SHAPE_TYPE,
// used by ParticleEffect entities
PROP_MAX_PARTICLES,
PROP_LIFESPAN,
PROP_EMIT_RATE,
PROP_EMIT_DIRECTION,
PROP_EMIT_STRENGTH,
PROP_LOCAL_GRAVITY,
PROP_PARTICLE_RADIUS,
PROP_COMPOUND_SHAPE_URL,
PROP_MARKETPLACE_ID,
PROP_ACCELERATION,
PROP_SIMULATOR_ID,
PROP_NAME,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties ABOVE this line
PROP_AFTER_LAST_ITEM,
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// WARNING! Do not add props here unless you intentionally mean to reuse PROP_ indexes
//
// These properties of TextEntity piggy back off of properties of ModelEntities, the type doesn't matter
// since the derived class knows how to interpret it's own properties and knows the types it expects
PROP_TEXT_COLOR = PROP_COLOR,
PROP_TEXT = PROP_MODEL_URL,
PROP_LINE_HEIGHT = PROP_ANIMATION_URL,
PROP_BACKGROUND_COLOR = PROP_ANIMATION_FPS,
PROP_COLLISION_MODEL_URL_OLD_VERSION = PROP_ANIMATION_FPS + 1,
// Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for
// other properties which will never overlap with each other. We do this so that we don't have to expand
// the size of the properties bitflags mask
PROP_KEYLIGHT_COLOR = PROP_COLOR,
PROP_KEYLIGHT_INTENSITY = PROP_INTENSITY,
PROP_KEYLIGHT_AMBIENT_INTENSITY = PROP_CUTOFF,
PROP_KEYLIGHT_DIRECTION = PROP_EXPONENT,
PROP_STAGE_SUN_MODEL_ENABLED = PROP_IS_SPOTLIGHT,
PROP_STAGE_LATITUDE = PROP_DIFFUSE_COLOR_UNUSED,
PROP_STAGE_LONGITUDE = PROP_AMBIENT_COLOR_UNUSED,
PROP_STAGE_ALTITUDE = PROP_SPECULAR_COLOR_UNUSED,
PROP_STAGE_DAY = PROP_LINEAR_ATTENUATION_UNUSED,
PROP_STAGE_HOUR = PROP_QUADRATIC_ATTENUATION_UNUSED,
// WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above
};
typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
// this is set at the top of EntityItemProperties.cpp to PROP_AFTER_LAST_ITEM - 1. PROP_AFTER_LAST_ITEM is always
// one greater than the last item property due to the enum's auto-incrementing.
extern EntityPropertyList PROP_LAST_ITEM;
#include "EntityPropertyFlags.h"
const quint64 UNKNOWN_CREATED_TIME = 0;
@ -242,6 +138,10 @@ public:
DEFINE_PROPERTY(PROP_STAGE_DAY, StageDay, stageDay, quint16);
DEFINE_PROPERTY(PROP_STAGE_HOUR, StageHour, stageHour, float);
DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString);
DEFINE_PROPERTY_GROUP(Atmosphere, atmosphere, AtmospherePropertyGroup);
DEFINE_PROPERTY_REF_ENUM(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, SkyboxMode);
static QString getSkyboxModeString(SkyboxMode mode);
public:
@ -376,6 +276,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, SkyboxMode, skyboxMode, "");
debug << " last edited:" << properties.getLastEdited() << "\n";
debug << " edited ago:" << properties.getEditedAgo() << "\n";

View file

@ -51,7 +51,6 @@
} \
}
#define READ_ENTITY_PROPERTY_QUAT(P,M) \
if (propertyFlags.getHasProperty(P)) { \
glm::quat fromBuffer; \
@ -181,15 +180,25 @@
somethingChanged = true; \
}
#define SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(G,P,p,M) \
if (properties.get##G().p##Changed()) { \
M(properties.get##G().get##P()); \
somethingChanged = true; \
}
#define SET_ENTITY_PROPERTY_FROM_PROPERTIES_GETTER(C,G,S) \
if (properties.C()) { \
S(properties.G()); \
somethingChanged = true; \
}
#define COPY_ENTITY_PROPERTY_TO_PROPERTIES(M,G) \
properties._##M = G(); \
properties._##M##Changed = false;
#define COPY_ENTITY_PROPERTY_TO_PROPERTIES(P,M) \
properties._##P = M(); \
properties._##P##Changed = false;
#define COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(G,P,M) \
properties.get##G().set##P(M()); \
properties.get##G().set##P##Changed(false);
#define CHECK_PROPERTY_CHANGE(P,M) \
if (_##M##Changed) { \
@ -197,6 +206,27 @@
}
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(G,P,p) \
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != _##p) { \
QScriptValue groupProperties = properties.property(#G); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
QScriptValue V = vec3toScriptValue(engine, _##p); \
groupProperties.setProperty(#p, V); \
properties.setProperty(#G, groupProperties); \
}
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,P,p) \
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != _##p) { \
QScriptValue groupProperties = properties.property(#G); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
groupProperties.setProperty(#p, _##p); \
properties.setProperty(#G, groupProperties); \
}
#define COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(P) \
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
QScriptValue P = vec3toScriptValue(engine, _##P); \
@ -243,6 +273,20 @@
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(G, P, S) \
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue P = G.property(#P); \
if (P.isValid()) { \
float newValue = P.toVariant().toFloat(); \
if (_defaultSettings || newValue != _##P) { \
S(newValue); \
} \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_INT(P, S) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
@ -261,6 +305,20 @@
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(G, P, S) \
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue P = G.property(#P); \
if (P.isValid()) { \
float newValue = P.toVariant().toBool(); \
if (_defaultSettings || newValue != _##P) { \
S(newValue); \
} \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(P, S)\
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
@ -299,6 +357,32 @@
} \
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_VEC3(G, P, S) \
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue P = G.property(#P); \
if (P.isValid()) { \
QScriptValue x = P.property("x"); \
QScriptValue y = P.property("y"); \
QScriptValue z = P.property("z"); \
if (x.isValid() && y.isValid() && z.isValid()) { \
glm::vec3 newValue; \
newValue.x = x.toVariant().toFloat(); \
newValue.y = y.toVariant().toFloat(); \
newValue.z = z.toVariant().toFloat(); \
bool isValid = !glm::isnan(newValue.x) && \
!glm::isnan(newValue.y) && \
!glm::isnan(newValue.z); \
if (isValid && \
(_defaultSettings || newValue != _##P)) { \
S(newValue); \
} \
} \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_QUAT(P, S) \
QScriptValue P = object.property(#P); \
@ -357,6 +441,14 @@
_##n(V), \
_##n##Changed(false)
#define DEFINE_PROPERTY_GROUP(N, n, T) \
public: \
const T& get##N() const { return _##n; } \
T& get##N() { return _##n; } \
private: \
T _##n; \
static T _static##N;
#define DEFINE_PROPERTY(P, N, n, T) \
public: \
T get##N() const { return _##n; } \
@ -365,7 +457,7 @@
void set##N##Changed(bool value) { _##n##Changed = value; } \
private: \
T _##n; \
bool _##n##Changed;
bool _##n##Changed = false;
#define DEFINE_PROPERTY_REF(P, N, n, T) \
public: \
@ -375,7 +467,7 @@
void set##N##Changed(bool value) { _##n##Changed = value; } \
private: \
T _##n; \
bool _##n##Changed;
bool _##n##Changed = false;
#define DEFINE_PROPERTY_REF_WITH_SETTER(P, N, n, T) \
public: \

View file

@ -0,0 +1,167 @@
//
// EntityPropertyFlags.h
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 12/4/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_EntityPropertyFlags_h
#define hifi_EntityPropertyFlags_h
/*
#include <stdint.h>
#include <glm/glm.hpp>
#include <glm/gtx/extented_min_max.hpp>
#include <QtScript/QScriptEngine>
#include <QtCore/QObject>
#include <QVector>
#include <QString>
#include <AACube.h>
#include <FBXReader.h> // for SittingPoint
*/
#include <PropertyFlags.h>
/*
#include <OctreeConstants.h>
#include <ShapeInfo.h>
#include "AtmospherePropertyGroup.h"
#include "EntityItemID.h"
#include "EntityItemPropertiesMacros.h"
#include "EntityTypes.h"
*/
enum EntityPropertyList {
PROP_PAGED_PROPERTY,
PROP_CUSTOM_PROPERTIES_INCLUDED,
// these properties are supported by the EntityItem base class
PROP_VISIBLE,
PROP_POSITION,
PROP_RADIUS, // NOTE: PROP_RADIUS is obsolete and only included in old format streams
PROP_DIMENSIONS = PROP_RADIUS,
PROP_ROTATION,
PROP_DENSITY,
PROP_VELOCITY,
PROP_GRAVITY,
PROP_DAMPING,
PROP_LIFETIME,
PROP_SCRIPT,
// these properties are supported by some derived classes
PROP_COLOR,
// these are used by models only
PROP_MODEL_URL,
PROP_ANIMATION_URL,
PROP_ANIMATION_FPS,
PROP_ANIMATION_FRAME_INDEX,
PROP_ANIMATION_PLAYING,
// these properties are supported by the EntityItem base class
PROP_REGISTRATION_POINT,
PROP_ANGULAR_VELOCITY,
PROP_ANGULAR_DAMPING,
PROP_IGNORE_FOR_COLLISIONS,
PROP_COLLISIONS_WILL_MOVE,
// property used by Light entity
PROP_IS_SPOTLIGHT,
PROP_DIFFUSE_COLOR_UNUSED,
PROP_AMBIENT_COLOR_UNUSED,
PROP_SPECULAR_COLOR_UNUSED,
PROP_INTENSITY, // Previously PROP_CONSTANT_ATTENUATION
PROP_LINEAR_ATTENUATION_UNUSED,
PROP_QUADRATIC_ATTENUATION_UNUSED,
PROP_EXPONENT,
PROP_CUTOFF,
// available to all entities
PROP_LOCKED,
PROP_TEXTURES, // used by Model entities
PROP_ANIMATION_SETTINGS, // used by Model entities
PROP_USER_DATA, // all entities
PROP_SHAPE_TYPE, // used by Model + zones entities
// used by ParticleEffect entities
PROP_MAX_PARTICLES,
PROP_LIFESPAN,
PROP_EMIT_RATE,
PROP_EMIT_DIRECTION,
PROP_EMIT_STRENGTH,
PROP_LOCAL_GRAVITY,
PROP_PARTICLE_RADIUS,
PROP_COMPOUND_SHAPE_URL, // used by Model + zones entities
PROP_MARKETPLACE_ID, // all entities
PROP_ACCELERATION, // all entities
PROP_SIMULATOR_ID, // all entities
PROP_NAME, // all entities
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties ABOVE this line
PROP_AFTER_LAST_ITEM,
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// WARNING! Do not add props here unless you intentionally mean to reuse PROP_ indexes
//
// These properties of TextEntity piggy back off of properties of ModelEntities, the type doesn't matter
// since the derived class knows how to interpret it's own properties and knows the types it expects
PROP_TEXT_COLOR = PROP_COLOR,
PROP_TEXT = PROP_MODEL_URL,
PROP_LINE_HEIGHT = PROP_ANIMATION_URL,
PROP_BACKGROUND_COLOR = PROP_ANIMATION_FPS,
PROP_COLLISION_MODEL_URL_OLD_VERSION = PROP_ANIMATION_FPS + 1,
// Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for
// other properties which will never overlap with each other. We do this so that we don't have to expand
// the size of the properties bitflags mask
PROP_KEYLIGHT_COLOR = PROP_COLOR,
PROP_KEYLIGHT_INTENSITY = PROP_INTENSITY,
PROP_KEYLIGHT_AMBIENT_INTENSITY = PROP_CUTOFF,
PROP_KEYLIGHT_DIRECTION = PROP_EXPONENT,
PROP_STAGE_SUN_MODEL_ENABLED = PROP_IS_SPOTLIGHT,
PROP_STAGE_LATITUDE = PROP_DIFFUSE_COLOR_UNUSED,
PROP_STAGE_LONGITUDE = PROP_AMBIENT_COLOR_UNUSED,
PROP_STAGE_ALTITUDE = PROP_SPECULAR_COLOR_UNUSED,
PROP_STAGE_DAY = PROP_LINEAR_ATTENUATION_UNUSED,
PROP_STAGE_HOUR = PROP_QUADRATIC_ATTENUATION_UNUSED,
PROP_ATMOSPHERE_CENTER = PROP_MAX_PARTICLES,
PROP_ATMOSPHERE_INNER_RADIUS = PROP_LIFESPAN,
PROP_ATMOSPHERE_OUTER_RADIUS = PROP_EMIT_RATE,
PROP_ATMOSPHERE_MIE_SCATTERING = PROP_EMIT_DIRECTION,
PROP_ATMOSPHERE_RAYLEIGH_SCATTERING = PROP_EMIT_STRENGTH,
PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS = PROP_LOCAL_GRAVITY,
PROP_ATMOSPHERE_HAS_STARS = PROP_PARTICLE_RADIUS,
PROP_SKYBOX_MODE = PROP_MODEL_URL,
// SunBrightness - same as KeyLight Intensity?
// SunLocation (or direction) - same as KeyLight
// WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above
};
typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
// this is set at the top of EntityItemProperties.cpp to PROP_AFTER_LAST_ITEM - 1. PROP_AFTER_LAST_ITEM is always
// one greater than the last item property due to the enum's auto-incrementing.
extern EntityPropertyList PROP_LAST_ITEM;
enum SkyboxMode {
SKYBOX_MODE_INHERIT,
SKYBOX_MODE_ATMOSPHERE,
SKYBOX_MODE_TEXTURE,
};
#endif // hifi_EntityPropertyFlags_h

View file

@ -0,0 +1,100 @@
//
// PropertyGroup.h
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 12/4/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_PropertyGroup_h
#define hifi_PropertyGroup_h
#include <QtScript/QScriptEngine>
//#include "EntityItemProperties.h"
#include "EntityPropertyFlags.h"
class EntityItemProperties;
class EncodeBitstreamParams;
class OctreePacketData;
class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
#include <OctreeElement.h>
/*
#include <stdint.h>
#include <glm/glm.hpp>
#include <glm/gtx/extented_min_max.hpp>
#include <QtCore/QObject>
#include <QVector>
#include <QString>
#include <AACube.h>
#include <FBXReader.h> // for SittingPoint
#include <PropertyFlags.h>
#include <OctreeConstants.h>
#include <ShapeInfo.h>
#include "EntityItemID.h"
#include "PropertyGroupMacros.h"
#include "EntityTypes.h"
*/
//typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
class PropertyGroup {
public:
PropertyGroup() {}
virtual ~PropertyGroup() {}
// EntityItemProperty related helpers
virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const = 0;
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) = 0;
virtual void debugDump() const { }
virtual bool appentToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const = 0;
virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) = 0;
virtual void markAllChanged() = 0;
virtual EntityPropertyFlags getChangedProperties() const = 0;
// EntityItem related helpers
// methods for getting/setting all properties of an entity
virtual void getProperties(EntityItemProperties& propertiesOut) const = 0;
/// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties) = 0;
/// Override this in your derived class if you'd like to be informed when something about the state of the entity
/// has changed. This will be called with properties change or when new data is loaded from a stream
virtual void somethingChangedNotification() { }
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const = 0;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const = 0;
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) = 0;
};
#endif // hifi_PropertyGroup_h

View file

@ -61,10 +61,32 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityIte
_stageHour = DEFAULT_STAGE_HOUR;
_shapeType = DEFAULT_SHAPE_TYPE;
_compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL;
_skyboxMode = SKYBOX_MODE_INHERIT;
setProperties(properties);
}
EnvironmentData ZoneEntityItem::getEnvironmentData() const {
EnvironmentData result;
result.setAtmosphereCenter(_atmospherePropeties.getCenter());
result.setAtmosphereInnerRadius(_atmospherePropeties.getInnerRadius());
result.setAtmosphereOuterRadius(_atmospherePropeties.getOuterRadius());
result.setRayleighScattering(_atmospherePropeties.getRayleighScattering());
result.setMieScattering(_atmospherePropeties.getMieScattering());
result.setScatteringWavelengths(_atmospherePropeties.getScatteringWavelengths());
result.setHasStars(_atmospherePropeties.getHasStars());
// NOTE: The sunLocation and SunBrightness will be overwritten in the EntityTreeRenderer to use the
// keyLight details from the scene interface
//result.setSunLocation(1000, 900, 1000));
//result.setSunBrightness(20.0f);
return result;
}
EntityItemProperties ZoneEntityItem::getProperties() const {
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
@ -81,6 +103,10 @@ EntityItemProperties ZoneEntityItem::getProperties() const {
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(skyboxMode, getSkyboxMode);
_atmospherePropeties.getProperties(properties);
return properties;
}
@ -100,6 +126,11 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageHour, setStageHour);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(skyboxMode, setSkyboxMode);
bool somethingChangedInAtmosphere = _atmospherePropeties.setProperties(properties);
somethingChanged = somethingChanged || somethingChangedInAtmosphere;
if (somethingChanged) {
bool wantDebug = false;
@ -111,13 +142,13 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
}
setLastEdited(properties._lastEdited);
}
return somethingChanged;
}
int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
int bytesRead = 0;
const unsigned char* dataAt = data;
@ -133,6 +164,9 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _stageHour);
READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
READ_ENTITY_PROPERTY_SETTER(PROP_SKYBOX_MODE, SkyboxMode, setSkyboxMode);
bytesRead += _atmospherePropeties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData);
return bytesRead;
}
@ -154,6 +188,8 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += PROP_STAGE_HOUR;
requestedProperties += PROP_SHAPE_TYPE;
requestedProperties += PROP_COMPOUND_SHAPE_URL;
requestedProperties += PROP_SKYBOX_MODE;
requestedProperties += _atmospherePropeties.getEntityProperties(params);
return requestedProperties;
}
@ -180,6 +216,11 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getStageHour());
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, appendValue, (uint32_t)getSkyboxMode()); // could this be a uint16??
_atmospherePropeties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
}
void ZoneEntityItem::debugDump() const {
@ -198,6 +239,9 @@ void ZoneEntityItem::debugDump() const {
qCDebug(entities) << " _stageAltitude:" << _stageAltitude;
qCDebug(entities) << " _stageDay:" << _stageDay;
qCDebug(entities) << " _stageHour:" << _stageHour;
qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getSkyboxModeString(_skyboxMode);
_atmospherePropeties.debugDump();
}
ShapeType ZoneEntityItem::getShapeType() const {

View file

@ -12,6 +12,9 @@
#ifndef hifi_ZoneEntityItem_h
#define hifi_ZoneEntityItem_h
#include <EnvironmentData.h>
#include "AtmospherePropertyGroup.h"
#include "EntityItem.h"
class ZoneEntityItem : public EntityItem {
@ -103,6 +106,11 @@ public:
const QString getCompoundShapeURL() const { return _compoundShapeURL; }
virtual void setCompoundShapeURL(const QString& url);
void setSkyboxMode(SkyboxMode value) { _skyboxMode = value; }
SkyboxMode getSkyboxMode() const { return _skyboxMode; }
EnvironmentData getEnvironmentData() const;
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,
@ -138,6 +146,9 @@ protected:
ShapeType _shapeType = SHAPE_TYPE_NONE;
QString _compoundShapeURL;
SkyboxMode _skyboxMode = SKYBOX_MODE_INHERIT;
AtmospherePropertyGroup _atmospherePropeties;
static bool _drawZoneBoundaries;
static bool _zonesArePickable;

View file

@ -27,7 +27,8 @@ EnvironmentData::EnvironmentData(int id) :
_mieScattering(0.0010f),
_scatteringWavelengths(0.650f, 0.570f, 0.475f),
_sunLocation(1000, 900, 1000),
_sunBrightness(20.0f) {
_sunBrightness(20.0f),
_hasStars(true) {
}
glm::vec3 EnvironmentData::getAtmosphereCenter(const glm::vec3& cameraPosition) const {

View file

@ -28,6 +28,9 @@ public:
void setGravity(float gravity) { _gravity = gravity; }
float getGravity() const { return _gravity; }
void setHasStars(bool value) { _hasStars = value; }
bool getHasStars() const { return _hasStars; }
void setAtmosphereCenter(const glm::vec3& center) { _atmosphereCenter = center; }
void setAtmosphereInnerRadius(float radius) { _atmosphereInnerRadius = radius; }
void setAtmosphereOuterRadius(float radius) { _atmosphereOuterRadius = radius; }
@ -73,6 +76,8 @@ private:
glm::vec3 _sunLocation;
float _sunBrightness;
bool _hasStars;
};
#endif // hifi_EnvironmentData_h

View file

@ -185,7 +185,7 @@ QVariantMap JSONBreakableMarshal::fromStringList(const QStringList& stringList)
// check if we need to resize the array
if (currentList.size() < arrayIndex + 1) {
for (int i = currentList.size() - 1; i < arrayIndex + 1; i++) {
for (int i = currentList.size(); i < arrayIndex + 1; i++) {
// add the null QJsonValue at this array index to get the array to the right size
currentList.push_back(QJsonValue());
}
@ -221,7 +221,7 @@ QVariantMap JSONBreakableMarshal::fromStringList(const QStringList& stringList)
nextBreakIndex = keySeparatorIndex;
nextKeypathStartIndex = keySeparatorIndex + 1;
} else if (keySeparatorIndex == -1 || (arrayBracketIndex != -1
&& keySeparatorIndex < arrayBracketIndex)) {
&& arrayBracketIndex < keySeparatorIndex)) {
nextBreakIndex = arrayBracketIndex;
nextKeypathStartIndex = arrayBracketIndex;
} else {

View file

@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) {
return 1;
case PacketTypeEntityAddOrEdit:
case PacketTypeEntityData:
return VERSION_ENTITIES_HAVE_NAMES;
return VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE;
case PacketTypeEntityErase:
return 2;
case PacketTypeAudioStreamStats:

View file

@ -140,5 +140,6 @@ const PacketVersion VERSION_ENTITIES_HAVE_UUIDS = 16;
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_EXIST = 17;
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE = 18;
const PacketVersion VERSION_ENTITIES_HAVE_NAMES = 19;
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE = 20;
#endif // hifi_PacketHeaders_h

View file

@ -18,6 +18,7 @@ class Transform;
class QThread;
class ViewFrustum;
class PickRay;
class EnvironmentData;
/// Interface provided by Application to other objects that need access to the current view state details
class AbstractViewStateInterface {
@ -32,6 +33,10 @@ public:
/// gets the current view frustum for rendering the view state
virtual ViewFrustum* getCurrentViewFrustum() = 0;
/// overrides environment data
virtual void overrideEnvironmentData(const EnvironmentData& newData) = 0;
virtual void endOverrideEnvironmentData() = 0;
/// gets the shadow view frustum for rendering the view state
virtual ViewFrustum* getShadowViewFrustum() = 0;

View file

@ -63,6 +63,14 @@ glm::quat Quat::angleAxis(float angle, const glm::vec3& v) {
return glm::angleAxis(glm::radians(angle), v);
}
glm::vec3 Quat::axis(const glm::quat& orientation) {
return glm::axis(orientation);
}
float Quat::angle(const glm::quat& orientation) {
return glm::angle(orientation);
}
glm::quat Quat::mix(const glm::quat& q1, const glm::quat& q2, float alpha) {
return safeMix(q1, q2, alpha);
}

View file

@ -35,6 +35,8 @@ public slots:
glm::vec3 getUp(const glm::quat& orientation);
glm::vec3 safeEulerAngles(const glm::quat& orientation); // degrees
glm::quat angleAxis(float angle, const glm::vec3& v); // degrees
glm::vec3 axis(const glm::quat& orientation);
float angle(const glm::quat& orientation);
glm::quat mix(const glm::quat& q1, const glm::quat& q2, float alpha);
glm::quat slerp(const glm::quat& q1, const glm::quat& q2, float alpha);
glm::quat squad(const glm::quat& q1, const glm::quat& q2, const glm::quat& s1, const glm::quat& s2, float h);

View file

@ -3,6 +3,6 @@ set(TARGET_NAME octree-tests)
setup_hifi_project(Script Network)
# link in the shared libraries
link_hifi_libraries(shared octree gpu model fbx networking entities avatars audio animation script-engine physics)
link_hifi_libraries(shared octree gpu model fbx networking environment entities avatars audio animation script-engine physics)
copy_dlls_beside_windows_executable()

View file

@ -36,6 +36,7 @@
#include "MessageDialog.h"
#include "VrMenu.h"
#include <QDesktopWidget>
class RateCounter {
std::vector<float> times;
@ -339,8 +340,14 @@ public:
makeCurrent();
offscreenUi->setProxyWindow(this);
setFramePosition(QPoint(-1000, 0));
resize(QSize(800, 600));
QDesktopWidget* desktop = QApplication::desktop();
QRect rect = desktop->availableGeometry(desktop->screenCount() - 1);
int height = rect.height();
//rect.setHeight(height / 2);
rect.setY(rect.y() + height / 2);
setGeometry(rect);
// setFramePosition(QPoint(-1000, 0));
// resize(QSize(800, 600));
#ifdef QML_CONTROL_GALLERY
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getTestQmlDir()));
@ -474,16 +481,8 @@ hifi.offscreen.focus.debug=false
qt.quick.mouse.debug=false
)V0G0N";
//int main(int argc, char *argv[]) {
// QGuiApplication app(argc, argv);
// QQmlApplicationEngine engine;
// engine.setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
// engine.load(QUrl("Main.qml"));
// return app.exec();
//}
int main(int argc, char** argv) {
QGuiApplication app(argc, argv);
QApplication app(argc, argv);
QLoggingCategory::setFilterRules(LOG_FILTER_RULES);
QTestWindow window;
app.exec();