mirror of
https://github.com/overte-org/overte.git
synced 2025-08-13 08:36:46 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
6419a148d4
89 changed files with 3029 additions and 1958 deletions
38
cmake/externals/openvr/CMakeLists.txt
vendored
Normal file
38
cmake/externals/openvr/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
include(ExternalProject)
|
||||
include(SelectLibraryConfigurations)
|
||||
|
||||
set(EXTERNAL_NAME OpenVR)
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://github.com/ValveSoftware/openvr/archive/0.9.0.zip
|
||||
URL_MD5 4fbde7759f604aaa68b9c40d628cc34a
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/headers CACHE TYPE INTERNAL)
|
||||
|
||||
if (WIN32)
|
||||
|
||||
# FIXME need to account for different architectures
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/win32/openvr_api.lib CACHE TYPE INTERNAL)
|
||||
|
||||
elseif(APPLE)
|
||||
|
||||
# FIXME need to account for different architectures
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx32/libopenvr_api.dylib CACHE TYPE INTERNAL)
|
||||
|
||||
elseif(NOT ANDROID)
|
||||
|
||||
# FIXME need to account for different architectures
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux32/libopenvr_api.so CACHE TYPE INTERNAL)
|
||||
|
||||
endif()
|
||||
|
21
cmake/modules/FindOpenVR.cmake
Normal file
21
cmake/modules/FindOpenVR.cmake
Normal file
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# FindLibOVR.cmake
|
||||
#
|
||||
# Try to find the LibOVR library to use the Oculus
|
||||
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENVR_FOUND - system found LibOVR
|
||||
# OPENVR_INCLUDE_DIRS - the LibOVR include directory
|
||||
# OPENVR_LIBRARIES - Link this to use LibOVR
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
if (NOT ANDROID)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OPENVR DEFAULT_MSG OPENVR_INCLUDE_DIRS OPENVR_LIBRARIES)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(OPENVR_INCLUDE_DIRS OPENVR_LIBRARIES OPENVR_SEARCH_DIRS)
|
|
@ -26,7 +26,7 @@ var viewHelpers = {
|
|||
|
||||
setting_value = _(values).valueForKeyPath(keypath);
|
||||
|
||||
if (!setting_value) {
|
||||
if (setting_value === undefined || setting_value === null) {
|
||||
if (_.has(setting, 'default')) {
|
||||
setting_value = setting.default;
|
||||
} else {
|
||||
|
|
File diff suppressed because it is too large
Load diff
266
examples/example/games/airHockey.js
Normal file
266
examples/example/games/airHockey.js
Normal file
|
@ -0,0 +1,266 @@
|
|||
//
|
||||
// AirHockey.js
|
||||
//
|
||||
// Created by Philip Rosedale on January 26, 2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// AirHockey table and pucks
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var debugVisible = false;
|
||||
|
||||
var FIELD_WIDTH = 1.21;
|
||||
var FIELD_LENGTH = 1.92;
|
||||
var FLOOR_THICKNESS = 0.20;
|
||||
var EDGE_THICKESS = 0.10;
|
||||
var EDGE_HEIGHT = 0.10;
|
||||
var DROP_HEIGHT = 0.3;
|
||||
var PUCK_SIZE = 0.15;
|
||||
var PUCK_THICKNESS = 0.05;
|
||||
var PADDLE_SIZE = 0.15;
|
||||
var PADDLE_THICKNESS = 0.05;
|
||||
|
||||
var GOAL_WIDTH = 0.35;
|
||||
|
||||
var GRAVITY = -9.8;
|
||||
var LIFETIME = 6000;
|
||||
var PUCK_DAMPING = 0.02;
|
||||
var PADDLE_DAMPING = 0.35;
|
||||
var ANGULAR_DAMPING = 0.4;
|
||||
var PADDLE_ANGULAR_DAMPING = 0.75;
|
||||
var MODEL_SCALE = 1.52;
|
||||
var MODEL_OFFSET = { x: 0, y: -0.19, z: 0 };
|
||||
|
||||
var scoreSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_score.wav");
|
||||
|
||||
var polyTable = "https://hifi-public.s3.amazonaws.com/ozan/props/airHockeyTable/airHockeyTableForPolyworld.fbx"
|
||||
var normalTable = "https://hifi-public.s3.amazonaws.com/ozan/props/airHockeyTable/airHockeyTable.fbx"
|
||||
var hitSound1 = "https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_hit1.wav"
|
||||
var hitSound2 = "https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_hit2.wav"
|
||||
var hitSideSound = "https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_hit3.wav"
|
||||
var puckModel = "https://hifi-public.s3.amazonaws.com/ozan/props/airHockeyTable/airHockeyPuck.fbx"
|
||||
var puckCollisionModel = "http://headache.hungry.com/~seth/hifi/airHockeyPuck-hull.obj"
|
||||
var paddleModel = "https://hifi-public.s3.amazonaws.com/ozan/props/airHockeyTable/airHockeyPaddle.obj"
|
||||
var paddleCollisionModel = "http://headache.hungry.com/~seth/hifi/paddle-hull.obj"
|
||||
|
||||
var center = Vec3.sum(MyAvatar.position, Vec3.multiply((FIELD_WIDTH + FIELD_LENGTH) * 0.60, Quat.getFront(Camera.getOrientation())));
|
||||
|
||||
var edgeRestitution = 0.9;
|
||||
var floorFriction = 0.01;
|
||||
|
||||
var floor = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: Vec3.subtract(center, { x: 0, y: 0, z: 0 }),
|
||||
dimensions: { x: FIELD_WIDTH, y: FLOOR_THICKNESS, z: FIELD_LENGTH },
|
||||
color: { red: 128, green: 128, blue: 128 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
locked: true,
|
||||
friction: floorFriction,
|
||||
visible: debugVisible,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var edge1 = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
collisionSoundURL: hitSideSound,
|
||||
position: Vec3.sum(center, { x: FIELD_WIDTH / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }),
|
||||
dimensions: { x: EDGE_THICKESS, y: EDGE_HEIGHT, z: FIELD_LENGTH + EDGE_THICKESS },
|
||||
color: { red: 100, green: 100, blue: 100 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
visible: debugVisible,
|
||||
restitution: edgeRestitution,
|
||||
locked: true,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var edge2 = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
collisionSoundURL: hitSideSound,
|
||||
position: Vec3.sum(center, { x: -FIELD_WIDTH / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }),
|
||||
dimensions: { x: EDGE_THICKESS, y: EDGE_HEIGHT, z: FIELD_LENGTH + EDGE_THICKESS },
|
||||
color: { red: 100, green: 100, blue: 100 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
visible: debugVisible,
|
||||
restitution: edgeRestitution,
|
||||
locked: true,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var edge3a = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
collisionSoundURL: hitSideSound,
|
||||
position: Vec3.sum(center, { x: FIELD_WIDTH / 4.0 + (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: -FIELD_LENGTH / 2.0 }),
|
||||
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
|
||||
color: { red: 100, green: 100, blue: 100 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
visible: debugVisible,
|
||||
restitution: edgeRestitution,
|
||||
locked: true,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var edge3b = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
collisionSoundURL: hitSideSound,
|
||||
position: Vec3.sum(center, { x: -FIELD_WIDTH / 4.0 - (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: -FIELD_LENGTH / 2.0 }),
|
||||
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
|
||||
color: { red: 100, green: 100, blue: 100 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
visible: debugVisible,
|
||||
restitution: edgeRestitution,
|
||||
locked: true,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var edge4a = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
collisionSoundURL: hitSideSound,
|
||||
position: Vec3.sum(center, { x: FIELD_WIDTH / 4.0 + (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: FIELD_LENGTH / 2.0 }),
|
||||
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
|
||||
color: { red: 100, green: 100, blue: 100 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
visible: debugVisible,
|
||||
restitution: edgeRestitution,
|
||||
locked: true,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var edge4b = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
collisionSoundURL: hitSideSound,
|
||||
position: Vec3.sum(center, { x: -FIELD_WIDTH / 4.0 - (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: FIELD_LENGTH / 2.0 }),
|
||||
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
|
||||
color: { red: 100, green: 100, blue: 100 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
visible: debugVisible,
|
||||
restitution: edgeRestitution,
|
||||
locked: true,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var table = Entities.addEntity(
|
||||
{ type: "Model",
|
||||
modelURL: polyTable,
|
||||
dimensions: Vec3.multiply({ x: 0.8, y: 0.45, z: 1.31 }, MODEL_SCALE),
|
||||
position: Vec3.sum(center, MODEL_OFFSET),
|
||||
ignoreCollisions: false,
|
||||
visible: true,
|
||||
locked: true,
|
||||
lifetime: LIFETIME });
|
||||
|
||||
var puck;
|
||||
var paddle1, paddle2;
|
||||
|
||||
// Create pucks
|
||||
|
||||
function makeNewProp(which) {
|
||||
if (which == "puck") {
|
||||
return Entities.addEntity(
|
||||
{ type: "Model",
|
||||
modelURL: puckModel,
|
||||
compoundShapeURL: puckCollisionModel,
|
||||
collisionSoundURL: hitSound1,
|
||||
position: Vec3.sum(center, { x: 0, y: DROP_HEIGHT, z: 0 }),
|
||||
dimensions: { x: PUCK_SIZE, y: PUCK_THICKNESS, z: PUCK_SIZE },
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
velocity: { x: 0, y: 0.05, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: PUCK_DAMPING,
|
||||
angularDamping: ANGULAR_DAMPING,
|
||||
lifetime: LIFETIME,
|
||||
collisionsWillMove: true });
|
||||
}
|
||||
else if (which == "paddle1") {
|
||||
return Entities.addEntity(
|
||||
{ type: "Model",
|
||||
modelURL: paddleModel,
|
||||
compoundShapeURL: paddleCollisionModel,
|
||||
collisionSoundURL: hitSound2,
|
||||
position: Vec3.sum(center, { x: 0, y: DROP_HEIGHT * 1.5, z: FIELD_LENGTH * 0.35 }),
|
||||
dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE },
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
velocity: { x: 0, y: 0.07, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: PADDLE_DAMPING,
|
||||
angularDamping: PADDLE_ANGULAR_DAMPING,
|
||||
lifetime: LIFETIME,
|
||||
collisionsWillMove: true });
|
||||
}
|
||||
else if (which == "paddle2") {
|
||||
return Entities.addEntity(
|
||||
{ type: "Model",
|
||||
modelURL: paddleModel,
|
||||
compoundShapeURL: paddleCollisionModel,
|
||||
collisionSoundURL: hitSound2,
|
||||
position: Vec3.sum(center, { x: 0, y: DROP_HEIGHT * 1.5, z: -FIELD_LENGTH * 0.35 }),
|
||||
dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE },
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
velocity: { x: 0, y: 0.07, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: PADDLE_DAMPING,
|
||||
angularDamping: PADDLE_ANGULAR_DAMPING,
|
||||
lifetime: LIFETIME,
|
||||
collisionsWillMove: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
puck = makeNewProp("puck");
|
||||
paddle1 = makeNewProp("paddle1");
|
||||
paddle2 = makeNewProp("paddle2");
|
||||
|
||||
function update(deltaTime) {
|
||||
if (Math.random() < 0.1) {
|
||||
puckProps = Entities.getEntityProperties(puck);
|
||||
paddle1Props = Entities.getEntityProperties(paddle1);
|
||||
paddle2Props = Entities.getEntityProperties(paddle2);
|
||||
if (puckProps.position.y < (center.y - DROP_HEIGHT)) {
|
||||
Audio.playSound(scoreSound, {
|
||||
position: center,
|
||||
volume: 1.0
|
||||
});
|
||||
Entities.deleteEntity(puck);
|
||||
puck = makeNewProp("puck");
|
||||
}
|
||||
|
||||
if (paddle1Props.position.y < (center.y - DROP_HEIGHT)) {
|
||||
Entities.deleteEntity(paddle1);
|
||||
paddle1 = makeNewProp("paddle1");
|
||||
}
|
||||
if (paddle2Props.position.y < (center.y - DROP_HEIGHT)) {
|
||||
Entities.deleteEntity(paddle2);
|
||||
paddle2 = makeNewProp("paddle2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
|
||||
Entities.editEntity(edge1, { locked: false });
|
||||
Entities.editEntity(edge2, { locked: false });
|
||||
Entities.editEntity(edge3a, { locked: false });
|
||||
Entities.editEntity(edge3b, { locked: false });
|
||||
Entities.editEntity(edge4a, { locked: false });
|
||||
Entities.editEntity(edge4b, { locked: false });
|
||||
Entities.editEntity(floor, { locked: false });
|
||||
Entities.editEntity(table, { locked: false });
|
||||
|
||||
|
||||
Entities.deleteEntity(edge1);
|
||||
Entities.deleteEntity(edge2);
|
||||
Entities.deleteEntity(edge3a);
|
||||
Entities.deleteEntity(edge3b);
|
||||
Entities.deleteEntity(edge4a);
|
||||
Entities.deleteEntity(edge4b);
|
||||
Entities.deleteEntity(floor);
|
||||
Entities.deleteEntity(puck);
|
||||
Entities.deleteEntity(paddle1);
|
||||
Entities.deleteEntity(paddle2);
|
||||
Entities.deleteEntity(table);
|
||||
}
|
||||
|
||||
Script.update.connect(update);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
278
examples/example/games/grabHockey.js
Normal file
278
examples/example/games/grabHockey.js
Normal file
|
@ -0,0 +1,278 @@
|
|||
|
||||
// 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 lineEntityID = null;
|
||||
var prevMouse = {};
|
||||
var deltaMouse = {
|
||||
z: 0
|
||||
}
|
||||
var entityProps;
|
||||
var moveUpDown = false;
|
||||
var CLOSE_ENOUGH = 0.001;
|
||||
var FULL_STRENGTH = 1.0;
|
||||
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 originalGravity = {x: 0, y: 0, z: 0};
|
||||
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");
|
||||
var VOLUME = 0.10;
|
||||
|
||||
var DROP_DISTANCE = 5.0;
|
||||
var DROP_COLOR = {
|
||||
red: 200,
|
||||
green: 200,
|
||||
blue: 200
|
||||
};
|
||||
var DROP_WIDTH = 2;
|
||||
|
||||
|
||||
var dropLine = Overlays.addOverlay("line3d", {
|
||||
color: DROP_COLOR,
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: DROP_WIDTH
|
||||
});
|
||||
|
||||
|
||||
function vectorIsZero(v) {
|
||||
return v.x == 0 && v.y == 0 && v.z == 0;
|
||||
}
|
||||
|
||||
function nearLinePoint(targetPosition) {
|
||||
// var handPosition = Vec3.sum(MyAvatar.position, {x:0, y:0.2, z:0});
|
||||
var handPosition = MyAvatar.getRightPalmPosition();
|
||||
var along = Vec3.subtract(targetPosition, handPosition);
|
||||
along = Vec3.normalize(along);
|
||||
along = Vec3.multiply(along, 0.4);
|
||||
return Vec3.sum(handPosition, along);
|
||||
}
|
||||
|
||||
|
||||
function mousePressEvent(event) {
|
||||
if (!event.isLeftButton) {
|
||||
return;
|
||||
}
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||
if (intersection.intersects && intersection.properties.collisionsWillMove) {
|
||||
grabbedEntity = intersection.entityID;
|
||||
var props = Entities.getEntityProperties(grabbedEntity)
|
||||
isGrabbing = true;
|
||||
originalGravity = props.gravity;
|
||||
targetPosition = props.position;
|
||||
currentPosition = props.position;
|
||||
currentVelocity = props.velocity;
|
||||
updateDropLine(targetPosition);
|
||||
|
||||
Entities.editEntity(grabbedEntity, {
|
||||
gravity: {x: 0, y: 0, z: 0}
|
||||
});
|
||||
|
||||
lineEntityID = Entities.addEntity({
|
||||
type: "Line",
|
||||
position: nearLinePoint(targetPosition),
|
||||
dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition)),
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
lifetime: 300 // if someone crashes while moving something, don't leave the line there forever.
|
||||
});
|
||||
|
||||
Audio.playSound(grabSound, {
|
||||
position: props.position,
|
||||
volume: VOLUME
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function mouseReleaseEvent() {
|
||||
if (isGrabbing) {
|
||||
isGrabbing = false;
|
||||
|
||||
// only restore the original gravity if it's not zero. This is to avoid...
|
||||
// 1. interface A grabs an entity and locally saves off its gravity
|
||||
// 2. interface A sets the entity's gravity to zero
|
||||
// 3. interface B grabs the entity and saves off its gravity (which is zero)
|
||||
// 4. interface A releases the entity and puts the original gravity back
|
||||
// 5. interface B releases the entity and puts the original gravity back (to zero)
|
||||
if (!vectorIsZero(originalGravity)) {
|
||||
Entities.editEntity(grabbedEntity, {
|
||||
gravity: originalGravity
|
||||
});
|
||||
}
|
||||
|
||||
Overlays.editOverlay(dropLine, {
|
||||
visible: false
|
||||
});
|
||||
targetPosition = null;
|
||||
|
||||
Entities.deleteEntity(lineEntityID);
|
||||
|
||||
Audio.playSound(releaseSound, {
|
||||
position: entityProps.position,
|
||||
volume: VOLUME
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
if (isGrabbing) {
|
||||
// see if something added/restored gravity
|
||||
var props = Entities.getEntityProperties(grabbedEntity);
|
||||
if (!vectorIsZero(props.gravity)) {
|
||||
originalGravity = props.gravity;
|
||||
}
|
||||
|
||||
deltaMouse.x = event.x - prevMouse.x;
|
||||
if (!moveUpDown) {
|
||||
deltaMouse.z = event.y - prevMouse.y;
|
||||
deltaMouse.y = 0;
|
||||
} else {
|
||||
deltaMouse.y = (event.y - prevMouse.y) * -1;
|
||||
deltaMouse.z = 0;
|
||||
}
|
||||
// Update the target position by the amount the mouse moved
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
Entities.editEntity(lineEntityID, {
|
||||
position: nearLinePoint(targetPosition),
|
||||
dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition))
|
||||
});
|
||||
}
|
||||
prevMouse.x = event.x;
|
||||
prevMouse.y = event.y;
|
||||
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
currentRotation = entityProps.rotation;
|
||||
|
||||
var dPosition = Vec3.subtract(targetPosition, currentPosition);
|
||||
|
||||
distanceToTarget = Vec3.length(dPosition);
|
||||
if (distanceToTarget > CLOSE_ENOUGH) {
|
||||
// compute current velocity in the direction we want to move
|
||||
velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition));
|
||||
velocityTowardTarget = Vec3.multiply(Vec3.normalize(dPosition), velocityTowardTarget);
|
||||
// compute the speed we would like to be going toward the target position
|
||||
|
||||
desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
|
||||
// compute how much we want to add to the existing velocity
|
||||
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
|
||||
} else {
|
||||
newVelocity = {x: 0, y: 0, z: 0};
|
||||
}
|
||||
if (shouldRotate) {
|
||||
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
|
||||
} else {
|
||||
angularVelocity = entityProps.angularVelocity;
|
||||
}
|
||||
|
||||
Entities.editEntity(grabbedEntity, {
|
||||
position: currentPosition,
|
||||
rotation: currentRotation,
|
||||
velocity: newVelocity,
|
||||
angularVelocity: angularVelocity
|
||||
});
|
||||
updateDropLine(targetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||
Script.update.connect(update);
|
303
examples/example/games/hydraGrabHockey.js
Normal file
303
examples/example/games/hydraGrabHockey.js
Normal file
|
@ -0,0 +1,303 @@
|
|||
//
|
||||
// hydraGrabHockey.js
|
||||
// examples
|
||||
//
|
||||
// Created by Eric Levin on 5/14/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// This script allows you to grab and move physical objects with the hydra
|
||||
// Same as hydraGrab.js, but you object movement is constrained to xz plane and cannot rotate object
|
||||
//
|
||||
//
|
||||
// Using the hydras :
|
||||
// grab physical entities with the right hydra trigger
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var addedVelocity, newVelocity, angularVelocity, dT, cameraEntityDistance;
|
||||
var LEFT = 0;
|
||||
var RIGHT = 1;
|
||||
var LASER_WIDTH = 3;
|
||||
var LASER_COLOR = {
|
||||
red: 50,
|
||||
green: 150,
|
||||
blue: 200
|
||||
};
|
||||
var LASER_HOVER_COLOR = {
|
||||
red: 200,
|
||||
green: 50,
|
||||
blue: 50
|
||||
};
|
||||
|
||||
var DROP_DISTANCE = 5.0;
|
||||
var DROP_COLOR = {
|
||||
red: 200,
|
||||
green: 200,
|
||||
blue: 200
|
||||
};
|
||||
|
||||
var FULL_STRENGTH = 0.2;
|
||||
var LASER_LENGTH_FACTOR = 500;
|
||||
var CLOSE_ENOUGH = 0.001;
|
||||
var SPRING_RATE = 1.5;
|
||||
var DAMPING_RATE = 0.8;
|
||||
var SCREEN_TO_METERS = 0.001;
|
||||
var DISTANCE_SCALE_FACTOR = 1000
|
||||
|
||||
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");
|
||||
|
||||
function getRayIntersection(pickRay) {
|
||||
var intersection = Entities.findRayIntersection(pickRay, true);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
|
||||
function controller(side) {
|
||||
this.triggerHeld = false;
|
||||
this.triggerThreshold = 0.9;
|
||||
this.side = side;
|
||||
this.palm = 2 * side;
|
||||
this.tip = 2 * side + 1;
|
||||
this.trigger = side;
|
||||
this.originalGravity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
|
||||
this.laser = Overlays.addOverlay("line3d", {
|
||||
start: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
end: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
color: LASER_COLOR,
|
||||
alpha: 1,
|
||||
lineWidth: LASER_WIDTH,
|
||||
anchor: "MyAvatar"
|
||||
});
|
||||
|
||||
this.dropLine = Overlays.addOverlay("line3d", {
|
||||
color: DROP_COLOR,
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: 2
|
||||
});
|
||||
|
||||
|
||||
this.update = function(deltaTime) {
|
||||
this.updateControllerState();
|
||||
this.moveLaser();
|
||||
this.checkTrigger();
|
||||
this.checkEntityIntersection();
|
||||
if (this.grabbing) {
|
||||
this.updateEntity(deltaTime);
|
||||
}
|
||||
|
||||
this.oldPalmPosition = this.palmPosition;
|
||||
this.oldTipPosition = this.tipPosition;
|
||||
}
|
||||
|
||||
this.updateEntity = function(deltaTime) {
|
||||
this.dControllerPosition = Vec3.subtract(this.palmPosition, this.oldPalmPosition);
|
||||
this.dControllerPosition.y = 0;
|
||||
this.cameraEntityDistance = Vec3.distance(Camera.getPosition(), this.currentPosition);
|
||||
this.targetPosition = Vec3.sum(this.targetPosition, Vec3.multiply(this.dControllerPosition, this.cameraEntityDistance * SCREEN_TO_METERS * DISTANCE_SCALE_FACTOR));
|
||||
|
||||
this.entityProps = Entities.getEntityProperties(this.grabbedEntity);
|
||||
this.currentPosition = this.entityProps.position;
|
||||
this.currentVelocity = this.entityProps.velocity;
|
||||
|
||||
var dPosition = Vec3.subtract(this.targetPosition, this.currentPosition);
|
||||
this.distanceToTarget = Vec3.length(dPosition);
|
||||
if (this.distanceToTarget > CLOSE_ENOUGH) {
|
||||
// compute current velocity in the direction we want to move
|
||||
this.velocityTowardTarget = Vec3.dot(this.currentVelocity, Vec3.normalize(dPosition));
|
||||
this.velocityTowardTarget = Vec3.multiply(Vec3.normalize(dPosition), this.velocityTowardTarget);
|
||||
// compute the speed we would like to be going toward the target position
|
||||
|
||||
this.desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
|
||||
// compute how much we want to add to the existing velocity
|
||||
this.addedVelocity = Vec3.subtract(this.desiredVelocity, this.velocityTowardTarget);
|
||||
//If target is to far, roll off force as inverse square of distance
|
||||
if(this.distanceToTarget/ this.cameraEntityDistance > FULL_STRENGTH) {
|
||||
this.addedVelocity = Vec3.multiply(this.addedVelocity, Math.pow(FULL_STRENGTH/ this.distanceToTarget, 2.0));
|
||||
}
|
||||
this.newVelocity = Vec3.sum(this.currentVelocity, this.addedVelocity);
|
||||
this.newVelocity = Vec3.subtract(this.newVelocity, Vec3.multiply(this.newVelocity, DAMPING_RATE));
|
||||
} else {
|
||||
this.newVelocity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
Entities.editEntity(this.grabbedEntity, {
|
||||
velocity: this.newVelocity,
|
||||
});
|
||||
|
||||
this.updateDropLine(this.targetPosition);
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.updateControllerState = function() {
|
||||
this.palmPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
this.tipPosition = Controller.getSpatialControlPosition(this.tip);
|
||||
this.triggerValue = Controller.getTriggerValue(this.trigger);
|
||||
}
|
||||
|
||||
this.checkTrigger = function() {
|
||||
if (this.triggerValue > this.triggerThreshold && !this.triggerHeld) {
|
||||
this.triggerHeld = true;
|
||||
} else if (this.triggerValue < this.triggerThreshold && this.triggerHeld) {
|
||||
this.triggerHeld = false;
|
||||
if (this.grabbing) {
|
||||
this.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.updateDropLine = function(position) {
|
||||
|
||||
Overlays.editOverlay(this.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
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
this.checkEntityIntersection = function() {
|
||||
|
||||
var pickRay = {
|
||||
origin: this.palmPosition,
|
||||
direction: Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition))
|
||||
};
|
||||
var intersection = getRayIntersection(pickRay, true);
|
||||
if (intersection.intersects && intersection.properties.collisionsWillMove) {
|
||||
this.laserWasHovered = true;
|
||||
if (this.triggerHeld && !this.grabbing) {
|
||||
this.grab(intersection.entityID);
|
||||
}
|
||||
Overlays.editOverlay(this.laser, {
|
||||
color: LASER_HOVER_COLOR
|
||||
});
|
||||
} else if (this.laserWasHovered) {
|
||||
this.laserWasHovered = false;
|
||||
Overlays.editOverlay(this.laser, {
|
||||
color: LASER_COLOR
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.grab = function(entityId) {
|
||||
this.grabbing = true;
|
||||
this.grabbedEntity = entityId;
|
||||
this.entityProps = Entities.getEntityProperties(this.grabbedEntity);
|
||||
this.targetPosition = this.entityProps.position;
|
||||
this.currentPosition = this.targetPosition;
|
||||
this.oldPalmPosition = this.palmPosition;
|
||||
this.originalGravity = this.entityProps.gravity;
|
||||
Entities.editEntity(this.grabbedEntity, {
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}
|
||||
});
|
||||
Overlays.editOverlay(this.laser, {
|
||||
visible: false
|
||||
});
|
||||
Audio.playSound(grabSound, {
|
||||
position: this.entityProps.position,
|
||||
volume: 0.25
|
||||
});
|
||||
}
|
||||
|
||||
this.release = function() {
|
||||
this.grabbing = false;
|
||||
this.grabbedEntity = null;
|
||||
Overlays.editOverlay(this.laser, {
|
||||
visible: true
|
||||
});
|
||||
Overlays.editOverlay(this.dropLine, {
|
||||
visible: false
|
||||
});
|
||||
|
||||
Audio.playSound(releaseSound, {
|
||||
position: this.entityProps.position,
|
||||
volume: 0.25
|
||||
});
|
||||
|
||||
// only restore the original gravity if it's not zero. This is to avoid...
|
||||
// 1. interface A grabs an entity and locally saves off its gravity
|
||||
// 2. interface A sets the entity's gravity to zero
|
||||
// 3. interface B grabs the entity and saves off its gravity (which is zero)
|
||||
// 4. interface A releases the entity and puts the original gravity back
|
||||
// 5. interface B releases the entity and puts the original gravity back (to zero)
|
||||
if(vectorIsZero(this.originalGravity)) {
|
||||
Entities.editEntity(this.grabbedEntity, {
|
||||
gravity: this.originalGravity
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.moveLaser = function() {
|
||||
var inverseRotation = Quat.inverse(MyAvatar.orientation);
|
||||
var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position));
|
||||
// startPosition = Vec3.multiply(startPosition, 1 / MyAvatar.scale);
|
||||
var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition));
|
||||
direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / (Vec3.length(direction) * MyAvatar.scale));
|
||||
var endPosition = Vec3.sum(startPosition, direction);
|
||||
|
||||
Overlays.editOverlay(this.laser, {
|
||||
start: startPosition,
|
||||
end: endPosition
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
this.cleanup = function() {
|
||||
Overlays.deleteOverlay(this.laser);
|
||||
Overlays.deleteOverlay(this.dropLine);
|
||||
}
|
||||
}
|
||||
|
||||
function update(deltaTime) {
|
||||
rightController.update(deltaTime);
|
||||
leftController.update(deltaTime);
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
rightController.cleanup();
|
||||
leftController.cleanup();
|
||||
}
|
||||
|
||||
function vectorIsZero(v) {
|
||||
return v.x === 0 && v.y === 0 && v.z === 0;
|
||||
}
|
||||
|
||||
var rightController = new controller(RIGHT);
|
||||
var leftController = new controller(LEFT);
|
||||
|
||||
|
||||
Script.update.connect(update);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
|
@ -17,6 +17,8 @@ const BASE_DIMENSION = { x: 7, y: 2, z: 7 };
|
|||
const BLOCKS_PER_LAYER = 3;
|
||||
const BLOCK_SIZE = {x: 0.2, y: 0.1, z: 0.8};
|
||||
const BLOCK_SPACING = BLOCK_SIZE.x / 3;
|
||||
// BLOCK_HEIGHT_VARIATION removes a random percentages of the default block height per block. (for example 0.001 %)
|
||||
const BLOCK_HEIGHT_VARIATION = 0.001;
|
||||
const GRAVITY = {x: 0, y: -2.8, z: 0};
|
||||
const DENSITY = 2000;
|
||||
const DAMPING_FACTOR = 0.98;
|
||||
|
@ -24,6 +26,7 @@ const ANGULAR_DAMPING_FACTOR = 0.8;
|
|||
const SPAWN_DISTANCE = 3;
|
||||
const BLOCK_YAW_OFFSET = 45;
|
||||
const BUTTON_DIMENSIONS = {width: 49, height: 49};
|
||||
const MAXIMUM_PERCENTAGE = 100.0;
|
||||
|
||||
var windowWidth = Window.innerWidth;
|
||||
var size;
|
||||
|
@ -94,7 +97,11 @@ function resetBlocks() {
|
|||
modelURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/block.fbx',
|
||||
shapeType: 'box',
|
||||
name: 'PlankyBlock' + ((layerIndex * BLOCKS_PER_LAYER) + blockIndex),
|
||||
dimensions: BLOCK_SIZE,
|
||||
dimensions: {
|
||||
x: BLOCK_SIZE.x,
|
||||
y: BLOCK_SIZE.y - ((BLOCK_SIZE.y * (BLOCK_HEIGHT_VARIATION / MAXIMUM_PERCENTAGE)) * Math.random()),
|
||||
z: BLOCK_SIZE.z
|
||||
},
|
||||
position: {
|
||||
x: basePosition.x + localTransform.x,
|
||||
y: basePosition.y + localTransform.y,
|
||||
|
|
|
@ -76,7 +76,7 @@ function mousePressEvent(event) {
|
|||
return;
|
||||
}
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Entities.findRayIntersection(pickRay);
|
||||
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||
if (intersection.intersects && intersection.properties.collisionsWillMove) {
|
||||
grabbedEntity = intersection.entityID;
|
||||
var props = Entities.getEntityProperties(grabbedEntity)
|
||||
|
|
|
@ -233,6 +233,9 @@
|
|||
var elAngularVelocityZ = document.getElementById("property-avel-z");
|
||||
var elAngularDamping = document.getElementById("property-adamping");
|
||||
|
||||
var elRestitution = document.getElementById("property-restitution");
|
||||
var elFriction = document.getElementById("property-friction");
|
||||
|
||||
var elGravityX = document.getElementById("property-grav-x");
|
||||
var elGravityY = document.getElementById("property-grav-y");
|
||||
var elGravityZ = document.getElementById("property-grav-z");
|
||||
|
@ -244,6 +247,7 @@
|
|||
var elDensity = document.getElementById("property-density");
|
||||
var elIgnoreForCollisions = document.getElementById("property-ignore-for-collisions");
|
||||
var elCollisionsWillMove = document.getElementById("property-collisions-will-move");
|
||||
var elCollisionSoundURL = document.getElementById("property-collision-sound-url");
|
||||
var elLifetime = document.getElementById("property-lifetime");
|
||||
var elScriptURL = document.getElementById("property-script-url");
|
||||
var elUserData = document.getElementById("property-user-data");
|
||||
|
@ -426,6 +430,9 @@
|
|||
elAngularVelocityZ.value = (properties.angularVelocity.z * RADIANS_TO_DEGREES).toFixed(2);
|
||||
elAngularDamping.value = properties.angularDamping.toFixed(2);
|
||||
|
||||
elRestitution.value = properties.restitution.toFixed(2);
|
||||
elFriction.value = properties.friction.toFixed(2);
|
||||
|
||||
elGravityX.value = properties.gravity.x.toFixed(2);
|
||||
elGravityY.value = properties.gravity.y.toFixed(2);
|
||||
elGravityZ.value = properties.gravity.z.toFixed(2);
|
||||
|
@ -437,6 +444,7 @@
|
|||
elDensity.value = properties.density.toFixed(2);
|
||||
elIgnoreForCollisions.checked = properties.ignoreForCollisions;
|
||||
elCollisionsWillMove.checked = properties.collisionsWillMove;
|
||||
elCollisionSoundURL.value = properties.collisionSoundURL;
|
||||
elLifetime.value = properties.lifetime;
|
||||
elScriptURL.value = properties.script;
|
||||
elUserData.value = properties.userData;
|
||||
|
@ -605,7 +613,10 @@
|
|||
elAngularVelocityX.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularVelocityY.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularVelocityZ.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('angularDamping'))
|
||||
elAngularDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('angularDamping'));
|
||||
|
||||
elRestitution.addEventListener('change', createEmitNumberPropertyUpdateFunction('restitution'));
|
||||
elFriction.addEventListener('change', createEmitNumberPropertyUpdateFunction('friction'));
|
||||
|
||||
var gravityChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'gravity', elGravityX, elGravityY, elGravityZ);
|
||||
|
@ -622,6 +633,8 @@
|
|||
elDensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('density'));
|
||||
elIgnoreForCollisions.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ignoreForCollisions'));
|
||||
elCollisionsWillMove.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionsWillMove'));
|
||||
elCollisionSoundURL.addEventListener('change', createEmitTextPropertyUpdateFunction('collisionSoundURL'));
|
||||
|
||||
elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime'));
|
||||
elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script'));
|
||||
elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData'));
|
||||
|
@ -959,6 +972,18 @@
|
|||
<input class="coord" type='number' id="property-adamping"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<div class="label">Restitution</div>
|
||||
<div class="value">
|
||||
<input class="coord" type='number' id="property-restitution"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<div class="label">Friction</div>
|
||||
<div class="value">
|
||||
<input class="coord" type='number' id="property-friction"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Gravity</div>
|
||||
|
@ -999,6 +1024,13 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Collision Sound URL</div>
|
||||
<div class="value">
|
||||
<input id="property-collision-sound-url" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Lifetime</div>
|
||||
<div class="value">
|
||||
|
|
|
@ -243,7 +243,6 @@ table#properties-list {
|
|||
|
||||
#properties-list .label {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
|
|
|
@ -185,6 +185,8 @@ EntityPropertyDialogBox = (function () {
|
|||
index++;
|
||||
array.push({ label: "Collisions Will Move:", type: "checkbox", value: properties.collisionsWillMove });
|
||||
index++;
|
||||
array.push({ label: "Collision Sound URL:", value: properties.collisionSoundURL });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Lifetime:", value: properties.lifetime.toFixed(decimals) });
|
||||
index++;
|
||||
|
|
|
@ -36,8 +36,22 @@ endif ()
|
|||
configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h")
|
||||
configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h")
|
||||
|
||||
|
||||
macro(GroupSources curdir)
|
||||
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
|
||||
foreach(child ${children})
|
||||
if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
|
||||
GroupSources(${curdir}/${child})
|
||||
else()
|
||||
string(REPLACE "/" "\\" groupname ${curdir})
|
||||
source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# grab the implementation and header files from src dirs
|
||||
file(GLOB_RECURSE INTERFACE_SRCS "src/*.cpp" "src/*.h")
|
||||
GroupSources("src")
|
||||
|
||||
# Add SpeechRecognizer if on Windows or OS X, otherwise remove
|
||||
if (WIN32)
|
||||
|
@ -58,6 +72,7 @@ find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Qml Quick Script Svg W
|
|||
|
||||
# grab the ui files in resources/ui
|
||||
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
|
||||
source_group("UI Files" FILES ${QT_UI_FILES})
|
||||
# have qt5 wrap them and generate the appropriate header files
|
||||
qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
||||
|
||||
|
|
|
@ -839,6 +839,11 @@ void Application::paintGL() {
|
|||
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
||||
resizeGL();
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("renderOverlay");
|
||||
_applicationOverlay.renderOverlay();
|
||||
}
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
|
@ -921,13 +926,9 @@ void Application::paintGL() {
|
|||
glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y,
|
||||
0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("renderOverlay");
|
||||
_applicationOverlay.renderOverlay();
|
||||
_applicationOverlay.displayOverlayTexture();
|
||||
}
|
||||
_applicationOverlay.displayOverlayTexture();
|
||||
}
|
||||
|
||||
if (!OculusManager::isConnected() || OculusManager::allowSwap()) {
|
||||
|
@ -2455,7 +2456,7 @@ void Application::update(float deltaTime) {
|
|||
|
||||
if (_physicsEngine.hasOutgoingChanges()) {
|
||||
_entitySimulation.lock();
|
||||
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
|
||||
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID());
|
||||
_entitySimulation.handleCollisionEvents(_physicsEngine.getCollisionEvents());
|
||||
_entitySimulation.unlock();
|
||||
_physicsEngine.dumpStatsIfNecessary();
|
||||
|
@ -3078,7 +3079,11 @@ PickRay Application::computePickRay(float x, float y) const {
|
|||
if (isHMDMode()) {
|
||||
ApplicationOverlay::computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction);
|
||||
} else {
|
||||
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
if (activeRenderingThread) {
|
||||
getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
} else {
|
||||
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -3133,6 +3138,16 @@ ViewFrustum* Application::getDisplayViewFrustum() {
|
|||
return &_displayViewFrustum;
|
||||
}
|
||||
|
||||
const ViewFrustum* Application::getDisplayViewFrustum() const {
|
||||
#ifdef DEBUG
|
||||
if (QThread::currentThread() != activeRenderingThread) {
|
||||
// FIXME, should this be an assert?
|
||||
qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
|
||||
}
|
||||
#endif
|
||||
return &_displayViewFrustum;
|
||||
}
|
||||
|
||||
void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs::RenderSide renderSide) {
|
||||
activeRenderingThread = QThread::currentThread();
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
|
@ -3362,7 +3377,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalAtmosphere(skyStage->getAtmosphere());
|
||||
// NOt yet DependencyManager::get<DeferredLightingEffect>()->setGlobalSkybox(skybox);
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalSkybox(skybox);
|
||||
|
||||
PROFILE_RANGE("DeferredLighting");
|
||||
PerformanceTimer perfTimer("lighting");
|
||||
|
|
|
@ -205,6 +205,7 @@ public:
|
|||
// which might be different from the viewFrustum, i.e. shadowmap
|
||||
// passes, mirror window passes, etc
|
||||
ViewFrustum* getDisplayViewFrustum();
|
||||
const ViewFrustum* getDisplayViewFrustum() const;
|
||||
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
|
||||
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
||||
EntityTreeRenderer* getEntities() { return &_entities; }
|
||||
|
|
|
@ -520,12 +520,6 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati
|
|||
return;
|
||||
}
|
||||
|
||||
ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
|
||||
|
||||
// We only need to render the overlays to a texture once, then we just render the texture on the hemisphere
|
||||
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
||||
applicationOverlay.renderOverlay();
|
||||
|
||||
//Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
||||
DependencyManager::get<GlowEffect>()->prepare();
|
||||
|
@ -614,9 +608,8 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati
|
|||
//glTranslatef(_eyeRenderDesc[eye].ViewAdjust.x, _eyeRenderDesc[eye].ViewAdjust.y, _eyeRenderDesc[eye].ViewAdjust.z);
|
||||
|
||||
_camera->setEyeOffsetPosition(glm::vec3(-_eyeRenderDesc[eye].HmdToEyeViewOffset.x, -_eyeRenderDesc[eye].HmdToEyeViewOffset.y, -_eyeRenderDesc[eye].HmdToEyeViewOffset.z));
|
||||
Application::getInstance()->displaySide(*_camera, false, RenderArgs::MONO);
|
||||
|
||||
applicationOverlay.displayOverlayTextureHmd(*_camera);
|
||||
qApp->displaySide(*_camera, false, RenderArgs::MONO);
|
||||
qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera);
|
||||
});
|
||||
_activeEye = ovrEye_Count;
|
||||
|
||||
|
|
|
@ -92,74 +92,40 @@ void TV3DManager::display(Camera& whichCamera) {
|
|||
int portalW = deviceSize.width() / 2;
|
||||
int portalH = deviceSize.height();
|
||||
|
||||
ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
|
||||
|
||||
// We only need to render the overlays to a texture once, then we just render the texture as a quad
|
||||
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
||||
applicationOverlay.renderOverlay();
|
||||
|
||||
DependencyManager::get<GlowEffect>()->prepare();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
// render left side view
|
||||
glViewport(portalX, portalY, portalW, portalH);
|
||||
glScissor(portalX, portalY, portalW, portalH);
|
||||
|
||||
Camera eyeCamera;
|
||||
eyeCamera.setRotation(whichCamera.getRotation());
|
||||
eyeCamera.setPosition(whichCamera.getPosition());
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glPushMatrix();
|
||||
{
|
||||
_activeEye = &_leftEye;
|
||||
forEachEye([&](eyeFrustum& eye){
|
||||
_activeEye = &eye;
|
||||
glViewport(portalX, portalY, portalW, portalH);
|
||||
glScissor(portalX, portalY, portalW, portalH);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity(); // reset projection matrix
|
||||
glFrustum(_leftEye.left, _leftEye.right, _leftEye.bottom, _leftEye.top, nearZ, farZ); // set left view frustum
|
||||
glFrustum(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ); // set left view frustum
|
||||
GLfloat p[4][4];
|
||||
// Really?
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
|
||||
float cotangent = p[1][1];
|
||||
GLfloat fov = atan(1.0f / cotangent);
|
||||
glTranslatef(_leftEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
|
||||
glTranslatef(eye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0));
|
||||
Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO);
|
||||
|
||||
applicationOverlay.displayOverlayTextureStereo(whichCamera, _aspect, fov);
|
||||
qApp->displaySide(eyeCamera, false, RenderArgs::MONO);
|
||||
qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov);
|
||||
_activeEye = NULL;
|
||||
}
|
||||
glPopMatrix();
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
// render right side view
|
||||
portalX = deviceSize.width() / 2;
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
// render left side view
|
||||
glViewport(portalX, portalY, portalW, portalH);
|
||||
glScissor(portalX, portalY, portalW, portalH);
|
||||
glPushMatrix();
|
||||
{
|
||||
_activeEye = &_rightEye;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity(); // reset projection matrix
|
||||
glFrustum(_rightEye.left, _rightEye.right, _rightEye.bottom, _rightEye.top, nearZ, farZ); // set right view frustum
|
||||
GLfloat p[4][4];
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
|
||||
GLfloat cotangent = p[1][1];
|
||||
GLfloat fov = atan(1.0f / cotangent);
|
||||
glTranslatef(_rightEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0));
|
||||
Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO);
|
||||
|
||||
applicationOverlay.displayOverlayTextureStereo(whichCamera, _aspect, fov);
|
||||
_activeEye = NULL;
|
||||
}
|
||||
}, [&]{
|
||||
// render right side view
|
||||
portalX = deviceSize.width() / 2;
|
||||
});
|
||||
glPopMatrix();
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
|
@ -167,11 +133,13 @@ void TV3DManager::display(Camera& whichCamera) {
|
|||
auto fboSize = finalFbo->getSize();
|
||||
// Get the ACTUAL device size for the BLIT
|
||||
deviceSize = qApp->getDeviceSize();
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo));
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, fboSize.x, fboSize.y,
|
||||
0, 0, deviceSize.width(), deviceSize.height(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
// reset the viewport to how we started
|
||||
glViewport(0, 0, deviceSize.width(), deviceSize.height());
|
||||
|
|
|
@ -44,6 +44,20 @@ private:
|
|||
static eyeFrustum _leftEye;
|
||||
static eyeFrustum _rightEye;
|
||||
static eyeFrustum* _activeEye;
|
||||
|
||||
// The first function is the code executed for each eye
|
||||
// while the second is code to be executed between the two eyes.
|
||||
// The use case here is to modify the output viewport coordinates
|
||||
// for the new eye.
|
||||
// FIXME: we'd like to have a default empty lambda for the second parameter,
|
||||
// but gcc 4.8.1 complains about it due to a bug. See
|
||||
// http://stackoverflow.com/questions/25490662/lambda-as-default-parameter-to-a-member-function-template
|
||||
template<typename F, typename FF>
|
||||
static void forEachEye(F f, FF ff) {
|
||||
f(_leftEye);
|
||||
ff();
|
||||
f(_rightEye);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // hifi_TV3DManager_h
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include <Application.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <devices/OculusManager.h>
|
||||
#include <LODManager.h>
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
|
@ -292,8 +291,8 @@ void Overlays::deleteOverlay(unsigned int id) {
|
|||
|
||||
unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||
glm::vec2 pointCopy = point;
|
||||
if (OculusManager::isConnected()) {
|
||||
pointCopy = Application::getInstance()->getApplicationOverlay().screenToOverlay(point);
|
||||
if (qApp->isHMDMode()) {
|
||||
pointCopy = qApp->getApplicationOverlay().screenToOverlay(point);
|
||||
}
|
||||
|
||||
QReadLocker lock(&_lock);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <SceneScriptingInterface.h>
|
||||
#include <ScriptEngine.h>
|
||||
#include <TextureCache.h>
|
||||
#include <SoundCache.h>
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
||||
|
@ -46,6 +47,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
_wantScripts(wantScripts),
|
||||
_entitiesScriptEngine(NULL),
|
||||
_sandboxScriptEngine(NULL),
|
||||
_localAudioInterface(NULL),
|
||||
_lastMouseEventValid(false),
|
||||
_viewState(viewState),
|
||||
_scriptingServices(scriptingServices),
|
||||
|
@ -848,9 +850,18 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
|
||||
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||
connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
||||
connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
||||
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface,
|
||||
[=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId){
|
||||
entityScriptingInterface->mousePressOnEntity(intersection.entityID, MouseEvent(*event, deviceId));
|
||||
});
|
||||
connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface,
|
||||
[=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) {
|
||||
entityScriptingInterface->mouseMoveOnEntity(intersection.entityID, MouseEvent(*event, deviceId));
|
||||
});
|
||||
connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface,
|
||||
[=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) {
|
||||
entityScriptingInterface->mouseReleaseOnEntity(intersection.entityID, MouseEvent(*event, deviceId));
|
||||
});
|
||||
|
||||
connect(this, &EntityTreeRenderer::clickDownOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickDownOnEntity);
|
||||
connect(this, &EntityTreeRenderer::holdingClickOnEntity, entityScriptingInterface, &EntityScriptingInterface::holdingClickOnEntity);
|
||||
|
@ -898,7 +909,7 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device
|
|||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||
emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
emit mousePressOnEntity(rayPickResult, event, deviceID);
|
||||
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
|
@ -928,7 +939,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int devi
|
|||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
emit mouseReleaseOnEntity(rayPickResult, event, deviceID);
|
||||
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
|
@ -977,7 +988,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
|
|||
}
|
||||
|
||||
//qCDebug(entitiesrenderer) << "mouseMoveEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
emit mouseMoveOnEntity(rayPickResult, event, deviceID);
|
||||
if (entityScript.property("mouseMoveOnEntity").isValid()) {
|
||||
entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
|
@ -1098,13 +1109,84 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB,
|
||||
void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision) {
|
||||
EntityItem* entity = entityTree->findEntityByEntityItemID(id);
|
||||
QUuid simulatorID = entity->getSimulatorID();
|
||||
if (simulatorID.isNull() || (simulatorID != myNodeID)) {
|
||||
return; // Only one injector per simulation, please.
|
||||
}
|
||||
const QString& collisionSoundURL = entity->getCollisionSoundURL();
|
||||
if (collisionSoundURL.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const float mass = entity->computeMass();
|
||||
const float COLLISION_PENTRATION_TO_VELOCITY = 50; // as a subsitute for RELATIVE entity->getVelocity()
|
||||
const float linearVelocity = glm::length(collision.penetration) * COLLISION_PENTRATION_TO_VELOCITY;
|
||||
const float energy = mass * linearVelocity * linearVelocity / 2.0f;
|
||||
const glm::vec3 position = collision.contactPoint;
|
||||
const float COLLISION_ENERGY_AT_FULL_VOLUME = 1.0f;
|
||||
const float COLLISION_MINIMUM_VOLUME = 0.001f;
|
||||
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
||||
if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) {
|
||||
return;
|
||||
}
|
||||
|
||||
SharedSoundPointer sound = DependencyManager::get<SoundCache>().data()->getSound(QUrl(collisionSoundURL));
|
||||
if (!sound->isReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all.
|
||||
const float COLLISION_SOUND_COMPRESSION_RANGE = 0.95f;
|
||||
float volume = energyFactorOfFull;
|
||||
volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
|
||||
|
||||
// This is quite similar to AudioScriptingInterface::playSound() and should probably be refactored.
|
||||
AudioInjectorOptions options;
|
||||
options.stereo = sound->isStereo();
|
||||
options.position = position;
|
||||
options.volume = volume;
|
||||
AudioInjector* injector = new AudioInjector(sound.data(), options);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
QThread* injectorThread = new QThread();
|
||||
injectorThread->setObjectName("Audio Injector Thread");
|
||||
injector->moveToThread(injectorThread);
|
||||
// start injecting when the injector thread starts
|
||||
connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio);
|
||||
// connect the right slots and signals for AudioInjector and thread cleanup
|
||||
connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit);
|
||||
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||
injectorThread->start();
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB,
|
||||
const Collision& collision) {
|
||||
// If we don't have a tree, or we're in the process of shutting down, then don't
|
||||
// process these events.
|
||||
if (!_tree || _shuttingDown) {
|
||||
return;
|
||||
}
|
||||
// Don't respond to small continuous contacts. It causes deadlocks when locking the entityTree.
|
||||
// Note that any entity script is likely to Entities.getEntityProperties(), which locks the tree.
|
||||
const float COLLISION_MINUMUM_PENETRATION = 0.001;
|
||||
if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we should play sounds
|
||||
EntityTree* entityTree = static_cast<EntityTree*>(_tree);
|
||||
if (!entityTree->tryLockForRead()) {
|
||||
// I don't know why this can happen, but if it does,
|
||||
// the consequences are a deadlock, so bail.
|
||||
qCDebug(entitiesrenderer) << "NOTICE: skipping collision type " << collision.type << " penetration " << glm::length(collision.penetration);
|
||||
return;
|
||||
}
|
||||
const QUuid& myNodeID = DependencyManager::get<NodeList>()->getSessionUUID();
|
||||
playEntityCollisionSound(myNodeID, entityTree, idA, collision);
|
||||
playEntityCollisionSound(myNodeID, entityTree, idB, collision);
|
||||
entityTree->unlock();
|
||||
|
||||
// And now the entity scripts
|
||||
QScriptValue entityScriptA = loadEntityScript(idA);
|
||||
if (entityScriptA.property("collisionWithEntity").isValid()) {
|
||||
QScriptValueList args;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <MouseEvent.h>
|
||||
#include <OctreeRenderer.h>
|
||||
#include <ScriptCache.h>
|
||||
#include <AbstractAudioInterface.h>
|
||||
|
||||
class AbstractScriptingServicesInterface;
|
||||
class AbstractViewStateInterface;
|
||||
|
@ -92,9 +93,9 @@ public:
|
|||
virtual void errorInLoadingScript(const QUrl& url);
|
||||
|
||||
signals:
|
||||
void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void mousePressOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId);
|
||||
void mouseMoveOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId);
|
||||
void mouseReleaseOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId);
|
||||
|
||||
void clickDownOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void holdingClickOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
|
@ -155,6 +156,9 @@ private:
|
|||
|
||||
QHash<EntityItemID, EntityScriptDetails> _entityScripts;
|
||||
|
||||
void playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision);
|
||||
AbstractAudioInterface* _localAudioInterface; // So we can render collision sounds
|
||||
|
||||
bool _lastMouseEventValid;
|
||||
MouseEvent _lastMouseEvent;
|
||||
AbstractViewStateInterface* _viewState;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <TextureCache.h>
|
||||
#include <gpu/GLBackend.h>
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
const float DPI = 30.47;
|
||||
const float METERS_TO_INCHES = 39.3701;
|
||||
|
@ -63,6 +65,7 @@ RenderableWebEntityItem::~RenderableWebEntityItem() {
|
|||
void RenderableWebEntityItem::render(RenderArgs* args) {
|
||||
QOpenGLContext * currentContext = QOpenGLContext::currentContext();
|
||||
QSurface * currentSurface = currentContext->surface();
|
||||
|
||||
if (!_webSurface) {
|
||||
_webSurface = new OffscreenQmlSurface();
|
||||
_webSurface->create(currentContext);
|
||||
|
@ -89,6 +92,52 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
|
|||
_webSurface->doneCurrent();
|
||||
}
|
||||
});
|
||||
|
||||
auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) {
|
||||
// Ignore mouse interaction if we're locked
|
||||
if (this->getLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (intersection.entityID.id == getID()) {
|
||||
if (event->button() == Qt::MouseButton::RightButton) {
|
||||
if (event->type() == QEvent::MouseButtonRelease) {
|
||||
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
|
||||
QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack");
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->button() == Qt::MouseButton::MiddleButton) {
|
||||
if (event->type() == QEvent::MouseButtonRelease) {
|
||||
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
|
||||
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Map the intersection point to an actual offscreen pixel
|
||||
glm::vec3 point = intersection.intersection;
|
||||
point -= getPosition();
|
||||
point = glm::inverse(getRotation()) * point;
|
||||
point /= _dimensions;
|
||||
point += 0.5f;
|
||||
point.y = 1.0f - point.y;
|
||||
point *= _dimensions * METERS_TO_INCHES * DPI;
|
||||
// Forward the mouse event.
|
||||
QMouseEvent mappedEvent(event->type(),
|
||||
QPoint((int)point.x, (int)point.y),
|
||||
event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent);
|
||||
}
|
||||
};
|
||||
EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer);
|
||||
QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent);
|
||||
QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent);
|
||||
QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent);
|
||||
}
|
||||
|
||||
glm::vec2 dims = glm::vec2(_dimensions);
|
||||
|
@ -106,8 +155,6 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
|
|||
glm::vec3 halfDimensions = dimensions / 2.0f;
|
||||
glm::quat rotation = getRotation();
|
||||
|
||||
//qCDebug(entitytree) << "RenderableWebEntityItem::render() id:" << getEntityItemID() << "text:" << getText();
|
||||
|
||||
glPushMatrix();
|
||||
{
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
|
|
|
@ -33,23 +33,23 @@ AtmospherePropertyGroup::AtmospherePropertyGroup() {
|
|||
}
|
||||
|
||||
void AtmospherePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, atmosphere, Center, center);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, Center, center);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, InnerRadius, innerRadius);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, OuterRadius, outerRadius);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, MieScattering, mieScattering);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, RayleighScattering, rayleighScattering);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, atmosphere, ScatteringWavelengths, scatteringWavelengths);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, ScatteringWavelengths, scatteringWavelengths);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, 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);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(atmosphere, center, glmVec3, setCenter);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(atmosphere, innerRadius, float, setInnerRadius);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(atmosphere, outerRadius, float, setOuterRadius);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(atmosphere, mieScattering, float, setMieScattering);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(atmosphere, rayleighScattering, float, setRayleighScattering);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(atmosphere, scatteringWavelengths, glmVec3, setScatteringWavelengths);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(atmosphere, hasStars, bool, setHasStars);
|
||||
}
|
||||
|
||||
void AtmospherePropertyGroup::debugDump() const {
|
||||
|
@ -72,13 +72,13 @@ bool AtmospherePropertyGroup::appentToEditPacket(OctreePacketData* packetData,
|
|||
|
||||
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());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, getCenter());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, getInnerRadius());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, getOuterRadius());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, getMieScattering());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, getRayleighScattering());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, getScatteringWavelengths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, getHasStars());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -89,13 +89,13 @@ bool AtmospherePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& property
|
|||
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);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, glm::vec3, setCenter);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, float, setInnerRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, float, setOuterRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, float, setMieScattering);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, float, setRayleighScattering);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, glm::vec3, setScatteringWavelengths);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, bool, setHasStars);
|
||||
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ATMOSPHERE_CENTER, Center);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ATMOSPHERE_INNER_RADIUS, InnerRadius);
|
||||
|
@ -183,13 +183,13 @@ void AtmospherePropertyGroup::appendSubclassData(OctreePacketData* packetData, E
|
|||
|
||||
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());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, getCenter());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, getInnerRadius());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, getOuterRadius());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, getMieScattering());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, getRayleighScattering());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, getScatteringWavelengths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, getHasStars());
|
||||
}
|
||||
|
||||
int AtmospherePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
|
@ -199,13 +199,13 @@ int AtmospherePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned cha
|
|||
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);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, glm::vec3, setCenter);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, float, setInnerRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_OUTER_RADIUS, float, setOuterRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_MIE_SCATTERING, float, setMieScattering);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, float, setRayleighScattering);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, glm::vec3, setScatteringWavelengths);
|
||||
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_HAS_STARS, bool, setHasStars);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ int BoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ void BoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
}
|
||||
|
||||
void BoxEntityItem::debugDump() const {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <PhysicsHelpers.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h> // usecTimestampNow()
|
||||
#include <SoundCache.h>
|
||||
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "EntityItem.h"
|
||||
|
@ -50,8 +51,11 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
|||
_gravity(ENTITY_ITEM_DEFAULT_GRAVITY),
|
||||
_acceleration(ENTITY_ITEM_DEFAULT_ACCELERATION),
|
||||
_damping(ENTITY_ITEM_DEFAULT_DAMPING),
|
||||
_restitution(ENTITY_ITEM_DEFAULT_RESTITUTION),
|
||||
_friction(ENTITY_ITEM_DEFAULT_FRICTION),
|
||||
_lifetime(ENTITY_ITEM_DEFAULT_LIFETIME),
|
||||
_script(ENTITY_ITEM_DEFAULT_SCRIPT),
|
||||
_collisionSoundURL(ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
|
||||
_registrationPoint(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT),
|
||||
_angularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY),
|
||||
_angularDamping(ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING),
|
||||
|
@ -98,8 +102,11 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
requestedProperties += PROP_GRAVITY;
|
||||
requestedProperties += PROP_ACCELERATION;
|
||||
requestedProperties += PROP_DAMPING;
|
||||
requestedProperties += PROP_RESTITUTION;
|
||||
requestedProperties += PROP_FRICTION;
|
||||
requestedProperties += PROP_LIFETIME;
|
||||
requestedProperties += PROP_SCRIPT;
|
||||
requestedProperties += PROP_COLLISION_SOUND_URL;
|
||||
requestedProperties += PROP_REGISTRATION_POINT;
|
||||
requestedProperties += PROP_ANGULAR_VELOCITY;
|
||||
requestedProperties += PROP_ANGULAR_DAMPING;
|
||||
|
@ -216,27 +223,30 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
// PROP_PAGED_PROPERTY,
|
||||
// PROP_CUSTOM_PROPERTIES_INCLUDED,
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, appendValue, getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, appendValue, getAcceleration());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, getAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, appendValue, getAngularDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, appendValue, getVisible());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, getIgnoreForCollisions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SIMULATOR_ID, appendValue, getSimulatorID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, getMarketplaceID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, appendValue, getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getDimensions()); // NOTE: PROP_RADIUS obsolete
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, getRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, getVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAVITY, getGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DAMPING, getDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_RESTITUTION, getRestitution());
|
||||
APPEND_ENTITY_PROPERTY(PROP_FRICTION, getFriction());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, getIgnoreForCollisions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, getCollisionsWillMove());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SIMULATOR_ID, getSimulatorID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, getMarketplaceID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, getCollisionSoundURL());
|
||||
|
||||
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
||||
requestedProperties,
|
||||
|
@ -511,9 +521,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
bytesRead += propertyFlags.getEncodedLength();
|
||||
bool useMeters = (args.bitstreamVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS);
|
||||
if (useMeters) {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePosition);
|
||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePositionInDomainUnits);
|
||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePositionInDomainUnits);
|
||||
}
|
||||
|
||||
// Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS
|
||||
|
@ -529,51 +539,53 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
}
|
||||
} else {
|
||||
if (useMeters) {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, updateDimensions);
|
||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, updateDimensionsInDomainUnits);
|
||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensionsInDomainUnits);
|
||||
}
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DENSITY, float, updateDensity);
|
||||
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation);
|
||||
READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity);
|
||||
if (useMeters) {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocity);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravity);
|
||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits);
|
||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits);
|
||||
}
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_ACCELERATION, glm::vec3, setAcceleration);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT, setScript);
|
||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, _registrationPoint);
|
||||
READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping);
|
||||
READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution);
|
||||
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
|
||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||
if (useMeters) {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, _angularDamping);
|
||||
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, _visible);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_COLLISIONS_WILL_MOVE, bool, updateCollisionsWillMove);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA, setUserData);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping);
|
||||
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
|
||||
READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, updateCollisionsWillMove);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
|
||||
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) {
|
||||
READ_ENTITY_PROPERTY_UUID(PROP_SIMULATOR_ID, setSimulatorID);
|
||||
READ_ENTITY_PROPERTY(PROP_SIMULATOR_ID, QUuid, updateSimulatorID);
|
||||
}
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) {
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_MARKETPLACE_ID, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_NAME, setName);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData);
|
||||
|
||||
////////////////////////////////////
|
||||
|
@ -584,7 +596,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
//
|
||||
// TODO: Remove this conde once we've sufficiently migrated content past this damaged version
|
||||
if (args.bitstreamVersion == VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED) {
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_MARKETPLACE_ID, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
}
|
||||
|
||||
if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES))) {
|
||||
|
@ -693,17 +705,6 @@ void EntityItem::setMass(float mass) {
|
|||
}
|
||||
}
|
||||
|
||||
const float DEFAULT_ENTITY_RESTITUTION = 0.5f;
|
||||
const float DEFAULT_ENTITY_FRICTION = 0.5f;
|
||||
|
||||
float EntityItem::getRestitution() const {
|
||||
return DEFAULT_ENTITY_RESTITUTION;
|
||||
}
|
||||
|
||||
float EntityItem::getFriction() const {
|
||||
return DEFAULT_ENTITY_FRICTION;
|
||||
}
|
||||
|
||||
void EntityItem::simulate(const quint64& now) {
|
||||
if (_lastSimulated == 0) {
|
||||
_lastSimulated = now;
|
||||
|
@ -896,8 +897,11 @@ EntityItemProperties EntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(gravity, getGravity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(acceleration, getAcceleration);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(damping, getDamping);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(restitution, getRestitution);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(friction, getFriction);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifetime, getLifetime);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getAngularVelocity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping);
|
||||
|
@ -928,8 +932,11 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(acceleration, setAcceleration);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, updateDamping);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(restitution, updateRestitution);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(friction, updateFriction);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, updateAngularVelocity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, updateAngularDamping);
|
||||
|
@ -940,7 +947,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulatorID, setSimulatorID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulatorID, updateSimulatorID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(marketplaceID, setMarketplaceID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName);
|
||||
|
||||
|
@ -1185,16 +1192,16 @@ void EntityItem::updateVelocityInDomainUnits(const glm::vec3& value) {
|
|||
void EntityItem::updateVelocity(const glm::vec3& value) {
|
||||
auto delta = glm::distance(_velocity, value);
|
||||
if (delta > IGNORE_LINEAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_LINEAR_VELOCITY;
|
||||
const float MIN_LINEAR_SPEED = 0.001f;
|
||||
if (glm::length(value) < MIN_LINEAR_SPEED) {
|
||||
_velocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_velocity = value;
|
||||
}
|
||||
_dirtyFlags |= EntityItem::DIRTY_LINEAR_VELOCITY;
|
||||
|
||||
if (delta > ACTIVATION_LINEAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
|
||||
// only activate when setting non-zero velocity
|
||||
if (delta > ACTIVATION_LINEAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1232,9 +1239,10 @@ void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
|||
_angularVelocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_angularVelocity = value;
|
||||
}
|
||||
if (delta > ACTIVATION_ANGULAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
|
||||
// only activate when setting non-zero velocity
|
||||
if (delta > ACTIVATION_ANGULAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1261,6 +1269,32 @@ void EntityItem::updateCollisionsWillMove(bool value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateRestitution(float value) {
|
||||
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_RESTITUTION, value), ENTITY_ITEM_MIN_RESTITUTION);
|
||||
if (_restitution != clampedValue) {
|
||||
_restitution = clampedValue;
|
||||
_dirtyFlags |= EntityItem::DIRTY_MATERIAL;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateFriction(float value) {
|
||||
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
|
||||
if (_friction != clampedValue) {
|
||||
_friction = clampedValue;
|
||||
_dirtyFlags |= EntityItem::DIRTY_MATERIAL;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::setRestitution(float value) {
|
||||
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_RESTITUTION, value), ENTITY_ITEM_MIN_RESTITUTION);
|
||||
_restitution = clampedValue;
|
||||
}
|
||||
|
||||
void EntityItem::setFriction(float value) {
|
||||
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
|
||||
_friction = clampedValue;
|
||||
}
|
||||
|
||||
void EntityItem::updateLifetime(float value) {
|
||||
if (_lifetime != value) {
|
||||
_lifetime = value;
|
||||
|
@ -1269,8 +1303,14 @@ void EntityItem::updateLifetime(float value) {
|
|||
}
|
||||
|
||||
void EntityItem::setSimulatorID(const QUuid& value) {
|
||||
_simulatorID = value;
|
||||
_simulatorIDChangedTime = usecTimestampNow();
|
||||
}
|
||||
|
||||
void EntityItem::updateSimulatorID(const QUuid& value) {
|
||||
if (_simulatorID != value) {
|
||||
_simulatorID = value;
|
||||
_simulatorIDChangedTime = usecTimestampNow();
|
||||
_dirtyFlags |= EntityItem::DIRTY_SIMULATOR_ID;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
DIRTY_UPDATEABLE = 0x0200,
|
||||
DIRTY_MATERIAL = 0x00400,
|
||||
DIRTY_PHYSICS_ACTIVATION = 0x0800, // we want to activate the object
|
||||
DIRTY_SIMULATOR_ID = 0x1000,
|
||||
DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION,
|
||||
DIRTY_VELOCITIES = DIRTY_LINEAR_VELOCITY | DIRTY_ANGULAR_VELOCITY
|
||||
};
|
||||
|
@ -221,8 +222,11 @@ public:
|
|||
float getDamping() const { return _damping; }
|
||||
void setDamping(float value) { _damping = value; }
|
||||
|
||||
float getRestitution() const;
|
||||
float getFriction() const;
|
||||
float getRestitution() const { return _restitution; }
|
||||
void setRestitution(float value);
|
||||
|
||||
float getFriction() const { return _friction; }
|
||||
void setFriction(float value);
|
||||
|
||||
// lifetime related properties.
|
||||
float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity
|
||||
|
@ -246,6 +250,8 @@ public:
|
|||
|
||||
const QString& getScript() const { return _script; }
|
||||
void setScript(const QString& value) { _script = value; }
|
||||
const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
|
||||
void setCollisionSoundURL(const QString& value) { _collisionSoundURL = value; }
|
||||
|
||||
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity
|
||||
|
||||
|
@ -284,6 +290,7 @@ public:
|
|||
|
||||
QUuid getSimulatorID() const { return _simulatorID; }
|
||||
void setSimulatorID(const QUuid& value);
|
||||
void updateSimulatorID(const QUuid& value);
|
||||
quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; }
|
||||
|
||||
const QString& getMarketplaceID() const { return _marketplaceID; }
|
||||
|
@ -312,6 +319,8 @@ public:
|
|||
void updateVelocityInDomainUnits(const glm::vec3& value);
|
||||
void updateVelocity(const glm::vec3& value);
|
||||
void updateDamping(float value);
|
||||
void updateRestitution(float value);
|
||||
void updateFriction(float value);
|
||||
void updateGravityInDomainUnits(const glm::vec3& value);
|
||||
void updateGravity(const glm::vec3& value);
|
||||
void updateAngularVelocity(const glm::vec3& value);
|
||||
|
@ -373,8 +382,11 @@ protected:
|
|||
glm::vec3 _gravity;
|
||||
glm::vec3 _acceleration;
|
||||
float _damping;
|
||||
float _restitution;
|
||||
float _friction;
|
||||
float _lifetime;
|
||||
QString _script;
|
||||
QString _collisionSoundURL;
|
||||
glm::vec3 _registrationPoint;
|
||||
glm::vec3 _angularVelocity;
|
||||
float _angularDamping;
|
||||
|
|
|
@ -44,8 +44,11 @@ EntityItemProperties::EntityItemProperties() :
|
|||
CONSTRUCT_PROPERTY(gravity, ENTITY_ITEM_DEFAULT_GRAVITY),
|
||||
CONSTRUCT_PROPERTY(acceleration, ENTITY_ITEM_DEFAULT_ACCELERATION),
|
||||
CONSTRUCT_PROPERTY(damping, ENTITY_ITEM_DEFAULT_DAMPING),
|
||||
CONSTRUCT_PROPERTY(restitution, ENTITY_ITEM_DEFAULT_RESTITUTION),
|
||||
CONSTRUCT_PROPERTY(friction, ENTITY_ITEM_DEFAULT_FRICTION),
|
||||
CONSTRUCT_PROPERTY(lifetime, ENTITY_ITEM_DEFAULT_LIFETIME),
|
||||
CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT),
|
||||
CONSTRUCT_PROPERTY(collisionSoundURL, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
|
||||
CONSTRUCT_PROPERTY(color, ),
|
||||
CONSTRUCT_PROPERTY(modelURL, ""),
|
||||
CONSTRUCT_PROPERTY(compoundShapeURL, ""),
|
||||
|
@ -286,8 +289,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_GRAVITY, gravity);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ACCELERATION, acceleration);
|
||||
CHECK_PROPERTY_CHANGE(PROP_DAMPING, damping);
|
||||
CHECK_PROPERTY_CHANGE(PROP_RESTITUTION, restitution);
|
||||
CHECK_PROPERTY_CHANGE(PROP_FRICTION, friction);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COLLISION_SOUND_URL, collisionSoundURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COLOR, color);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
|
@ -350,16 +356,18 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
}
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(type, EntityTypes::getEntityTypeName(_type));
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(position);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(dimensions);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(position);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(dimensions);
|
||||
if (!skipDefaults) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(naturalDimensions); // gettable, but not settable
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(naturalDimensions); // gettable, but not settable
|
||||
}
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_QUAT(rotation);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(velocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(gravity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(acceleration);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(rotation);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(velocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(gravity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(acceleration);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(damping);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(restitution);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(friction);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(density);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lifetime);
|
||||
if (!skipDefaults) {
|
||||
|
@ -367,11 +375,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable
|
||||
}
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(script);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(registrationPoint);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(angularVelocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(registrationPoint);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(angularVelocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(angularDamping);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(visible);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(modelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationURL);
|
||||
|
@ -393,23 +401,24 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(simulatorID, getSimulatorIDAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(text);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(textColor, getTextColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(backgroundColor, getBackgroundColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(maxParticles);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lifespan);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(emitDirection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(emitDirection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(name);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(collisionSoundURL);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(keyLightColor);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightColor);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightIntensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightAmbientIntensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(keyLightDirection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightDirection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(backgroundMode, getBackgroundModeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(sourceUrl);
|
||||
|
||||
|
@ -459,61 +468,64 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
|
|||
setType(typeScriptValue.toVariant().toString());
|
||||
}
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(position, setPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(dimensions, setDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_QUAT(rotation, setRotation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(density, setDensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(velocity, setVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(gravity, setGravity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(acceleration, setAcceleration);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(damping, setDamping);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lifetime, setLifetime);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(script, setScript);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(registrationPoint, setRegistrationPoint);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(angularVelocity, setAngularVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(angularDamping, setAngularDamping);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(visible, setVisible);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(color, setColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(modelURL, setModelURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(compoundShapeURL, setCompoundShapeURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(animationURL, setAnimationURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(animationIsPlaying, setAnimationIsPlaying);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(animationFPS, setAnimationFPS);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(animationFrameIndex, setAnimationFrameIndex);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(animationSettings, setAnimationSettings);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(glowLevel, setGlowLevel);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localRenderAlpha, setLocalRenderAlpha);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(ignoreForCollisions, setIgnoreForCollisions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(collisionsWillMove, setCollisionsWillMove);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(isSpotlight, setIsSpotlight);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(intensity, setIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(exponent, setExponent);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(cutoff, setCutoff);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(locked, setLocked);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(textures, setTextures);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(userData, setUserData);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_UUID(simulatorID, setSimulatorID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(text, setText);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(position, glmVec3, setPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, glmVec3, setDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, glmQuat, setRotation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(density, float, setDensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(velocity, glmVec3, setVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(gravity, glmVec3, setGravity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(acceleration, glmVec3, setAcceleration);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(damping, float, setDamping);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(restitution, float, setRestitution);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(friction, float, setFriction);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifetime, float, setLifetime);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(script, QString, setScript);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, glmVec3, setRegistrationPoint);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(visible, bool, setVisible);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(color, xColor, setColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(modelURL, QString, setModelURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationURL, QString, setAnimationURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationIsPlaying, bool, setAnimationIsPlaying);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationFPS, float, setAnimationFPS);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationFrameIndex, float, setAnimationFrameIndex);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationSettings, QString, setAnimationSettings);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(glowLevel, float, setGlowLevel);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRenderAlpha, float, setLocalRenderAlpha);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(ignoreForCollisions, bool, setIgnoreForCollisions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionsWillMove, bool, setCollisionsWillMove);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isSpotlight, bool, setIsSpotlight);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(intensity, float, setIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(exponent, float, setExponent);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(cutoff, float, setCutoff);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(locked, bool, setLocked);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(textures, QString, setTextures);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(userData, QString, setUserData);
|
||||
//COPY_PROPERTY_FROM_QSCRIPTVALUE(simulatorID, QUuid, setSimulatorID); DO NOT accept this info from QScriptValue
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(text, QString, setText);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lineHeight, float, setLineHeight);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(textColor, xColor, setTextColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(backgroundColor, xColor, setBackgroundColor);
|
||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(maxParticles, setMaxParticles);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lifespan, setLifespan);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitRate, setEmitRate);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(emitDirection, setEmitDirection);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitStrength, setEmitStrength);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localGravity, setLocalGravity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(marketplaceID, setMarketplaceID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(name, setName);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, float, setMaxParticles);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitDirection, glmVec3, setEmitDirection);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitStrength, float, setEmitStrength);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localGravity, float, setLocalGravity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionSoundURL, QString, setCollisionSoundURL);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(keyLightColor, setKeyLightColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(keyLightIntensity, setKeyLightIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(keyLightAmbientIntensity, setKeyLightAmbientIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(keyLightDirection, setKeyLightDirection);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightColor, xColor, setKeyLightColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightIntensity, float, setKeyLightIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightAmbientIntensity, float, setKeyLightAmbientIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightDirection, glmVec3, setKeyLightDirection);
|
||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(backgroundMode, BackgroundMode);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(sourceUrl, setSourceUrl);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl);
|
||||
|
||||
_stage.copyFromScriptValue(object, _defaultSettings);
|
||||
_atmosphere.copyFromScriptValue(object, _defaultSettings);
|
||||
|
@ -650,81 +662,83 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
// PROP_PAGED_PROPERTY,
|
||||
// PROP_CUSTOM_PROPERTIES_INCLUDED,
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, properties.getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, properties.getDimensions()); // NOTE: PROP_RADIUS obsolete
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, properties.getRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, appendValue, properties.getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, properties.getVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, properties.getGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, appendValue, properties.getAcceleration());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, properties.getDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, properties.getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, properties.getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, properties.getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, properties.getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, properties.getAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, appendValue, properties.getAngularDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, appendValue, properties.getVisible());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, properties.getIgnoreForCollisions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, properties.getCollisionsWillMove());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, properties.getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, properties.getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SIMULATOR_ID, appendValue, properties.getSimulatorID());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, properties.getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, properties.getDimensions()); // NOTE: PROP_RADIUS obsolete
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, properties.getRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, properties.getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, properties.getVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAVITY, properties.getGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, properties.getAcceleration());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DAMPING, properties.getDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_RESTITUTION, properties.getRestitution());
|
||||
APPEND_ENTITY_PROPERTY(PROP_FRICTION, properties.getFriction());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, properties.getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, properties.getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, properties.getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, properties.getAngularDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, properties.getVisible());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, properties.getIgnoreForCollisions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, properties.getCollisionsWillMove());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, properties.getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, properties.getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SIMULATOR_ID, properties.getSimulatorID());
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, appendValue, properties.getSourceUrl());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Text) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT, appendValue, properties.getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, properties.getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, properties.getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, properties.getBackgroundColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, properties.getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, properties.getBackgroundColor());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, properties.getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, properties.getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, properties.getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, properties.getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, properties.getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)(properties.getShapeType()));
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, properties.getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, properties.getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, properties.getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, properties.getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, properties.getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, properties.getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)(properties.getShapeType()));
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, properties.getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, properties.getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_INTENSITY, appendValue, properties.getIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, properties.getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, properties.getCutoff());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, properties.getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_INTENSITY, properties.getIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, properties.getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, properties.getCutoff());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::ParticleEffect) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, properties.getMaxParticles());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, properties.getLifespan());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, properties.getEmitRate());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, properties.getEmitDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, properties.getEmitStrength());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, properties.getLocalGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, properties.getParticleRadius());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, properties.getMaxParticles());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, properties.getLifespan());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, properties.getEmitDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, properties.getEmitStrength());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, properties.getLocalGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Zone) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, appendColor, properties.getKeyLightColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, appendValue, properties.getKeyLightIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, appendValue, properties.getKeyLightAmbientIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, appendValue, properties.getKeyLightDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, properties.getKeyLightColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, properties.getKeyLightIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, properties.getKeyLightAmbientIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, properties.getKeyLightDirection());
|
||||
|
||||
_staticStage.setProperties(properties);
|
||||
_staticStage.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
|
||||
|
||||
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_SHAPE_TYPE, (uint32_t)properties.getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, appendValue, (uint32_t)properties.getBackgroundMode());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, (uint32_t)properties.getBackgroundMode());
|
||||
|
||||
_staticAtmosphere.setProperties(properties);
|
||||
_staticAtmosphere.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
|
||||
|
@ -733,8 +747,9 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
_staticSkybox.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, appendValue, properties.getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, properties.getMarketplaceID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL());
|
||||
}
|
||||
if (propertyCount > 0) {
|
||||
int endOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
@ -911,15 +926,17 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POSITION, glm::vec3, setPosition);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIMENSIONS, glm::vec3, setDimensions); // NOTE: PROP_RADIUS obsolete
|
||||
READ_ENTITY_PROPERTY_QUAT_TO_PROPERTIES(PROP_ROTATION, setRotation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ROTATION, glm::quat, setRotation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DENSITY, float, setDensity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VELOCITY, glm::vec3, setVelocity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_GRAVITY, glm::vec3, setGravity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACCELERATION, glm::vec3, setAcceleration);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DAMPING, float, setDamping);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RESTITUTION, float, setRestitution);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FRICTION, float, setFriction);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFETIME, float, setLifetime);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_SCRIPT,setScript);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_COLOR, setColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT,QString, setScript);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, xColor, setColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
||||
|
@ -927,35 +944,35 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_FOR_COLLISIONS, bool, setIgnoreForCollisions);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONS_WILL_MOVE, bool, setCollisionsWillMove);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_USER_DATA, setUserData);
|
||||
READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES(PROP_SIMULATOR_ID, setSimulatorID);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SIMULATOR_ID, QUuid, setSimulatorID);
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_SOURCE_URL, setSourceUrl);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Text) {
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXT, setText);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_TEXT_COLOR, setTextColor);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_BACKGROUND_COLOR, setBackgroundColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_COLOR, xColor, setTextColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_COLOR, xColor, setBackgroundColor);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MODEL_URL, setModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_URL, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MODEL_URL, QString, setModelURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_URL, QString, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_COLOR, setColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, xColor, setColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_INTENSITY, float, setIntensity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff);
|
||||
|
@ -972,7 +989,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Zone) {
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_KEYLIGHT_COLOR, setKeyLightColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_COLOR, xColor, setKeyLightColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_INTENSITY, float, setKeyLightIntensity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, setKeyLightAmbientIntensity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_DIRECTION, glm::vec3, setKeyLightDirection);
|
||||
|
@ -980,15 +997,16 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
properties.getStage().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
|
||||
|
||||
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_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
|
||||
properties.getAtmosphere().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
|
||||
properties.getSkybox().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_NAME, setName);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1030,10 +1048,13 @@ void EntityItemProperties::markAllChanged() {
|
|||
_gravityChanged = true;
|
||||
_accelerationChanged = true;
|
||||
_dampingChanged = true;
|
||||
_restitutionChanged = true;
|
||||
_frictionChanged = true;
|
||||
_lifetimeChanged = true;
|
||||
_userDataChanged = true;
|
||||
_simulatorIDChanged = true;
|
||||
_scriptChanged = true;
|
||||
_collisionSoundURLChanged = true;
|
||||
_registrationPointChanged = true;
|
||||
_angularVelocityChanged = true;
|
||||
_angularDampingChanged = true;
|
||||
|
@ -1130,3 +1151,5 @@ AABox EntityItemProperties::getAABox() const {
|
|||
|
||||
return AABox(rotatedExtentsRelativeToRegistrationPoint);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -95,8 +95,11 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_GRAVITY, Gravity, gravity, glm::vec3);
|
||||
DEFINE_PROPERTY_REF(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3);
|
||||
DEFINE_PROPERTY(PROP_DAMPING, Damping, damping, float);
|
||||
DEFINE_PROPERTY(PROP_RESTITUTION, Restitution, restitution, float);
|
||||
DEFINE_PROPERTY(PROP_FRICTION, Friction, friction, float);
|
||||
DEFINE_PROPERTY(PROP_LIFETIME, Lifetime, lifetime, float);
|
||||
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString);
|
||||
|
@ -242,8 +245,11 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
|||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Gravity, gravity, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Acceleration, acceleration, "in meters per second");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Damping, damping, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Restitution, restitution, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Friction, friction, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifetime, lifetime, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionSoundURL, collisionSoundURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CompoundShapeURL, compoundShapeURL, "");
|
||||
|
|
|
@ -30,6 +30,7 @@ const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f;
|
|||
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
|
||||
|
||||
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");
|
||||
const QString ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL = QString("");
|
||||
const glm::vec3 ENTITY_ITEM_DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); // center
|
||||
|
||||
const float ENTITY_ITEM_IMMORTAL_LIFETIME = -1.0f; /// special lifetime which means the entity lives for ever
|
||||
|
@ -52,6 +53,14 @@ const glm::vec3 ENTITY_ITEM_DEFAULT_ACCELERATION = ENTITY_ITEM_ZERO_VEC3;
|
|||
const float ENTITY_ITEM_DEFAULT_DAMPING = 0.39347f; // approx timescale = 2.0 sec (see damping timescale formula in header)
|
||||
const float ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING = 0.39347f; // approx timescale = 2.0 sec (see damping timescale formula in header)
|
||||
|
||||
const float ENTITY_ITEM_MIN_RESTITUTION = 0.0f;
|
||||
const float ENTITY_ITEM_MAX_RESTITUTION = 0.99f;
|
||||
const float ENTITY_ITEM_DEFAULT_RESTITUTION = 0.5f;
|
||||
|
||||
const float ENTITY_ITEM_MIN_FRICTION = 0.0f;
|
||||
const float ENTITY_ITEM_MAX_FRICTION = 0.99f;
|
||||
const float ENTITY_ITEM_DEFAULT_FRICTION = 0.5f;
|
||||
|
||||
const bool ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS = false;
|
||||
const bool ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE = false;
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
#ifndef hifi_EntityItemPropertiesMacros_h
|
||||
#define hifi_EntityItemPropertiesMacros_h
|
||||
|
||||
#define APPEND_ENTITY_PROPERTY(P,O,V) \
|
||||
#define APPEND_ENTITY_PROPERTY(P,V) \
|
||||
if (requestedProperties.getHasProperty(P)) { \
|
||||
LevelDetails propertyLevel = packetData->startLevel(); \
|
||||
successPropertyFits = packetData->O(V); \
|
||||
successPropertyFits = packetData->appendValue(V); \
|
||||
if (successPropertyFits) { \
|
||||
propertyFlags |= P; \
|
||||
propertiesDidntFit -= P; \
|
||||
|
@ -29,82 +29,15 @@
|
|||
propertiesDidntFit -= P; \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY(P,T,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
memcpy(&fromBuffer, dataAt, sizeof(fromBuffer)); \
|
||||
dataAt += sizeof(fromBuffer); \
|
||||
bytesRead += sizeof(fromBuffer); \
|
||||
if (overwriteLocalData) { \
|
||||
M = fromBuffer; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_SETTER(P,T,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
memcpy(&fromBuffer, dataAt, sizeof(fromBuffer)); \
|
||||
dataAt += sizeof(fromBuffer); \
|
||||
bytesRead += sizeof(fromBuffer); \
|
||||
if (overwriteLocalData) { \
|
||||
M(fromBuffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_QUAT(P,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
glm::quat fromBuffer; \
|
||||
int bytes = unpackOrientationQuatFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
bytesRead += bytes; \
|
||||
if (overwriteLocalData) { \
|
||||
M = fromBuffer; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_QUAT_SETTER(P,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
glm::quat fromBuffer; \
|
||||
int bytes = unpackOrientationQuatFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
bytesRead += bytes; \
|
||||
if (overwriteLocalData) { \
|
||||
M(fromBuffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_STRING(P,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
uint16_t length; \
|
||||
memcpy(&length, dataAt, sizeof(length)); \
|
||||
dataAt += sizeof(length); \
|
||||
bytesRead += sizeof(length); \
|
||||
QString value((const char*)dataAt); \
|
||||
dataAt += length; \
|
||||
bytesRead += length; \
|
||||
if (overwriteLocalData) { \
|
||||
O(value); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_UUID(P,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
uint16_t length; \
|
||||
memcpy(&length, dataAt, sizeof(length)); \
|
||||
dataAt += sizeof(length); \
|
||||
bytesRead += sizeof(length); \
|
||||
QUuid value; \
|
||||
if (length == 0) { \
|
||||
value = QUuid(); \
|
||||
} else { \
|
||||
QByteArray ba((const char*)dataAt, length); \
|
||||
value = QUuid::fromRfc4122(ba); \
|
||||
dataAt += length; \
|
||||
bytesRead += length; \
|
||||
} \
|
||||
if (overwriteLocalData) { \
|
||||
O(value); \
|
||||
} \
|
||||
#define READ_ENTITY_PROPERTY(P,T,S) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
int bytes = OctreePacketData::uppackDataFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
bytesRead += bytes; \
|
||||
if (overwriteLocalData) { \
|
||||
S(fromBuffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DECODE_GROUP_PROPERTY_HAS_CHANGED(P,N) \
|
||||
|
@ -112,82 +45,14 @@
|
|||
set##N##Changed(true); \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_COLOR(P,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
if (overwriteLocalData) { \
|
||||
memcpy(M, dataAt, sizeof(M)); \
|
||||
} \
|
||||
dataAt += sizeof(rgbColor); \
|
||||
bytesRead += sizeof(rgbColor); \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_XCOLOR(P,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
if (overwriteLocalData) { \
|
||||
M.red = dataAt[RED_INDEX]; \
|
||||
M.green = dataAt[GREEN_INDEX]; \
|
||||
M.blue = dataAt[BLUE_INDEX]; \
|
||||
} \
|
||||
dataAt += sizeof(rgbColor); \
|
||||
bytesRead += sizeof(rgbColor); \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_TO_PROPERTIES(P,T,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
memcpy(&fromBuffer, dataAt, sizeof(fromBuffer)); \
|
||||
dataAt += sizeof(fromBuffer); \
|
||||
processedBytes += sizeof(fromBuffer); \
|
||||
properties.O(fromBuffer); \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_QUAT_TO_PROPERTIES(P,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
glm::quat fromBuffer; \
|
||||
int bytes = unpackOrientationQuatFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
processedBytes += bytes; \
|
||||
properties.O(fromBuffer); \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(P,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
uint16_t length; \
|
||||
memcpy(&length, dataAt, sizeof(length)); \
|
||||
dataAt += sizeof(length); \
|
||||
processedBytes += sizeof(length); \
|
||||
QString value((const char*)dataAt); \
|
||||
dataAt += length; \
|
||||
processedBytes += length; \
|
||||
properties.O(value); \
|
||||
}
|
||||
|
||||
|
||||
#define READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES(P,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
uint16_t length; \
|
||||
memcpy(&length, dataAt, sizeof(length)); \
|
||||
dataAt += sizeof(length); \
|
||||
processedBytes += sizeof(length); \
|
||||
QUuid value; \
|
||||
if (length == 0) { \
|
||||
value = QUuid(); \
|
||||
} else { \
|
||||
QByteArray ba((const char*)dataAt, length); \
|
||||
value = QUuid::fromRfc4122(ba); \
|
||||
dataAt += length; \
|
||||
processedBytes += length; \
|
||||
} \
|
||||
properties.O(value); \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(P,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
xColor color; \
|
||||
memcpy(&color, dataAt, sizeof(color)); \
|
||||
dataAt += sizeof(color); \
|
||||
processedBytes += sizeof(color); \
|
||||
properties.O(color); \
|
||||
#define READ_ENTITY_PROPERTY_TO_PROPERTIES(P,T,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
int bytes = OctreePacketData::uppackDataFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
processedBytes += bytes; \
|
||||
properties.O(fromBuffer); \
|
||||
}
|
||||
|
||||
#define SET_ENTITY_PROPERTY_FROM_PROPERTIES(P,M) \
|
||||
|
@ -221,63 +86,30 @@
|
|||
changedProperties += P; \
|
||||
}
|
||||
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { return vec3toScriptValue(e, v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); }
|
||||
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; }
|
||||
|
||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(G,g,P,p) \
|
||||
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != _##p) { \
|
||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,g,P,p) \
|
||||
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P()) { \
|
||||
QScriptValue groupProperties = properties.property(#g); \
|
||||
if (!groupProperties.isValid()) { \
|
||||
groupProperties = engine->newObject(); \
|
||||
} \
|
||||
QScriptValue V = vec3toScriptValue(engine, _##p); \
|
||||
QScriptValue V = convertScriptValue(engine, get##P()); \
|
||||
groupProperties.setProperty(#p, V); \
|
||||
properties.setProperty(#g, groupProperties); \
|
||||
}
|
||||
|
||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,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_GROUP_PROPERTY_TO_QSCRIPTVALUE_COLOR(G,g,P,p) \
|
||||
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != _##p) { \
|
||||
QScriptValue groupProperties = properties.property(#g); \
|
||||
if (!groupProperties.isValid()) { \
|
||||
groupProperties = engine->newObject(); \
|
||||
} \
|
||||
QScriptValue colorValue = xColorToScriptValue(engine, _##p); \
|
||||
groupProperties.setProperty(#p, colorValue); \
|
||||
properties.setProperty(#g, groupProperties); \
|
||||
}
|
||||
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(P) \
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
QScriptValue P = vec3toScriptValue(engine, _##P); \
|
||||
properties.setProperty(#P, P); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_QUAT(P) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
QScriptValue P = quatToScriptValue(engine, _##P); \
|
||||
properties.setProperty(#P, P); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(P) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
QScriptValue P = xColorToScriptValue(engine, _##P); \
|
||||
properties.setProperty(#P, P); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(P,G) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
QScriptValue P = xColorToScriptValue(engine, G); \
|
||||
properties.setProperty(#P, P); \
|
||||
QScriptValue V = convertScriptValue(engine, _##P); \
|
||||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(P, G) \
|
||||
|
@ -285,257 +117,114 @@
|
|||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(P, G) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
properties.setProperty(#P, G); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
properties.setProperty(#P, _##P); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
float newValue = P.toVariant().toFloat(); \
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(P, S, G) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
float newValue = P.toVariant().toFloat(); \
|
||||
if (_defaultSettings || newValue != G()) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#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_GROUP_PROPERTY_FROM_QSCRIPTVALUE_UINT16(G, P, S) \
|
||||
{ \
|
||||
QScriptValue G = object.property(#G); \
|
||||
if (G.isValid()) { \
|
||||
QScriptValue P = G.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
uint16_t newValue = P.toVariant().toInt(); \
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_INT(P, S) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
int newValue = P.toVariant().toInt(); \
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_INT_GETTER(P, S, G) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
int newValue = P.toVariant().toInt(); \
|
||||
if (_defaultSettings || newValue != G()) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(P, S) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
bool newValue = P.toVariant().toBool(); \
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL_GETTER(P, S, G) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
bool newValue = P.toVariant().toBool(); \
|
||||
if (_defaultSettings || newValue != G()) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#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()) { \
|
||||
QString newValue = P.toVariant().toString().trimmed();\
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_STRING(G, P, S)\
|
||||
{ \
|
||||
QScriptValue G = object.property(#G); \
|
||||
if (G.isValid()) { \
|
||||
QScriptValue P = G.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
QString newValue = P.toVariant().toString().trimmed();\
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_UUID(P, S) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
QUuid newValue = P.toVariant().toUuid(); \
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(P, S) \
|
||||
QScriptValue P = object.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_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); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
QScriptValue V = convertScriptValue(engine, G); \
|
||||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_QUAT(P, S) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
QScriptValue x = P.property("x"); \
|
||||
QScriptValue y = P.property("y"); \
|
||||
QScriptValue z = P.property("z"); \
|
||||
QScriptValue w = P.property("w"); \
|
||||
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { \
|
||||
glm::quat newValue; \
|
||||
newValue.x = x.toVariant().toFloat(); \
|
||||
newValue.y = y.toVariant().toFloat(); \
|
||||
newValue.z = z.toVariant().toFloat(); \
|
||||
newValue.w = w.toVariant().toFloat(); \
|
||||
bool isValid = !glm::isnan(newValue.x) && \
|
||||
!glm::isnan(newValue.y) && \
|
||||
!glm::isnan(newValue.z) && \
|
||||
!glm::isnan(newValue.w); \
|
||||
if (isValid && \
|
||||
(_defaultSettings || newValue != _##P)) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
} \
|
||||
typedef glm::vec3 glmVec3;
|
||||
typedef glm::quat glmQuat;
|
||||
inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
|
||||
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
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 glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
QScriptValue y = v.property("y");
|
||||
QScriptValue z = v.property("z");
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
glm::vec3 newValue(0);
|
||||
newValue.x = x.toVariant().toFloat();
|
||||
newValue.y = y.toVariant().toFloat();
|
||||
newValue.z = z.toVariant().toFloat();
|
||||
isValid = !glm::isnan(newValue.x) &&
|
||||
!glm::isnan(newValue.y) &&
|
||||
!glm::isnan(newValue.z);
|
||||
if (isValid) {
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
return glm::vec3(0);
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(P, S) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
QScriptValue r = P.property("red"); \
|
||||
QScriptValue g = P.property("green"); \
|
||||
QScriptValue b = P.property("blue"); \
|
||||
if (r.isValid() && g.isValid() && b.isValid()) {\
|
||||
xColor newColor; \
|
||||
newColor.red = r.toVariant().toInt(); \
|
||||
newColor.green = g.toVariant().toInt(); \
|
||||
newColor.blue = b.toVariant().toInt(); \
|
||||
if (_defaultSettings || \
|
||||
(newColor.red != _color.red || \
|
||||
newColor.green != _color.green || \
|
||||
newColor.blue != _color.blue)) { \
|
||||
S(newColor); \
|
||||
inline glmQuat glmQuat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
QScriptValue y = v.property("y");
|
||||
QScriptValue z = v.property("z");
|
||||
QScriptValue w = v.property("w");
|
||||
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
|
||||
glm::quat newValue;
|
||||
newValue.x = x.toVariant().toFloat();
|
||||
newValue.y = y.toVariant().toFloat();
|
||||
newValue.z = z.toVariant().toFloat();
|
||||
newValue.w = w.toVariant().toFloat();
|
||||
isValid = !glm::isnan(newValue.x) &&
|
||||
!glm::isnan(newValue.y) &&
|
||||
!glm::isnan(newValue.z) &&
|
||||
!glm::isnan(newValue.w);
|
||||
if (isValid) {
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
inline xColor xColor_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
xColor newValue;
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue r = v.property("red");
|
||||
QScriptValue g = v.property("green");
|
||||
QScriptValue b = v.property("blue");
|
||||
if (r.isValid() && g.isValid() && b.isValid()) {
|
||||
newValue.red = r.toVariant().toInt();
|
||||
newValue.green = g.toVariant().toInt();
|
||||
newValue.blue = b.toVariant().toInt();
|
||||
isValid = true;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE(P, T, S) \
|
||||
{ \
|
||||
QScriptValue V = object.property(#P); \
|
||||
if (V.isValid()) { \
|
||||
bool isValid = false; \
|
||||
T newValue = T##_convertFromScriptValue(V, isValid); \
|
||||
if (isValid && (_defaultSettings || newValue != _##P)) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_COLOR(G, P, S) \
|
||||
{ \
|
||||
QScriptValue G = object.property(#G); \
|
||||
if (G.isValid()) { \
|
||||
QScriptValue P = G.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
QScriptValue r = P.property("red"); \
|
||||
QScriptValue g = P.property("green"); \
|
||||
QScriptValue b = P.property("blue"); \
|
||||
if (r.isValid() && g.isValid() && b.isValid()) {\
|
||||
xColor newColor; \
|
||||
newColor.red = r.toVariant().toInt(); \
|
||||
newColor.green = g.toVariant().toInt(); \
|
||||
newColor.blue = b.toVariant().toInt(); \
|
||||
if (_defaultSettings || \
|
||||
(newColor.red != _color.red || \
|
||||
newColor.green != _color.green || \
|
||||
newColor.blue != _color.blue)) { \
|
||||
S(newColor); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(P, T, S, G) \
|
||||
{ \
|
||||
QScriptValue V = object.property(#P); \
|
||||
if (V.isValid()) { \
|
||||
bool isValid = false; \
|
||||
T newValue = T##_convertFromScriptValue(V, isValid); \
|
||||
if (isValid && (_defaultSettings || newValue != G())) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}\
|
||||
}
|
||||
|
||||
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(G, P, T, S) \
|
||||
{ \
|
||||
QScriptValue G = object.property(#G); \
|
||||
if (G.isValid()) { \
|
||||
QScriptValue V = G.property(#P); \
|
||||
if (V.isValid()) { \
|
||||
bool isValid = false; \
|
||||
T newValue = T##_convertFromScriptValue(V, isValid); \
|
||||
if (isValid && (_defaultSettings || newValue != _##P)) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(P, S) \
|
||||
|
|
|
@ -75,7 +75,7 @@ enum EntityPropertyList {
|
|||
|
||||
// property used by Light entity
|
||||
PROP_IS_SPOTLIGHT,
|
||||
PROP_DIFFUSE_COLOR_UNUSED,
|
||||
PROP_DIFFUSE_COLOR,
|
||||
PROP_AMBIENT_COLOR_UNUSED,
|
||||
PROP_SPECULAR_COLOR_UNUSED,
|
||||
PROP_INTENSITY, // Previously PROP_CONSTANT_ATTENUATION
|
||||
|
@ -106,6 +106,9 @@ enum EntityPropertyList {
|
|||
PROP_ACCELERATION, // all entities
|
||||
PROP_SIMULATOR_ID, // all entities
|
||||
PROP_NAME, // all entities
|
||||
PROP_COLLISION_SOUND_URL,
|
||||
PROP_RESTITUTION,
|
||||
PROP_FRICTION,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties ABOVE this line
|
||||
|
@ -131,7 +134,7 @@ enum EntityPropertyList {
|
|||
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_LATITUDE = PROP_DIFFUSE_COLOR,
|
||||
PROP_STAGE_LONGITUDE = PROP_AMBIENT_COLOR_UNUSED,
|
||||
PROP_STAGE_ALTITUDE = PROP_SPECULAR_COLOR_UNUSED,
|
||||
PROP_STAGE_DAY = PROP_LINEAR_ATTENUATION_UNUSED,
|
||||
|
@ -162,11 +165,4 @@ typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
|
|||
extern EntityPropertyList PROP_LAST_ITEM;
|
||||
|
||||
|
||||
enum BackgroundMode {
|
||||
BACKGROUND_MODE_INHERIT,
|
||||
BACKGROUND_MODE_ATMOSPHERE,
|
||||
BACKGROUND_MODE_SKYBOX,
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_EntityPropertyFlags_h
|
||||
|
|
|
@ -61,13 +61,12 @@ void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setSimId(EntityItemProperties& propertiesWithSimID, EntityItem* entity) {
|
||||
void bidForSimulationOwnership(EntityItemProperties& properties) {
|
||||
// We make a bid for simulation ownership by declaring our sessionID as simulation owner
|
||||
// in the outgoing properties. The EntityServer may accept the bid or might not.
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||
propertiesWithSimID.setSimulatorID(myNodeID);
|
||||
entity->setSimulatorID(myNodeID);
|
||||
properties.setSimulatorID(myNodeID);
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,7 +88,7 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro
|
|||
entity->setLastBroadcast(usecTimestampNow());
|
||||
if (entity) {
|
||||
// This Node is creating a new object. If it's in motion, set this Node as the simulator.
|
||||
setSimId(propertiesWithSimID, entity);
|
||||
bidForSimulationOwnership(propertiesWithSimID);
|
||||
} else {
|
||||
qCDebug(entities) << "script failed to add new Entity to local Octree";
|
||||
success = false;
|
||||
|
@ -163,29 +162,31 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E
|
|||
}
|
||||
}
|
||||
|
||||
EntityItemProperties propertiesWithSimID = properties;
|
||||
|
||||
// If we have a local entity tree set, then also update it. We can do this even if we don't know
|
||||
// the actual id, because we can edit out local entities just with creatorTokenID
|
||||
if (_entityTree) {
|
||||
_entityTree->lockForWrite();
|
||||
_entityTree->updateEntity(entityID, propertiesWithSimID, canAdjustLocks());
|
||||
_entityTree->updateEntity(entityID, properties);
|
||||
_entityTree->unlock();
|
||||
}
|
||||
|
||||
// if at this point, we know the id, send the update to the entity server
|
||||
if (entityID.isKnownID) {
|
||||
// make sure the properties has a type, so that the encode can know which properties to include
|
||||
if (propertiesWithSimID.getType() == EntityTypes::Unknown) {
|
||||
if (properties.getType() == EntityTypes::Unknown) {
|
||||
EntityItem* entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
if (entity) {
|
||||
// we need to change the outgoing properties, so we make a copy, modify, and send.
|
||||
EntityItemProperties modifiedProperties = properties;
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
propertiesWithSimID.setType(entity->getType());
|
||||
setSimId(propertiesWithSimID, entity);
|
||||
modifiedProperties.setType(entity->getType());
|
||||
bidForSimulationOwnership(modifiedProperties);
|
||||
queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, modifiedProperties);
|
||||
return entityID;
|
||||
}
|
||||
}
|
||||
|
||||
queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, propertiesWithSimID);
|
||||
queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, properties);
|
||||
}
|
||||
|
||||
return entityID;
|
||||
|
|
|
@ -37,7 +37,8 @@ const int DIRTY_SIMULATION_FLAGS =
|
|||
EntityItem::DIRTY_SHAPE |
|
||||
EntityItem::DIRTY_LIFETIME |
|
||||
EntityItem::DIRTY_UPDATEABLE |
|
||||
EntityItem::DIRTY_MATERIAL;
|
||||
EntityItem::DIRTY_MATERIAL |
|
||||
EntityItem::DIRTY_SIMULATOR_ID;
|
||||
|
||||
class EntitySimulation : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -86,7 +86,7 @@ void EntityTree::postAddEntity(EntityItem* entity) {
|
|||
emit addingEntity(entity->getEntityItemID());
|
||||
}
|
||||
|
||||
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, bool allowLockChange) {
|
||||
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
|
||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||
if (!containingElement) {
|
||||
qCDebug(entities) << "UNEXPECTED!!!! EntityTree::updateEntity() entityID doesn't exist!!! entityID=" << entityID;
|
||||
|
@ -99,22 +99,34 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
|
|||
return false;
|
||||
}
|
||||
|
||||
return updateEntityWithElement(existingEntity, properties, containingElement, allowLockChange);
|
||||
return updateEntityWithElement(existingEntity, properties, containingElement, senderNode);
|
||||
}
|
||||
|
||||
bool EntityTree::updateEntity(EntityItem* entity, const EntityItemProperties& properties, bool allowLockChange) {
|
||||
bool EntityTree::updateEntity(EntityItem* entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
|
||||
EntityTreeElement* containingElement = getContainingElement(entity->getEntityItemID());
|
||||
if (!containingElement) {
|
||||
qCDebug(entities) << "UNEXPECTED!!!! EntityTree::updateEntity() entity-->element lookup failed!!! entityID="
|
||||
<< entity->getEntityItemID();
|
||||
return false;
|
||||
}
|
||||
return updateEntityWithElement(entity, properties, containingElement, allowLockChange);
|
||||
return updateEntityWithElement(entity, properties, containingElement, senderNode);
|
||||
}
|
||||
|
||||
bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemProperties& origProperties,
|
||||
EntityTreeElement* containingElement, bool allowLockChange) {
|
||||
EntityTreeElement* containingElement, const SharedNodePointer& senderNode) {
|
||||
EntityItemProperties properties = origProperties;
|
||||
|
||||
bool allowLockChange;
|
||||
QUuid senderID;
|
||||
if (senderNode.isNull()) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
allowLockChange = nodeList->getThisNodeCanAdjustLocks();
|
||||
senderID = nodeList->getSessionUUID();
|
||||
} else {
|
||||
allowLockChange = senderNode->getCanAdjustLocks();
|
||||
senderID = senderNode->getUUID();
|
||||
}
|
||||
|
||||
if (!allowLockChange && (entity->getLocked() != properties.getLocked())) {
|
||||
qCDebug(entities) << "Refusing disallowed lock adjustment.";
|
||||
return false;
|
||||
|
@ -134,22 +146,41 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (properties.simulatorIDChanged() &&
|
||||
!entity->getSimulatorID().isNull() &&
|
||||
properties.getSimulatorID() != entity->getSimulatorID()) {
|
||||
// A Node is trying to take ownership of the simulation of this entity from another Node. Only allow this
|
||||
// if ownership hasn't recently changed.
|
||||
if (usecTimestampNow() - entity->getSimulatorIDChangedTime() < SIMULATOR_CHANGE_LOCKOUT_PERIOD) {
|
||||
qCDebug(entities) << "simulator_change_lockout_period:"
|
||||
<< entity->getSimulatorID() << "to" << properties.getSimulatorID();
|
||||
if (getIsServer()) {
|
||||
bool simulationBlocked = !entity->getSimulatorID().isNull();
|
||||
if (properties.simulatorIDChanged()) {
|
||||
QUuid submittedID = properties.getSimulatorID();
|
||||
// a legit interface will only submit their own ID or NULL:
|
||||
if (submittedID.isNull()) {
|
||||
if (entity->getSimulatorID() == senderID) {
|
||||
// We only allow the simulation owner to clear their own simulationID's.
|
||||
simulationBlocked = false;
|
||||
}
|
||||
// else: We assume the sender really did believe it was the simulation owner when it sent
|
||||
} else if (submittedID == senderID) {
|
||||
// the sender is trying to take or continue ownership
|
||||
if (entity->getSimulatorID().isNull() || entity->getSimulatorID() == senderID) {
|
||||
simulationBlocked = false;
|
||||
} else {
|
||||
// the sender is trying to steal ownership from another simulator
|
||||
// so we apply the ownership change filter
|
||||
if (usecTimestampNow() - entity->getSimulatorIDChangedTime() > SIMULATOR_CHANGE_LOCKOUT_PERIOD) {
|
||||
simulationBlocked = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the entire update is suspect --> ignore it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (simulationBlocked) {
|
||||
// squash the physics-related changes.
|
||||
properties.setSimulatorIDChanged(false);
|
||||
properties.setPositionChanged(false);
|
||||
properties.setRotationChanged(false);
|
||||
} else {
|
||||
qCDebug(entities) << "allowing simulatorID change";
|
||||
}
|
||||
}
|
||||
// else client accepts what the server says
|
||||
|
||||
QString entityScriptBefore = entity->getScript();
|
||||
uint32_t preFlags = entity->getDirtyFlags();
|
||||
|
@ -664,7 +695,7 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
|
|||
qCDebug(entities) << "User [" << senderNode->getUUID() << "] editing entity. ID:" << entityItemID;
|
||||
qCDebug(entities) << " properties:" << properties;
|
||||
}
|
||||
updateEntity(entityItemID, properties, senderNode->getCanAdjustLocks());
|
||||
updateEntity(entityItemID, properties, senderNode);
|
||||
existingEntity->markAsChangedOnServer();
|
||||
} else {
|
||||
qCDebug(entities) << "User attempted to edit an unknown entity. ID:" << entityItemID;
|
||||
|
|
|
@ -88,10 +88,10 @@ public:
|
|||
EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
// use this method if you only know the entityID
|
||||
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, bool allowLockChange);
|
||||
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
||||
|
||||
// use this method if you have a pointer to the entity (avoid an extra entity lookup)
|
||||
bool updateEntity(EntityItem* entity, const EntityItemProperties& properties, bool allowLockChange);
|
||||
bool updateEntity(EntityItem* entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
||||
|
||||
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = false);
|
||||
void deleteEntities(QSet<EntityItemID> entityIDs, bool force = false, bool ignoreWarnings = false);
|
||||
|
@ -180,7 +180,8 @@ private:
|
|||
|
||||
void processRemovedEntities(const DeleteEntityOperator& theOperator);
|
||||
bool updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties,
|
||||
EntityTreeElement* containingElement, bool allowLockChange);
|
||||
EntityTreeElement* containingElement,
|
||||
const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
||||
static bool findNearPointOperation(OctreeElement* element, void* extraData);
|
||||
static bool findInSphereOperation(OctreeElement* element, void* extraData);
|
||||
static bool findInCubeOperation(OctreeElement* element, void* extraData);
|
||||
|
|
|
@ -124,37 +124,32 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
const unsigned char* dataAt = data;
|
||||
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES) {
|
||||
rgbColor ignoredColor;
|
||||
float ignoredAttenuation;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight);
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
|
||||
// _diffuseColor has been renamed to _color
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_DIFFUSE_COLOR_UNUSED, _color);
|
||||
READ_ENTITY_PROPERTY(PROP_DIFFUSE_COLOR, rgbColor, setColor);
|
||||
|
||||
// Ambient and specular color are from an older format and are no longer supported.
|
||||
// Their values will be ignored.
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_AMBIENT_COLOR_UNUSED, ignoredColor);
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_SPECULAR_COLOR_UNUSED, ignoredColor);
|
||||
READ_ENTITY_PROPERTY(PROP_AMBIENT_COLOR_UNUSED, rgbColor, setIgnoredColor);
|
||||
READ_ENTITY_PROPERTY(PROP_SPECULAR_COLOR_UNUSED, rgbColor, setIgnoredColor);
|
||||
|
||||
// _constantAttenuation has been renamed to _intensity
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, _intensity);
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, setIntensity);
|
||||
|
||||
// Linear and quadratic attenuation are from an older format and are no longer supported.
|
||||
// Their values will be ignored.
|
||||
READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION_UNUSED, float, ignoredAttenuation);
|
||||
READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION_UNUSED, float, ignoredAttenuation);
|
||||
READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION_UNUSED, float, setIgnoredAttenuation);
|
||||
READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION_UNUSED, float, setIgnoredAttenuation);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff);
|
||||
|
||||
(void) ignoredAttenuation; // suppress compiler warning
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, setCutoff);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight);
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, _intensity);
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff);
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, setIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, setCutoff);
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
|
@ -181,9 +176,9 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_INTENSITY, appendValue, getIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, getCutoff());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_INTENSITY, getIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, getCutoff());
|
||||
}
|
||||
|
|
|
@ -58,6 +58,9 @@ public:
|
|||
bool getIsSpotlight() const { return _isSpotlight; }
|
||||
void setIsSpotlight(bool value);
|
||||
|
||||
void setIgnoredColor(const rgbColor& value) { }
|
||||
void setIgnoredAttenuation(float value) { }
|
||||
|
||||
float getIntensity() const { return _intensity; }
|
||||
void setIntensity(float value) { _intensity = value; }
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ void LineEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
}
|
||||
|
||||
void LineEntityItem::debugDump() const {
|
||||
|
|
|
@ -95,16 +95,16 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_MODEL_URL, setModelURL);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL);
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_HAS_COLLISION_MODEL) {
|
||||
setCompoundShapeURL("");
|
||||
} else if (args.bitstreamVersion == VERSION_ENTITIES_HAS_COLLISION_MODEL) {
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
}
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_URL, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setAnimationURL);
|
||||
|
||||
// Because we're using AnimationLoop which will reset the frame index if you change it's running state
|
||||
// we want to read these values in the order they appear in the buffer, but call our setters in an
|
||||
|
@ -112,9 +112,9 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
float animationFPS = getAnimationFPS();
|
||||
float animationFrameIndex = getAnimationFrameIndex();
|
||||
bool animationIsPlaying = getAnimationIsPlaying();
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, animationFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, animationFrameIndex);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
|
||||
if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) {
|
||||
if (animationIsPlaying != getAnimationIsPlaying()) {
|
||||
|
@ -128,9 +128,9 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
setAnimationFrameIndex(animationFrameIndex);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -162,16 +162,16 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
|
||||
// Because we're using AnimationLoop which will reset the frame index if you change it's running state
|
||||
// we want to read these values in the order they appear in the buffer, but call our setters in an
|
||||
|
@ -161,9 +161,9 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
float animationFPS = getAnimationFPS();
|
||||
float animationFrameIndex = getAnimationFrameIndex();
|
||||
bool animationIsPlaying = getAnimationIsPlaying();
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, animationFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, animationFrameIndex);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
|
||||
if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) {
|
||||
if (animationIsPlaying != getAnimationIsPlaying()) {
|
||||
|
@ -177,16 +177,16 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
setAnimationFrameIndex(animationFrameIndex);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, _maxParticles);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, _lifespan);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, _emitRate);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, _emitStrength);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, _localGravity);
|
||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, _particleRadius);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, setEmitStrength);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, setLocalGravity);
|
||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -223,20 +223,20 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
|
|||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, getMaxParticles());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, getLifespan());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, getEmitRate());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, getEmitDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, getEmitStrength());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, getLocalGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, getEmitDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, getEmitStrength());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, getLocalGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
}
|
||||
|
||||
bool ParticleEffectEntityItem::isAnimatingSomething() const {
|
||||
|
|
|
@ -32,6 +32,7 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) {
|
|||
SharedNodePointer ownerNode = nodeList->nodeWithUUID(entity->getSimulatorID());
|
||||
if (ownerNode.isNull() || !ownerNode->isAlive()) {
|
||||
qCDebug(entities) << "auto-removing simulation owner" << entity->getSimulatorID();
|
||||
// TODO: zero velocities when we clear simulatorID?
|
||||
entity->setSimulatorID(QUuid());
|
||||
itemItr = _hasSimulationOwnerEntities.erase(itemItr);
|
||||
} else {
|
||||
|
|
|
@ -21,13 +21,13 @@ SkyboxPropertyGroup::SkyboxPropertyGroup() {
|
|||
}
|
||||
|
||||
void SkyboxPropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_COLOR(Skybox, skybox, Color, color);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Skybox, skybox, Color, color);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Skybox, skybox, URL, url);
|
||||
}
|
||||
|
||||
void SkyboxPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_COLOR(skybox, color, setColor);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_STRING(skybox, url, setURL);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(skybox, color, xColor, setColor);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(skybox, url, QString, setURL);
|
||||
}
|
||||
|
||||
void SkyboxPropertyGroup::debugDump() const {
|
||||
|
@ -45,8 +45,8 @@ bool SkyboxPropertyGroup::appentToEditPacket(OctreePacketData* packetData,
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_URL, appendValue, getURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_URL, getURL());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ bool SkyboxPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlag
|
|||
int bytesRead = 0;
|
||||
bool overwriteLocalData = true;
|
||||
|
||||
READ_ENTITY_PROPERTY_XCOLOR(PROP_SKYBOX_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_SKYBOX_URL, setURL);
|
||||
READ_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, xColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_SKYBOX_URL, QString, setURL);
|
||||
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_SKYBOX_COLOR, Color);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_SKYBOX_URL, URL);
|
||||
|
@ -115,8 +115,8 @@ void SkyboxPropertyGroup::appendSubclassData(OctreePacketData* packetData, Encod
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_URL, appendValue, getURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_URL, getURL());
|
||||
}
|
||||
|
||||
int SkyboxPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
|
@ -126,8 +126,8 @@ int SkyboxPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* d
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_XCOLOR(PROP_SKYBOX_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_SKYBOX_URL, setURL);
|
||||
READ_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, xColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_SKYBOX_URL, QString, setURL);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ int SphereEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi
|
|||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
}
|
||||
|
||||
bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
|
|
@ -49,20 +49,20 @@ void StagePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngi
|
|||
void StagePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||
|
||||
// Backward compatibility support for the old way of doing stage properties
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL_GETTER(stageSunModelEnabled, setSunModelEnabled, getSunModelEnabled);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageLatitude, setLatitude, getLatitude);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageLongitude, setLongitude, getLongitude);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageAltitude, setAltitude, getAltitude);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_INT_GETTER(stageDay, setDay, getDay);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT_GETTER(stageHour, setHour, getHour);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(stageSunModelEnabled, bool, setSunModelEnabled, getSunModelEnabled);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(stageLatitude, float, setLatitude, getLatitude);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(stageLongitude, float, setLongitude, getLongitude);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(stageAltitude, float, setAltitude, getAltitude);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(stageDay, uint16_t, setDay, getDay);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(stageHour, float, setHour, getHour);
|
||||
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(stage, sunModelEnabled, setSunModelEnabled);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, latitude, setLatitude);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, longitude, setLongitude);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, altitude, setAltitude);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_UINT16(stage, day, setDay);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stage, hour, setHour);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_BOOL(stage, automaticHourDay, setAutomaticHourDay);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(stage, sunModelEnabled, bool, setSunModelEnabled);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(stage, latitude, float, setLatitude);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(stage, longitude, float, setLongitude);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(stage, altitude, float, setAltitude);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(stage, day, uint16_t, setDay);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(stage, hour, float, setHour);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(stage, automaticHourDay, bool, setAutomaticHourDay);
|
||||
}
|
||||
|
||||
void StagePropertyGroup::debugDump() const {
|
||||
|
@ -85,13 +85,13 @@ bool StagePropertyGroup::appentToEditPacket(OctreePacketData* packetData,
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, getSunModelEnabled());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, getLatitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, getLongitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getAltitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getHour());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, appendValue, getAutomaticHourDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, getSunModelEnabled());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, getLatitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, getLongitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, getAltitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, getDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, getHour());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, getAutomaticHourDay());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -102,13 +102,13 @@ bool StagePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags
|
|||
int bytesRead = 0;
|
||||
bool overwriteLocalData = true;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, _sunModelEnabled);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, _latitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, _longitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _altitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _day);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _hour);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, bool, _automaticHourDay);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, setSunModelEnabled);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, setLatitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, setLongitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, setAltitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, setDay);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, setHour);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, bool, setAutomaticHourDay);
|
||||
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_SUN_MODEL_ENABLED, SunModelEnabled);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_STAGE_LATITUDE, Latitude);
|
||||
|
@ -195,13 +195,13 @@ void StagePropertyGroup::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, getSunModelEnabled());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, getLatitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, getLongitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getAltitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getHour());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, appendValue, getAutomaticHourDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, getSunModelEnabled());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, getLatitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, getLongitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, getAltitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, getDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, getHour());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, getAutomaticHourDay());
|
||||
}
|
||||
|
||||
int StagePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
|
@ -211,13 +211,13 @@ int StagePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, _sunModelEnabled);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, _latitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, _longitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _altitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _day);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _hour);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, bool, _automaticHourDay);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, setSunModelEnabled);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, setLatitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, setLongitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, setAltitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, setDay);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, setHour);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_AUTOMATIC_HOURDAY, bool, setAutomaticHourDay);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
|
|
@ -88,10 +88,10 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_TEXT, setText);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, _lineHeight);
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_TEXT_COLOR, _textColor);
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_BACKGROUND_COLOR, _backgroundColor);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXT, QString, setText);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXT_COLOR, rgbColor, setTextColor);
|
||||
READ_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, rgbColor, setBackgroundColor);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -117,10 +117,10 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT, appendValue, getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT, getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, getBackgroundColor());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_SOURCE_URL, setSourceUrl);
|
||||
READ_ENTITY_PROPERTY(PROP_SOURCE_URL, QString, setSourceUrl);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst
|
|||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, appendValue, _sourceUrl);
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, _sourceUrl);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -135,10 +135,10 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_KEYLIGHT_COLOR, _keyLightColor);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, _keyLightIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, _keyLightAmbientIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, _keyLightDirection);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, rgbColor, setKeyLightColor);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setKeyLightIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, setKeyLightAmbientIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setKeyLightDirection);
|
||||
|
||||
int bytesFromStage = _stageProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData);
|
||||
|
@ -146,9 +146,9 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
bytesRead += bytesFromStage;
|
||||
dataAt += bytesFromStage;
|
||||
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
|
||||
|
||||
int bytesFromAtmosphere = _atmosphereProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData);
|
||||
|
@ -193,18 +193,18 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, appendColor, _keyLightColor);
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, appendValue, getKeyLightIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, appendValue, getKeyLightAmbientIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, appendValue, getKeyLightDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, _keyLightColor);
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getKeyLightIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, getKeyLightAmbientIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getKeyLightDirection());
|
||||
|
||||
_stageProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, appendValue, (uint32_t)getBackgroundMode()); // could this be a uint16??
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, (uint32_t)getBackgroundMode()); // could this be a uint16??
|
||||
|
||||
_atmosphereProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
|
|
|
@ -51,6 +51,12 @@ public:
|
|||
_keyLightColor[BLUE_INDEX] = value.blue;
|
||||
}
|
||||
|
||||
void setKeyLightColor(const rgbColor& value) {
|
||||
_keyLightColor[RED_INDEX] = value[RED_INDEX];
|
||||
_keyLightColor[GREEN_INDEX] = value[GREEN_INDEX];
|
||||
_keyLightColor[BLUE_INDEX] = value[BLUE_INDEX];
|
||||
}
|
||||
|
||||
glm::vec3 getKeyLightColorVec3() const {
|
||||
const quint8 MAX_COLOR = 255;
|
||||
glm::vec3 color = { (float)_keyLightColor[RED_INDEX] / (float)MAX_COLOR,
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <NumericalConstants.h>
|
||||
#include <OctalCode.h>
|
||||
#include <Shape.h>
|
||||
#include <gpu/Format.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "FBXReader.h"
|
||||
#include "ModelFormatLogging.h"
|
||||
|
@ -1276,6 +1278,153 @@ FBXLight extractLight(const FBXNode& object) {
|
|||
return light;
|
||||
}
|
||||
|
||||
|
||||
#if USE_MODEL_MESH
|
||||
void buildModelMesh(ExtractedMesh& extracted) {
|
||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*");
|
||||
|
||||
if (extracted.mesh.vertices.size() == 0) {
|
||||
extracted.mesh._mesh = model::Mesh();
|
||||
qCDebug(modelformat) << "buildModelMesh failed -- no vertices";
|
||||
return;
|
||||
}
|
||||
FBXMesh& fbxMesh = extracted.mesh;
|
||||
model::Mesh mesh;
|
||||
|
||||
// Grab the vertices in a buffer
|
||||
gpu::BufferPointer vb(new gpu::Buffer());
|
||||
vb->setData(extracted.mesh.vertices.size() * sizeof(glm::vec3),
|
||||
(const gpu::Byte*) extracted.mesh.vertices.data());
|
||||
gpu::BufferView vbv(vb, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
mesh.setVertexBuffer(vbv);
|
||||
|
||||
// evaluate all attribute channels sizes
|
||||
int normalsSize = fbxMesh.normals.size() * sizeof(glm::vec3);
|
||||
int tangentsSize = fbxMesh.tangents.size() * sizeof(glm::vec3);
|
||||
int colorsSize = fbxMesh.colors.size() * sizeof(glm::vec3);
|
||||
int texCoordsSize = fbxMesh.texCoords.size() * sizeof(glm::vec2);
|
||||
int texCoords1Size = fbxMesh.texCoords1.size() * sizeof(glm::vec2);
|
||||
int clusterIndicesSize = fbxMesh.clusterIndices.size() * sizeof(glm::vec4);
|
||||
int clusterWeightsSize = fbxMesh.clusterWeights.size() * sizeof(glm::vec4);
|
||||
|
||||
int normalsOffset = 0;
|
||||
int tangentsOffset = normalsOffset + normalsSize;
|
||||
int colorsOffset = tangentsOffset + tangentsSize;
|
||||
int texCoordsOffset = colorsOffset + colorsSize;
|
||||
int texCoords1Offset = texCoordsOffset + texCoordsSize;
|
||||
int clusterIndicesOffset = texCoords1Offset + texCoords1Size;
|
||||
int clusterWeightsOffset = clusterIndicesOffset + clusterIndicesSize;
|
||||
int totalAttributeSize = clusterWeightsOffset + clusterWeightsSize;
|
||||
|
||||
// Copy all attribute data in a single attribute buffer
|
||||
gpu::BufferPointer attribBuffer(new gpu::Buffer());
|
||||
attribBuffer->resize(totalAttributeSize);
|
||||
attribBuffer->setSubData(normalsOffset, normalsSize, (gpu::Byte*) fbxMesh.normals.constData());
|
||||
attribBuffer->setSubData(tangentsOffset, tangentsSize, (gpu::Byte*) fbxMesh.tangents.constData());
|
||||
attribBuffer->setSubData(colorsOffset, colorsSize, (gpu::Byte*) fbxMesh.colors.constData());
|
||||
attribBuffer->setSubData(texCoordsOffset, texCoordsSize, (gpu::Byte*) fbxMesh.texCoords.constData());
|
||||
attribBuffer->setSubData(texCoords1Offset, texCoords1Size, (gpu::Byte*) fbxMesh.texCoords1.constData());
|
||||
attribBuffer->setSubData(clusterIndicesOffset, clusterIndicesSize, (gpu::Byte*) fbxMesh.clusterIndices.constData());
|
||||
attribBuffer->setSubData(clusterWeightsOffset, clusterWeightsSize, (gpu::Byte*) fbxMesh.clusterWeights.constData());
|
||||
|
||||
if (normalsSize) {
|
||||
mesh.addAttribute(gpu::Stream::NORMAL,
|
||||
model::BufferView(attribBuffer, normalsOffset, normalsSize,
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)));
|
||||
}
|
||||
if (tangentsSize) {
|
||||
mesh.addAttribute(gpu::Stream::TANGENT,
|
||||
model::BufferView(attribBuffer, tangentsOffset, tangentsSize,
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)));
|
||||
}
|
||||
if (colorsSize) {
|
||||
mesh.addAttribute(gpu::Stream::COLOR,
|
||||
model::BufferView(attribBuffer, colorsOffset, colorsSize,
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)));
|
||||
}
|
||||
if (texCoordsSize) {
|
||||
mesh.addAttribute(gpu::Stream::TEXCOORD,
|
||||
model::BufferView( attribBuffer, texCoordsOffset, texCoordsSize,
|
||||
gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)));
|
||||
}
|
||||
if (texCoords1Size) {
|
||||
mesh.addAttribute(gpu::Stream::TEXCOORD1,
|
||||
model::BufferView(attribBuffer, texCoords1Offset, texCoords1Size,
|
||||
gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)));
|
||||
}
|
||||
if (clusterIndicesSize) {
|
||||
mesh.addAttribute(gpu::Stream::SKIN_CLUSTER_INDEX,
|
||||
model::BufferView(attribBuffer, clusterIndicesOffset, clusterIndicesSize,
|
||||
gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)));
|
||||
}
|
||||
if (clusterWeightsSize) {
|
||||
mesh.addAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT,
|
||||
model::BufferView(attribBuffer, clusterWeightsOffset, clusterWeightsSize,
|
||||
gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)));
|
||||
}
|
||||
|
||||
|
||||
unsigned int totalIndices = 0;
|
||||
|
||||
foreach(const FBXMeshPart& part, extracted.mesh.parts) {
|
||||
totalIndices += (part.quadIndices.size() + part.triangleIndices.size());
|
||||
}
|
||||
|
||||
if (! totalIndices) {
|
||||
extracted.mesh._mesh = model::Mesh();
|
||||
qCDebug(modelformat) << "buildModelMesh failed -- no indices";
|
||||
return;
|
||||
}
|
||||
|
||||
gpu::BufferPointer ib(new gpu::Buffer());
|
||||
ib->resize(totalIndices * sizeof(int));
|
||||
|
||||
int indexNum = 0;
|
||||
int offset = 0;
|
||||
|
||||
std::vector< model::Mesh::Part > parts;
|
||||
|
||||
foreach(const FBXMeshPart& part, extracted.mesh.parts) {
|
||||
model::Mesh::Part quadPart(indexNum, part.quadIndices.size(), 0, model::Mesh::QUADS);
|
||||
if (quadPart._numIndices) {
|
||||
parts.push_back(quadPart);
|
||||
ib->setSubData(offset, part.quadIndices.size() * sizeof(int),
|
||||
(gpu::Byte*) part.quadIndices.constData());
|
||||
offset += part.quadIndices.size() * sizeof(int);
|
||||
indexNum += part.quadIndices.size();
|
||||
}
|
||||
model::Mesh::Part triPart(indexNum, part.triangleIndices.size(), 0, model::Mesh::TRIANGLES);
|
||||
if (triPart._numIndices) {
|
||||
ib->setSubData(offset, part.triangleIndices.size() * sizeof(int),
|
||||
(gpu::Byte*) part.triangleIndices.constData());
|
||||
offset += part.triangleIndices.size() * sizeof(int);
|
||||
indexNum += part.triangleIndices.size();
|
||||
}
|
||||
}
|
||||
|
||||
gpu::BufferView ibv(ib, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::XYZ));
|
||||
mesh.setIndexBuffer(ibv);
|
||||
|
||||
if (parts.size()) {
|
||||
gpu::BufferPointer pb(new gpu::Buffer());
|
||||
pb->setData(parts.size() * sizeof(model::Mesh::Part), (const gpu::Byte*) parts.data());
|
||||
gpu::BufferView pbv(pb, gpu::Element(gpu::VEC4, gpu::UINT32, gpu::XYZW));
|
||||
mesh.setPartBuffer(pbv);
|
||||
} else {
|
||||
extracted.mesh._mesh = model::Mesh();
|
||||
qCDebug(modelformat) << "buildModelMesh failed -- no parts";
|
||||
return;
|
||||
}
|
||||
|
||||
// model::Box box =
|
||||
mesh.evalPartBound(0);
|
||||
|
||||
extracted.mesh._mesh = mesh;
|
||||
}
|
||||
#endif // USE_MODEL_MESH
|
||||
|
||||
|
||||
|
||||
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) {
|
||||
QHash<QString, ExtractedMesh> meshes;
|
||||
QHash<QString, QString> modelIDsToNames;
|
||||
|
@ -2431,6 +2580,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
|||
}
|
||||
}
|
||||
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
|
||||
|
||||
# if USE_MODEL_MESH
|
||||
buildModelMesh(extracted);
|
||||
# endif
|
||||
|
||||
geometry.meshes.append(extracted.mesh);
|
||||
int meshIndex = geometry.meshes.size() - 1;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_FBXReader_h
|
||||
#define hifi_FBXReader_h
|
||||
|
||||
#define USE_MODEL_MESH 1
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QUrl>
|
||||
#include <QVarLengthArray>
|
||||
|
@ -154,6 +156,9 @@ public:
|
|||
bool hasEmissiveTexture() const;
|
||||
|
||||
unsigned int meshIndex; // the order the meshes appeared in the object file
|
||||
# if USE_MODEL_MESH
|
||||
model::Mesh _mesh;
|
||||
# endif
|
||||
};
|
||||
|
||||
/// A single animation frame extracted from an FBX document.
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
#include "GPULogging.h"
|
||||
#include "GLBackendShared.h"
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||
{
|
||||
|
@ -521,3 +522,29 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) {
|
|||
(void) CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void GLBackend::loadMatrix(GLenum target, const glm::mat4 & m) {
|
||||
glMatrixMode(target);
|
||||
glLoadMatrixf(glm::value_ptr(m));
|
||||
}
|
||||
|
||||
void GLBackend::fetchMatrix(GLenum target, glm::mat4 & m) {
|
||||
switch (target) {
|
||||
case GL_MODELVIEW_MATRIX:
|
||||
case GL_PROJECTION_MATRIX:
|
||||
break;
|
||||
|
||||
// Lazy cheating
|
||||
case GL_MODELVIEW:
|
||||
target = GL_MODELVIEW_MATRIX;
|
||||
break;
|
||||
case GL_PROJECTION:
|
||||
target = GL_PROJECTION_MATRIX;
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT_X(false, "GLBackend::fetchMatrix", "Bad matrix target");
|
||||
}
|
||||
glGetFloatv(target, glm::value_ptr(m));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -79,6 +79,9 @@ public:
|
|||
static GLShader* syncGPUObject(const Shader& shader);
|
||||
static GLuint getShaderID(const ShaderPointer& shader);
|
||||
|
||||
static void loadMatrix(GLenum target, const glm::mat4 & m);
|
||||
static void fetchMatrix(GLenum target, glm::mat4 & m);
|
||||
|
||||
class GLState : public GPUObject {
|
||||
public:
|
||||
class Command {
|
||||
|
|
|
@ -57,7 +57,7 @@ const Texture::PixelsPointer Texture::Storage::getMipFace(uint16 level, uint8 fa
|
|||
|
||||
void Texture::Storage::notifyMipFaceGPULoaded(uint16 level, uint8 face) const {
|
||||
PixelsPointer mipFace = getMipFace(level, face);
|
||||
if (mipFace) {
|
||||
if (mipFace && (_type != TEX_CUBE)) {
|
||||
mipFace->_isGPULoaded = true;
|
||||
mipFace->_sysmem.resize(0);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ public:
|
|||
CUBE_FACE_LEFT_NEG_X,
|
||||
CUBE_FACE_TOP_POS_Y,
|
||||
CUBE_FACE_BOTTOM_NEG_Y,
|
||||
CUBE_FACE_BACK_POS_X,
|
||||
CUBE_FACE_BACK_POS_Z,
|
||||
CUBE_FACE_FRONT_NEG_Z,
|
||||
|
||||
NUM_CUBE_FACES, // Not a valid vace index
|
||||
|
|
|
@ -99,3 +99,6 @@ void Light::setShowContour(float show) {
|
|||
}
|
||||
editSchema()._control.w = show;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
typedef std::shared_ptr< SphericalHarmonics > SHPointer;
|
||||
|
||||
class Light {
|
||||
public:
|
||||
|
|
|
@ -39,6 +39,9 @@ void Skybox::setColor(const Color& color) {
|
|||
}
|
||||
|
||||
void Skybox::setCubemap(const gpu::TexturePointer& cubemap) {
|
||||
if (_isSHValid && (cubemap != _cubemap)) {
|
||||
_isSHValid = false;
|
||||
}
|
||||
_cubemap = cubemap;
|
||||
}
|
||||
|
||||
|
@ -49,6 +52,9 @@ void Skybox::clearCubemap() {
|
|||
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) {
|
||||
|
||||
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
|
||||
|
||||
skybox.getIrradianceSH();
|
||||
|
||||
static gpu::PipelinePointer thePipeline;
|
||||
static gpu::BufferPointer theBuffer;
|
||||
static gpu::Stream::FormatPointer theFormat;
|
||||
|
@ -113,3 +119,223 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(skybox.getColor(),1.0f), 0.f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 sRGBToLinear(glm::vec3& color) {
|
||||
const float GAMMA_CORRECTION = 2.2f;
|
||||
return glm::pow(color, glm::vec3(GAMMA_CORRECTION));
|
||||
}
|
||||
|
||||
glm::vec3 linearTosRGB(glm::vec3& color) {
|
||||
const float GAMMA_CORRECTION_INV = 1.0f / 2.2f;
|
||||
return glm::pow(color, glm::vec3(GAMMA_CORRECTION_INV));
|
||||
}
|
||||
|
||||
// Originial code for the Spherical Harmonics taken from "Sun and Black Cat- Igor Dykhta (igor dykhta email) © 2007-2014 "
|
||||
void sphericalHarmonicsAdd(float * result, int order, const float * inputA, const float * inputB) {
|
||||
const int numCoeff = order * order;
|
||||
for(int i=0; i < numCoeff; i++) {
|
||||
result[i] = inputA[i] + inputB[i];
|
||||
}
|
||||
}
|
||||
|
||||
void sphericalHarmonicsScale(float * result, int order, const float * input, float scale) {
|
||||
const int numCoeff = order * order;
|
||||
for(int i=0; i < numCoeff; i++) {
|
||||
result[i] = input[i] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
void sphericalHarmonicsEvaluateDirection(float * result, int order, const glm::vec3 & dir) {
|
||||
// calculate coefficients for first 3 bands of spherical harmonics
|
||||
double P_0_0 = 0.282094791773878140;
|
||||
double P_1_0 = 0.488602511902919920 * dir.z;
|
||||
double P_1_1 = -0.488602511902919920;
|
||||
double P_2_0 = 0.946174695757560080 * dir.z * dir.z - 0.315391565252520050;
|
||||
double P_2_1 = -1.092548430592079200 * dir.z;
|
||||
double P_2_2 = 0.546274215296039590;
|
||||
result[0] = P_0_0;
|
||||
result[1] = P_1_1 * dir.y;
|
||||
result[2] = P_1_0;
|
||||
result[3] = P_1_1 * dir.x;
|
||||
result[4] = P_2_2 * (dir.x * dir.y + dir.y * dir.x);
|
||||
result[5] = P_2_1 * dir.y;
|
||||
result[6] = P_2_0;
|
||||
result[7] = P_2_1 * dir.x;
|
||||
result[8] = P_2_2 * (dir.x * dir.x - dir.y * dir.y);
|
||||
}
|
||||
|
||||
void sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<glm::vec3> & output, const uint order) {
|
||||
const uint sqOrder = order*order;
|
||||
|
||||
// allocate memory for calculations
|
||||
output.resize(sqOrder);
|
||||
std::vector<float> resultR(sqOrder);
|
||||
std::vector<float> resultG(sqOrder);
|
||||
std::vector<float> resultB(sqOrder);
|
||||
|
||||
int width, height;
|
||||
|
||||
// initialize values
|
||||
float fWt = 0.0f;
|
||||
for(uint i=0; i < sqOrder; i++) {
|
||||
output[i] = glm::vec3(0.0f);
|
||||
resultR[i] = 0.0f;
|
||||
resultG[i] = 0;
|
||||
resultB[i] = 0;
|
||||
}
|
||||
std::vector<float> shBuff(sqOrder);
|
||||
std::vector<float> shBuffB(sqOrder);
|
||||
// get width and height
|
||||
width = height = cubeTexture.getWidth();
|
||||
if(width != height) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float UCHAR_TO_FLOAT = 1.0f / float(std::numeric_limits<unsigned char>::max());
|
||||
|
||||
// for each face of cube texture
|
||||
for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) {
|
||||
|
||||
auto numComponents = cubeTexture.accessStoredMipFace(0,face)->_format.getDimensionCount();
|
||||
auto data = cubeTexture.accessStoredMipFace(0,face)->_sysmem.readData();
|
||||
if (data == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// step between two texels for range [0, 1]
|
||||
float invWidth = 1.0f / float(width);
|
||||
// initial negative bound for range [-1, 1]
|
||||
float negativeBound = -1.0f + invWidth;
|
||||
// step between two texels for range [-1, 1]
|
||||
float invWidthBy2 = 2.0f / float(width);
|
||||
|
||||
for(int y=0; y < width; y++) {
|
||||
// texture coordinate V in range [-1 to 1]
|
||||
const float fV = negativeBound + float(y) * invWidthBy2;
|
||||
|
||||
for(int x=0; x < width; x++) {
|
||||
// texture coordinate U in range [-1 to 1]
|
||||
const float fU = negativeBound + float(x) * invWidthBy2;
|
||||
|
||||
// determine direction from center of cube texture to current texel
|
||||
glm::vec3 dir;
|
||||
switch(face) {
|
||||
case gpu::Texture::CUBE_FACE_RIGHT_POS_X: {
|
||||
dir.x = 1.0f;
|
||||
dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
|
||||
dir.z = 1.0f - (invWidthBy2 * float(x) + invWidth);
|
||||
dir = -dir;
|
||||
break;
|
||||
}
|
||||
case gpu::Texture::CUBE_FACE_LEFT_NEG_X: {
|
||||
dir.x = -1.0f;
|
||||
dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
|
||||
dir.z = -1.0f + (invWidthBy2 * float(x) + invWidth);
|
||||
dir = -dir;
|
||||
break;
|
||||
}
|
||||
case gpu::Texture::CUBE_FACE_TOP_POS_Y: {
|
||||
dir.x = - 1.0f + (invWidthBy2 * float(x) + invWidth);
|
||||
dir.y = 1.0f;
|
||||
dir.z = - 1.0f + (invWidthBy2 * float(y) + invWidth);
|
||||
dir = -dir;
|
||||
break;
|
||||
}
|
||||
case gpu::Texture::CUBE_FACE_BOTTOM_NEG_Y: {
|
||||
dir.x = - 1.0f + (invWidthBy2 * float(x) + invWidth);
|
||||
dir.y = - 1.0f;
|
||||
dir.z = 1.0f - (invWidthBy2 * float(y) + invWidth);
|
||||
dir = -dir;
|
||||
break;
|
||||
}
|
||||
case gpu::Texture::CUBE_FACE_BACK_POS_Z: {
|
||||
dir.x = - 1.0f + (invWidthBy2 * float(x) + invWidth);
|
||||
dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
|
||||
dir.z = 1.0f;
|
||||
break;
|
||||
}
|
||||
case gpu::Texture::CUBE_FACE_FRONT_NEG_Z: {
|
||||
dir.x = 1.0f - (invWidthBy2 * float(x) + invWidth);
|
||||
dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
|
||||
dir.z = - 1.0f;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// normalize direction
|
||||
dir = glm::normalize(dir);
|
||||
|
||||
// scale factor depending on distance from center of the face
|
||||
const float fDiffSolid = 4.0f / ((1.0f + fU*fU + fV*fV) *
|
||||
sqrtf(1.0f + fU*fU + fV*fV));
|
||||
fWt += fDiffSolid;
|
||||
|
||||
// calculate coefficients of spherical harmonics for current direction
|
||||
sphericalHarmonicsEvaluateDirection(shBuff.data(), order, dir);
|
||||
|
||||
// index of texel in texture
|
||||
uint pixOffsetIndex = (x + y * width) * numComponents;
|
||||
|
||||
// get color from texture and map to range [0, 1]
|
||||
glm::vec3 clr(float(data[pixOffsetIndex]) * UCHAR_TO_FLOAT,
|
||||
float(data[pixOffsetIndex+1]) * UCHAR_TO_FLOAT,
|
||||
float(data[pixOffsetIndex+2]) * UCHAR_TO_FLOAT);
|
||||
|
||||
// Gamma correct
|
||||
clr = sRGBToLinear(clr);
|
||||
|
||||
// scale color and add to previously accumulated coefficients
|
||||
sphericalHarmonicsScale(shBuffB.data(), order,
|
||||
shBuff.data(), clr.r * fDiffSolid);
|
||||
sphericalHarmonicsAdd(resultR.data(), order,
|
||||
resultR.data(), shBuffB.data());
|
||||
sphericalHarmonicsScale(shBuffB.data(), order,
|
||||
shBuff.data(), clr.g * fDiffSolid);
|
||||
sphericalHarmonicsAdd(resultG.data(), order,
|
||||
resultG.data(), shBuffB.data());
|
||||
sphericalHarmonicsScale(shBuffB.data(), order,
|
||||
shBuff.data(), clr.b * fDiffSolid);
|
||||
sphericalHarmonicsAdd(resultB.data(), order,
|
||||
resultB.data(), shBuffB.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// final scale for coefficients
|
||||
const float fNormProj = (4.0f * glm::pi<float>()) / fWt;
|
||||
sphericalHarmonicsScale(resultR.data(), order, resultR.data(), fNormProj);
|
||||
sphericalHarmonicsScale(resultG.data(), order, resultG.data(), fNormProj);
|
||||
sphericalHarmonicsScale(resultB.data(), order, resultB.data(), fNormProj);
|
||||
|
||||
// save result
|
||||
for(uint i=0; i < sqOrder; i++) {
|
||||
// gamma Correct
|
||||
// output[i] = linearTosRGB(glm::vec3(resultR[i], resultG[i], resultB[i]));
|
||||
output[i] = glm::vec3(resultR[i], resultG[i], resultB[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const SphericalHarmonics& Skybox::getIrradianceSH() const {
|
||||
if (!_isSHValid) {
|
||||
if (_cubemap && _cubemap->isDefined()) {
|
||||
std::vector< glm::vec3 > coefs;
|
||||
sphericalHarmonicsFromTexture(*_cubemap, coefs, 3);
|
||||
|
||||
_irradianceSH.L00 = coefs[0];
|
||||
_irradianceSH.L1m1 = coefs[1];
|
||||
_irradianceSH.L10 = coefs[2];
|
||||
_irradianceSH.L11 = coefs[3];
|
||||
_irradianceSH.L2m2 = coefs[4];
|
||||
_irradianceSH.L2m1 = coefs[5];
|
||||
_irradianceSH.L20 = coefs[6];
|
||||
_irradianceSH.L21 = coefs[7];
|
||||
_irradianceSH.L22 = coefs[8];
|
||||
|
||||
_isSHValid = true;
|
||||
}
|
||||
}
|
||||
return _irradianceSH;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "gpu/Texture.h"
|
||||
|
||||
#include "Light.h"
|
||||
|
||||
class ViewFrustum;
|
||||
//class Transform;
|
||||
namespace gpu { class Batch; }
|
||||
|
@ -34,11 +36,16 @@ public:
|
|||
const gpu::TexturePointer& getCubemap() const { return _cubemap; }
|
||||
void clearCubemap();
|
||||
|
||||
const SphericalHarmonics& getIrradianceSH() const;
|
||||
|
||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox);
|
||||
|
||||
protected:
|
||||
gpu::TexturePointer _cubemap;
|
||||
|
||||
mutable SphericalHarmonics _irradianceSH;
|
||||
mutable bool _isSHValid = false;
|
||||
|
||||
Color _color{1.0f, 1.0f, 1.0f};
|
||||
};
|
||||
typedef std::shared_ptr< Skybox > SkyboxPointer;
|
||||
|
|
|
@ -20,5 +20,6 @@ varying vec3 color;
|
|||
void main(void) {
|
||||
vec3 coord = normalize(normal);
|
||||
vec4 texel = textureCube(cubeMap, coord);
|
||||
gl_FragData[0] = vec4(texel.xyz * color, 0.0);
|
||||
vec3 pixel = pow(texel.xyz * color, vec3(1.0/2.2)); // manual Gamma correction
|
||||
gl_FragData[0] = vec4(pixel, 0.0);
|
||||
}
|
||||
|
|
|
@ -71,14 +71,14 @@ public:
|
|||
EarthSunModel() { valid(); }
|
||||
|
||||
protected:
|
||||
double _scale = 1000.0; //Km
|
||||
float _scale = 1000.0f; //Km
|
||||
double _earthRadius = 6360.0;
|
||||
|
||||
Quat _surfaceOrientation;
|
||||
|
||||
double _longitude = 0.0;
|
||||
double _latitude = 0.0;
|
||||
double _altitude = 0.01;
|
||||
float _longitude = 0.0f;
|
||||
float _latitude = 0.0f;
|
||||
float _altitude = 0.01f;
|
||||
mutable Vec3d _surfacePos;
|
||||
mutable Mat4d _worldToSurfaceMat;
|
||||
mutable Mat4d _surfaceToWorldMat;
|
||||
|
@ -93,8 +93,8 @@ protected:
|
|||
mutable Mat4d _worldToEyeMat;
|
||||
mutable Mat4d _eyeToWorldMat;
|
||||
|
||||
double _sunLongitude = 0.0;
|
||||
double _sunLatitude = 0.0;
|
||||
float _sunLongitude = 0.0f;
|
||||
float _sunLatitude = 0.0f;
|
||||
mutable Vec3d _sunDir;
|
||||
mutable Vec3d _surfaceSunDir;
|
||||
void updateSun() const;
|
||||
|
|
|
@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
return 1;
|
||||
case PacketTypeEntityAddOrEdit:
|
||||
case PacketTypeEntityData:
|
||||
return VERSION_ENTITIES_HAVE_LINE_TYPE;
|
||||
return VERSION_ENTITIES_HAVE_FRICTION;
|
||||
case PacketTypeEntityErase:
|
||||
return 2;
|
||||
case PacketTypeAudioStreamStats:
|
||||
|
|
|
@ -176,5 +176,7 @@ const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX = 21;
|
|||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_STAGE_HAS_AUTOMATIC_HOURDAY = 22;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLE_ENTITIES_HAVE_TEXTURES = 23;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_LINE_TYPE = 24;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_COLLISION_SOUND_URL = 25;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_FRICTION = 26;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -281,15 +281,15 @@ bool OctreePacketData::appendBitMask(unsigned char bitmask) {
|
|||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendColor(const nodeColor& color) {
|
||||
bool OctreePacketData::appendValue(const nodeColor& color) {
|
||||
return appendColor(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]);
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendColor(const xColor& color) {
|
||||
bool OctreePacketData::appendValue(const xColor& color) {
|
||||
return appendColor(color.red, color.green, color.blue);
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendColor(const rgbColor& color) {
|
||||
bool OctreePacketData::appendValue(const rgbColor& color) {
|
||||
return appendColor(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]);
|
||||
}
|
||||
|
||||
|
@ -544,3 +544,32 @@ void OctreePacketData::debugContent() {
|
|||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, QString& result) {
|
||||
uint16_t length;
|
||||
memcpy(&length, dataBytes, sizeof(length));
|
||||
dataBytes += sizeof(length);
|
||||
QString value((const char*)dataBytes);
|
||||
result = value;
|
||||
return sizeof(length) + length;
|
||||
}
|
||||
|
||||
int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, QUuid& result) {
|
||||
uint16_t length;
|
||||
memcpy(&length, dataBytes, sizeof(length));
|
||||
dataBytes += sizeof(length);
|
||||
if (length == 0) {
|
||||
result = QUuid();
|
||||
} else {
|
||||
QByteArray ba((const char*)dataBytes, length);
|
||||
result = QUuid::fromRfc4122(ba);
|
||||
}
|
||||
return sizeof(length) + length;
|
||||
}
|
||||
|
||||
int OctreePacketData::uppackDataFromBytes(const unsigned char* dataBytes, xColor& result) {
|
||||
result.red = dataBytes[RED_INDEX];
|
||||
result.green = dataBytes[GREEN_INDEX];
|
||||
result.blue = dataBytes[BLUE_INDEX];
|
||||
return sizeof(rgbColor);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,15 @@
|
|||
#ifndef hifi_OctreePacketData_h
|
||||
#define hifi_OctreePacketData_h
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QUuid>
|
||||
|
||||
#include <LimitedNodeList.h> // for MAX_PACKET_SIZE
|
||||
#include <PacketHeaders.h> // for MAX_PACKET_HEADER_BYTES
|
||||
#include <SharedUtil.h>
|
||||
#include <ShapeInfo.h>
|
||||
#include <BackgroundMode.h>
|
||||
|
||||
#include "OctreeConstants.h"
|
||||
#include "OctreeElement.h"
|
||||
|
@ -127,18 +133,18 @@ public:
|
|||
/// Might fail if the new bytes would cause packet to be less compressed, or if offset and length was out of range.
|
||||
bool updatePriorBytes(int offset, const unsigned char* replacementBytes, int length);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendColor(const nodeColor& color);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendColor(const xColor& color);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendColor(const rgbColor& color);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendColor(colorPart red, colorPart green, colorPart blue);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const nodeColor& color);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const xColor& color);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const rgbColor& color);
|
||||
|
||||
/// appends a unsigned 8 bit int to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(uint8_t value);
|
||||
|
||||
|
@ -219,6 +225,21 @@ public:
|
|||
static quint64 getTotalBytesOfOctalCodes() { return _totalBytesOfOctalCodes; } /// total bytes for octal codes
|
||||
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);
|
||||
|
||||
private:
|
||||
/// appends raw bytes, might fail if byte would cause packet to be too large
|
||||
|
|
|
@ -25,7 +25,7 @@ static const quint8 STEPS_TO_DECIDE_BALLISTIC = 4;
|
|||
EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity) :
|
||||
ObjectMotionState(shape),
|
||||
_entity(entity),
|
||||
_sentMoving(false),
|
||||
_sentActive(false),
|
||||
_numNonMovingUpdates(0),
|
||||
_lastStep(0),
|
||||
_serverPosition(0.0f),
|
||||
|
@ -35,8 +35,9 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity
|
|||
_serverGravity(0.0f),
|
||||
_serverAcceleration(0.0f),
|
||||
_accelerationNearlyGravityCount(0),
|
||||
_shouldClaimSimulationOwnership(false),
|
||||
_movingStepsWithoutSimulationOwner(0)
|
||||
_candidateForOwnership(false),
|
||||
_loopsSinceOwnershipBid(0),
|
||||
_loopsWithoutOwner(0)
|
||||
{
|
||||
_type = MOTION_STATE_TYPE_ENTITY;
|
||||
assert(entity != nullptr);
|
||||
|
@ -66,6 +67,28 @@ void EntityMotionState::updateServerPhysicsVariables(uint32_t flags) {
|
|||
void EntityMotionState::handleEasyChanges(uint32_t flags) {
|
||||
updateServerPhysicsVariables(flags);
|
||||
ObjectMotionState::handleEasyChanges(flags);
|
||||
if (flags & EntityItem::DIRTY_SIMULATOR_ID) {
|
||||
_loopsWithoutOwner = 0;
|
||||
_candidateForOwnership = 0;
|
||||
if (_entity->getSimulatorID().isNull()
|
||||
&& !_entity->isMoving()
|
||||
&& _body->isActive()) {
|
||||
// remove the ACTIVATION flag because this object is coming to rest
|
||||
// according to a remote simulation and we don't want to wake it up again
|
||||
flags &= ~EntityItem::DIRTY_PHYSICS_ACTIVATION;
|
||||
_body->setActivationState(WANTS_DEACTIVATION);
|
||||
} else {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid& sessionID = nodeList->getSessionUUID();
|
||||
if (_entity->getSimulatorID() != sessionID) {
|
||||
_loopsSinceOwnershipBid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((flags & EntityItem::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) {
|
||||
_body->activate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,15 +118,6 @@ bool EntityMotionState::isMoving() const {
|
|||
return _entity && _entity->isMoving();
|
||||
}
|
||||
|
||||
bool EntityMotionState::isMovingVsServer() const {
|
||||
auto alignmentDot = glm::abs(glm::dot(_serverRotation, _entity->getRotation()));
|
||||
if (glm::distance(_serverPosition, _entity->getPosition()) > IGNORE_POSITION_DELTA ||
|
||||
alignmentDot < IGNORE_ALIGNMENT_DOT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This callback is invoked by the physics simulation in two cases:
|
||||
// (1) when the RigidBody is first added to the world
|
||||
// (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC)
|
||||
|
@ -143,19 +157,16 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
|
||||
_entity->setLastSimulated(usecTimestampNow());
|
||||
|
||||
// if (_entity->getSimulatorID().isNull() && isMoving()) {
|
||||
if (_entity->getSimulatorID().isNull() && isMovingVsServer()) {
|
||||
// if object is moving and has no owner, attempt to claim simulation ownership.
|
||||
_movingStepsWithoutSimulationOwner++;
|
||||
if (_entity->getSimulatorID().isNull()) {
|
||||
_loopsWithoutOwner++;
|
||||
|
||||
const uint32_t OWNERSHIP_BID_DELAY = 50;
|
||||
if (_loopsWithoutOwner > OWNERSHIP_BID_DELAY) {
|
||||
//qDebug() << "Warning -- claiming something I saw moving." << getName();
|
||||
_candidateForOwnership = true;
|
||||
}
|
||||
} else {
|
||||
_movingStepsWithoutSimulationOwner = 0;
|
||||
}
|
||||
|
||||
uint32_t ownershipClaimDelay = 50; // TODO -- how to pick this? based on meters from our characterController?
|
||||
|
||||
if (_movingStepsWithoutSimulationOwner > ownershipClaimDelay) {
|
||||
//qDebug() << "Warning -- claiming something I saw moving." << getName();
|
||||
setShouldClaimSimulationOwnership(true);
|
||||
_loopsWithoutOwner = 0;
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
|
@ -177,8 +188,11 @@ void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
|
|||
// we alwasy resend packets for objects that have stopped moving up to some max limit.
|
||||
const int MAX_NUM_NON_MOVING_UPDATES = 5;
|
||||
|
||||
bool EntityMotionState::doesNotNeedToSendUpdate() const {
|
||||
return !_body || (_body->isActive() && _numNonMovingUpdates > MAX_NUM_NON_MOVING_UPDATES);
|
||||
bool EntityMotionState::isCandidateForOwnership(const QUuid& sessionID) const {
|
||||
if (!_body || !_entity) {
|
||||
return false;
|
||||
}
|
||||
return _candidateForOwnership || sessionID == _entity->getSimulatorID();
|
||||
}
|
||||
|
||||
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||
|
@ -191,6 +205,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
_serverVelocity = bulletToGLM(_body->getLinearVelocity());
|
||||
_serverAngularVelocity = bulletToGLM(_body->getAngularVelocity());
|
||||
_lastStep = simulationStep;
|
||||
_sentActive = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -202,21 +217,26 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
|
||||
int numSteps = simulationStep - _lastStep;
|
||||
float dt = (float)(numSteps) * PHYSICS_ENGINE_FIXED_SUBSTEP;
|
||||
_lastStep = simulationStep;
|
||||
bool isActive = _body->isActive();
|
||||
|
||||
const float INACTIVE_UPDATE_PERIOD = 0.5f;
|
||||
if (!_sentActive) {
|
||||
// we resend the inactive update every INACTIVE_UPDATE_PERIOD
|
||||
// until it is removed from the outgoing updates
|
||||
// (which happens when we don't own the simulation and it isn't touching our simulation)
|
||||
return (dt > INACTIVE_UPDATE_PERIOD);
|
||||
}
|
||||
|
||||
bool isActive = _body->isActive();
|
||||
if (!isActive) {
|
||||
if (_sentMoving) {
|
||||
// this object just went inactive so send an update immediately
|
||||
return true;
|
||||
} else {
|
||||
const float NON_MOVING_UPDATE_PERIOD = 1.0f;
|
||||
if (dt > NON_MOVING_UPDATE_PERIOD && _numNonMovingUpdates < MAX_NUM_NON_MOVING_UPDATES) {
|
||||
// RELIABLE_SEND_HACK: since we're not yet using a reliable method for non-moving update packets we repeat these
|
||||
// at a faster rate than the MAX period above, and only send a limited number of them.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// object has gone inactive but our last send was moving --> send non-moving update immediately
|
||||
return true;
|
||||
}
|
||||
|
||||
_lastStep = simulationStep;
|
||||
if (glm::length2(_serverVelocity) > 0.0f) {
|
||||
_serverVelocity += _serverAcceleration * dt;
|
||||
_serverVelocity *= powf(1.0f - _body->getLinearDamping(), dt);
|
||||
_serverPosition += dt * _serverVelocity;
|
||||
}
|
||||
|
||||
// Else we measure the error between current and extrapolated transform (according to expected behavior
|
||||
|
@ -224,15 +244,10 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
|
||||
// NOTE: math is done in the simulation-frame, which is NOT necessarily the same as the world-frame
|
||||
// due to _worldOffset.
|
||||
// TODO: compensate for _worldOffset offset here
|
||||
|
||||
// compute position error
|
||||
if (glm::length2(_serverVelocity) > 0.0f) {
|
||||
_serverVelocity += _serverAcceleration * dt;
|
||||
_serverVelocity *= powf(1.0f - _body->getLinearDamping(), dt);
|
||||
_serverPosition += dt * _serverVelocity;
|
||||
}
|
||||
|
||||
// TODO: compensate for simulation offset here
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
|
||||
|
||||
|
@ -285,42 +300,50 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
return (fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT);
|
||||
}
|
||||
|
||||
bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) {
|
||||
if (!_entity || !remoteSimulationOutOfSync(simulationFrame)) {
|
||||
bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID) {
|
||||
// NOTE: we expect _entity and _body to be valid in this context, since shouldSendUpdate() is only called
|
||||
// after doesNotNeedToSendUpdate() returns false and that call should return 'true' if _entity or _body are NULL.
|
||||
assert(_entity);
|
||||
assert(_body);
|
||||
|
||||
if (!remoteSimulationOutOfSync(simulationStep)) {
|
||||
_candidateForOwnership = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getShouldClaimSimulationOwnership()) {
|
||||
if (_entity->getSimulatorID() == sessionID) {
|
||||
// we own the simulation
|
||||
_candidateForOwnership = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
const QUuid& simulatorID = _entity->getSimulatorID();
|
||||
|
||||
if (simulatorID != myNodeID) {
|
||||
// some other Node owns the simulating of this, so don't broadcast the results of local simulation.
|
||||
return false;
|
||||
const uint32_t FRAMES_BETWEEN_OWNERSHIP_CLAIMS = 30;
|
||||
if (_candidateForOwnership) {
|
||||
_candidateForOwnership = false;
|
||||
++_loopsSinceOwnershipBid;
|
||||
if (_loopsSinceOwnershipBid > FRAMES_BETWEEN_OWNERSHIP_CLAIMS) {
|
||||
// we don't own the simulation, but it's time to bid for it
|
||||
_loopsSinceOwnershipBid = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
_candidateForOwnership = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) {
|
||||
if (!_entity || !_entity->isKnownID()) {
|
||||
return; // never update entities that are unknown
|
||||
}
|
||||
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step) {
|
||||
assert(_entity);
|
||||
assert(_entity->isKnownID());
|
||||
|
||||
bool active = _body->isActive();
|
||||
if (!active) {
|
||||
if (_sentMoving) {
|
||||
// make sure all derivatives are zero
|
||||
glm::vec3 zero(0.0f);
|
||||
_entity->setVelocity(zero);
|
||||
_entity->setAngularVelocity(zero);
|
||||
_entity->setAcceleration(zero);
|
||||
}
|
||||
|
||||
// make sure all derivatives are zero
|
||||
glm::vec3 zero(0.0f);
|
||||
_entity->setVelocity(zero);
|
||||
_entity->setAngularVelocity(zero);
|
||||
_entity->setAcceleration(zero);
|
||||
_sentActive = false;
|
||||
} else {
|
||||
float gravityLength = glm::length(_entity->getGravity());
|
||||
float accVsGravity = glm::abs(glm::length(_measuredAcceleration) - gravityLength);
|
||||
|
@ -343,6 +366,21 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
} else {
|
||||
_entity->setAcceleration(glm::vec3(0.0f));
|
||||
}
|
||||
|
||||
const float DYNAMIC_LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec
|
||||
const float DYNAMIC_ANGULAR_VELOCITY_THRESHOLD = 0.087266f; // ~5 deg/sec
|
||||
bool movingSlowly = glm::length2(_entity->getVelocity()) < (DYNAMIC_LINEAR_VELOCITY_THRESHOLD * DYNAMIC_LINEAR_VELOCITY_THRESHOLD)
|
||||
&& glm::length2(_entity->getAngularVelocity()) < (DYNAMIC_ANGULAR_VELOCITY_THRESHOLD * DYNAMIC_ANGULAR_VELOCITY_THRESHOLD)
|
||||
&& _entity->getAcceleration() == glm::vec3(0.0f);
|
||||
|
||||
if (movingSlowly) {
|
||||
// velocities might not be zero, but we'll fake them as such, which will hopefully help convince
|
||||
// other simulating observers to deactivate their own copies
|
||||
glm::vec3 zero(0.0f);
|
||||
_entity->setVelocity(zero);
|
||||
_entity->setAngularVelocity(zero);
|
||||
}
|
||||
_sentActive = true;
|
||||
}
|
||||
|
||||
// remember properties for local server prediction
|
||||
|
@ -352,59 +390,41 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
_serverAcceleration = _entity->getAcceleration();
|
||||
_serverAngularVelocity = _entity->getAngularVelocity();
|
||||
|
||||
_sentMoving = _serverVelocity != glm::vec3(0.0f) || _serverAngularVelocity != glm::vec3(0.0f);
|
||||
|
||||
EntityItemProperties properties = _entity->getProperties();
|
||||
|
||||
// explicitly set the properties that changed
|
||||
// explicitly set the properties that changed so that they will be packed
|
||||
properties.setPosition(_serverPosition);
|
||||
properties.setRotation(_serverRotation);
|
||||
properties.setVelocity(_serverVelocity);
|
||||
properties.setAcceleration(_serverAcceleration);
|
||||
properties.setAngularVelocity(_serverAngularVelocity);
|
||||
|
||||
// RELIABLE_SEND_HACK: count number of updates for entities at rest
|
||||
// so we can stop sending them after some limit.
|
||||
if (_sentMoving) {
|
||||
_numNonMovingUpdates = 0;
|
||||
// we only update lastEdited when we're sending new physics data
|
||||
quint64 lastSimulated = _entity->getLastSimulated();
|
||||
_entity->setLastEdited(lastSimulated);
|
||||
properties.setLastEdited(lastSimulated);
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(physics) << "EntityMotionState::sendUpdate()";
|
||||
qCDebug(physics) << " EntityItemId:" << _entity->getEntityItemID()
|
||||
<< "---------------------------------------------";
|
||||
qCDebug(physics) << " lastSimulated:" << debugTime(lastSimulated, now);
|
||||
#endif //def WANT_DEBUG
|
||||
|
||||
if (sessionID == _entity->getSimulatorID()) {
|
||||
// we think we own the simulation
|
||||
if (!active) {
|
||||
// we own the simulation but the entity has stopped, so we tell the server that we're clearing simulatorID
|
||||
// but we remember that we do still own it... and rely on the server to tell us that we don't
|
||||
properties.setSimulatorID(QUuid());
|
||||
} else {
|
||||
// explicitly set the property's simulatorID so that it is flagged as changed and will be packed
|
||||
properties.setSimulatorID(sessionID);
|
||||
}
|
||||
} else {
|
||||
_numNonMovingUpdates++;
|
||||
}
|
||||
if (_numNonMovingUpdates <= 1) {
|
||||
// we only update lastEdited when we're sending new physics data
|
||||
quint64 lastSimulated = _entity->getLastSimulated();
|
||||
_entity->setLastEdited(lastSimulated);
|
||||
properties.setLastEdited(lastSimulated);
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(physics) << "EntityMotionState::sendUpdate()";
|
||||
qCDebug(physics) << " EntityItemId:" << _entity->getEntityItemID()
|
||||
<< "---------------------------------------------";
|
||||
qCDebug(physics) << " lastSimulated:" << debugTime(lastSimulated, now);
|
||||
#endif //def WANT_DEBUG
|
||||
|
||||
} else {
|
||||
properties.setLastEdited(_entity->getLastEdited());
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
QUuid myNodeID = nodeList->getSessionUUID();
|
||||
QUuid simulatorID = _entity->getSimulatorID();
|
||||
|
||||
if (getShouldClaimSimulationOwnership()) {
|
||||
// we think we should own it, so we tell the server that we do,
|
||||
// but we don't remember that we own it...
|
||||
// instead we expect the sever to tell us later whose ownership it has accepted
|
||||
properties.setSimulatorID(myNodeID);
|
||||
setShouldClaimSimulationOwnership(false);
|
||||
} else if (simulatorID == myNodeID
|
||||
&& !_sentMoving
|
||||
&& _numNonMovingUpdates == MAX_NUM_NON_MOVING_UPDATES) {
|
||||
// we own it, the entity has stopped, and we're sending the last non-moving update
|
||||
// --> give up ownership
|
||||
_entity->setSimulatorID(QUuid());
|
||||
properties.setSimulatorID(QUuid());
|
||||
// we don't own the simulation for this entity yet, but we're sending a bid for it
|
||||
properties.setSimulatorID(sessionID);
|
||||
}
|
||||
|
||||
if (EntityItem::getSendPhysicsUpdates()) {
|
||||
|
@ -453,7 +473,7 @@ QUuid EntityMotionState::getSimulatorID() const {
|
|||
|
||||
// virtual
|
||||
void EntityMotionState::bump() {
|
||||
setShouldClaimSimulationOwnership(true);
|
||||
_candidateForOwnership = true;
|
||||
}
|
||||
|
||||
void EntityMotionState::resetMeasuredBodyAcceleration() {
|
||||
|
|
|
@ -36,7 +36,6 @@ public:
|
|||
virtual MotionType computeObjectMotionType() const;
|
||||
|
||||
virtual bool isMoving() const;
|
||||
virtual bool isMovingVsServer() const;
|
||||
|
||||
// this relays incoming position/rotation to the RigidBody
|
||||
virtual void getWorldTransform(btTransform& worldTrans) const;
|
||||
|
@ -46,13 +45,10 @@ public:
|
|||
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo);
|
||||
|
||||
bool doesNotNeedToSendUpdate() const;
|
||||
bool isCandidateForOwnership(const QUuid& sessionID) const;
|
||||
bool remoteSimulationOutOfSync(uint32_t simulationStep);
|
||||
bool shouldSendUpdate(uint32_t simulationFrame);
|
||||
void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step);
|
||||
|
||||
void setShouldClaimSimulationOwnership(bool value) { _shouldClaimSimulationOwnership = value; }
|
||||
bool getShouldClaimSimulationOwnership() { return _shouldClaimSimulationOwnership; }
|
||||
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
|
||||
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
|
||||
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() const;
|
||||
|
||||
|
@ -92,7 +88,7 @@ protected:
|
|||
|
||||
EntityItem* _entity;
|
||||
|
||||
bool _sentMoving; // true if last update was moving
|
||||
bool _sentActive; // true if body was active when we sent last update
|
||||
int _numNonMovingUpdates; // RELIABLE_SEND_HACK for "not so reliable" resends of packets for non-moving objects
|
||||
|
||||
// these are for the prediction of the remote server's simple extrapolation
|
||||
|
@ -109,8 +105,9 @@ protected:
|
|||
glm::vec3 _measuredAcceleration;
|
||||
|
||||
quint8 _accelerationNearlyGravityCount;
|
||||
bool _shouldClaimSimulationOwnership;
|
||||
quint32 _movingStepsWithoutSimulationOwner;
|
||||
bool _candidateForOwnership;
|
||||
uint32_t _loopsSinceOwnershipBid;
|
||||
uint32_t _loopsWithoutOwner;
|
||||
};
|
||||
|
||||
#endif // hifi_EntityMotionState_h
|
||||
|
|
|
@ -146,10 +146,6 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags) {
|
|||
_body->setMassProps(mass, inertia);
|
||||
_body->updateInertiaTensor();
|
||||
}
|
||||
|
||||
if (flags & EntityItem::DIRTY_PHYSICS_ACTIVATION) {
|
||||
_body->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
|
||||
|
|
|
@ -36,11 +36,11 @@ enum MotionStateType {
|
|||
// and re-added to the physics engine and "easy" which just updates the body properties.
|
||||
const uint32_t HARD_DIRTY_PHYSICS_FLAGS = (uint32_t)(EntityItem::DIRTY_MOTION_TYPE | EntityItem::DIRTY_SHAPE);
|
||||
const uint32_t EASY_DIRTY_PHYSICS_FLAGS = (uint32_t)(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES |
|
||||
EntityItem::DIRTY_MASS | EntityItem::DIRTY_COLLISION_GROUP |
|
||||
EntityItem::DIRTY_MATERIAL | EntityItem::DIRTY_PHYSICS_ACTIVATION);
|
||||
EntityItem::DIRTY_MASS | EntityItem::DIRTY_COLLISION_GROUP);
|
||||
|
||||
// These are the set of incoming flags that the PhysicsEngine needs to hear about:
|
||||
const uint32_t DIRTY_PHYSICS_FLAGS = HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS;
|
||||
const uint32_t DIRTY_PHYSICS_FLAGS = HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS |
|
||||
EntityItem::DIRTY_MATERIAL | (uint32_t)EntityItem::DIRTY_PHYSICS_ACTIVATION;
|
||||
|
||||
// These are the outgoing flags that the PhysicsEngine can affect:
|
||||
const uint32_t OUTGOING_DIRTY_PHYSICS_FLAGS = EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES;
|
||||
|
|
|
@ -188,7 +188,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToChange() {
|
|||
return _tempVector;
|
||||
}
|
||||
|
||||
void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motionStates) {
|
||||
void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motionStates, const QUuid& sessionID) {
|
||||
// walk the motionStates looking for those that correspond to entities
|
||||
for (auto stateItr : motionStates) {
|
||||
ObjectMotionState* state = &(*stateItr);
|
||||
|
@ -196,24 +196,32 @@ void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motio
|
|||
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
|
||||
EntityItem* entity = entityState->getEntity();
|
||||
if (entity) {
|
||||
_outgoingChanges.insert(entityState);
|
||||
if (entity->isKnownID() && entityState->isCandidateForOwnership(sessionID)) {
|
||||
_outgoingChanges.insert(entityState);
|
||||
}
|
||||
_entitiesToSort.insert(entityState->getEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send outgoing packets
|
||||
uint32_t numSubsteps = _physicsEngine->getNumSubsteps();
|
||||
if (_lastStepSendPackets != numSubsteps) {
|
||||
_lastStepSendPackets = numSubsteps;
|
||||
|
||||
if (sessionID.isNull()) {
|
||||
// usually don't get here, but if so --> nothing to do
|
||||
_outgoingChanges.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// send outgoing packets
|
||||
QSet<EntityMotionState*>::iterator stateItr = _outgoingChanges.begin();
|
||||
while (stateItr != _outgoingChanges.end()) {
|
||||
EntityMotionState* state = *stateItr;
|
||||
if (state->doesNotNeedToSendUpdate()) {
|
||||
if (!state->isCandidateForOwnership(sessionID)) {
|
||||
stateItr = _outgoingChanges.erase(stateItr);
|
||||
} else if (state->shouldSendUpdate(numSubsteps)) {
|
||||
state->sendUpdate(_entityPacketSender, numSubsteps);
|
||||
} else if (state->shouldSendUpdate(numSubsteps, sessionID)) {
|
||||
state->sendUpdate(_entityPacketSender, sessionID, numSubsteps);
|
||||
++stateItr;
|
||||
} else {
|
||||
++stateItr;
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
VectorOfMotionStates& getObjectsToAdd();
|
||||
VectorOfMotionStates& getObjectsToChange();
|
||||
|
||||
void handleOutgoingChanges(VectorOfMotionStates& motionStates);
|
||||
void handleOutgoingChanges(VectorOfMotionStates& motionStates, const QUuid& sessionID);
|
||||
void handleCollisionEvents(CollisionEvents& collisionEvents);
|
||||
|
||||
private:
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
void init();
|
||||
|
||||
void setSessionUUID(const QUuid& sessionID) { _sessionID = sessionID; }
|
||||
const QUuid& getSessionID() const { return _sessionID; }
|
||||
|
||||
void addObject(ObjectMotionState* motionState);
|
||||
void removeObject(ObjectMotionState* motionState);
|
||||
|
|
|
@ -15,36 +15,48 @@
|
|||
#include "BulletUtil.h"
|
||||
|
||||
|
||||
// find the average point on a convex shape
|
||||
glm::vec3 findCenter(const QVector<glm::vec3>& points) {
|
||||
glm::vec3 result = glm::vec3(0);
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
result += points[i];
|
||||
|
||||
btConvexHullShape* ShapeInfoUtil::createConvexHull(const QVector<glm::vec3>& points) {
|
||||
assert(points.size() > 0);
|
||||
|
||||
btConvexHullShape* hull = new btConvexHullShape();
|
||||
glm::vec3 center = points[0];
|
||||
glm::vec3 maxCorner = center;
|
||||
glm::vec3 minCorner = center;
|
||||
for (int i = 1; i < points.size(); i++) {
|
||||
center += points[i];
|
||||
maxCorner = glm::max(maxCorner, points[i]);
|
||||
minCorner = glm::min(minCorner, points[i]);
|
||||
}
|
||||
return result * (1.0f / points.size());
|
||||
}
|
||||
center /= (float)(points.size());
|
||||
|
||||
float margin = hull->getMargin();
|
||||
|
||||
// bullet puts "margins" around all the collision shapes. This can cause shapes will hulls
|
||||
// to float a bit above what they are sitting on, etc. One option is to call:
|
||||
//
|
||||
// compound->setMargin(0.01);
|
||||
//
|
||||
// to reduce the size of the margin, but this has some consequences for the
|
||||
// performance and stability of the simulation. Instead, we clench in all the points of
|
||||
// the hull by the margin. These clenched points + bullets margin will but the actual
|
||||
// collision hull fairly close to the visual edge of the object.
|
||||
QVector<glm::vec3> shrinkByMargin(const QVector<glm::vec3>& points, const glm::vec3 center, float margin) {
|
||||
QVector<glm::vec3> result(points.size());
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
glm::vec3 pVec = points[ i ] - center;
|
||||
glm::vec3 pVecNorm = glm::normalize(pVec);
|
||||
result[ i ] = center + pVec - (pVecNorm * margin);
|
||||
// Bullet puts "margins" around all the collision shapes. This can cause objects that use ConvexHull shapes
|
||||
// to have visible gaps between them and the surface they touch. One option is to reduce the size of the margin
|
||||
// but this can reduce the performance and stability of the simulation (e.g. the GJK algorithm will fail to provide
|
||||
// nearest contact points and narrow-phase collisions will fall into more expensive code paths). Alternatively
|
||||
// one can shift the geometry of the shape to make the margin surface approximately close to the visible surface.
|
||||
// This is the strategy we try, but if the object is too small then we start to reduce the margin down to some minimum.
|
||||
|
||||
const float MIN_MARGIN = 0.01f;
|
||||
glm::vec3 diagonal = maxCorner - minCorner;
|
||||
float minDimension = glm::min(diagonal[0], diagonal[1]);
|
||||
minDimension = glm::min(minDimension, diagonal[2]);
|
||||
margin = glm::min(glm::max(0.5f * minDimension, MIN_MARGIN), margin);
|
||||
hull->setMargin(margin);
|
||||
|
||||
// add the points, correcting for margin
|
||||
glm::vec3 relativeScale = (diagonal - glm::vec3(2.0f * margin)) / diagonal;
|
||||
glm::vec3 correctedPoint;
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
correctedPoint = (points[i] - center) * relativeScale + center;
|
||||
hull->addPoint(btVector3(correctedPoint[0], correctedPoint[1], correctedPoint[2]), false);
|
||||
}
|
||||
return result;
|
||||
hull->recalcLocalAabb();
|
||||
return hull;
|
||||
}
|
||||
|
||||
|
||||
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
||||
btCollisionShape* shape = NULL;
|
||||
switch(info.getType()) {
|
||||
|
@ -68,30 +80,14 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
|||
const QVector<QVector<glm::vec3>>& points = info.getPoints();
|
||||
uint32_t numSubShapes = info.getNumSubShapes();
|
||||
if (numSubShapes == 1) {
|
||||
auto hull = new btConvexHullShape();
|
||||
const QVector<QVector<glm::vec3>>& points = info.getPoints();
|
||||
glm::vec3 center = findCenter(points[0]);
|
||||
QVector<glm::vec3> shrunken = shrinkByMargin(points[0], center, hull->getMargin());
|
||||
foreach (glm::vec3 point, shrunken) {
|
||||
btVector3 btPoint(point[0], point[1], point[2]);
|
||||
hull->addPoint(btPoint, false);
|
||||
}
|
||||
hull->recalcLocalAabb();
|
||||
shape = hull;
|
||||
shape = createConvexHull(info.getPoints()[0]);
|
||||
} else {
|
||||
assert(numSubShapes > 1);
|
||||
auto compound = new btCompoundShape();
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
foreach (QVector<glm::vec3> hullPoints, points) {
|
||||
auto hull = new btConvexHullShape();
|
||||
glm::vec3 center = findCenter(points[0]);
|
||||
QVector<glm::vec3> shrunken = shrinkByMargin(hullPoints, center, hull->getMargin());
|
||||
foreach (glm::vec3 point, shrunken) {
|
||||
btVector3 btPoint(point[0], point[1], point[2]);
|
||||
hull->addPoint(btPoint, false);
|
||||
}
|
||||
hull->recalcLocalAabb();
|
||||
btConvexHullShape* hull = createConvexHull(hullPoints);
|
||||
compound->addChildShape (trans, hull);
|
||||
}
|
||||
shape = compound;
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
// TODO: rename this to ShapeFactory
|
||||
namespace ShapeInfoUtil {
|
||||
|
||||
btConvexHullShape* createConvexHull(const QVector<glm::vec3>& points);
|
||||
|
||||
btCollisionShape* createShapeFromInfo(const ShapeInfo& info);
|
||||
};
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@ vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal,
|
|||
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
|
||||
vec3 color = diffuse.rgb * evalSkyboxLight(fragNormal, 0.75).xyz * getLightAmbientIntensity(light);
|
||||
|
||||
vec3 color = diffuse.rgb * evalSphericalLight(ambientSphere, fragNormal).xyz * getLightAmbientIntensity(light);
|
||||
|
||||
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||
|
||||
color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
||||
|
|
|
@ -291,7 +291,12 @@ void DeferredLightingEffect::render() {
|
|||
auto globalLight = _allocatedLights[_globalLights.front()];
|
||||
|
||||
if (locations->ambientSphere >= 0) {
|
||||
auto sh = globalLight->getAmbientSphere();
|
||||
model::SphericalHarmonics sh;
|
||||
if (useSkyboxCubemap) {
|
||||
sh = _skybox->getIrradianceSH();
|
||||
} else {
|
||||
sh = globalLight->getAmbientSphere();
|
||||
}
|
||||
for (int i =0; i <model::SphericalHarmonics::NUM_COEFFICIENTS; i++) {
|
||||
program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i));
|
||||
}
|
||||
|
|
|
@ -142,22 +142,12 @@ gpu::FramebufferPointer GlowEffect::render() {
|
|||
gpu::FramebufferPointer destFBO = textureCache->getSecondaryFramebuffer();
|
||||
if (!_enabled || _isEmpty) {
|
||||
// copy the primary to the screen
|
||||
if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO);
|
||||
glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(),
|
||||
0, 0, framebufferSize.width(), framebufferSize.height(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
} else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
|
||||
glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_LIGHTING);
|
||||
renderFullscreenQuad();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_LIGHTING);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO);
|
||||
glBlitFramebuffer(
|
||||
0, 0, framebufferSize.width(), framebufferSize.height(),
|
||||
0, 0, framebufferSize.width(), framebufferSize.height(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
} else {
|
||||
// diffuse into the secondary/tertiary (alternating between frames)
|
||||
auto oldDiffusedFBO =
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "MatrixStack.h"
|
43
libraries/render-utils/src/OffscreenGlContext.cpp
Normal file
43
libraries/render-utils/src/OffscreenGlContext.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// OffscreenGlCanvas.cpp
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2014/04/09.
|
||||
// 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 "OffscreenGlContext.h"
|
||||
|
||||
OffscreenGlContext::OffscreenGlContext() {
|
||||
}
|
||||
|
||||
void OffscreenGlContext::create(QOpenGLContext * sharedContext) {
|
||||
QSurfaceFormat format;
|
||||
format.setDepthBufferSize(16);
|
||||
format.setStencilBufferSize(8);
|
||||
format.setMajorVersion(4);
|
||||
format.setMinorVersion(1);
|
||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
|
||||
|
||||
_context.setFormat(format);
|
||||
if (nullptr != sharedContext) {
|
||||
_context.setShareContext(sharedContext);
|
||||
}
|
||||
_context.create();
|
||||
|
||||
_offscreenSurface.setFormat(_context.format());
|
||||
_offscreenSurface.create();
|
||||
}
|
||||
|
||||
bool OffscreenGlContext::makeCurrent() {
|
||||
return _context.makeCurrent(&_offscreenSurface);
|
||||
}
|
||||
|
||||
void OffscreenGlContext::doneCurrent() {
|
||||
_context.doneCurrent();
|
||||
}
|
||||
|
33
libraries/render-utils/src/OffscreenGlContext.h
Normal file
33
libraries/render-utils/src/OffscreenGlContext.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// OffscreenGlCanvas.h
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2014/04/09.
|
||||
// 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
|
||||
//
|
||||
#pragma once
|
||||
#ifndef hifi_OffscreenGlContext_h
|
||||
#define hifi_OffscreenGlContext_h
|
||||
|
||||
#include <QOpenGLContext>
|
||||
#include <QOffscreenSurface>
|
||||
|
||||
class OffscreenGlContext : public QObject {
|
||||
public:
|
||||
OffscreenGlContext();
|
||||
void create(QOpenGLContext * sharedContext = nullptr);
|
||||
bool makeCurrent();
|
||||
void doneCurrent();
|
||||
QOpenGLContext * getContext() {
|
||||
return &_context;
|
||||
}
|
||||
|
||||
protected:
|
||||
QOpenGLContext _context;
|
||||
QOffscreenSurface _offscreenSurface;
|
||||
};
|
||||
|
||||
#endif // hifi_OffscreenGlCanvas_h
|
|
@ -374,3 +374,6 @@ void OffscreenQmlSurface::setProxyWindow(QWindow* window) {
|
|||
_renderControl->_renderWindow = window;
|
||||
}
|
||||
|
||||
QQuickWindow* OffscreenQmlSurface::getWindow() {
|
||||
return _quickWindow;
|
||||
}
|
|
@ -71,6 +71,7 @@ public:
|
|||
|
||||
void setBaseUrl(const QUrl& baseUrl);
|
||||
QQuickItem* getRootItem();
|
||||
QQuickWindow* getWindow();
|
||||
|
||||
virtual bool eventFilter(QObject* originalDestination, QEvent* event);
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_RenderUtil_h
|
||||
#define hifi_RenderUtil_h
|
||||
|
||||
#include <MatrixStack.h>
|
||||
|
||||
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, tMin) to (sMax, tMax).
|
||||
void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f, float tMin = 0.0f, float tMax = 1.0f);
|
||||
|
||||
|
|
|
@ -548,18 +548,23 @@ float TextRenderer::draw(float x, float y, const QString & str,
|
|||
|
||||
float scale = (_pointSize / DEFAULT_POINT_SIZE) * 0.25f;
|
||||
glm::vec2 result;
|
||||
MatrixStack::withGlMatrices([&] {
|
||||
|
||||
MatrixStack::withPushAll([&] {
|
||||
MatrixStack & mv = MatrixStack::modelview();
|
||||
// scale the modelview into font units
|
||||
// FIXME migrate the constant scale factor into the geometry of the
|
||||
// fonts so we don't have to flip the Y axis here and don't have to
|
||||
// scale at all.
|
||||
mv.translate(glm::vec2(x, y)).scale(glm::vec3(scale, -scale, scale));
|
||||
// The font does all the OpenGL work
|
||||
if (_font) {
|
||||
result = _font->drawString(x, y, str, actualColor, _effectType, bounds / scale);
|
||||
}
|
||||
});
|
||||
MatrixStack & pr = MatrixStack::projection();
|
||||
gpu::GLBackend::fetchMatrix(GL_MODELVIEW_MATRIX, mv.top());
|
||||
gpu::GLBackend::fetchMatrix(GL_PROJECTION_MATRIX, pr.top());
|
||||
|
||||
// scale the modelview into font units
|
||||
// FIXME migrate the constant scale factor into the geometry of the
|
||||
// fonts so we don't have to flip the Y axis here and don't have to
|
||||
// scale at all.
|
||||
mv.translate(glm::vec2(x, y)).scale(glm::vec3(scale, -scale, scale));
|
||||
// The font does all the OpenGL work
|
||||
if (_font) {
|
||||
result = _font->drawString(x, y, str, actualColor, _effectType, bounds / scale);
|
||||
}
|
||||
});
|
||||
return result.x;
|
||||
}
|
||||
|
||||
|
|
|
@ -514,7 +514,8 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
|
|||
|
||||
if ((_width > 0) && (_height > 0)) {
|
||||
|
||||
bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
||||
// bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
||||
bool isLinearRGB = !(_type == CUBE_TEXTURE); //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
||||
|
||||
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
||||
gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
||||
|
@ -602,6 +603,45 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
|
|||
faces.push_back(image.copy(QRect(3 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
// Front = -Z
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
|
||||
} else if ((_height / 4) == (_width / 3)) {
|
||||
int faceWidth = _height / 4;
|
||||
|
||||
// Here is the expected layout for the faces in an image with the 4/3 aspect ratio:
|
||||
//
|
||||
// <-------WIDTH-------->
|
||||
// ^ +------+------+------+
|
||||
// | | | | |
|
||||
// | | | +Y | |
|
||||
// | | | | |
|
||||
// H +------+------+------+
|
||||
// E | | | |
|
||||
// I | -X | -Z | +X |
|
||||
// G | | | |
|
||||
// H +------+------+------+
|
||||
// T | | | |
|
||||
// | | | -Y | |
|
||||
// | | | | |
|
||||
// | +------+------+------+
|
||||
// | | | | |
|
||||
// | | | +Z! | | <+Z is upside down!
|
||||
// | | | | |
|
||||
// V +------+------+------+
|
||||
//
|
||||
// FaceWidth = width / 3 = height / 4
|
||||
|
||||
// Right = +X
|
||||
faces.push_back(image.copy(QRect(2 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
// Left = -X
|
||||
faces.push_back(image.copy(QRect(0 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
// Top = +Y
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, 0, faceWidth, faceWidth)).mirrored(false, true));
|
||||
// Bottom = -Y
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, 2 * faceWidth, faceWidth, faceWidth)).mirrored(false, true));
|
||||
// Back = +Z
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, 3 * faceWidth, faceWidth, faceWidth)).mirrored(false, true));
|
||||
// Front = -Z
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
}
|
||||
|
||||
if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) {
|
||||
|
|
|
@ -24,7 +24,7 @@ MenuItemProperties::MenuItemProperties() :
|
|||
afterItem(""),
|
||||
isCheckable(false),
|
||||
isChecked(false),
|
||||
isSeparator(false)
|
||||
isSeparator(false)
|
||||
{
|
||||
};
|
||||
|
||||
|
|
22
libraries/shared/src/BackgroundMode.h
Normal file
22
libraries/shared/src/BackgroundMode.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// BackgroundMode.h
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// 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_BackgroundMode_h
|
||||
#define hifi_BackgroundMode_h
|
||||
|
||||
enum BackgroundMode {
|
||||
BACKGROUND_MODE_INHERIT,
|
||||
BACKGROUND_MODE_ATMOSPHERE,
|
||||
BACKGROUND_MODE_SKYBOX,
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_BackgroundMode_h
|
||||
|
9
libraries/shared/src/MatrixStack.cpp
Normal file
9
libraries/shared/src/MatrixStack.cpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis
|
||||
// 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 "MatrixStack.h"
|
|
@ -1,21 +1,10 @@
|
|||
/************************************************************************************
|
||||
|
||||
Authors : Bradley Austin Davis <bdavis@saintandreas.org>
|
||||
Copyright : Copyright Brad Davis. All Rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
************************************************************************************/
|
||||
//
|
||||
// Created by Bradley Austin Davis
|
||||
// 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
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <glm/glm.hpp>
|
||||
|
@ -26,10 +15,6 @@
|
|||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <stack>
|
||||
|
||||
#include <gpu/GPUConfig.h>
|
||||
|
||||
|
||||
|
||||
class MatrixStack : public std::stack<glm::mat4> {
|
||||
|
||||
public:
|
||||
|
@ -183,22 +168,5 @@ public:
|
|||
stack2.withPush(f);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
static void withGlMatrices(Function f) {
|
||||
// Push the current stack, and then copy the values out of OpenGL
|
||||
withPushAll([&] {
|
||||
// Fetch the current matrices out of GL stack
|
||||
// FIXME, eliminate the usage of deprecated GL
|
||||
MatrixStack & mv = MatrixStack::modelview();
|
||||
MatrixStack & pr = MatrixStack::projection();
|
||||
glm::mat4 & mvm = mv.top();
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, &(mvm[0][0]));
|
||||
|
||||
glm::mat4 & prm = pr.top();
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, &(prm[0][0]));
|
||||
f();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -103,7 +103,7 @@ void EntityTests::entityTreeTests(bool verbose) {
|
|||
|
||||
properties.setPosition(newPosition);
|
||||
|
||||
tree.updateEntity(entityID, properties, true);
|
||||
tree.updateEntity(entityID, properties);
|
||||
|
||||
float targetRadius = oneMeter * 2.0f;
|
||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOrigin, targetRadius);
|
||||
|
@ -143,7 +143,7 @@ void EntityTests::entityTreeTests(bool verbose) {
|
|||
|
||||
properties.setPosition(newPosition);
|
||||
|
||||
tree.updateEntity(entityID, properties, true);
|
||||
tree.updateEntity(entityID, properties);
|
||||
|
||||
float targetRadius = oneMeter * 2.0f;
|
||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius);
|
||||
|
|
Loading…
Reference in a new issue