@pmndrs/xr
Version:
VR/AR for threejs
60 lines (59 loc) • 2.54 kB
JavaScript
import { MeshBasicMaterial, Quaternion, Vector3, } from 'three';
export class PointerCursorMaterial extends MeshBasicMaterial {
constructor() {
super({ transparent: true, toneMapped: false, depthWrite: false });
}
onBeforeCompile(parameters, renderer) {
super.onBeforeCompile(parameters, renderer);
parameters.vertexShader = `varying vec2 vLocalPosition;\n` + parameters.vertexShader;
parameters.vertexShader = parameters.vertexShader.replace(`#include <color_vertex>`, `#include <color_vertex>
vLocalPosition = position.xy * 2.0;`);
parameters.fragmentShader = `varying vec2 vLocalPosition;\n` + parameters.fragmentShader;
parameters.fragmentShader = parameters.fragmentShader.replace('#include <color_fragment>', `#include <color_fragment>
float value = max(0.0, 1.0 - sqrt(dot(vLocalPosition, vLocalPosition)));
diffuseColor.a = diffuseColor.a * value * value;`);
}
}
const ZAxis = new Vector3(0, 0, 1);
const quaternionHelper = new Quaternion();
const offsetHelper = new Vector3();
export function updatePointerCursorModel(pointerGroup, mesh, material, pointer, options) {
const intersection = pointer.getIntersection();
if (intersection == null ||
!pointer.getEnabled() ||
intersection.object.isVoidObject === true ||
!isVisble(pointerGroup)) {
mesh.visible = false;
return;
}
mesh.visible = true;
const color = typeof options.color === 'function' ? options.color(pointer) : options.color;
if (Array.isArray(color)) {
material.color.set(...color);
}
else {
material.color.set(color ?? 'white');
}
material.opacity = typeof options.opacity === 'function' ? options.opacity(pointer) : (options.opacity ?? 0.4);
mesh.position.copy(intersection.pointOnFace);
mesh.scale.setScalar(options.size ?? 0.1);
const normal = intersection.normal ?? intersection.face?.normal;
if (normal != null) {
quaternionHelper.setFromUnitVectors(ZAxis, normal);
intersection.object.getWorldQuaternion(mesh.quaternion);
mesh.quaternion.multiply(quaternionHelper);
offsetHelper.set(0, 0, options.cursorOffset ?? 0.01);
offsetHelper.applyQuaternion(mesh.quaternion);
mesh.position.add(offsetHelper);
}
mesh.updateMatrix();
}
function isVisble({ visible, parent }) {
if (!visible) {
return false;
}
if (parent == null) {
return true;
}
return isVisble(parent);
}