Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support left & right eyes #1697

Merged
merged 4 commits into from
May 29, 2024
Merged
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
5 changes: 5 additions & 0 deletions .changeset/blue-knives-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@antv/g-plugin-device-renderer': patch
---

Support left and right eyes in ar session.
5 changes: 5 additions & 0 deletions .changeset/sweet-apples-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@antv/g-plugin-device-renderer': patch
---

Support hit testing in webxr.
3 changes: 1 addition & 2 deletions __tests__/demos/3d/cylinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ export async function cylinder(context) {

const cylinder = new Mesh({
style: {
x: 300,
y: 250,
transform: `translate3d(300, 250, 0)`,
fill: 'white',
opacity: 1,
geometry: cylinderGeometry,
Expand Down
67 changes: 35 additions & 32 deletions __tests__/demos/3d/force.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1709,18 +1709,18 @@ export async function force(context) {
// });
// canvas.appendChild(circle);

// const label = new Text({
// style: {
// x: node.x + 310,
// y: node.y + 250,
// z: node.z + 1,
// fontFamily: 'sans-serif',
// text: node.id,
// fontSize: 6,
// fill: 'black',
// isBillboard: true,
// },
// });
const label = new Text({
style: {
x: node.x + 310,
y: node.y + 250,
z: node.z + 1,
fontFamily: 'sans-serif',
text: node.id,
fontSize: 6,
fill: 'black',
isBillboard: true,
},
});

// const rect = new Rect({
// style: {
Expand All @@ -1735,27 +1735,27 @@ export async function force(context) {
// },
// });
// canvas.appendChild(rect);
// canvas.appendChild(label);
canvas.appendChild(label);
});

// dataset.links.forEach((edge) => {
// const { source, target } = edge;
// const line = new Line({
// style: {
// x1: source.x + 300,
// y1: source.y + 250,
// z1: source.z,
// x2: target.x + 300,
// y2: target.y + 250,
// z2: target.z,
// stroke: 'black',
// lineWidth: 2,
// opacity: 0.5,
// isBillboard: true, // 濮嬬粓闈㈠悜灞忓箷
// },
// });
// canvas.appendChild(line);
// });
dataset.links.forEach((edge) => {
const { source, target } = edge;
const line = new Line({
style: {
x1: source.x + 300,
y1: source.y + 250,
z1: source.z,
x2: target.x + 300,
y2: target.y + 250,
z2: target.z,
stroke: 'black',
lineWidth: 2,
opacity: 0.5,
isBillboard: true, // 濮嬬粓闈㈠悜灞忓箷
},
});
canvas.appendChild(line);
});

// add a directional light into scene
const light = new DirectionalLight({
Expand All @@ -1777,7 +1777,10 @@ export async function force(context) {

canvas.getConfig().disableHitTesting = true;

const $button = ARButton.createButton(canvas, renderer, {});
const $button = ARButton.createButton(canvas, renderer, {
// @see https://github.com/immersive-web/webxr-samples/blob/main/hit-test.html
requiredFeatures: ['local', 'hit-test'],
});
container.appendChild($button);
}

Expand Down
183 changes: 183 additions & 0 deletions __tests__/demos/3d/hit-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { CanvasEvent, Canvas } from '../../../packages/g';
import {
CubeGeometry,
CylinderGeometry,
MeshPhongMaterial,
MeshBasicMaterial,
DirectionalLight,
Mesh,
Plugin as Plugin3D,
} from '../../../packages/g-plugin-3d';
import { ARButton, Renderer } from '../../../packages/g-webgl';

/**
* @see https://github.com/immersive-web/webxr-samples/blob/main/hit-test.html
*/
export async function hit_test(context: {
canvas: Canvas;
renderer: Renderer;
container: HTMLDivElement;
}) {
const { canvas, renderer, container } = context;

// wait for canvas' initialization complete
await canvas.ready;

// use GPU device
const plugin = renderer.getPlugin('device-renderer');
const device = plugin.getDevice();

// create a sphere geometry
const cylinderGeometry = new CylinderGeometry(device, {
radius: 100,
height: 50,
});
// create a material with Phong lighting model
const material = new MeshPhongMaterial(device, {
shininess: 30,
});

// 1. load texture with URL
const map = plugin.loadTexture(
'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*_aqoS73Se3sAAAAAAAAAAAAAARQnAQ',
);
const cubeGeometry = new CubeGeometry(device, {
width: 200,
height: 200,
depth: 200,
});
const basicMaterial = new MeshBasicMaterial(device, {
// wireframe: true,
map,
});

const reticle = new Mesh({
style: {
fill: 'red',
opacity: 1,
geometry: cylinderGeometry,
material,
},
});
reticle.setPosition(300, 300, 0);
canvas.appendChild(reticle);

// add a directional light into scene
const light = new DirectionalLight({
style: {
fill: 'white',
direction: [-1, 0, 1],
},
});
canvas.appendChild(light);

// adjust camera's position
const camera = canvas.getCamera();
camera.setPerspective(0.1, 1000, 45, 640 / 640);

let hitTestSource: XRHitTestSource | null = null;
let hitTestSourceRequested = false;
let xrViewerSpace: XRReferenceSpace | null = null;
canvas.addEventListener(CanvasEvent.BEFORE_RENDER, (e) => {
const frame = e.detail as XRFrame;
if (frame) {
const referenceSpace = renderer.xr.getReferenceSpace();
const session = renderer.xr.getSession();
let pose = frame.getViewerPose(referenceSpace);

reticle.style.visibility = 'hidden';

if (hitTestSourceRequested === false) {
session.requestReferenceSpace('viewer').then(function (referenceSpace) {
xrViewerSpace = referenceSpace;
session
.requestHitTestSource?.({ space: referenceSpace })
?.then(function (source) {
hitTestSource = source;
});
});

session.addEventListener('end', function () {
hitTestSourceRequested = false;
hitTestSource = null;
});

hitTestSourceRequested = true;
}

if (hitTestSource && pose) {
const hitTestResults = frame.getHitTestResults(hitTestSource);

if (hitTestResults.length) {
const hit = hitTestResults[0];
reticle.style.visibility = 'visible';
reticle.setLocalTransform(
hit.getPose(referenceSpace)?.transform.matrix,
);

// console.log('position', reticle.getLocalPosition());
// console.log('rotation', reticle.getRotation());
// console.log('scale', reticle.getScale());

const [x, y, z] = reticle.getLocalPosition();

const width =
session.renderState.baseLayer?.framebufferWidth! /
window.devicePixelRatio;
const height =
session.renderState.baseLayer?.framebufferHeight! /
window.devicePixelRatio;

$domOverlay.innerHTML = `${x}, ${y}, ${z}, ${width}, ${height}`;

// console.log(`${x}, ${y}, ${z}, ${width}, ${height}`);

reticle.setLocalPosition(
x * width + width / 2,
height - y * height - height / 2,
z,
);
} else {
reticle.style.visibility = 'hidden';
}
}
}
// sphere.rotate(0, 0.1, 0);
});

canvas.getConfig().disableHitTesting = true;

const $domOverlay = document.createElement('div');
$domOverlay.id = 'overlay';
document.body.appendChild($domOverlay);

const $button = ARButton.createButton(canvas, renderer, {
// @see https://github.com/immersive-web/webxr-samples/blob/main/hit-test.html
requiredFeatures: ['local', 'hit-test', 'dom-overlay'],
domOverlay: {
root: document.getElementById('overlay')!,
},
});
container.appendChild($button);

const controller = renderer.xr.getController(0);
controller.addEventListener('select', (e) => {
if (reticle.style.visibility === 'visible') {
const cube = new Mesh({
style: {
fill: '#1890FF',
opacity: 1,
geometry: cubeGeometry,
material: basicMaterial,
},
});
cube.setLocalTransform(reticle.getLocalTransform());
canvas.appendChild(cube);
}
});
canvas.appendChild(controller);
}

hit_test.initRenderer = (renderer) => {
renderer.registerPlugin(new Plugin3D());
};
1 change: 1 addition & 0 deletions __tests__/demos/3d/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export { torus } from './torus';
export { cylinder } from './cylinder';
export { force } from './force';
export { ar } from './webar';
export { hit_test } from './hit-test';
4 changes: 1 addition & 3 deletions __tests__/demos/3d/sphere.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ export async function sphere(context) {
// create a mesh
const sphere = new Mesh({
style: {
x: 320,
y: 320,
z: 0,
transform: `translate3d(320, 320, 0)`,
transformOrigin: 'center',
fill: '#1890FF',
opacity: 1,
Expand Down
3 changes: 1 addition & 2 deletions __tests__/demos/3d/torus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ export async function torus(context) {

const torus = new Mesh({
style: {
x: 300,
y: 250,
transform: `translate3d(320, 250, 0)`,
fill: 'white',
opacity: 1,
geometry: torusGeometry,
Expand Down
4 changes: 2 additions & 2 deletions __tests__/demos/bugfix/1636.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function image(context) {
y: 0,
width: 100,
height: 100,
img,
src: img,
},
});
const image2 = new Image({
Expand All @@ -36,7 +36,7 @@ export async function image(context) {
y: 0,
width: 100,
height: 100,
img,
src: img,
},
});
group.appendChild(image);
Expand Down
Loading
Loading