File size: 2,843 Bytes
df38526
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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();
    }
}