Skip to content

Commit 25676ad

Browse files
committed
🚧 Added transformation to AnimationNodes
- Simplified `pos`, `rot`, and `scale` on `IAnimationNodes`.
1 parent af302d1 commit 25676ad

File tree

8 files changed

+83
-50
lines changed

8 files changed

+83
-50
lines changed

schemas/jsonExport.schema.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@
197197
}
198198
},
199199
"vec3": { "type": "array", "items": { "type": "number" }, "minItems": 3, "maxItems": 3 },
200+
"vec4": { "type": "array", "items": { "type": "number" }, "minItems": 4, "maxItems": 4 },
200201
"vanillaModel": {
201202
"type": "object",
202203
"required": ["textures", "elements", "display"],
@@ -306,6 +307,11 @@
306307
"minItems": 16,
307308
"maxItems": 16
308309
},
310+
"transformation": {
311+
"translation": { "$ref": "#/definitions/vec3" },
312+
"left_rotation": { "$ref": "#/definitions/vec4" },
313+
"scale": { "$ref": "#/definitions/vec3" }
314+
},
309315
"pos": { "$ref": "#/definitions/vec3" },
310316
"rot": { "$ref": "#/definitions/vec3" },
311317
"scale": { "$ref": "#/definitions/vec3" },

src/systems/animated_java.mcb

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,6 @@ dir <%export_namespace%> {
378378
global.isStepInterpolation = !!(last?.interpolation === 'step')
379379
global.lastActiveFrame[node.uuid] = node
380380
%%>
381-
# It's actually faster to use an on passeners call that checks tag immediately
382-
# than to spread it into a function that runs a bunch of tag checks on each bone.
383381
IF (node.interpolation === 'pre-post' || global.isStepInterpolation) {
384382
$data merge entity $(<%node.type + '_' + node.name%>) { \
385383
transformation: <%matrixToNbtFloatArray(node.matrix).toString()%>, \
@@ -396,24 +394,23 @@ dir <%export_namespace%> {
396394
} ELSE IF (node.type === 'locator') {
397395
IF (rig.nodeMap[node.uuid]?.config?.use_entity || rig.nodeMap[node.uuid]?.config?.ticking_commands) {
398396
<%%
399-
global.rot = getRotationFromQuaternion(node.rot)
400397
global.merged.locators[node.name] = {
401-
posx: node.pos.x,
402-
posy: node.pos.y,
403-
posz: node.pos.z,
404-
rotx: global.rot.x,
405-
roty: global.rot.y
398+
posx: node.pos[0],
399+
posy: node.pos[1],
400+
posz: node.pos[2],
401+
rotx: node.rot[0],
402+
roty: node.rot[1]
406403
}
407404
%%>
408405
}
409406
IF (node.commands) {
410407
execute on vehicle <%node.execute_condition ? node.execute_condition.trim() + ' ' : ''%>positioned \
411-
^<%roundTo(node.pos.x, 10)%> \
412-
^<%roundTo(node.pos.y, 10)%> \
413-
^<%roundTo(node.pos.z, 10)%> \
408+
^<%roundTo(node.pos[0], 10)%> \
409+
^<%roundTo(node.pos[1], 10)%> \
410+
^<%roundTo(node.pos[2], 10)%> \
414411
rotated \
415-
~<%roundTo(node.rot.x, 10)%> \
416-
~<%roundTo(node.rot.y, 10)%> \
412+
~<%roundTo(node.rot[0], 10)%> \
413+
~<%roundTo(node.rot[1], 10)%> \
417414
run {
418415
<%%
419416
emit.mcb(node.commands)
@@ -423,13 +420,12 @@ dir <%export_namespace%> {
423420
} ELSE IF (node.type === 'camera') {
424421
IF (rig.nodeMap[node.uuid]) {
425422
<%%
426-
global.rot = getRotationFromQuaternion(node.rot)
427423
global.merged.cameras[node.name] = {
428-
posx: node.pos.x,
429-
posy: node.pos.y,
430-
posz: node.pos.z,
431-
rotx: global.rot.x,
432-
roty: global.rot.y
424+
posx: node.pos[0],
425+
posy: node.pos[1],
426+
posz: node.pos[2],
427+
rotx: node.rot[0],
428+
roty: node.rot[1]
433429
}
434430
%%>
435431
}

src/systems/animationRenderer.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { TextDisplay } from '../outliner/textDisplay'
99
import { VanillaBlockDisplay } from '../outliner/vanillaBlockDisplay'
1010
import { VanillaItemDisplay } from '../outliner/vanillaItemDisplay'
1111
import { toSafeFuntionName } from '../util/minecraftUtil'
12-
import { roundToNth } from '../util/misc'
12+
import { eulerFromQuaternion, roundToNth } from '../util/misc'
1313
import { AnyRenderedNode, IRenderedRig } from './rigRenderer'
1414
import * as crypto from 'crypto'
1515

@@ -29,10 +29,6 @@ function getNodeMatrix(node: OutlinerElement, scale: number) {
2929
matrixWorld.setPosition(pos)
3030

3131
const scaleVec = new THREE.Vector3().setScalar(scale)
32-
// Hacky way to force the matrix to update in-game
33-
// scaleVec.x += Math.random() * 0.00001
34-
// scaleVec.y += Math.random() * 0.00001
35-
// scaleVec.z += Math.random() * 0.00001
3632
matrixWorld.scale(scaleVec)
3733

3834
if (node instanceof TextDisplay) {
@@ -44,15 +40,28 @@ function getNodeMatrix(node: OutlinerElement, scale: number) {
4440
return matrixWorld
4541
}
4642

43+
function getDecomposedTransformation(matrix: THREE.Matrix4) {
44+
const translation = new THREE.Vector3()
45+
const left_rotation = new THREE.Quaternion()
46+
const scale = new THREE.Vector3()
47+
matrix.decompose(translation, left_rotation, scale)
48+
return { translation, left_rotation, scale }
49+
}
50+
4751
export interface IAnimationNode {
4852
type: 'bone' | 'camera' | 'locator' | 'text_display' | 'item_display' | 'block_display'
4953
name: string
5054
uuid: string
5155
node?: Group | NullObject | Locator | OutlinerElement | TextDisplay
5256
matrix: THREE.Matrix4
53-
pos: THREE.Vector3
54-
rot: THREE.Quaternion
55-
scale: THREE.Vector3
57+
transformation: {
58+
translation: THREE.Vector3
59+
left_rotation: THREE.Quaternion
60+
scale: THREE.Vector3
61+
}
62+
pos: ArrayVector3
63+
rot: ArrayVector3
64+
scale: ArrayVector3
5665
interpolation?: 'step' | 'pre-post'
5766
/**
5867
* Commands is only set for locator nodes
@@ -190,16 +199,18 @@ export function getAnimationNodes(
190199
const rot = new THREE.Quaternion()
191200
const scale = new THREE.Vector3()
192201
matrix.decompose(pos, rot, scale)
202+
const decomposed = getDecomposedTransformation(matrix)
193203

194204
nodes.push({
195205
type: node.type,
196206
name: node.name,
197207
uuid,
198208
node: node.node,
199209
matrix,
200-
pos,
201-
rot,
202-
scale,
210+
transformation: decomposed,
211+
pos: [pos.x, pos.y, pos.z],
212+
rot: eulerFromQuaternion(rot).toArray(),
213+
scale: [scale.x, scale.y, scale.z],
203214
interpolation,
204215
commands,
205216
execute_condition: executeCondition,
@@ -291,9 +302,9 @@ export function hashAnimations(animations: IRenderedAnimation[]) {
291302
hash.update(';' + frame.time.toString())
292303
for (const node of frame.nodes) {
293304
hash.update(';' + node.uuid)
294-
hash.update(';' + node.pos.toArray().join(';'))
295-
hash.update(';' + node.rot.toArray().join(';'))
296-
hash.update(';' + node.scale.toArray().join(';'))
305+
hash.update(';' + node.pos.join(';'))
306+
hash.update(';' + node.rot.join(';'))
307+
hash.update(';' + node.scale.join(';'))
297308
node.interpolation && hash.update(';' + node.interpolation)
298309
if (node.commands) hash.update(';' + node.commands)
299310
if (node.execute_condition) hash.update(';' + node.execute_condition)

src/systems/datapackCompiler.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
matrixToNbtFloatArray,
1212
replacePathPart,
1313
sortObjectKeys,
14+
transformationToNbt,
1415
zip,
1516
} from './util'
1617
import { BoneConfig, TextDisplayConfig } from '../nodeConfigs'
@@ -23,7 +24,7 @@ import {
2324
} from '../util/minecraftUtil'
2425
import { JsonText } from './minecraft/jsonText'
2526
import { MAX_PROGRESS, PROGRESS, PROGRESS_DESCRIPTION } from '../interface/exportProgressDialog'
26-
import { getRotationFromQuaternion, roundTo } from '../util/misc'
27+
import { eulerFromQuaternion, roundTo } from '../util/misc'
2728
import { setTimeout } from 'timers'
2829

2930
const BONE_TYPES = ['bone', 'text_display', 'item_display', 'block_display']
@@ -467,13 +468,12 @@ function createPassengerStorage(rig: IRenderedRig) {
467468
switch (node.type) {
468469
case 'locator':
469470
case 'camera': {
470-
const rot = getRotationFromQuaternion(node.rot)
471471
const data = new NbtCompound()
472-
.set('posx', new NbtFloat(node.pos.x))
473-
.set('posy', new NbtFloat(node.pos.y))
474-
.set('posz', new NbtFloat(node.pos.z))
475-
.set('rotx', new NbtFloat(Math.radToDeg(rot.x)))
476-
.set('roty', new NbtFloat(Math.radToDeg(rot.y)))
472+
.set('posx', new NbtFloat(node.pos[0]))
473+
.set('posy', new NbtFloat(node.pos[1]))
474+
.set('posz', new NbtFloat(node.pos[2]))
475+
.set('rotx', new NbtFloat(Math.radToDeg(node.rot[0])))
476+
.set('roty', new NbtFloat(Math.radToDeg(node.rot[1])))
477477
if (
478478
node.type === 'locator' &&
479479
(rig.nodeMap[node.uuid].node as Locator).config.use_entity
@@ -605,6 +605,7 @@ export async function compileDataPack(options: {
605605
TELLRAW,
606606
custom_summon_commands: aj.summon_commands,
607607
matrixToNbtFloatArray,
608+
transformationToNbt,
608609
use_storage_for_animation: aj.use_storage_for_animation,
609610
animationStorage: createAnimationStorage(animations),
610611
rigHash,
@@ -613,7 +614,7 @@ export async function compileDataPack(options: {
613614
BoneConfig,
614615
roundTo,
615616
nodeSorter,
616-
getRotationFromQuaternion,
617+
getRotationFromQuaternion: eulerFromQuaternion,
617618
}
618619
console.log('Compiler Variables:', variables)
619620

src/systems/jsonExporter.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ import type {
1414
IRenderedRig,
1515
} from './rigRenderer'
1616

17-
type ExportedAnimationNode = Omit<IAnimationNode, 'node' | 'matrix' | 'pos' | 'rot' | 'scale'> & {
17+
type ExportedAnimationNode = Omit<IAnimationNode, 'node' | 'matrix' | 'transformation'> & {
1818
matrix: number[]
19+
transformation: {
20+
translation: ArrayVector3
21+
left_rotation: ArrayVector4
22+
scale: ArrayVector3
23+
}
1924
pos: ArrayVector3
2025
rot: ArrayVector3
2126
scale: ArrayVector3
@@ -191,9 +196,14 @@ function serailizeAnimationNode(node: IAnimationNode): ExportedAnimationNode {
191196
name: node.name,
192197
uuid: node.uuid,
193198
matrix: node.matrix.elements,
194-
pos: [node.pos.x, node.pos.y, node.pos.z],
195-
rot: [node.rot.x, node.rot.y, node.rot.z],
196-
scale: [node.scale.x, node.scale.y, node.scale.z],
199+
transformation: {
200+
translation: node.transformation.translation.toArray(),
201+
left_rotation: node.transformation.left_rotation.toArray() as ArrayVector4,
202+
scale: node.transformation.scale.toArray(),
203+
},
204+
pos: node.pos,
205+
rot: node.rot,
206+
scale: node.scale,
197207
interpolation: node.interpolation,
198208
commands: node.commands,
199209
execute_condition: node.execute_condition,

src/systems/util.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NbtFloat, NbtList } from 'deepslate/lib/nbt'
1+
import { NbtCompound, NbtFloat, NbtList } from 'deepslate/lib/nbt'
22
import {
33
AsyncZipOptions,
44
AsyncZippable,
@@ -7,6 +7,7 @@ import {
77
type AsyncUnzipOptions,
88
type Unzipped,
99
} from 'fflate/browser'
10+
import { IAnimationNode } from './animationRenderer'
1011

1112
export function arrayToNbtFloatArray(array: number[]) {
1213
return new NbtList(array.map(v => new NbtFloat(v)))
@@ -17,6 +18,14 @@ export function matrixToNbtFloatArray(matrix: THREE.Matrix4) {
1718
return arrayToNbtFloatArray(matrixArray)
1819
}
1920

21+
export function transformationToNbt(transformation: IAnimationNode['transformation']): NbtCompound {
22+
const compound = new NbtCompound()
23+
compound.set('translation', arrayToNbtFloatArray(transformation.translation.toArray()))
24+
compound.set('left_rotation', arrayToNbtFloatArray(transformation.left_rotation.toArray()))
25+
compound.set('scale', arrayToNbtFloatArray(transformation.scale.toArray()))
26+
return compound
27+
}
28+
2029
export function replacePathPart(path: string, oldPart: string, newPart: string) {
2130
return path
2231
.split(PathModule.sep)

src/util/misc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function detectCircularReferences(obj: any): boolean {
103103
}
104104
}
105105

106-
export function getRotationFromQuaternion(q: THREE.Quaternion) {
106+
export function eulerFromQuaternion(q: THREE.Quaternion) {
107107
const euler = new THREE.Euler().setFromQuaternion(q, 'YXZ')
108108
const rot = new THREE.Vector3(euler.x, euler.y, euler.z).multiplyScalar(180 / Math.PI)
109109
rot.x *= -1

test_blueprints/armor_stand.ajblueprint

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"meta": {
33
"format": "animated_java_blueprint",
4-
"format_version": "0.5.7",
4+
"format_version": "0.5.8",
55
"uuid": "167b27cd-b559-3f13-a97c-0841fe21f1d1",
66
"save_location": "D:\\github-repos\\animated-java\\animated-java\\test_blueprints\\armor_stand.ajblueprint",
77
"last_used_export_namespace": "armor_stand"
@@ -11,7 +11,7 @@
1111
"show_bounding_box": false,
1212
"auto_bounding_box": true,
1313
"bounding_box": [95, 32],
14-
"enable_plugin_mode": false,
14+
"enable_plugin_mode": true,
1515
"resource_pack_export_mode": "raw",
1616
"data_pack_export_mode": "raw",
1717
"display_item": "minecraft:white_dye",
@@ -27,7 +27,7 @@
2727
"interpolation_duration": 1,
2828
"teleportation_duration": 1,
2929
"use_storage_for_animation": false,
30-
"baked_animations": false,
30+
"baked_animations": true,
3131
"json_file": "D:\\github-repos\\animated-java\\animated-java\\dist\\test.json",
3232
"custom_summon_commands": ""
3333
},

0 commit comments

Comments
 (0)