Fix handle scaling entity with non-center registration point

This commit is contained in:
David Rowe 2017-07-19 17:51:36 +12:00
parent 5cb5c71966
commit f1fd6264f3

View file

@ -568,13 +568,9 @@
rootEntityID = null, rootEntityID = null,
rootPosition, rootPosition,
rootOrientation, rootOrientation,
scaleRootPosition,
scaleRootRegistrationPoint,
scaleRootRegistrationOffset,
scaleCenter, scaleCenter,
scaleRootOffset, scaleRootOffset,
scaleRootOrientation, scaleRootOrientation,
isRootCenterRegistration,
ENTITY_TYPE = "entity"; ENTITY_TYPE = "entity";
function traverseEntityTree(id, result) { function traverseEntityTree(id, result) {
@ -766,28 +762,20 @@
} }
function startHandleScaling() { function startHandleScaling() {
// Save initial position data so that can scale relative to these without accumulating float errors. // Nothing to do.
scaleRootPosition = rootPosition;
scaleRootRegistrationPoint = selection[0].registrationPoint;
isRootCenterRegistration = Vec3.equal(scaleRootRegistrationPoint, Vec3.HALF);
scaleRootRegistrationOffset = Vec3.subtract(scaleRootRegistrationPoint, Vec3.HALF);
} }
function handleScale(factor) { function handleScale(factor, position, orientation) {
// Scale selection about bounding box center. // Scale and reposition and orient selection.
// Scale and position root. // Scale and position root.
if (isRootCenterRegistration) { rootPosition = position;
Entities.editEntity(selection[0].id, { rootOrientation = orientation;
dimensions: Vec3.multiplyVbyV(factor, selection[0].dimensions) Entities.editEntity(selection[0].id, {
}); dimensions: Vec3.multiplyVbyV(factor, selection[0].dimensions),
} else { position: rootPosition,
rootPosition = Vec3.sum(scaleRootPosition, Vec3.multiplyVbyV(factor, scaleRootRegistrationOffset)); rotation: rootOrientation
Entities.editEntity(selection[0].id, { });
dimensions: Vec3.multiplyVbyV(factor, selection[0].dimensions),
position: rootPosition
});
}
// Scale and position children. // Scale and position children.
// TODO // TODO
@ -1260,7 +1248,9 @@
handleScaleDirections, handleScaleDirections,
handleHandOffset, handleHandOffset,
initialHandleDistance, initialHandleDistance,
initialHandleScaleOrientationInverse, initialHandleOrientationInverse,
initialHandleRegistrationOffset,
initialSelectionOrientationInverse,
intersection; intersection;
@ -1348,22 +1338,25 @@
// Keep grabbed handle highlighted and hide other handles. // Keep grabbed handle highlighted and hide other handles.
handles.grab(overlayID); handles.grab(overlayID);
handleUnitScaleAxis = handles.scalingAxis(overlayID); // Unit vector in direction of scaling.
handleScaleDirections = handles.scalingDirections(overlayID); // Which axes to scale the selection on.
// Vector from target to bounding box center. // Vector from target to bounding box center.
initialTargetPosition = getScaleTargetPosition(); initialTargetPosition = getScaleTargetPosition();
boundingBox = selection.boundingBox(); boundingBox = selection.boundingBox();
initialTargetToBoundingBoxCenter = Vec3.subtract(boundingBox.center, initialTargetPosition); initialTargetToBoundingBoxCenter = Vec3.subtract(boundingBox.center, initialTargetPosition);
// Initial hand orientation. // Selection information.
initialHandleScaleOrientationInverse = Quat.inverse(hand.orientation()); selectionPositionAndOrientation = selection.getPositionAndOrientation();
initialSelectionOrientationInverse = Quat.inverse(selectionPositionAndOrientation.orientation);
// Distance from handle to bounding box center. // Handle information.
initialHandleOrientationInverse = Quat.inverse(hand.orientation());
handleUnitScaleAxis = handles.scalingAxis(overlayID); // Unit vector in direction of scaling.
handleScaleDirections = handles.scalingDirections(overlayID); // Which axes to scale the selection on.
initialHandleDistance = Vec3.length(Vec3.multiplyVbyV(boundingBox.dimensions, handleScaleDirections)) / 2; initialHandleDistance = Vec3.length(Vec3.multiplyVbyV(boundingBox.dimensions, handleScaleDirections)) / 2;
initialHandleRegistrationOffset = Vec3.multiplyQbyV(initialSelectionOrientationInverse,
Vec3.subtract(selectionPositionAndOrientation.position, boundingBox.center));
// Distance from hand to handle in direction of handle. // Distance from hand to handle in direction of handle.
scaleAxis = Vec3.multiplyQbyV(selection.getPositionAndOrientation().orientation, handleUnitScaleAxis); scaleAxis = Vec3.multiplyQbyV(selectionPositionAndOrientation.orientation, handleUnitScaleAxis);
handDistance = Math.abs(Vec3.dot(Vec3.subtract(otherTargetPosition, boundingBox.center), scaleAxis)); handDistance = Math.abs(Vec3.dot(Vec3.subtract(otherTargetPosition, boundingBox.center), scaleAxis));
handleHandOffset = handDistance - initialHandleDistance; handleHandOffset = handDistance - initialHandleDistance;
@ -1429,20 +1422,26 @@
function applyHandleScale() { function applyHandleScale() {
// Scales selection per changing position of scaling hand; positions and orients per grabbing hand. // Scales selection per changing position of scaling hand; positions and orients per grabbing hand.
var targetPosition, var targetPosition,
deltaOrientation, deltaHandOrientation,
deltaHandleOrientation,
selectionPosition,
selectionOrientation,
boundingBoxCenter, boundingBoxCenter,
scaleAxis, scaleAxis,
handleDistance, handleDistance,
scale, scale,
scale3D; scale3D,
selectionPositionAndOrientation;
// Position and orient selection per grabbing hand before scaling it per scaling hand. // Orient selection per grabbing hand.
applyGrab(); deltaHandOrientation = Quat.multiply(hand.orientation(), initialHandOrientationInverse);
selectionOrientation = Quat.multiply(deltaHandOrientation, initialSelectionOrientation);
// Desired distance of handle from center of bounding box. // Desired distance of handle from center of bounding box.
targetPosition = getScaleTargetPosition(); targetPosition = getScaleTargetPosition();
deltaOrientation = Quat.multiply(hand.orientation(), initialHandleScaleOrientationInverse); deltaHandleOrientation = Quat.multiply(hand.orientation(), initialHandleOrientationInverse);
boundingBoxCenter = Vec3.sum(targetPosition, Vec3.multiplyQbyV(deltaOrientation, initialTargetToBoundingBoxCenter)); boundingBoxCenter = Vec3.sum(targetPosition,
Vec3.multiplyQbyV(deltaHandleOrientation, initialTargetToBoundingBoxCenter));
scaleAxis = Vec3.multiplyQbyV(selection.getPositionAndOrientation().orientation, handleUnitScaleAxis); scaleAxis = Vec3.multiplyQbyV(selection.getPositionAndOrientation().orientation, handleUnitScaleAxis);
handleDistance = Math.abs(Vec3.dot(Vec3.subtract(otherTargetPosition, boundingBoxCenter), scaleAxis)); handleDistance = Math.abs(Vec3.dot(Vec3.subtract(otherTargetPosition, boundingBoxCenter), scaleAxis));
handleDistance -= handleHandOffset; handleDistance -= handleHandOffset;
@ -1455,8 +1454,20 @@
y: scale3D.y !== 0 ? scale3D.y : 1, y: scale3D.y !== 0 ? scale3D.y : 1,
z: scale3D.z !== 0 ? scale3D.z : 1 z: scale3D.z !== 0 ? scale3D.z : 1
}; };
// Reposition selection per scale.
selectionPosition = Vec3.sum(boundingBoxCenter,
Vec3.multiplyQbyV(selectionOrientation, Vec3.multiplyVbyV(scale3D, initialHandleRegistrationOffset)));
// Scale.
handles.scale(scale3D); handles.scale(scale3D);
selection.handleScale(scale3D); selection.handleScale(scale3D, selectionPosition, selectionOrientation);
// Update grab offset.
selectionPositionAndOrientation = selection.getPositionAndOrientation();
initialHandOrientationInverse = Quat.inverse(hand.orientation());
initialHandToSelectionVector = Vec3.subtract(selectionPositionAndOrientation.position, hand.position());
initialSelectionOrientation = selectionPositionAndOrientation.orientation;
} }