Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 33 additions & 9 deletions apps/simple-video-layers/multiple-layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,26 @@ class App {

handleSelectEnd(controller) {
this.mediaLayers.forEach((layerObj, layerKey) => {
if (layerObj.glassLayer) {
if (controller.userData.engagedMove && layerObj.glassLayer) {
layerObj.glassLayer.move();
controller.remove(layerObj.glass);
}
if (
layerObj.glassLayer &&
controller.userData.engagedResize &&
layerObj
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add this check before layerObj.glassLayer

) {
layerObj.toolbar.disengageResize(controller);
controller.userData.engagedResize = false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we are passing controller here, let us modify this env variable inside the disengageResize

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cabanier do you have any suggestions on this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it seems that this logic should move to disengageResize.
Maybe have an engaged attribute on controller.userdata?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm my idea was that since in handleSelectEnd we access controller.userData.engagedResize directly, as in:

if (layerObj.glassLayer && controller.userData.engagedResize && layerObj) {
                            // ^^^^^^^^^^^^^^^^^^^^^^^
    layerObj.toolbar.disengageResize(controller);
    controller.userData.engagedResize = false;
}

we should explicitly modify this field in the driver itself.

}
if (controller.userData.engagedResize && layerObj) {
layerObj.toolbar.disengageResize(controller);
controller.userData.engagedResize = false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this condition is duplicated

}
if (controller.userData.engagedResize && layerObj) {
layerObj.toolbar.disengageResize(controller);
controller.userData.engagedResize = false;
}
});
}

Expand All @@ -337,18 +353,13 @@ class App {
this.scene.add(layerObj.toolbarGroup);

if (layerObj.glassLayer) {
this.scene.add(layerObj.glass);
this.scene.add(layerObj.glassLayer.object);
}
} else {
this.handleToolbarIntersections(controller, {
layerKey,
layerObj,
});

// Handle moving of video layer
if (layerObj.glassLayer) {
controller.attach(layerObj.glass);
}
}
});
}
Expand All @@ -361,6 +372,19 @@ class App {

if (intersections.length > 0) {
layerObj.update(intersections);

// Handle moving of video layer
if (intersections[0].object === layerObj.glassLayer.object) {
console.log("move engaged");
controller.userData.engagedMove = true;
controller.attach(layerObj.glass);
} else if (
intersections[0].object === layerObj.toolbar.resizeHandle
) {
console.log("resize engaged");
controller.userData.engagedResize = true;
layerObj.toolbar.engageResize(controller);
}
} else {
this.scene.userData.isToolbarVisible[layerKey] = false;
this.scene.remove(layerObj.toolbarGroup);
Expand Down Expand Up @@ -432,8 +456,8 @@ class App {
if (!this.scene.userData.isToolbarVisible) {
this.scene.userData.isToolbarVisible = {};
}
for(const layerKey of this.mediaLayers.keys()) {

for (const layerKey of this.mediaLayers.keys()) {
this.scene.userData.isToolbarVisible[layerKey] = false;
}
}
Expand Down
Binary file added util/models/fbx/OculusHand_L.fbx
Binary file not shown.
Binary file added util/models/fbx/OculusHand_L_low.fbx
Binary file not shown.
Binary file added util/models/fbx/OculusHand_R.fbx
Binary file not shown.
Binary file added util/models/fbx/OculusHand_R_low.fbx
Binary file not shown.
39 changes: 18 additions & 21 deletions util/webxr/MediaLayerManager/GlassLayer.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as THREE from "three";

export default class GlassLayer {
constructor(layer, renderer) {
this.layer = layer;
this.renderer = renderer;

this.glassObject = this.createGlassObject(this.layer);
}

Expand All @@ -30,18 +30,29 @@ export default class GlassLayer {
return glass;
}

move({ x, y, z }) {
updateDimensions({ width, height }) {
this.glassObject.scale.set(2 * width, 2 * height, 1);
}

/**
* Updates position and quaternion of glass layer objects when quad video layer is moved
*/
updateOrientation(position, quaternion) {
const { x, y, z } = position;
// update position x, y, z
this.glassObject.position.set(x, y, z);
this.glassObject.position.needsUpdate = true;
// update quaternion (3d heading and orientation)
this.glassObject.quaternion.copy(quaternion);
}

updatePosition() {
/**
* Updates position and quaternion of media layer when glass layer is moved
*/
updateLayerOrientation() {
const position = new THREE.Vector3();
const quaternion = new THREE.Quaternion();

this.glassObject.getWorldPosition(position);
this.glassObject.getWorldQuaternion(quaternion);

const { x, y, z } = position;
this.layer.transform = new XRRigidTransform(
{
Expand All @@ -54,23 +65,9 @@ export default class GlassLayer {
);
}

updateDimensions({ width, height }) {
this.glassObject.scale.set(2 * width, 2 * height, 1);
}

/**
* Updates position and quaternion of glass layer when quad video layer is moved
*/
updateOrientation(position, quaternion) {
// update position x, y, z
this.glassObject.position.set(position.x, position.y, position.z);
// update quaternion (3d heading and orientation)
this.glassObject.quaternion.copy(quaternion);
}

updateOnRender() {
this.updateDimensions(this.layer);
this.updatePosition();
this.updateLayerOrientation();
}

move() {
Expand Down
154 changes: 149 additions & 5 deletions util/webxr/Toolbar.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import * as THREE from "three";

import { CanvasUI } from "../CanvasUI";
const RESIZE_HANDLE_THICKNESS = 0.05;
const MIN_LAYER_WIDTH = 0.5;
const MAX_LAYER_WIDTH = 10;

class Toolbar {
constructor(layer, renderer, video, options) {
Expand All @@ -19,12 +22,30 @@ class Toolbar {
// Progress Bar
this.progressBar = this.createProgressBar();

// Resize Handle
this.resizeHandle = this.createResizeHandle();
this.resizeHandleClone = null;

// Toolbar Group
this.toolbarGroup = this.createToolbarGroup(toolbarGroupConfig);
}

get objects() {
return [this.ui.mesh, ...this.progressBar.children];
return [this.ui.mesh, ...this.progressBar.children, this.resizeHandle];
}

createResizeHandle() {
const handleGeometry = new THREE.PlaneGeometry(1, 1); // to scale
const handleMaterial = new THREE.MeshBasicMaterial({ color: "white" });

// bottom handle
const handle = new THREE.Mesh(handleGeometry, handleMaterial);
handle.scale.set(this.layer.width, RESIZE_HANDLE_THICKNESS, 1);
const { x, y, z } = this.ui.mesh.position;
handle.position.set(x, y - this.uiHeight, z);

handle.name = "resizeHandle";
return handle;
}

createProgressBar() {
Expand Down Expand Up @@ -53,6 +74,7 @@ class Toolbar {
const toolbarGroup = new THREE.Group();
toolbarGroup.add(this.ui.mesh);
toolbarGroup.add(this.progressBar);
toolbarGroup.add(this.resizeHandle);

const { x, y, z } = toolbarGroupConfig.position;
toolbarGroup.position.set(x, y, z);
Expand Down Expand Up @@ -86,6 +108,16 @@ class Toolbar {
this.ui.updateElement("pause", label);
};

const onExpand = () => {
this.layer.width *= 1.25;
this.layer.height *= 1.25;
};

const onCompress = () => {
this.layer.width /= 1.25;
this.layer.height /= 1.25;
};

const colors = {
blue: {
light: "#1bf",
Expand All @@ -97,6 +129,7 @@ class Toolbar {
bright: "#ff0",
dark: "#bb0",
},
black: "#000",
};

const config = {
Expand All @@ -117,7 +150,7 @@ class Toolbar {
pause: {
type: "button",
position: { top: 35, left: 64 },
width: 128,
width: 96,
height: 52,
fontColor: colors.white,
backgroundColor: colors.red,
Expand All @@ -126,18 +159,38 @@ class Toolbar {
},
next: {
type: "button",
position: { top: 32, left: 192 },
position: { top: 32, left: 160 },
width: 64,
fontColor: colors.yellow.dark,
hover: colors.yellow.bright,
onSelect: () => onSkip(5),
},
expand: {
type: "button",
position: { top: 35, right: 200 },
width: 32,
height: 52,
fontColor: colors.black,
backgroundColor: colors.blue.light,
hover: colors.blue.lighter,
onSelect: onExpand,
},
compress: {
type: "button",
position: { top: 35, right: 240 },
width: 32,
height: 52,
fontColor: colors.black,
backgroundColor: colors.blue.light,
hover: colors.blue.lighter,
onSelect: onCompress,
},
restart: {
type: "button",
position: { top: 35, right: 10 },
width: 200,
width: 150,
height: 52,
fontColor: colors.white,
fontColor: colors.black,
backgroundColor: colors.blue.light,
hover: colors.blue.lighter,
onSelect: onRestart,
Expand All @@ -149,6 +202,8 @@ class Toolbar {
prev: "<path>M 10 32 L 54 10 L 54 54 Z</path>",
pause: "||",
next: "<path>M 54 32 L 10 10 L 10 54 Z</path>",
expand: "E",
compress: "C",
restart: "Restart",
};

Expand Down Expand Up @@ -200,12 +255,16 @@ class Toolbar {
this.updateProgressBar();
}

this.updateResizeHandle();

if (hasGlassLayer) {
this.updateOrientation(
this.layer.transform.position,
this.layer.transform.orientation
);
}

this.fluidResize();
}

/**
Expand All @@ -225,6 +284,91 @@ class Toolbar {
this.toolbarGroup.quaternion.needsUpdate = true;
}

updateResizeHandle() {
this.resizeHandle.scale.set(
this.layer.width,
RESIZE_HANDLE_THICKNESS,
1
);
}

/**
* Store the resizeHandle's position at the moment of engaging fluid resizing.
* Currently uses the resizeHandle itself, but intend to use a transparent clone
* of the resizeHandle to handle the engage/disengage, while keeping the actual
* visible resizeHandle "fixed" at the same position as the layer is resized.
*/
engageResize(controller) {
const { x, y, z } = this.resizeHandle.position;
const pointGeometry = new THREE.PlaneGeometry(0.1, 0.1);

this.handleLeftPoint = new THREE.Points(pointGeometry);
this.handleLeftPoint.position.set(x - this.layer.width / 2, y, z);
this.handleRightPoint = new THREE.Points(pointGeometry);
this.handleRightPoint.position.set(x + this.layer.width / 2, y, z);

this.resizeHandleClone = this.resizeHandle.clone();
this.resizeHandleClone.name = "resizeHandleClone";

const engagePosition = new THREE.Vector3();
// world position necessary
this.resizeHandleClone.getWorldPosition(engagePosition);
controller.attach(this.resizeHandleClone);
this.resizeHandleClone.userData.engageResizePosition = engagePosition;
}

fluidResize() {
if (
!this.resizeHandleClone ||
!this.resizeHandleClone.userData.engageResizePosition
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this condition is a bit weird. We can just combine them into one condition using optional chaining

) {
return;
}

const engagePosition = this.resizeHandleClone.userData
.engageResizePosition;
const currPosition = new THREE.Vector3();
this.resizeHandleClone.getWorldPosition(currPosition);
// absolute euclidean distance
const distanceEtoCurr = engagePosition.distanceTo(currPosition);

const handleLeftPosition = new THREE.Vector3();
const handleRightPosition = new THREE.Vector3();
this.handleLeftPoint.getWorldPosition(handleLeftPosition);
this.handleRightPoint.getWorldPosition(handleRightPosition);

// console.log("handle left", handleLeftPosition);
// console.log("handle right", handleRightPosition);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove these

// console.log("curr position", currPosition);

const distanceLtoCurr = handleLeftPosition.distanceTo(currPosition);
const distanceRtoCurr = handleRightPosition.distanceTo(currPosition);
// console.log("dist to left", distanceLtoCurr);
// console.log("dist to right", distanceRtoCurr);
// console.log(distanceRtoCurr < distanceLtoCurr ? "expand" : "compress");
const sign = distanceRtoCurr < distanceLtoCurr ? 1 : -1;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets use better variable names here since it is not explicit what these variables mean just by the name? Can you explain what they are doing here in a comment?


const resizeFactor =
1 + (sign * distanceEtoCurr * 0.01) / this.layer.width;

// hack
if (this.layer.width <= MIN_LAYER_WIDTH) {
this.layer.width *= 1.001;
this.layer.height *= 1.001;
} else if (this.layer.width >= MAX_LAYER_WIDTH) {
this.layer.width *= 0.999;
this.layer.height *= 0.999;
} else {
this.layer.width *= resizeFactor;
this.layer.height *= resizeFactor;
}
}

disengageResize(controller) {
this.resizeHandleClone.userData.engageResizePosition = null;
controller.remove(this.resizeHandleClone);
}

/**
* Updates progress bar as video plays
*/
Expand Down