diff --git a/src/util/functions/updateTextNode.ts b/src/util/functions/updateTextNode.ts index 5e96b2d..a8bd186 100644 --- a/src/util/functions/updateTextNode.ts +++ b/src/util/functions/updateTextNode.ts @@ -1,4 +1,14 @@ -import {AbstractMesh, Color3, DynamicTexture, Material, MeshBuilder, StandardMaterial} from "@babylonjs/core"; +import { + AbstractMesh, + Color3, + DynamicTexture, + Material, + Mesh, + MeshBuilder, + Scene, + StandardMaterial, + Vector3 +} from "@babylonjs/core"; import log from "loglevel"; @@ -10,10 +20,11 @@ export function updateTextNode(mesh: AbstractMesh, text: string) { return null; } const textNodes = mesh.getChildren((node) => { - return node.metadata?.text == true; + return node.metadata?.label == true; }); if (textNodes && textNodes.length > 0) { textNodes.forEach((node) => { + node.parent = null; node.dispose(false, true); }); } @@ -23,7 +34,7 @@ export function updateTextNode(mesh: AbstractMesh, text: string) { } //Set font - const height = 0.05; + const height = 0.08; const font_size = 24; const font = "bold " + font_size + "px Arial"; //Set height for dynamic texture @@ -39,19 +50,22 @@ export function updateTextNode(mesh: AbstractMesh, text: string) { //Calculate width the plane has to be const planeWidth = DTWidth * ratio; - + temp.dispose(); //Create dynamic texture and write the text const dynamicTexture = new DynamicTexture("DynamicTexture", { width: DTWidth, height: DTHeight }, mesh.getScene(), false); + dynamicTexture.drawText(text, null, null, font, "#ffffff", "#000000", true); + const mat = new StandardMaterial("mat", mesh.getScene()); mat.diffuseColor = Color3.Black(); mat.disableLighting = true; mat.backFaceCulling = true; mat.emissiveTexture = dynamicTexture; + mat.freeze(); //mat.emissiveColor = Color3.White(); - dynamicTexture.drawText(text, null, null, font, "#ffffff", "#000000", true); + //Create plane and set dynamic texture as material //const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene()); const plane1 = createPlane(mat, mesh, text, planeWidth, height); @@ -77,6 +91,22 @@ function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth } else { plane.position.y = yOffset + (height * plane.scaling.y); } - + //plane.addLODLevel(5, getDistantPlane(mesh.getScene(), plane.scaling, planeWidth, height)); + plane.addLODLevel(3, null); return plane; } + +let distantPlane = null; + +function getDistantPlane(scene: Scene, scaling: Vector3, planeWidth: number, planeHeight: number): Mesh { + //if (distantPlane == null) { + distantPlane = MeshBuilder.CreatePlane("distantPlane", {width: planeWidth, height: planeHeight}, scene); + distantPlane.scaling = scaling; + //distantPlane.scaling.y = distantPlane.scaling.y /4; + const material = new StandardMaterial("distantPlaneMaterial", scene); + material.emissiveColor = Color3.White() + material.freeze() + distantPlane.material = material; + // } + return distantPlane; +} diff --git a/src/util/textMeshGenerator.ts b/src/util/textMeshGenerator.ts new file mode 100644 index 0000000..064dd21 --- /dev/null +++ b/src/util/textMeshGenerator.ts @@ -0,0 +1,78 @@ +import { + Color3, + DynamicTexture, + InstancedMesh, + Mesh, + MeshBuilder, + Scene, + StandardMaterial, + TransformNode +} from "@babylonjs/core"; +import {DefaultScene} from "../defaultScene"; + +export class TextMeshGenerator { + private _scene: Scene; + private _textMeshes: Map = new Map(); + + constructor() { + this._scene = DefaultScene.Scene; + this.initialize(); + } + + public getMesh(input: string): TransformNode { + const transformNode = new TransformNode("textMesh-" + input, this._scene); + let x = 0; + for (const char of input) { + const mesh = new InstancedMesh("instance_" + input, this._textMeshes.get(char)); + mesh.parent = transformNode; + x = x + Math.abs(mesh.getBoundingInfo().boundingBox.minimum.x); + mesh.position.x = x; + x = x + mesh.getBoundingInfo().boundingBox.maximum.x; + } + return transformNode; + } + + public generateCharMesh(input: string): Mesh { + console.log("Generating text mesh for: " + input); + //Set font + const height = 0.05; + const font_size = 28; + const font = "bold " + font_size + "px Arial"; + //Set height for dynamic texture + const DTHeight = 1.5 * font_size; //or set as wished + //Calc Ratio + const ratio = height / DTHeight; + + //Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas + const temp = new DynamicTexture("DynamicTexture", 32, this._scene); + const tmpctx = temp.getContext(); + tmpctx.font = font; + const DTWidth = tmpctx.measureText(input).width + 8; + + //Calculate width the plane has to be + const planeWidth = DTWidth * ratio; + const dynamicTexture = new DynamicTexture("DynamicTexture", { + width: DTWidth, + height: DTHeight + }, this._scene, false); + dynamicTexture.drawText(input, null, null, font, "#ffffff", "#000000", true); + temp.dispose(); + const mat = new StandardMaterial("mat", this._scene); + mat.diffuseColor = Color3.Black(); + mat.disableLighting = true; + mat.backFaceCulling = true; + mat.emissiveTexture = dynamicTexture; + const plane = MeshBuilder.CreatePlane("character" + input, {width: planeWidth, height: height}, this._scene); + plane.material = mat; + return plane; + } + + private initialize() { + for (let i = 32; i < 127; ++i) { + const mesh = this.generateCharMesh(String.fromCharCode(i)); + this._textMeshes.set(String.fromCharCode(i), mesh); + } + } + + +} \ No newline at end of file diff --git a/src/vrApp.ts b/src/vrApp.ts index f6602f3..ee0db22 100644 --- a/src/vrApp.ts +++ b/src/vrApp.ts @@ -71,6 +71,18 @@ export class VrApp { }) } this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer'); + /* + + const textGen = new TextMeshGenerator(); + let y = .1; + for (let i = 0; i < 1000; i++) { + const text = textGen.generateCharMesh("hijklmnop Hello World"); + text.position.y = y; + text.position.z = -5; + text.rotation.y = Math.PI; + y+=.1; + } + */ let i = 0; this.engine.runRenderLoop(() => { scene.render();