发布时间:2026/8/18 14:18:43
【maya】在maya中对物体创建locator定位器做跟踪 用途灯光跟随 or 对角色某个顶点跟踪1、创建locator又名定位器有多种创建方式可以在创建下拉菜单中创建也可直接在绑定面板创建方法1方法22、maya使用情况一有一个情景角色在跑步和跳跃需要被聚光灯持续照射。对应角色在不停的运动灯光需要对角色跟踪的情况。第一步首先是创建locator随后将locator按住X吸附到物体身上选择子物体定位器 → 再选父物体角色 → 按P绑定父子级关系。这一步是让locator跟着角色运动第二步创建 SpotLight选择物体下的locator再选择需要被约束SpotLight做一个目标约束层级关系如下让Locator随着角色运动而运动了灯光始终对准角色不改变。物体移动↓带动Locator移动↓Spot Light跟随旋转运动↓灯光跟随物体甚至可以在目标约束的同时套娃一个父子约束让灯光不单单固定在原点对角色追踪像是把一个灯光绑定在摇臂上始终跟拍随角色运动locator的作用由于在项目中经常使用引用物体的abc因此物体是不允许改变的运动locator就起代替的作用例如希望对物体进行一个追光/扫光最后离开角色直接对locator进行动画的K帧就能较为轻易控制追光出现的位置。又或者比如灯光追踪目标晃动感直接给locator些表达式rotateY noise(time*0.5)*0.5;就可以使用上了。具体maya表达式怎么写直接问AI即可3、maya导出locator在nuke中使用一个情景是我需要把一个定位器放在角色身上某个位置例如角色带结算的耳环角色牙齿上角色手环这种角度刁钻的位置选择物体顶点创建一个铆钉会在角色身上生成一个始终跟随的定位器这个定位器生成跟随与角色顶点UV有关顶点UV错误情况下定位器也会有bug角色顶点定位器跟随的效果创建铆钉会发现虽然定位器可以始终跟随在角色身上但是pinOutput定位器的位移数值始终是0即使导出abc也没有正确的数值。解决方式是自己创建一个locator使用父子约束或者是点约束取消偏移让新的locator获取到pinOutput的位移数值选择locator烘焙关键帧再正常导出abc即可得到一个带位移的locator最后再nuke中按R选择路径下的locator.abc导入或者创建Axis读取还有一种办法是用Reconcile3D节点将三维的数据转为2d平面的跟踪数据这样好处是对一些比较刁钻的区域免去了手Kroto麻烦注意需要在copy时需减去原来的数值我将创建locator功能导出abc用ai快速写一个maya脚本# -*- coding: utf-8 -*- Maya 2022 Rivet - Locator - Bake - Alembic Tool 工作流 1. 选择模型上的 Vertex / Edge / Face 2. Create Rivet Locator 3. Maya 创建 uvPin pinOutput 4. 创建新的 Locator 5. pinOutput - Parent Constraint - Locator 6. Bake Locator 7. 删除约束和临时 Rivet 8. 可选择导出 Locator 为 Alembic Author: GPT import maya.cmds as cmds import maya.mel as mel import os WINDOW rivet_locator_tool # --------------------------------------------------------- # 工具函数 # --------------------------------------------------------- def get_selected_components(): 获取当前选择的模型组件 sel cmds.ls(slTrue, flTrue) if not sel: return [] components [] for item in sel: if . in item: components.append(item) return components def get_pin_outputs(): Rivet 执行后 Maya 会选择 uvPin pinOutput 找出其中的 pinOutput。 sel cmds.ls(slTrue, typetransform) outputs [] for obj in sel: if cmds.objExists(obj): # Maya Rivet 创建出来的输出 locator if pinOutput in obj: outputs.append(obj) return outputs def get_uvpin_nodes(): 获取当前场景中所有 uvPin return cmds.ls(typeuvPin) or [] def get_new_uvpin(before): 找出 Rivet 新创建的 uvPin after get_uvpin_nodes() for node in after: if node not in before: return node return None # --------------------------------------------------------- # 创建 Rivet # --------------------------------------------------------- def create_rivet_locator(*args): 选择 Vertex / Edge / Face 后 Component ↓ cmds.Rivet() ↓ uvPin ↓ pinOutput ↓ Parent Constraint ↓ Locator components get_selected_components() if not components: cmds.warning( 请先选择模型上的 Vertex / Edge / Face。 ) return # 检查是否来自同一个模型 meshes [] for comp in components: mesh comp.split(.)[0] if mesh not in meshes: meshes.append(mesh) if len(meshes) ! 1: cmds.warning( 一次操作请选择同一个模型上的组件。 ) return # 保存当前选择 original_selection list(components) # 记录创建前的 uvPin before_uvpin get_uvpin_nodes() try: # ------------------------------------------------- # Maya 原生 Rivet # ------------------------------------------------- cmds.select(original_selection, rTrue) cmds.Rivet() except Exception as e: cmds.warning( Rivet 创建失败{}.format(e) ) return # ----------------------------------------------------- # 找新创建的 uvPin # ----------------------------------------------------- uvpin get_new_uvpin(before_uvpin) # ----------------------------------------------------- # 找 pinOutput # ----------------------------------------------------- rivet_selection cmds.ls(slTrue, typetransform) or [] pin_outputs [] for obj in rivet_selection: if pinOutput in obj: pin_outputs.append(obj) if not pin_outputs: cmds.warning( 没有找到 Maya 创建的 pinOutput。 ) return # ----------------------------------------------------- # 如果选择多个组件会创建多个 pinOutput # ----------------------------------------------------- created_locators [] for pin_output in pin_outputs: # 创建新的真正 Locator locator cmds.spaceLocator( namebakedLocator# )[0] # ------------------------------------------------- # 先让 Locator 对齐 pinOutput # ------------------------------------------------- cmds.delete( cmds.parentConstraint( pin_output, locator, moFalse ) ) # ------------------------------------------------- # 再建立 Parent Constraint # ------------------------------------------------- constraint cmds.parentConstraint( pin_output, locator, moFalse )[0] created_locators.append( (locator, constraint, pin_output) ) # ----------------------------------------------------- # 重新选择 Locator # ----------------------------------------------------- cmds.select( [x[0] for x in created_locators], rTrue ) # ----------------------------------------------------- # UI 显示 # ----------------------------------------------------- cmds.inViewMessage( amghlRivet Locator Created/hl, posmidCenter, fadeTrue ) print() print(Rivet Locator 创建完成) print(uvPin :, uvpin) print(Locator :, [x[0] for x in created_locators]) print() # --------------------------------------------------------- # Bake Locator # --------------------------------------------------------- def bake_selected_locators(*args): Bake 当前选择的 Locator。 Bake 后 pinOutput ↓ Constraint ↓ Locator 变成 Locator translate / rotate 每帧都有 key locators cmds.ls(slTrue, typetransform) if not locators: cmds.warning( 请先选择需要 Bake 的 Locator。 ) return start cmds.playbackOptions( qTrue, minTrue ) end cmds.playbackOptions( qTrue, maxTrue ) # ----------------------------------------------------- # Bake # ----------------------------------------------------- cmds.bakeResults( locators, t(start, end), simulationTrue, sampleBy1, disableImplicitControlTrue, preserveOutsideKeysTrue, sparseAnimCurveBakeFalse, removeBakedAttributeFromLayerFalse, bakeOnOverrideLayerFalse, minimizeRotationTrue ) # ----------------------------------------------------- # 删除 Locator 上的约束 # ----------------------------------------------------- for locator in locators: constraints cmds.listRelatives( locator, typeconstraint ) or [] if constraints: cmds.delete(constraints) cmds.select(locators, rTrue) cmds.inViewMessage( amghlLocator Bake Complete/hl, posmidCenter, fadeTrue ) print(Bake 完成) print(locators) # --------------------------------------------------------- # Bake 清理 # --------------------------------------------------------- def bake_and_cleanup(*args): 一键完成 Bake ↓ 删除 Parent Constraint ↓ 删除 pinOutput ↓ 删除 uvPin locators cmds.ls(slTrue, typetransform) if not locators: cmds.warning( 请先选择需要 Bake 的 Locator。 ) return start cmds.playbackOptions( qTrue, minTrue ) end cmds.playbackOptions( qTrue, maxTrue ) # ----------------------------------------------------- # Bake # ----------------------------------------------------- cmds.bakeResults( locators, t(start, end), simulationTrue, sampleBy1, disableImplicitControlTrue, preserveOutsideKeysTrue, sparseAnimCurveBakeFalse, minimizeRotationTrue ) # ----------------------------------------------------- # 删除约束 # ----------------------------------------------------- for locator in locators: constraints cmds.listRelatives( locator, typeconstraint ) or [] if constraints: cmds.delete(constraints) # ----------------------------------------------------- # 删除对应 pinOutput # ----------------------------------------------------- for locator in locators: # 根据 Locator 名字无法可靠找到 pinOutput # 所以这里通过场景中的连接关系查找。 connections cmds.listConnections( locator, sTrue, dFalse ) or [] for node in connections: if cmds.nodeType(node) uvPin: outputs cmds.listConnections( node .outputMatrix, sFalse, dTrue ) or [] for output in outputs: if cmds.objExists(output): try: cmds.delete(output) except: pass try: cmds.delete(node) except: pass cmds.select(locators, rTrue) cmds.inViewMessage( amghlBake Cleanup Complete/hl, posmidCenter, fadeTrue ) # --------------------------------------------------------- # Alembic Export # --------------------------------------------------------- def export_selected_abc(*args): 导出当前选择的 Locator 为 Alembic。 locators cmds.ls(slTrue, typetransform) if not locators: cmds.warning( 请先选择需要导出的 Locator。 ) return # ----------------------------------------------------- # 获取路径 # ----------------------------------------------------- result cmds.fileDialog2( fileMode0, captionExport Alembic, fileFilterAlembic (*.abc) ) if not result: return filepath result[0] if not filepath.lower().endswith(.abc): filepath .abc # ----------------------------------------------------- # 时间范围 # ----------------------------------------------------- start cmds.playbackOptions( qTrue, minTrue ) end cmds.playbackOptions( qTrue, maxTrue ) # ----------------------------------------------------- # 加载 AbcExport # ----------------------------------------------------- if not cmds.pluginInfo( AbcExport, qTrue, loadedTrue ): try: cmds.loadPlugin(AbcExport) except: cmds.warning( 无法加载 AbcExport 插件。 ) return # ----------------------------------------------------- # Alembic Job # ----------------------------------------------------- root_flags for locator in locators: root_flags -root {}.format(locator) job ( -frameRange {} {} -uvWrite -worldSpace -writeVisibility -dataFormat ogawa {} -file {} ).format( start, end, root_flags, filepath ) try: cmds.AbcExport( jjob ) except Exception as e: cmds.warning( Alembic 导出失败{}.format(e) ) return cmds.inViewMessage( amghlABC Export Complete/hl, posmidCenter, fadeTrue ) print(Alembic exported:) print(filepath) # --------------------------------------------------------- # 一键流程 # --------------------------------------------------------- def create_bake_export(*args): 一键 Component ↓ Rivet ↓ Locator ↓ Bake ↓ Cleanup ↓ Export ABC create_rivet_locator() cmds.refresh() locators cmds.ls( slTrue, typetransform ) if not locators: return bake_and_cleanup() cmds.refresh() export_selected_abc() # --------------------------------------------------------- # UI # --------------------------------------------------------- def show_ui(): if cmds.window( WINDOW, existsTrue ): cmds.deleteUI(WINDOW) window cmds.window( WINDOW, titleRivet Locator Tool, sizeableTrue, widthHeight(420, 420) ) cmds.columnLayout( adjustableColumnTrue, rowSpacing8 ) cmds.separator( height10, stylenone ) cmds.text( labelRivet Locator Tool, fontboldLabelFont, height30 ) cmds.text( labelMaya 2022 / UV Pin Rivet Workflow, height20 ) cmds.separator( height10, stylein ) # ----------------------------------------------------- # Step 1 # ----------------------------------------------------- cmds.text( labelSTEP 1 | 选择模型组件, alignleft, fontboldLabelFont ) cmds.text( labelVertex / Edge / Face 均可, alignleft ) cmds.separator( height8, stylenone ) cmds.button( label① 创建 Rivet Locator, height45, backgroundColor(0.25, 0.45, 0.65), commandcreate_rivet_locator ) # ----------------------------------------------------- # Step 2 # ----------------------------------------------------- cmds.text( labelSTEP 2 | Bake, alignleft, fontboldLabelFont ) cmds.button( label② Bake Locator, height40, commandbake_selected_locators ) cmds.button( label③ Bake Cleanup Rivet, height40, commandbake_and_cleanup ) # ----------------------------------------------------- # Step 3 # ----------------------------------------------------- cmds.text( labelSTEP 3 | Alembic, alignleft, fontboldLabelFont ) cmds.button( label④ Export Selected Locator → ABC, height45, backgroundColor(0.35, 0.55, 0.35), commandexport_selected_abc ) cmds.separator( height10, stylein ) # ----------------------------------------------------- # One Click # ----------------------------------------------------- cmds.button( label一键Rivet → Bake → Cleanup → ABC, height50, backgroundColor(0.55, 0.40, 0.20), commandcreate_bake_export ) cmds.separator( height10, stylenone ) cmds.showWindow(window) # --------------------------------------------------------- # Run # --------------------------------------------------------- show_ui()

相关新闻

2026/8/18 14:13:43

JKSM 3DS存档管理指南:3步给几百小时游戏进度上一道双保险

JKSM 3DS存档管理指南:3步给几百小时游戏进度上一道双保险 【免费下载链接】JKSM JKs Save Manager for 3DS 项目地址: https://gitcode.com/gh_mirrors/jk/JKSM 凌晨三点,你从床上一跃而起,反复插拔卡带、重启机器,屏幕上…

2026/8/18 15:34:09

Milvus 迁移到 RAG:先守住索引和评测口径

Milvus 迁移到 RAG:先守住索引和评测口径 把 Milvus 接入 RAG,不是把文档写进去、能搜出几条就完事。切分策略、embedding 模型、字段过滤和索引参数共同决定候选;生成模型看到的又只是候选中的一小部分。迁移时先守住这些口径,后…

2026/8/18 15:29:07

node-blog安全加固清单:XSS与CSRF攻击防范的完整方案

node-blog安全加固清单:XSS与CSRF攻击防范的完整方案 【免费下载链接】node-blog :rocket:《Node.js从入门到上线》A blog build with Koa2. 项目地址: https://gitcode.com/gh_mirrors/node/node-blog node-blog 是一个基于 Koa2 和 MongoDB 的开源博客项目…

2026/8/17 10:49:52

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/18 6:58:27

工业传感器与变送器详解:序章 从物理世界到工业数据

序章 从物理世界到工业数据 ——重新认识工业传感器与变送器 工业自动化系统正变得日益复杂。今天的工业现场早已不是简单的控制回路,而是由多层技术共同构成的立体体系:PLC、DCS、SCADA、MES、工业互联网、边缘计算与人工智能。控制系统可以执行复杂算法,工业网络可以实现…

2026/8/18 0:02:05

Qwen3.8-27B本地部署实战:17GB内存运行270亿参数大模型

1. 这篇文章真正要解决的问题 你是否曾对动辄需要上百GB显存才能运行的百亿参数大模型望而却步?是否觉得在个人电脑上部署一个功能强大的语言模型是天方夜谭?最近,通义千问团队发布的 Qwen3.8-27B 模型,宣称仅需 17GB 内存即可在本…

2026/8/18 0:02:05

ME3169 36V,8A,180KHz 恒压Buck DC-DC 转换器

概述ME3169 是一款180KHz,PWM 模式恒压Buck DC-DC 转换器,8V 到36V 宽工作电压范围,低纹波,内置低导通电阻功率MOS。ME3169 内置环路补偿电路,可以减少外围元器件数量。内部设计有恒压环路,可以通过外部电阻…

2026/8/17 15:07:41

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/17 17:27:06

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/18 7:12:40

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…