Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
32 changes: 22 additions & 10 deletions apps/simple-video-layers/multiple-layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,13 @@ 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);
layerObj.glassLayer.detach(controller);
}
if (controller.userData.engagedResize && layerObj) {
layerObj.toolbar.disengageResize(controller);
controller.userData.engagedResize = false;
}
});
}
Expand All @@ -337,18 +341,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 +360,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;
layerObj.glassLayer.attach(controller);
} 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 +444,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.
56 changes: 31 additions & 25 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,25 @@ export default class GlassLayer {
return glass;
}

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

updatePosition() {
const position = new THREE.Vector3();
const quaternion = new THREE.Quaternion();

this.glassObject.getWorldPosition(position);
this.glassObject.getWorldQuaternion(quaternion);
/**
* 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);
// update quaternion (3d heading and orientation)
this.glassObject.quaternion.copy(quaternion);
}

/**
* Updates position and quaternion of media layer when glass layer is moved
*/
updateLayerOrientation(position, quaternion) {
const { x, y, z } = position;
this.layer.transform = new XRRigidTransform(
{
Expand All @@ -54,23 +61,14 @@ 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();

const position = new THREE.Vector3();
const quaternion = new THREE.Quaternion();
this.glassObject.getWorldPosition(position);
this.glassObject.getWorldQuaternion(quaternion);
Comment thread
zhixiangteoh marked this conversation as resolved.
Outdated
this.updateLayerOrientation(position, quaternion);
}

move() {
Expand All @@ -79,4 +77,12 @@ export default class GlassLayer {
this.layer.transform.orientation
);
}

attach(controller) {
controller.attach(this.glassObject);
}
Comment thread
zhixiangteoh marked this conversation as resolved.
Outdated

detach(controller) {
controller.remove(this.glassObject);
Comment thread
zhixiangteoh marked this conversation as resolved.
Outdated
}
}
127 changes: 122 additions & 5 deletions util/webxr/Toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as THREE from "three";

import { CanvasUI } from "../CanvasUI";

const RESIZE_HANDLE_THICKNESS = 0.05;
Comment thread
zhixiangteoh marked this conversation as resolved.
class Toolbar {
constructor(layer, renderer, video, options) {
this.layer = layer;
Expand All @@ -19,12 +20,29 @@ class Toolbar {
// Progress Bar
this.progressBar = this.createProgressBar();

// Resize Handle
this.resizeHandle = this.createResizeHandle();
this.resizeHandleClone = null;
Comment thread
zhixiangteoh marked this conversation as resolved.

// 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);

return handle;
}

createProgressBar() {
Expand Down Expand Up @@ -53,6 +71,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 +105,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 +126,7 @@ class Toolbar {
bright: "#ff0",
dark: "#bb0",
},
black: "#000",
};

const config = {
Expand All @@ -117,7 +147,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 +156,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 +199,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 @@ -206,6 +258,8 @@ class Toolbar {
this.layer.transform.orientation
);
}

this.updateResizeHandle();
}

/**
Expand All @@ -225,6 +279,69 @@ 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) {
// this.resizeHandleClone = this.resizeHandle.clone();
// this.resizeHandleClone.material = new THREE.MeshBasicMaterial({
// transparent: true,
// opacity: 0.5, // test
// });
// this.resizeHandleClone.name = "resizeHandle";
// const engagePosition = new THREE.Vector3();
// this.resizeHandleClone.getWorldPosition(engagePosition);
// controller.attach(this.resizeHandleClone);
// this.resizeHandleClone.userData.engageResizePosition = engagePosition;
// console.log(this.resizeHandleClone);

const engagePosition = new THREE.Vector3();
// world position necessary
this.resizeHandle.getWorldPosition(engagePosition);
this.resizeHandle.name = "resizeHandle";
controller.attach(this.resizeHandle);
this.resizeHandle.userData.engageResizePosition = engagePosition;
console.log(this.resizeHandle);
}

/**
*
*/
disengageResize(controller) {
// const resizeHandleClone = controller.getObjectByName("resizeHandle");
// console.log(resizeHandleClone);
// const engagePosition = resizeHandleClone.userData.engageResizePosition;
// const disengagePosition = new THREE.Vector3();
// resizeHandleClone.getWorldPosition(disengagePosition);
// const distance = engagePosition.distanceTo(disengagePosition);
// console.log(distance);
// controller.remove(resizeHandleClone);

const resizeHandle = controller.getObjectByName("resizeHandle");
console.log(resizeHandle);
const engagePosition = resizeHandle.userData.engageResizePosition;
const disengagePosition = new THREE.Vector3();
resizeHandle.getWorldPosition(disengagePosition);
// absolute euclidean distance
const distance = engagePosition.distanceTo(disengagePosition);

// use distance to scale layer proportionally, on each render (fluid resizing)
console.log(distance);

controller.remove(resizeHandle);
}

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