Отказ от ответственности: я не 3D-моделист и не аниматор, новичок...
Мои сильные стороны: Front-End Dev, аудиоинженерия, C#, Julia (сейчас я использую ChatGPT для Python и ненавижу его. Код внизу).
Я работаю в Blender 5.0 (модель изначально взята из Maya) с академической установкой FBX для гортани.
3D-модель гортани, исходный код FBX
Модель содержит каркас с костями с анатомическими названиями и несколько запеченных анимационных действий. Моя цель — удалить всю запеченную анимацию и заменить ее процедурным управлением с использованием драйверов, чтобы установка могла позже управляться внешними сигналами (аудио/ИИ).
Я написал скрипт Python, который очищает данные анимации на арматуре, удаляет все действия, добавляет к арматуре пользовательские свойства и устанавливает скриптовые драйверы на определенные кости позы (положение, вращение, масштаб). Скрипт выполняется с ошибками, появляются некоторые пользовательские свойства и создаются драйверы, но перемещение ползунков пользовательских свойств не приводит к перемещению костей.
Я пытаюсь понять, чего мне не хватает в архитектурном отношении, а не просто исправлять синтаксис. Возможные проблемы, которые я рассматриваю:
- неправильные пути к данным для драйверов костей позы.
- необходимость явного задания режима вращения костей позы.
- трансформации переопределяются позой покоя или ограничениями.
- драйверы создаются, но не оцениваются.
- ограничения драйверов на костях позы при отсутствии ключевых кадров
- неправильное наименование арматуры или проблемы с контекстом
- полного удаления запеченной анимации из импортированной rig, и
- процедурно управлять костями позы, используя пользовательские свойства или внешние входные данные.
Моя КОНЕЧНАЯ цель — анимировать это в Three.js иorbitcontrols.js и мне нужно вызвать отдельные узлы или драйверы или что-то еще, чтобы заставить их перейти к аудио. Я сделал это с черепом, теперь пробую гортань и легкие, которые уже имеют гладкую поверхность и имеют элементы управления анимацией. Тогда крутой скайбокс.
import bpy
import math
# =====================================================
# CONFIG
# =====================================================
ARMATURE_NAME = "LarynxRig"
# =====================================================
# UTILITIES
# =====================================================
def get_armature(name):
obj = bpy.data.objects.get(name)
if not obj:
raise RuntimeError(f"Armature '{name}' not found")
if obj.type != 'ARMATURE':
raise RuntimeError(f"Object '{name}' is not an armature")
return obj
def clear_object_animation(obj):
if obj.animation_data:
obj.animation_data_clear()
def ensure_prop(obj, name, default=0.0):
if name not in obj:
obj[name] = default
ui = obj.id_properties_ui(name)
ui.update(
min=-1.0,
max=1.0,
soft_min=-1.0,
soft_max=1.0
)
def add_driver(pose_bone, data_path, index, prop_name, scale):
fcurve = pose_bone.driver_add(data_path, index)
drv = fcurve.driver
drv.type = 'SCRIPTED'
var = drv.variables.new()
var.name = "x"
var.targets[0].id = arm
var.targets[0].data_path = f'["{prop_name}"]'
drv.expression = f"x * {scale}"
# =====================================================
# STEP 1: GET ARMATURE
# =====================================================
arm = get_armature(ARMATURE_NAME)
# Ensure Object Mode
if bpy.context.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
# =====================================================
# STEP 2: STRIP ALL BAKED ANIMATION
# =====================================================
clear_object_animation(arm)
# Remove all Actions (safe for this file)
for action in list(bpy.data.actions):
bpy.data.actions.remove(action)
print("✔ Baked animations stripped")
# =====================================================
# STEP 3: CREATE PROCEDURAL CONTROL PROPERTIES
# =====================================================
ensure_prop(arm, "larynx_lift", 0.0) # pitch / emphasis
ensure_prop(arm, "inlet_constrict", 0.0) # voiced vs unvoiced
ensure_prop(arm, "epiglottis_tilt", 0.0) # swallow / shielding
ensure_prop(arm, "airflow", 0.0) # breath intensity
print("✔ Control properties installed")
# =====================================================
# STEP 4: INSTALL PROCEDURAL DRIVERS
# =====================================================
# ---- Larynx vertical movement (pitch, emphasis)
if "Larynx_ROOT" in arm.pose.bones:
pb = arm.pose.bones["Larynx_ROOT"]
add_driver(pb, "location", 1, "larynx_lift", 0.02)
# ---- Top half larynx tilt (epilaryngeal shaping)
if "B_Top_half_larynx" in arm.pose.bones:
pb = arm.pose.bones["B_Top_half_larynx"]
add_driver(pb, "rotation_euler", 0, "inlet_constrict", math.radians(8))
# ---- Corniculate cartilage constriction
if "B_Corniculate_cartilage" in arm.pose.bones:
pb = arm.pose.bones["B_Corniculate_cartilage"]
add_driver(pb, "location", 0, "inlet_constrict", -0.01)
# ---- Epiglottis tilt (secondary coupling)
if "B_Thyroepiglottic1" in arm.pose.bones:
pb = arm.pose.bones["B_Thyroepiglottic1"]
add_driver(pb, "rotation_euler", 0, "epiglottis_tilt", math.radians(10))
# ---- Trachea expansion (airflow feedback)
if "B_Trachea" in arm.pose.bones:
pb = arm.pose.bones["B_Trachea"]
add_driver(pb, "scale", 1, "airflow", 0.08)
print("✔ Procedural drivers installed")
print("
Подробнее здесь: https://stackoverflow.com/questions/798 ... bones-proc
Мобильная версия