mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' into 20639
Conflicts: interface/src/Menu.h
This commit is contained in:
commit
83ab37be0f
9 changed files with 110 additions and 214 deletions
230
examples/edit.js
230
examples/edit.js
|
@ -291,22 +291,18 @@ var toolBar = (function () {
|
|||
var RESIZE_TIMEOUT = 120000; // 2 minutes
|
||||
var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL;
|
||||
function addModel(url) {
|
||||
var position;
|
||||
var entityID = createNewEntity({
|
||||
type: "Model",
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
modelURL: url
|
||||
}, false);
|
||||
|
||||
position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
var entityId = Entities.addEntity({
|
||||
type: "Model",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
modelURL: url
|
||||
});
|
||||
if (entityID) {
|
||||
print("Model added: " + url);
|
||||
|
||||
var checkCount = 0;
|
||||
function resize() {
|
||||
var entityProperties = Entities.getEntityProperties(entityId);
|
||||
var entityProperties = Entities.getEntityProperties(entityID);
|
||||
var naturalDimensions = entityProperties.naturalDimensions;
|
||||
|
||||
checkCount++;
|
||||
|
@ -318,21 +314,41 @@ var toolBar = (function () {
|
|||
print("Resize failed: timed out waiting for model (" + url + ") to load");
|
||||
}
|
||||
} else {
|
||||
Entities.editEntity(entityId, { dimensions: naturalDimensions });
|
||||
Entities.editEntity(entityID, { dimensions: naturalDimensions });
|
||||
|
||||
// Reset selection so that the selection overlays will be updated
|
||||
selectionManager.setSelections([entityId]);
|
||||
selectionManager.setSelections([entityID]);
|
||||
}
|
||||
}
|
||||
|
||||
selectionManager.setSelections([entityId]);
|
||||
selectionManager.setSelections([entityID]);
|
||||
|
||||
Script.setTimeout(resize, RESIZE_INTERVAL);
|
||||
} else {
|
||||
Window.alert("Can't add model: Model would be out of bounds.");
|
||||
}
|
||||
}
|
||||
|
||||
function createNewEntity(properties, dragOnCreate) {
|
||||
// Default to true if not passed in
|
||||
dragOnCreate = dragOnCreate == undefined ? true : dragOnCreate;
|
||||
|
||||
var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS;
|
||||
var position = getPositionToCreateEntity();
|
||||
var entityID = null;
|
||||
if (position != null) {
|
||||
position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions),
|
||||
properties.position = position;
|
||||
|
||||
entityID = Entities.addEntity(properties);
|
||||
if (dragOnCreate) {
|
||||
placingEntityID = entityID;
|
||||
}
|
||||
} else {
|
||||
Window.alert("Can't create " + properties.type + ": " + properties.type + " would be out of bounds.");
|
||||
}
|
||||
|
||||
return entityID;
|
||||
}
|
||||
|
||||
var newModelButtonDown = false;
|
||||
var browseMarketplaceButtonDown = false;
|
||||
that.mousePressEvent = function (event) {
|
||||
|
@ -363,127 +379,82 @@ var toolBar = (function () {
|
|||
}
|
||||
|
||||
if (newCubeButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = getPositionToCreateEntity();
|
||||
createNewEntity({
|
||||
type: "Box",
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
color: { red: 255, green: 0, blue: 0 }
|
||||
});
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
placingEntityID = Entities.addEntity({
|
||||
type: "Box",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
color: { red: 255, green: 0, blue: 0 }
|
||||
|
||||
});
|
||||
} else {
|
||||
Window.alert("Can't create box: Box would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newSphereButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = getPositionToCreateEntity();
|
||||
createNewEntity({
|
||||
type: "Sphere",
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
color: { red: 255, green: 0, blue: 0 }
|
||||
});
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
placingEntityID = Entities.addEntity({
|
||||
type: "Sphere",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
||||
dimensions: DEFAULT_DIMENSIONS,
|
||||
color: { red: 255, green: 0, blue: 0 }
|
||||
});
|
||||
} else {
|
||||
Window.alert("Can't create sphere: Sphere would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newLightButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = getPositionToCreateEntity();
|
||||
createNewEntity({
|
||||
type: "Light",
|
||||
dimensions: DEFAULT_LIGHT_DIMENSIONS,
|
||||
isSpotlight: false,
|
||||
color: { red: 150, green: 150, blue: 150 },
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
placingEntityID = Entities.addEntity({
|
||||
type: "Light",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_LIGHT_DIMENSIONS), DEFAULT_LIGHT_DIMENSIONS),
|
||||
dimensions: DEFAULT_LIGHT_DIMENSIONS,
|
||||
isSpotlight: false,
|
||||
color: { red: 150, green: 150, blue: 150 },
|
||||
constantAttenuation: 1,
|
||||
linearAttenuation: 0,
|
||||
quadraticAttenuation: 0,
|
||||
exponent: 0,
|
||||
cutoff: 180, // in degrees
|
||||
});
|
||||
|
||||
constantAttenuation: 1,
|
||||
linearAttenuation: 0,
|
||||
quadraticAttenuation: 0,
|
||||
exponent: 0,
|
||||
cutoff: 180, // in degrees
|
||||
});
|
||||
} else {
|
||||
Window.alert("Can't create Light: Light would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (newTextButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = getPositionToCreateEntity();
|
||||
createNewEntity({
|
||||
type: "Text",
|
||||
dimensions: { x: 0.65, y: 0.3, z: 0.01 },
|
||||
backgroundColor: { red: 64, green: 64, blue: 64 },
|
||||
textColor: { red: 255, green: 255, blue: 255 },
|
||||
text: "some text",
|
||||
lineHeight: 0.06
|
||||
});
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
placingEntityID = Entities.addEntity({
|
||||
type: "Text",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
||||
dimensions: { x: 0.65, y: 0.3, z: 0.01 },
|
||||
backgroundColor: { red: 64, green: 64, blue: 64 },
|
||||
textColor: { red: 255, green: 255, blue: 255 },
|
||||
text: "some text",
|
||||
lineHeight: 0.06
|
||||
});
|
||||
} else {
|
||||
Window.alert("Can't create box: Text would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newWebButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = getPositionToCreateEntity();
|
||||
createNewEntity({
|
||||
type: "Web",
|
||||
dimensions: { x: 1.6, y: 0.9, z: 0.01 },
|
||||
sourceUrl: "https://highfidelity.com/",
|
||||
});
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
placingEntityID = Entities.addEntity({
|
||||
type: "Web",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
||||
dimensions: { x: 1.6, y: 0.9, z: 0.01 },
|
||||
sourceUrl: "https://highfidelity.com/",
|
||||
});
|
||||
} else {
|
||||
Window.alert("Can't create Web Entity: would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newZoneButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = getPositionToCreateEntity();
|
||||
createNewEntity({
|
||||
type: "Zone",
|
||||
dimensions: { x: 10, y: 10, z: 10 },
|
||||
});
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
placingEntityID = Entities.addEntity({
|
||||
type: "Zone",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
||||
dimensions: { x: 10, y: 10, z: 10 },
|
||||
});
|
||||
} else {
|
||||
Window.alert("Can't create box: Text would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newPolyVoxButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = getPositionToCreateEntity();
|
||||
createNewEntity({
|
||||
type: "PolyVox",
|
||||
dimensions: { x: 10, y: 10, z: 10 },
|
||||
voxelVolumeSize: {x:16, y:16, z:16},
|
||||
voxelSurfaceStyle: 1
|
||||
});
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
placingEntityID = Entities.addEntity({
|
||||
type: "PolyVox",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS),
|
||||
DEFAULT_DIMENSIONS),
|
||||
dimensions: { x: 10, y: 10, z: 10 },
|
||||
voxelVolumeSize: {x:16, y:16, z:16},
|
||||
voxelSurfaceStyle: 1
|
||||
});
|
||||
} else {
|
||||
Window.alert("Can't create PolyVox: would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -666,7 +637,7 @@ function handleIdleMouse() {
|
|||
idleMouseTimerId = null;
|
||||
if (isActive) {
|
||||
highlightEntityUnderCursor(lastMousePosition, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function highlightEntityUnderCursor(position, accurateRay) {
|
||||
|
@ -837,15 +808,15 @@ function setupModelMenus() {
|
|||
}
|
||||
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Entity List...", shortcutKey: "CTRL+META+L", afterItem: "Models" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L",
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L",
|
||||
afterItem: "Entity List...", isCheckable: true, isChecked: true });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S",
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S",
|
||||
afterItem: "Allow Selecting of Large Models", isCheckable: true, isChecked: true });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L",
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L",
|
||||
afterItem: "Allow Selecting of Small Models", isCheckable: true });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities In Box", shortcutKey: "CTRL+SHIFT+META+A",
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities In Box", shortcutKey: "CTRL+SHIFT+META+A",
|
||||
afterItem: "Allow Selecting of Lights" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities Touching Box", shortcutKey: "CTRL+SHIFT+META+T",
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities Touching Box", shortcutKey: "CTRL+SHIFT+META+T",
|
||||
afterItem: "Select All Entities In Box" });
|
||||
|
||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
|
||||
|
@ -962,7 +933,7 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
|||
entities.splice(i, 1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
selectionManager.setSelections(entities);
|
||||
}
|
||||
|
@ -1038,17 +1009,29 @@ function handeMenuEvent(menuItem) {
|
|||
tooltip.show(false);
|
||||
}
|
||||
|
||||
// This function tries to find a reasonable position to place a new entity based on the camera
|
||||
// position. If a reasonable position within the world bounds can't be found, `null` will
|
||||
// be returned. The returned position will also take into account grid snapping settings.
|
||||
function getPositionToCreateEntity() {
|
||||
var distance = cameraManager.enabled ? cameraManager.zoomDistance : DEFAULT_ENTITY_DRAG_DROP_DISTANCE;
|
||||
var direction = Quat.getFront(Camera.orientation);
|
||||
var offset = Vec3.multiply(distance, direction);
|
||||
var position = Vec3.sum(Camera.position, offset);
|
||||
var placementPosition = Vec3.sum(Camera.position, offset);
|
||||
|
||||
position.x = Math.max(0, position.x);
|
||||
position.y = Math.max(0, position.y);
|
||||
position.z = Math.max(0, position.z);
|
||||
var cameraPosition = Camera.position;
|
||||
|
||||
return position;
|
||||
var cameraOutOfBounds = cameraPosition.x < 0 || cameraPosition.y < 0 || cameraPosition.z < 0;
|
||||
var placementOutOfBounds = placementPosition.x < 0 || placementPosition.y < 0 || placementPosition.z < 0;
|
||||
|
||||
if (cameraOutOfBounds && placementOutOfBounds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
placementPosition.x = Math.max(0, placementPosition.x);
|
||||
placementPosition.y = Math.max(0, placementPosition.y);
|
||||
placementPosition.z = Math.max(0, placementPosition.z);
|
||||
|
||||
return placementPosition;
|
||||
}
|
||||
|
||||
function importSVO(importURL) {
|
||||
|
@ -1064,17 +1047,18 @@ function importSVO(importURL) {
|
|||
|
||||
if (success) {
|
||||
var VERY_LARGE = 10000;
|
||||
var position = { x: 0, y: 0, z: 0};
|
||||
var position = { x: 0, y: 0, z: 0 };
|
||||
if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) {
|
||||
position = getPositionToCreateEntity();
|
||||
}
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
if (position != null) {
|
||||
var pastedEntityIDs = Clipboard.pasteEntities(position);
|
||||
|
||||
if (isActive) {
|
||||
selectionManager.setSelections(pastedEntityIDs);
|
||||
}
|
||||
Window.raiseMainWindow();
|
||||
|
||||
Window.raiseMainWindow();
|
||||
} else {
|
||||
Window.alert("Can't import objects: objects would be out of bounds.");
|
||||
}
|
||||
|
@ -1264,7 +1248,7 @@ PropertiesTool = function(opts) {
|
|||
if (data.properties.keyLightDirection !== undefined) {
|
||||
data.properties.keyLightDirection = Vec3.fromPolar(
|
||||
data.properties.keyLightDirection.x * DEGREES_TO_RADIANS, data.properties.keyLightDirection.y * DEGREES_TO_RADIANS);
|
||||
}
|
||||
}
|
||||
Entities.editEntity(selectionManager.selections[0], data.properties);
|
||||
if (data.properties.name != undefined) {
|
||||
entityListTool.sendUpdate();
|
||||
|
@ -1360,8 +1344,8 @@ PropertiesTool = function(opts) {
|
|||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
if (properties.type == "Zone") {
|
||||
var centerOfZone = properties.boundingBox.center;
|
||||
var atmosphereCenter = { x: centerOfZone.x,
|
||||
y: centerOfZone.y - properties.atmosphere.innerRadius,
|
||||
var atmosphereCenter = { x: centerOfZone.x,
|
||||
y: centerOfZone.y - properties.atmosphere.innerRadius,
|
||||
z: centerOfZone.z };
|
||||
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
|
|
|
@ -249,8 +249,6 @@ Menu::Menu() {
|
|||
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableCharacterController, 0, true,
|
||||
avatar, SLOT(updateMotionBehavior()));
|
||||
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ShiftHipsForIdleAnimations, 0, false,
|
||||
avatar, SLOT(updateMotionBehavior()));
|
||||
|
||||
MenuWrapper* viewMenu = addMenu("View");
|
||||
|
||||
|
|
|
@ -273,7 +273,6 @@ namespace MenuOption {
|
|||
const QString SimpleShadows = "Simple";
|
||||
const QString SixenseEnabled = "Enable Hydra Support";
|
||||
const QString SixenseMouseInput = "Enable Sixense Mouse Input";
|
||||
const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations";
|
||||
const QString SimulateEyeTracking = "Simulate";
|
||||
const QString SMIEyeTracking = "SMI Eye Tracking";
|
||||
const QString Stars = "Stars";
|
||||
|
|
|
@ -98,7 +98,6 @@ MyAvatar::MyAvatar() :
|
|||
_lookAtTargetAvatar(),
|
||||
_shouldRender(true),
|
||||
_billboardValid(false),
|
||||
_feetTouchFloor(true),
|
||||
_eyeContactTarget(LEFT_EYE),
|
||||
_realWorldFieldOfView("realWorldFieldOfView",
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
|
||||
|
@ -166,9 +165,6 @@ void MyAvatar::update(float deltaTime) {
|
|||
head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
|
||||
|
||||
simulate(deltaTime);
|
||||
if (_feetTouchFloor) {
|
||||
_skeletonModel.updateStandingFoot();
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::simulate(float deltaTime) {
|
||||
|
@ -1140,11 +1136,7 @@ glm::vec3 MyAvatar::getSkeletonPosition() const {
|
|||
// The avatar is rotated PI about the yAxis, so we have to correct for it
|
||||
// to get the skeleton offset contribution in the world-frame.
|
||||
const glm::quat FLIP = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glm::vec3 skeletonOffset = _skeletonOffset;
|
||||
if (_feetTouchFloor) {
|
||||
skeletonOffset += _skeletonModel.getStandingOffset();
|
||||
}
|
||||
return _position + getOrientation() * FLIP * skeletonOffset;
|
||||
return _position + getOrientation() * FLIP * _skeletonOffset;
|
||||
}
|
||||
return Avatar::getPosition();
|
||||
}
|
||||
|
@ -1622,7 +1614,6 @@ void MyAvatar::updateMotionBehavior() {
|
|||
_motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED;
|
||||
}
|
||||
_characterController.setEnabled(menu->isOptionChecked(MenuOption::EnableCharacterController));
|
||||
_feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations);
|
||||
}
|
||||
|
||||
//Renders sixense laser pointers for UI selection with controllers
|
||||
|
|
|
@ -258,7 +258,6 @@ private:
|
|||
|
||||
QList<AnimationHandlePointer> _animationHandles;
|
||||
|
||||
bool _feetTouchFloor;
|
||||
eyeContactTarget _eyeContactTarget;
|
||||
|
||||
RecorderPointer _recorder;
|
||||
|
|
|
@ -24,12 +24,6 @@
|
|||
#include "Util.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
enum StandingFootState {
|
||||
LEFT_FOOT,
|
||||
RIGHT_FOOT,
|
||||
NO_FOOT
|
||||
};
|
||||
|
||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
||||
Model(parent),
|
||||
_triangleFanID(DependencyManager::get<GeometryCache>()->allocateID()),
|
||||
|
@ -37,9 +31,6 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
|||
_boundingShape(),
|
||||
_boundingShapeLocalOffset(0.0f),
|
||||
_defaultEyeModelPosition(glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||
_standingFoot(NO_FOOT),
|
||||
_standingOffset(0.0f),
|
||||
_clampedFootPosition(0.0f),
|
||||
_headClipDistance(DEFAULT_NEAR_CLIP),
|
||||
_isFirstPerson(false)
|
||||
{
|
||||
|
@ -573,65 +564,6 @@ glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const {
|
|||
return _owningAvatar->getScale() * _defaultEyeModelPosition;
|
||||
}
|
||||
|
||||
/// \return offset of hips after foot animation
|
||||
void SkeletonModel::updateStandingFoot() {
|
||||
if (_geometry == NULL) {
|
||||
return;
|
||||
}
|
||||
glm::vec3 offset(0.0f);
|
||||
int leftFootIndex = _geometry->getFBXGeometry().leftToeJointIndex;
|
||||
int rightFootIndex = _geometry->getFBXGeometry().rightToeJointIndex;
|
||||
|
||||
if (leftFootIndex != -1 && rightFootIndex != -1) {
|
||||
glm::vec3 leftPosition, rightPosition;
|
||||
getJointPosition(leftFootIndex, leftPosition);
|
||||
getJointPosition(rightFootIndex, rightPosition);
|
||||
|
||||
int lowestFoot = (leftPosition.y < rightPosition.y) ? LEFT_FOOT : RIGHT_FOOT;
|
||||
const float MIN_STEP_HEIGHT_THRESHOLD = 0.05f;
|
||||
bool oneFoot = fabsf(leftPosition.y - rightPosition.y) > MIN_STEP_HEIGHT_THRESHOLD;
|
||||
int currentFoot = oneFoot ? lowestFoot : _standingFoot;
|
||||
|
||||
if (_standingFoot == NO_FOOT) {
|
||||
currentFoot = lowestFoot;
|
||||
}
|
||||
if (currentFoot != _standingFoot) {
|
||||
if (_standingFoot == NO_FOOT) {
|
||||
// pick the lowest foot
|
||||
glm::vec3 lowestPosition = (currentFoot == LEFT_FOOT) ? leftPosition : rightPosition;
|
||||
// we ignore zero length positions which can happen for a few frames until skeleton is fully loaded
|
||||
if (glm::length(lowestPosition) > 0.0f) {
|
||||
_standingFoot = currentFoot;
|
||||
_clampedFootPosition = lowestPosition;
|
||||
}
|
||||
} else {
|
||||
// swap feet
|
||||
_standingFoot = currentFoot;
|
||||
glm::vec3 nextPosition = leftPosition;
|
||||
glm::vec3 prevPosition = rightPosition;
|
||||
if (_standingFoot == RIGHT_FOOT) {
|
||||
nextPosition = rightPosition;
|
||||
prevPosition = leftPosition;
|
||||
}
|
||||
glm::vec3 oldOffset = _clampedFootPosition - prevPosition;
|
||||
_clampedFootPosition = oldOffset + nextPosition;
|
||||
offset = _clampedFootPosition - nextPosition;
|
||||
}
|
||||
} else {
|
||||
glm::vec3 nextPosition = (_standingFoot == LEFT_FOOT) ? leftPosition : rightPosition;
|
||||
offset = _clampedFootPosition - nextPosition;
|
||||
}
|
||||
|
||||
// clamp the offset to not exceed some max distance
|
||||
const float MAX_STEP_OFFSET = 1.0f;
|
||||
float stepDistance = glm::length(offset);
|
||||
if (stepDistance > MAX_STEP_OFFSET) {
|
||||
offset *= (MAX_STEP_OFFSET / stepDistance);
|
||||
}
|
||||
}
|
||||
_standingOffset = offset;
|
||||
}
|
||||
|
||||
float DENSITY_OF_WATER = 1000.0f; // kg/m^3
|
||||
float MIN_JOINT_MASS = 1.0f;
|
||||
float VERY_BIG_MASS = 1.0e6f;
|
||||
|
|
|
@ -96,10 +96,6 @@ public:
|
|||
/// \return whether or not the head was found.
|
||||
glm::vec3 getDefaultEyeModelPosition() const;
|
||||
|
||||
/// skeleton offset caused by moving feet
|
||||
void updateStandingFoot();
|
||||
const glm::vec3& getStandingOffset() const { return _standingOffset; }
|
||||
|
||||
void computeBoundingShape(const FBXGeometry& geometry);
|
||||
void renderBoundingCollisionShapes(gpu::Batch& batch, float alpha);
|
||||
float getBoundingShapeRadius() const { return _boundingShape.getRadius(); }
|
||||
|
@ -169,9 +165,6 @@ private:
|
|||
glm::vec3 _boundingShapeLocalOffset;
|
||||
|
||||
glm::vec3 _defaultEyeModelPosition;
|
||||
int _standingFoot;
|
||||
glm::vec3 _standingOffset;
|
||||
glm::vec3 _clampedFootPosition;
|
||||
|
||||
float _headClipDistance; // Near clip distance to use if no separate head model
|
||||
|
||||
|
|
|
@ -306,7 +306,8 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
|
|||
}
|
||||
QByteArray token = tokenizer.getDatum();
|
||||
//qCDebug(modelformat) << token;
|
||||
if (token == "g") {
|
||||
// we don't support separate objects in the same file, so treat "o" the same as "g".
|
||||
if (token == "g" || token == "o") {
|
||||
if (sawG) {
|
||||
// we've encountered the beginning of the next group.
|
||||
tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN);
|
||||
|
|
|
@ -215,7 +215,6 @@ public:
|
|||
SixenseEnabled,
|
||||
SixenseMouseInput,
|
||||
SixenseLasers,
|
||||
ShiftHipsForIdleAnimations,
|
||||
Stars,
|
||||
Stats,
|
||||
StereoAudio,
|
||||
|
|
Loading…
Reference in a new issue