import { Vector3 } from './vector.js'; import { Quaternion } from './quaternion.js'; import { Matrix } from './matrix.js'; export class Transform { constructor() { this.position = new Vector3(); this.rotation = new Quaternion(); this.scale = new Vector3(1, 1, 1); this.parent = null; this.children = new Set(); this.isDirty = true; } setPosition(x, y, z) { this.position = new Vector3(x, y, z); this.markDirty(); } setRotation(x, y, z) { this.rotation = Quaternion.fromEuler(x, y, z); this.markDirty(); } setScale(x, y, z) { this.scale = new Vector3(x, y, z); this.markDirty(); } addChild(child) { if (child.parent) { child.parent.children.delete(child); } child.parent = this; this.children.add(child); child.markDirty(); } markDirty() { this.isDirty = true; this.children.forEach(child => child.markDirty()); } getWorldMatrix() { // Start with translation matrix let matrix = Matrix.translation( this.position.x, this.position.y, this.position.z ); // Apply rotation from quaternion matrix = Matrix.multiply( matrix, Matrix.fromQuaternion(this.rotation) ); // Apply scale matrix = Matrix.multiply( matrix, Matrix.scaling(this.scale.x, this.scale.y, this.scale.z) ); // If we have a parent, multiply with parent's world matrix if (this.parent) { matrix = Matrix.multiply( this.parent.getWorldMatrix(), matrix ); } return matrix; } translate(x, y, z) { this.position = this.position.add(new Vector3(x, y, z)); this.markDirty(); } rotate(x, y, z) { const rotation = Quaternion.fromEuler(x, y, z); this.rotation = Quaternion.multiply(this.rotation, rotation); this.markDirty(); } scaleBy(x, y, z) { this.scale = new Vector3( this.scale.x * x, this.scale.y * y, this.scale.z * z ); this.markDirty(); } setLocalPosition(x, y, z) { this.position = new Vector3(x, y, z); this.markDirty(); } setLocalRotation(x, y, z) { this.rotation = Quaternion.fromEuler(x, y, z); this.markDirty(); } setLocalScale(x, y, z) { this.scale = new Vector3(x, y, z); this.markDirty(); } getLocalPosition() { return this.position.clone(); } getLocalRotation() { return this.rotation.clone(); } getLocalScale() { return this.scale.clone(); } }