Files
AR-Menu/AR Menu/Needle/MenuScene/node_modules/three-mesh-ui/examples/dev__frames.js
2025-11-30 08:35:03 +02:00

366 lines
11 KiB
JavaScript

import * as THREE from 'three';
import { Color, DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry, PointLight, SpotLight, SpotLightHelper } from 'three';
import { VRButton } from 'three/examples/jsm/webxr/VRButton.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { BoxLineGeometry } from 'three/examples/jsm/geometries/BoxLineGeometry.js';
import ThreeMeshUI, { FontLibrary } from 'three-mesh-ui';
import Stats from 'three/examples/jsm/libs/stats.module';
import FrameDepthMaterial from '../src/frame/materials/FrameDepthMaterial';
import FramePhysicalMaterial from 'three-mesh-ui/examples/materials/frame/FramePhysicalMaterial';
import FrameBasicMaterial from 'three-mesh-ui/examples/materials/frame/FrameBasicMaterial';
import MSDFNormalMaterial from 'three-mesh-ui/examples/materials/msdf/MSDFNormalMaterial';
import ROBOTO_ADJUSTMENT from 'three-mesh-ui/examples/assets/fonts/msdf/roboto/adjustment';
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
let scene, camera, renderer, controls, panel, panelScale, lightHelper, stats, topLeft, topMiddleRight, topRight, bottomMiddle;
// Using `ThreeMeshUI.FontLibrary.prepare( fontFamily, [...fontFamily] )
// We can ensure any fontFamily passed in that function and theirs variants are properly loaded and setup
FontLibrary.prepare(
FontLibrary
// Registering a fontFamily called "Roboto", the name is up to us.
.addFontFamily("Roboto")
// On the fontFamily added, lets add a variant
// a font variant usually requires 4 parameters
.addVariant(
// The weight of the variant '100'|'200'|'300'|'400'|'600'|'700'|'800'|'900'
// LIGHTER NORMAL BOLD BOLDER
'400',
// The style of the variant 'normal'|'italic'|'oblique'|'oblique(x deg)'
"normal",
// The json definition of the msdf font 'urlToLoad'|loadedObject
"./assets/fonts/msdf/roboto/regular.json",
// The texture of the msdf font 'urlToLoad'|Texture
"./assets/fonts/msdf/roboto/regular.png"
)
// Registering additional variants
.addVariant("700", "italic", "./assets/fonts/msdf/roboto/bold-italic.json", "./assets/fonts/msdf/roboto/bold-italic.png" )
.addVariant("700", "normal", "./assets/fonts/msdf/roboto/bold.json", "./assets/fonts/msdf/roboto/bold.png" )
.addVariant("400", "italic", "./assets/fonts/msdf/roboto/italic.json", "./assets/fonts/msdf/roboto/italic.png" )
// FontLibrary.prepare() returns a Promise, we can therefore add a callback to be executed when all files are loaded
).then( () => {
// Once font are registered, we can get the font family
const RobotoFamily = FontLibrary.getFontFamily("Roboto");
// And then retrieve a fontVariant defined in this Family
const RobotoRegular = RobotoFamily.getVariant('400','normal');
// Having font variant allows us to perform some modifications
// 1. Adjustments
// If you look closely the `Getting started - Basic Setup` you may have noticed that :
// - the `h` character is slightly below the baseline
// This can be adjusted per fontVariant
RobotoRegular.adjustTypographicGlyphs( {
// 'h' character must change some of its properties defined in the json
h: {
// the yoffset property should be 2 (instead of 4 in the json)
yoffset: 2
}
} );
// Once adjusted, any three-mesh-ui Text using this font variant will use the adjusted properties
// 1. Material
// Instead of assigning custom materials to Text one by one
// We can assign a Material(class) to a font variant (Here the bold one)
RobotoFamily.getVariant('700','normal').fontMaterial = MSDFNormalMaterial;
// Once set, any three-mesh-ui Text using this font variant will use the defined material
// We may encounter the following lines in other examples,
// they are adjusting font variants to display a nice baseline
RobotoFamily.getVariant('700','normal').adjustTypographicGlyphs( ROBOTO_ADJUSTMENT );
RobotoFamily.getVariant('700','italic').adjustTypographicGlyphs( ROBOTO_ADJUSTMENT );
RobotoFamily.getVariant('400','italic').adjustTypographicGlyphs( ROBOTO_ADJUSTMENT );
// Now that the font are loaded and adjusted,
init();
});
window.addEventListener( 'resize', onWindowResize );
//
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x505050 );
camera = new THREE.PerspectiveCamera( 60, WIDTH / HEIGHT, 0.1, 100 );
renderer = new THREE.WebGLRenderer( {
antialias: true
} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( WIDTH, HEIGHT );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
renderer.xr.enabled = true;
document.body.appendChild( VRButton.createButton( renderer ) );
document.body.appendChild( renderer.domElement );
stats = new Stats();
document.body.appendChild( stats.dom );
controls = new OrbitControls( camera, renderer.domElement );
camera.position.set( 0, 1.6, 0.5 );
controls.target = new THREE.Vector3( 0, 1, -1.8 );
controls.update();
// ROOM
const room = new THREE.LineSegments(
new BoxLineGeometry( 6, 6, 6, 10, 10, 10 ).translate( 0, 3, 0 ),
new THREE.LineBasicMaterial( { color: 0x808080 } )
);
room.position.z = -1.5;
scene.add( room );
// LIGHTS
const floor = new Mesh(
new PlaneGeometry(6,6,5,5),
new MeshStandardMaterial( {color:0xffffff} )
);
floor.rotation.x = - Math.PI / 2;
floor.position.z = -1.5;
floor.position.y = -0.01
floor.receiveShadow = true;
scene.add(floor);
const light = new SpotLight(0xffffff,1, 8, Math.PI / 6, 1.0, 1.0);
window.light = light;
light.position.set(0,5,0.75);
light.castShadow = true;
//Set up shadow properties for the light
light.shadow.mapSize.width = 1024; // default
light.shadow.mapSize.height = 1024; // default
light.shadow.camera.near = 0.5; // default
light.shadow.camera.far = 500; // default
scene.add(light);
scene.add(light.target);
lightHelper = new SpotLightHelper(light,0xff0000);
scene.add(lightHelper);
light.target.position.set(0,0.75,-2);
const plight = new PointLight( 0xffffff, 1, 8, 1.0);
plight.position.set(0,2, -2)
scene.add(plight)
// TEXT PANEL
const container = makeTextPanel();
window.rootBlock = container;
// container.frame.visible = false;
const top = makeRow();
container.add( top );
// // top.frame.visible = false;
topLeft = makeBoxForBorder('borderTopLeft');
topLeft.set({borderRadius:'0.1 0 0 0', borderWidth:0.05, borderColor: new Color(0xff0000)});
const topMiddleLeft = makeBoxForBorder('TopMiddleLeft?');
topMiddleLeft.set({borderRadius:'0.05 0.25', borderLeftWidth:0.1})
const topMiddle = makeBoxForBorder('borderTop');
topMiddle.set({borderRadius: '0.05 0.05 0 0'})
topMiddleRight = makeBoxForBorder('TopMiddleRight?');
topMiddleRight.set({borderRadius: [0.25, 0.05], borderColor: new Color(0xff9900), borderWidth: 0.02});
topRight = makeBoxForBorder('BorderTopRight');
topRight.set({borderRadius:0.2, borderWidth:0.05, borderColor: new Color(0x99ff99)});
top.add( topLeft, topMiddleLeft, topMiddle, topMiddleRight, topRight)
//
const middle = makeRow();
container.add( middle );
const middleLeft = makeBoxForBorder('borderMiddleLeft');
middleLeft.set({borderRadius:"0.05 0 0 0.05"});
const middleMiddleLeft = makeBoxForBorder('MiddleMiddleLeft?');
middleMiddleLeft.set({height: 0.2 , borderRadius: '0.05 1 0.05 0'});
const middleMiddle = makeBoxForBorder('borderMiddle');
panel = middleMiddle;
const middleMiddleRight = makeBoxForBorder('MiddleMiddleRight?');
middleMiddleRight.set({borderRadius: "0 0.5 0.5 0", borderWidth:'0 0 0 0.05', borderColor: new Color(0x99ff00)});
const middleRight = makeBoxForBorder('BorderMiddleRight');
middleRight.set({borderRadius: "0 0.3 0.3 0"});
middle.add( middleLeft, middleMiddleLeft, middleMiddle, middleMiddleRight, middleRight)
const bottom = makeRow();
container.add( bottom );
const bottomLeft = makeBoxForBorder('borderBottomLeft');
bottomLeft.set({flexDirection:"row"})
bottomLeft.set({borderRadius: '0 0 0 0.1'});
const bottomMiddleLeft = makeBoxForBorder('BottomMiddleLeft?');
// bottomMiddleLeft.backgroundColor = new Color(0xffffff);
bottomMiddleLeft.set({borderRadius:'0.2 0.1', backgroundColor: 0xffffff, backgroundOpacity:1});
bottomMiddleLeft.backgroundMaterial = new FramePhysicalMaterial({
side:DoubleSide,
transmission: 1,
opacity: 1,
metalness: 0,
roughness: 0,
ior: 2,
thickness: 0.1,
specularIntensity: 1,
envMapIntensity: 1});
bottomMiddle = makeBoxForBorder('borderBottom');
bottomMiddle.set({borderRadius:'0 0 0.1 0.1'})
const bottomMiddleRight = makeBoxForBorder('BottomMiddleRight?');
bottomMiddleRight.set({borderRadius:0.5,
borderWidth:'0 0 0.05 0',borderColor:new Color(0xff9900)});
bottomMiddleRight.backgroundMaterial = new FrameBasicMaterial({side:DoubleSide});
panelScale = bottomMiddleRight;
const bottomRight = makeBoxForBorder('BorderBottomRight');
bottomRight.set({borderWidth:'0.1 0.2 0.1 0.05', borderRadius:0.5, borderColor: new Color(0x99ffff)});
bottom.add( bottomLeft, bottomMiddleLeft, bottomMiddle, bottomMiddleRight, bottomRight)
// console.log( bottom.frame.customDepthMaterial );
renderer.setAnimationLoop( loop );
}
//
function makeTextPanel() {
const panel = new ThreeMeshUI.Block( {
width: 3.25,
height: 3,
fontSize: 0.045,
flexDirection: 'column',
alignItems: 'center',
textAlign: 'center',
justifyContent: 'space-evenly',
// backgroundOpacity: 0.5,
// backgroundColor: 0xff9900,
fontFamily: "Roboto",
} );
panel.position.set( 0, 1, -1.8 );
panel.rotation.x = -0.55;
panel.backgroundCastShadow = true;
scene.add( panel );
return panel;
}
function makeRow() {
return new ThreeMeshUI.Block({
// height: 0.9,
// margin: 0.05,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundOpacity: 0.25,
});
}
function makeBoxForBorder( text, visible = true ) {
const panel = new ThreeMeshUI.Block( {
width: 0.5,
height: 0.5,
margin: 0.05,
justifyContent: 'center',
textAlign: 'center',
boxSizing: 'border-box',
visible,
backgroundColor: 0x000000,
backgroundOpacity : 0.5,
} );
panel.backgroundSide = DoubleSide;
panel.backgroundCastShadow = true;
panel.backgroundCustomDepthMaterial = new FrameDepthMaterial();
//
panel.add(
new ThreeMeshUI.Text( {
textContent: text,
backgroundColor: 'yellow'
} )
);
return panel;
}
// handles resizing the renderer when the viewport is resized
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function loop() {
panel.set( {
borderRadius: 0.2 * Math.sin( Date.now() / 500 ),
// borderRadius: [ 0, 0.2 + 0.2 * Math.sin( Date.now() / 500 ), 0, 0 ],
borderWidth: 0.08 - 0.06 * Math.sin( Date.now() / 500 ),
borderColor: new THREE.Color( 0.5 + 0.5 * Math.sin( Date.now() / 500 ), 0.5, 1 ),
borderOpacity: 1
} );
topMiddleRight.set({ borderWidth: Math.abs( 0.15 * Math.sin( Date.now() / 500 ) ) })
topLeft.set({borderRadius: [Math.abs( 0.5 * Math.sin( Date.now() / 500 ) ),0,0,0] })
const size = 0.15 + Math.abs(0.35 * Math.sin( Date.now() / 500 ) );
panelScale.set( {width: size, height: size});
lightHelper.update();
// Don't forget, ThreeMeshUI must be updated manually.
// This has been introduced in version 3.0.0 in order
// to improve performance
// ThreeMeshUI.update();
ThreeMeshUI.update();
controls.update();
renderer.render( scene, camera );
stats.update()
}