Skip to content
This repository was archived by the owner on Mar 22, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ maven.install(
"org.antlr:antlr4-runtime:4.13.1",
"io.github.douira:glsl-transformer:2.0.1",
"org.anarres:jcpp:1.4.14",
"com.illposed.osc:javaosc-core:0.9",

# test dependencies
"org.jetbrains.kotlin:kotlin-test-junit5:2.1.10",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,34 +90,57 @@ sealed class Expression {
vrm0Name = "LookRight",
vrm1Name = "lookRight",
);

companion object {
private val vrm0NameMap = entries
.mapNotNull { it.takeIf { it.vrm0Name != null } }
.associateBy { it.vrm0Name!!.lowercase() }

private val vrm1NameMap = entries
.mapNotNull { it.takeIf { it.vrm1Name != null } }
.associateBy { it.vrm1Name!!.lowercase() }

private val pmxJapaneseMap = entries
.mapNotNull { it.takeIf { it.pmxJapanese != null } }
.associateBy { it.pmxJapanese!!.lowercase() }

private val pmxEnglishMap = entries
.mapNotNull { it.takeIf { it.pmxEnglish != null } }
.associateBy { it.pmxEnglish!!.lowercase() }

fun fromVrm0Name(name: String): Tag? = vrm0NameMap[name.lowercase()]
fun fromVrm1Name(name: String): Tag? = vrm1NameMap[name.lowercase()]
fun fromPmxJapanese(name: String): Tag? = pmxJapaneseMap[name.lowercase()]
fun fromPmxEnglish(name: String): Tag? = pmxEnglishMap[name.lowercase()]
}
}

data class Target(
override val name: String? = null,
override val tag: Tag? = null,
val isBinary: Boolean = false,
val bindings: List<Binding>,
): Expression() {
) : Expression() {
sealed class Binding {
data class NodeMorphTarget(
val nodeId: NodeId,
val index: Int,
val weight: Float,
): Binding()
) : Binding()

data class MeshMorphTarget(
val meshId: MeshId,
val index: Int,
val weight: Float,
): Binding()
) : Binding()
}
}

data class Group(
override val name: String? = null,
override val tag: Tag? = null,
val targets: List<TargetItem>,
): Expression() {
) : Expression() {
data class TargetItem(
val target: Target,
val influence: Float,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,98 @@
package top.fifthlight.blazerod.model

// VRM spec: https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/humanoid.md#list-of-humanoid-bones
// PMX reference: https://vrstormlab.com/dancexr/features/bones
enum class HumanoidTag(
val vrmName: String? = null,
val pmxEnglish: String? = null,
val pmxJapanese: String? = null,
) {
CENTER(vrmName = "hips", pmxEnglish = "Root", pmxJapanese = "センター"),
HEAD(vrmName = "head", pmxEnglish = "Head", pmxJapanese = "頭");
// Torso
HIPS(vrmName = "hips", pmxEnglish = "Center", pmxJapanese = "センター"),
SPINE(vrmName = "spine", pmxEnglish = "Torso", pmxJapanese = "上半身"),
CHEST(vrmName = "chest", pmxEnglish = "Torso2", pmxJapanese = "上半身2"),
UPPER_CHEST(vrmName = "upperChest"),
NECK(vrmName = "neck", pmxEnglish = "Neck", pmxJapanese = "首"),

// Head
HEAD(vrmName = "head", pmxEnglish = "Head", pmxJapanese = "頭"),

// Disable them because we have no correct VRM gaze control
// LEFT_EYE(vrmName = "leftEye", pmxEnglish = "LeftEye", pmxJapanese = "左目"),
// RIGHT_EYE(vrmName = "rightEye", pmxEnglish = "RightEye", pmxJapanese = "右目"),
JAW(vrmName = "jaw"),

// Leg
LEFT_UPPER_LEG(vrmName = "leftUpperLeg", pmxEnglish = "LeftLeg", pmxJapanese = "左足"),
LEFT_LOWER_LEG(vrmName = "leftLowerLeg", pmxEnglish = "LeftKnee", pmxJapanese = "左ひざ"),
LEFT_FOOT(vrmName = "leftFoot", pmxEnglish = "LeftAnkle", pmxJapanese = "左足首"),
LEFT_TOES(vrmName = "leftToes", pmxEnglish = "LeftToe", pmxJapanese = "左つま先"),
RIGHT_UPPER_LEG(vrmName = "rightUpperLeg", pmxEnglish = "RightLeg", pmxJapanese = "右足"),
RIGHT_LOWER_LEG(vrmName = "rightLowerLeg", pmxEnglish = "RightKnee", pmxJapanese = "右ひざ"),
RIGHT_FOOT(vrmName = "rightFoot", pmxEnglish = "RightAnkle", pmxJapanese = "右足首"),
RIGHT_TOES(vrmName = "rightToes", pmxEnglish = "RightToe", pmxJapanese = "右つま先"),

// Arm
LEFT_SHOULDER(vrmName = "leftShoulder", pmxEnglish = "LeftShoulder", pmxJapanese = "左肩"),
LEFT_UPPER_ARM(vrmName = "leftUpperArm", pmxEnglish = "LeftArm", pmxJapanese = "左腕"),
LEFT_LOWER_ARM(vrmName = "leftLowerArm", pmxEnglish = "LeftElbow", pmxJapanese = "左ひじ"),
LEFT_HAND(vrmName = "leftHand", pmxEnglish = "LeftWrist", pmxJapanese = "左手首"),
RIGHT_SHOULDER(vrmName = "rightShoulder", pmxEnglish = "RightShoulder", pmxJapanese = "右肩"),
RIGHT_UPPER_ARM(vrmName = "rightUpperArm", pmxEnglish = "RightArm", pmxJapanese = "右腕"),
RIGHT_LOWER_ARM(vrmName = "rightLowerArm", pmxEnglish = "RightElbow", pmxJapanese = "右ひじ"),
RIGHT_HAND(vrmName = "rightHand", pmxEnglish = "RightWrist", pmxJapanese = "右手首"),

// Finger
LEFT_THUMB_METACARPAL(vrmName = "leftThumbMetacarpal", pmxEnglish = "LeftThumb1", pmxJapanese = "左親指1"),
LEFT_THUMB_PROXIMAL(vrmName = "leftThumbProximal", pmxEnglish = "LeftThumb2", pmxJapanese = "左親指2"),
LEFT_THUMB_DISTAL(vrmName = "leftThumbDistal", pmxEnglish = "LeftThumb3", pmxJapanese = "左親指3"),
LEFT_INDEX_PROXIMAL(vrmName = "leftIndexProximal", pmxEnglish = "LeftIndexFinger1", pmxJapanese = "左人指1"),
LEFT_INDEX_INTERMEDIATE(
vrmName = "leftIndexIntermediate",
pmxEnglish = "LeftIndexFinger2",
pmxJapanese = "左人指2"
),
LEFT_INDEX_DISTAL(vrmName = "leftIndexDistal", pmxEnglish = "LeftIndexFinger3", pmxJapanese = "左人指3"),
LEFT_MIDDLE_PROXIMAL(vrmName = "leftMiddleProximal", pmxEnglish = "LeftMiddleFinger1", pmxJapanese = "左中指1"),
LEFT_MIDDLE_INTERMEDIATE(
vrmName = "leftMiddleIntermediate",
pmxEnglish = "LeftMiddleFinger2",
pmxJapanese = "左中指2"
),
LEFT_MIDDLE_DISTAL(vrmName = "leftMiddleDistal", pmxEnglish = "LeftMiddleFinger3", pmxJapanese = "左中指3"),
LEFT_RING_PROXIMAL(vrmName = "leftRingProximal", pmxEnglish = "LeftRingFinger1", pmxJapanese = "左薬指1"),
LEFT_RING_INTERMEDIATE(vrmName = "leftRingIntermediate", pmxEnglish = "LeftRingFinger2", pmxJapanese = "左薬指2"),
LEFT_RING_DISTAL(vrmName = "leftRingDistal", pmxEnglish = "LeftRingFinger3", pmxJapanese = "左薬指3"),
LEFT_LITTLE_PROXIMAL(vrmName = "leftLittleProximal", pmxEnglish = "LeftPinky1", pmxJapanese = "左小指1"),
LEFT_LITTLE_INTERMEDIATE(vrmName = "leftLittleIntermediate", pmxEnglish = "LeftPinky2", pmxJapanese = "左小指2"),
LEFT_LITTLE_DISTAL(vrmName = "leftLittleDistal", pmxEnglish = "LeftPinky3", pmxJapanese = "左小指3"),
RIGHT_THUMB_METACARPAL(vrmName = "rightThumbMetacarpal", pmxEnglish = "RightThumb1", pmxJapanese = "右親指1"),
RIGHT_THUMB_PROXIMAL(vrmName = "rightThumbProximal", pmxEnglish = "RightThumb2", pmxJapanese = "右親指2"),
RIGHT_THUMB_DISTAL(vrmName = "rightThumbDistal", pmxEnglish = "RightThumb3", pmxJapanese = "右親指3"),
RIGHT_INDEX_PROXIMAL(vrmName = "rightIndexProximal", pmxEnglish = "RightIndexFinger1", pmxJapanese = "右人指1"),
RIGHT_INDEX_INTERMEDIATE(
vrmName = "rightIndexIntermediate",
pmxEnglish = "RightIndexFinger2",
pmxJapanese = "右人指2"
),
RIGHT_INDEX_DISTAL(vrmName = "rightIndexDistal", pmxEnglish = "RightIndexFinger3", pmxJapanese = "右人指3"),
RIGHT_MIDDLE_PROXIMAL(vrmName = "rightMiddleProximal", pmxEnglish = "RightMiddleFinger1", pmxJapanese = "右中指1"),
RIGHT_MIDDLE_INTERMEDIATE(
vrmName = "rightMiddleIntermediate",
pmxEnglish = "RightMiddleFinger2",
pmxJapanese = "右中指2"
),
RIGHT_MIDDLE_DISTAL(vrmName = "rightMiddleDistal", pmxEnglish = "RightMiddleFinger3", pmxJapanese = "右中指3"),
RIGHT_RING_PROXIMAL(vrmName = "rightRingProximal", pmxEnglish = "RightRingFinger1", pmxJapanese = "右薬指1"),
RIGHT_RING_INTERMEDIATE(
vrmName = "rightRingIntermediate",
pmxEnglish = "RightRingFinger2",
pmxJapanese = "右薬指2"
),
RIGHT_RING_DISTAL(vrmName = "rightRingDistal", pmxEnglish = "RightRingFinger3", pmxJapanese = "右薬指3"),
RIGHT_LITTLE_PROXIMAL(vrmName = "rightLittleProximal", pmxEnglish = "RightPinky1", pmxJapanese = "右小指1"),
RIGHT_LITTLE_INTERMEDIATE(vrmName = "rightLittleIntermediate", pmxEnglish = "RightPinky2", pmxJapanese = "右小指2"),
RIGHT_LITTLE_DISTAL(vrmName = "rightLittleDistal", pmxEnglish = "RightPinky3", pmxJapanese = "右小指3");

companion object {
private val vrmNameMap = entries.associateBy { it.vrmName }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,7 @@ internal class GltfLoader(
expressions = vrmV0.map { expression ->
Expression.Target(
name = expression.name,
tag = Expression.Tag.entries.firstOrNull {
it.vrm0Name.equals(expression.presetName, ignoreCase = true)
},
tag = expression.presetName?.let(Expression.Tag::fromVrm0Name),
bindings = expression.binds?.map { bind ->
Expression.Target.Binding.MeshMorphTarget(
meshId = MeshId(uuid, bind.mesh),
Expand All @@ -587,9 +585,7 @@ internal class GltfLoader(
Expression.Target(
name = name,
isBinary = value.isBinary ?: false,
tag = Expression.Tag.entries.firstOrNull {
it.vrm1Name.equals(name, ignoreCase = true)
},
tag = Expression.Tag.fromVrm1Name(name),
bindings = value.morphTargetBinds?.map { bind ->
Expression.Target.Binding.NodeMorphTarget(
nodeId = NodeId(uuid, bind.node),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -739,8 +739,7 @@ class PmxLoader : ModelFileLoader {
val nameLocal = loadString(buffer)
val nameUniversal = loadString(buffer)
val expressionTag =
Expression.Tag.entries.firstOrNull { it.pmxJapanese.equals(nameLocal, ignoreCase = true) }
?: Expression.Tag.entries.firstOrNull { it.pmxEnglish.equals(nameUniversal, ignoreCase = true) }
Expression.Tag.fromPmxJapanese(nameLocal) ?: Expression.Tag.fromPmxEnglish(nameUniversal)
val panelType = buffer.get().toInt()
.let { type -> PmxMorphPanelType.entries.firstOrNull { it.value == type } }
?: throw PmxLoadException("Unknown panel type")
Expand Down
57 changes: 53 additions & 4 deletions maven_install.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
"__INPUT_ARTIFACTS_HASH": 668299150,
"__RESOLVED_ARTIFACTS_HASH": -119811499,
"__INPUT_ARTIFACTS_HASH": -570601380,
"__RESOLVED_ARTIFACTS_HASH": -144996448,
"conflict_resolution": {
"com.google.code.gson:gson:2.8.9": "com.google.code.gson:gson:2.10.1",
"com.google.errorprone:error_prone_annotations:2.23.0": "com.google.errorprone:error_prone_annotations:2.24.1",
Expand Down Expand Up @@ -179,6 +179,12 @@
},
"version": "72.1"
},
"com.illposed.osc:javaosc-core": {
"shasums": {
"jar": "9d2b8011ca8046cd8685911ae5d1b989c4fe424cbf372303f6af41e62ae770ec"
},
"version": "0.9"
},
"com.squareup.okhttp:okhttp": {
"shasums": {
"jar": "88ac9fd1bb51f82bcc664cc1eb9c225c90dc4389d660231b4cc737bebfe7d0aa"
Expand Down Expand Up @@ -967,9 +973,15 @@
},
"org.slf4j:slf4j-api": {
"shasums": {
"jar": "18c4a0095d5c1da6b817592e767bb23d29dd2f560ad74df75ff3961dbde25b79"
"jar": "e7c2a48e8515ba1f49fa637d57b4e2f590b3f5bd97407ac699c3aa5efb1204a9"
},
"version": "1.7.25"
"version": "2.0.13"
},
"org.slf4j:slf4j-ext": {
"shasums": {
"jar": "9963ed4a45df1ad7d197f6940e99b8063edab645370d427bea4901bad5846c95"
},
"version": "2.0.13"
},
"org.vineflower:vineflower": {
"shasums": {
Expand Down Expand Up @@ -1100,6 +1112,10 @@
"org.checkerframework:checker-qual",
"org.ow2.asm:asm"
],
"com.illposed.osc:javaosc-core": [
"org.slf4j:slf4j-api",
"org.slf4j:slf4j-ext"
],
"com.squareup.okhttp:okhttp": [
"com.squareup.okio:okio"
],
Expand Down Expand Up @@ -1477,6 +1493,9 @@
"org.ow2.asm:asm",
"org.ow2.asm:asm-analysis",
"org.ow2.asm:asm-tree"
],
"org.slf4j:slf4j-ext": [
"org.slf4j:slf4j-api"
]
},
"packages": {
Expand Down Expand Up @@ -1885,6 +1904,16 @@
"com.ibm.icu.text",
"com.ibm.icu.util"
],
"com.illposed.osc:javaosc-core": [
"com.illposed.osc",
"com.illposed.osc.argument",
"com.illposed.osc.argument.handler",
"com.illposed.osc.messageselector",
"com.illposed.osc.transport",
"com.illposed.osc.transport.channel",
"com.illposed.osc.transport.tcp",
"com.illposed.osc.transport.udp"
],
"com.squareup.okhttp:okhttp": [
"com.squareup.okhttp",
"com.squareup.okhttp.internal",
Expand Down Expand Up @@ -3180,6 +3209,14 @@
"org.slf4j.helpers",
"org.slf4j.spi"
],
"org.slf4j:slf4j-ext": [
"org.slf4j",
"org.slf4j.agent",
"org.slf4j.cal10n",
"org.slf4j.ext",
"org.slf4j.instrumentation",
"org.slf4j.profiler"
],
"org.vineflower:vineflower": [
"net.fabricmc.fernflower.api",
"org.jetbrains.java.decompiler.api",
Expand Down Expand Up @@ -3248,6 +3285,7 @@
"com.google.truth:truth",
"com.h2database:h2",
"com.ibm.icu:icu4j",
"com.illposed.osc:javaosc-core",
"com.squareup.okhttp:okhttp",
"com.squareup.okio:okio",
"com.sun.jersey:jersey-client",
Expand Down Expand Up @@ -3380,6 +3418,7 @@
"org.ow2.asm:asm-tree",
"org.ow2.asm:asm-util",
"org.slf4j:slf4j-api",
"org.slf4j:slf4j-ext",
"org.vineflower:vineflower"
],
"https://maven.fabricmc.net/": [
Expand Down Expand Up @@ -3411,6 +3450,7 @@
"com.google.truth:truth",
"com.h2database:h2",
"com.ibm.icu:icu4j",
"com.illposed.osc:javaosc-core",
"com.squareup.okhttp:okhttp",
"com.squareup.okio:okio",
"com.sun.jersey:jersey-client",
Expand Down Expand Up @@ -3543,6 +3583,7 @@
"org.ow2.asm:asm-tree",
"org.ow2.asm:asm-util",
"org.slf4j:slf4j-api",
"org.slf4j:slf4j-ext",
"org.vineflower:vineflower"
],
"https://maven.terraformersmc.com/": [
Expand Down Expand Up @@ -3574,6 +3615,7 @@
"com.google.truth:truth",
"com.h2database:h2",
"com.ibm.icu:icu4j",
"com.illposed.osc:javaosc-core",
"com.squareup.okhttp:okhttp",
"com.squareup.okio:okio",
"com.sun.jersey:jersey-client",
Expand Down Expand Up @@ -3706,6 +3748,7 @@
"org.ow2.asm:asm-tree",
"org.ow2.asm:asm-util",
"org.slf4j:slf4j-api",
"org.slf4j:slf4j-ext",
"org.vineflower:vineflower"
],
"https://maven.nucleoid.xyz/": [
Expand Down Expand Up @@ -3737,6 +3780,7 @@
"com.google.truth:truth",
"com.h2database:h2",
"com.ibm.icu:icu4j",
"com.illposed.osc:javaosc-core",
"com.squareup.okhttp:okhttp",
"com.squareup.okio:okio",
"com.sun.jersey:jersey-client",
Expand Down Expand Up @@ -3869,6 +3913,7 @@
"org.ow2.asm:asm-tree",
"org.ow2.asm:asm-util",
"org.slf4j:slf4j-api",
"org.slf4j:slf4j-ext",
"org.vineflower:vineflower"
],
"https://masa.dy.fi/maven/": [
Expand Down Expand Up @@ -3900,6 +3945,7 @@
"com.google.truth:truth",
"com.h2database:h2",
"com.ibm.icu:icu4j",
"com.illposed.osc:javaosc-core",
"com.squareup.okhttp:okhttp",
"com.squareup.okio:okio",
"com.sun.jersey:jersey-client",
Expand Down Expand Up @@ -4032,6 +4078,7 @@
"org.ow2.asm:asm-tree",
"org.ow2.asm:asm-util",
"org.slf4j:slf4j-api",
"org.slf4j:slf4j-ext",
"org.vineflower:vineflower"
],
"https://api.modrinth.com/maven/": [
Expand Down Expand Up @@ -4063,6 +4110,7 @@
"com.google.truth:truth",
"com.h2database:h2",
"com.ibm.icu:icu4j",
"com.illposed.osc:javaosc-core",
"com.squareup.okhttp:okhttp",
"com.squareup.okio:okio",
"com.sun.jersey:jersey-client",
Expand Down Expand Up @@ -4195,6 +4243,7 @@
"org.ow2.asm:asm-tree",
"org.ow2.asm:asm-util",
"org.slf4j:slf4j-api",
"org.slf4j:slf4j-ext",
"org.vineflower:vineflower"
]
},
Expand Down
Loading