Fix label positioning to use world space bounding boxes
Labels were incorrectly mixing local and global transform matrices, causing incorrect positioning on scaled/rotated meshes. Now properly converts world space bounding box positions to mesh local space using temporary TransformNode. Changes: - updateTextNode.ts: Use boundingBox.maximumWorld instead of boundingSphere.maximum - diagramObject.ts: Add empty object param to refreshBoundingInfo() - inputTextView.ts: Adjust input handle default position and mesh offsets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7849bf4eb2
commit
0b81605bdf
@ -205,7 +205,7 @@ export class DiagramObject {
|
|||||||
public updateLabelPosition() {
|
public updateLabelPosition() {
|
||||||
if (this._label) {
|
if (this._label) {
|
||||||
this._mesh.computeWorldMatrix(true);
|
this._mesh.computeWorldMatrix(true);
|
||||||
this._mesh.refreshBoundingInfo();
|
this._mesh.refreshBoundingInfo({});
|
||||||
|
|
||||||
if (this._from && this._to) {
|
if (this._from && this._to) {
|
||||||
// Connection labels (arrows/lines)
|
// Connection labels (arrows/lines)
|
||||||
|
|||||||
@ -31,9 +31,11 @@ export class InputTextView {
|
|||||||
this.handle = new Handle({
|
this.handle = new Handle({
|
||||||
contentMesh: this.inputMesh,
|
contentMesh: this.inputMesh,
|
||||||
label: 'Input',
|
label: 'Input',
|
||||||
defaultPosition: new Vector3(0, .4, .5),
|
defaultPosition: new Vector3(0, .8, .7),
|
||||||
defaultRotation: new Vector3(0, 0, 0)
|
defaultRotation: new Vector3(.36, 0, 0)
|
||||||
});
|
});
|
||||||
|
this.inputMesh.position.y = .02;
|
||||||
|
this.inputMesh.position.z = .01;
|
||||||
// Position is now controlled by Handle class
|
// Position is now controlled by Handle class
|
||||||
this.createKeyboard();
|
this.createKeyboard();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {AbstractMesh, Color3, DynamicTexture, Material, MeshBuilder, StandardMaterial} from "@babylonjs/core";
|
import {AbstractMesh, Color3, DynamicTexture, Material, MeshBuilder, StandardMaterial, TransformNode} from "@babylonjs/core";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
|
|
||||||
|
|
||||||
@ -63,7 +63,6 @@ export function updateTextNode(mesh: AbstractMesh, text: string) {
|
|||||||
|
|
||||||
function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth: number, height: number): AbstractMesh {
|
function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth: number, height: number): AbstractMesh {
|
||||||
const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
||||||
const yOffset = mesh.getBoundingInfo().boundingSphere.maximum.y;
|
|
||||||
|
|
||||||
plane.parent = mesh;
|
plane.parent = mesh;
|
||||||
plane.scaling.y = (1 / mesh.scaling.y);
|
plane.scaling.y = (1 / mesh.scaling.y);
|
||||||
@ -75,9 +74,26 @@ function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth
|
|||||||
if (mesh.metadata?.template == "#connection-template") {
|
if (mesh.metadata?.template == "#connection-template") {
|
||||||
plane.billboardMode = AbstractMesh.BILLBOARDMODE_Y;
|
plane.billboardMode = AbstractMesh.BILLBOARDMODE_Y;
|
||||||
plane.position.y = mesh.position.y + .1;
|
plane.position.y = mesh.position.y + .1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
plane.position.y = yOffset + (height * plane.scaling.y);
|
// Calculate label position using world space bounding box
|
||||||
|
// This ensures labels are positioned correctly regardless of mesh transforms
|
||||||
|
mesh.computeWorldMatrix(true);
|
||||||
|
mesh.refreshBoundingInfo();
|
||||||
|
|
||||||
|
// Get the top of the bounding box in world space
|
||||||
|
const top = mesh.getBoundingInfo().boundingBox.maximumWorld;
|
||||||
|
|
||||||
|
// Convert world space position to mesh's local space
|
||||||
|
// Use temporary TransformNode to handle the transformation
|
||||||
|
const temp = new TransformNode("temp", mesh.getScene());
|
||||||
|
temp.position = top;
|
||||||
|
temp.setParent(mesh);
|
||||||
|
const y = temp.position.y;
|
||||||
|
temp.dispose();
|
||||||
|
|
||||||
|
// Position label above the mesh with offset
|
||||||
|
// Add additional offset for the scaled height of the label
|
||||||
|
plane.position.y = y + 0.06 + (height * plane.scaling.y / 2);
|
||||||
}
|
}
|
||||||
plane.addLODLevel(3, null);
|
plane.addLODLevel(3, null);
|
||||||
return plane;
|
return plane;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user