《Rust 接入 DCC》- Maya Plugin
前言
在 21 年年初我在 Rust 语言中文社区发布了一篇关于 Rust 接入 Maya API 的文章《Maya 中使用 Rust》,并在 21 年 Rust 社区晚会中讲解了一下当时的实现方式,Rust -> Python -> C++ 这套流程。这种方式写起来并不舒服,而且避免不了中间有个 Python 解释器。于是,时隔两年,我又琢磨了一套玩法 Rust -> C++。
开工
原理
使用 Rust 构建出一个动态链接库(dll),并使用 cbindgen 生成 C 头文件,C++ 去调用 Rust 生成的库。我们把核心的算法内容写在 Rust 库中,C++ 去操作 API 并调用 Rust 库。
准备环境
- Maya 2018
- Rust 1.68.0-nightly
- Visual Studio 2019
- Maya 2018 Devkit
创建项目
我们需要创建两个项目,一个 Rust 动态链接库项目,一个 Maya C++ API 项目,将这两个项目的输出目录都指到 build 文件夹,cbindgen 输出指到 build/include,mll 文件指到 build/plug-in。
如何创建这两个项目就不在这讲解了
build:构建结果
rust-noise-lib:Rust Dyn Library
rust-noise-plugin:Maya C++ Plugin
配置一下 mod 文件(记得改路径)
+ RustNoiseModule 1.0 E:\User\Choi-Jungwoo\Desktop\rust-noise\build
PATH+:=release
MAYA_PLUG_IN_PATH+:=plug-ins
Rust 部分实现
在 Rust 中实现了个随机向量,是个很简单的 noise vector 的案例。
use rand::Rng;
/// cbindgen:derive-eq
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct NoiseVector {
x: f32,
y: f32,
z: f32,
}
impl NoiseVector {
pub fn new() -> NoiseVector {
NoiseVector {
x: 0f32,
y: 0f32,
z: 0f32,
}
}
fn gen_point(displacement: f32) -> f32 {
rand::thread_rng().gen::<f32>() * displacement
}
pub fn gen(&mut self, displacement: f32) {
self.x = NoiseVector::gen_point(displacement);
self.y = NoiseVector::gen_point(displacement);
self.z = NoiseVector::gen_point(displacement);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gen_noise() {
let mut noise = NoiseVector::new();
noise.gen(0.002);
println!("{:?}", noise);
}
}
lib.rs
pub mod noise_vector;
#[no_mangle]
pub extern "C" fn new_rust_noise_vector() -> noise_vector::NoiseVector {
noise_vector::NoiseVector::new()
}
#[no_mangle]
pub extern "C" fn gen_noise(noise_vector: &mut noise_vector::NoiseVector, displacement: f32) {
noise_vector.gen(displacement);
}
Maya C++ Plugin 中的实现
本文仅展示了部分代码,删除了插件初始化,类构建函数等,完整代码请到 git 上查看,此文章也会在 Rust 语言中文社区中发布。24 行 - 30 行,就是 Rust 与 C++ 交互的部分。
#include "RustNoisePlugin.h"
MStatus RustNoisePlugin::rustNoise(MString objectName, double displacementNum)
{
MStatus status;
MSelectionList selection;
MDagPath dagPath;
MItSelectionList iter(selection);
selection.add(objectName);
selection.getDagPath(0, dagPath);
MItGeometry geoIter(dagPath);
MPointArray pArray;
status = geoIter.allPositions(pArray, MSpace::kWorld);
if (status != MS::kSuccess)
{
MGlobal::displayError("Failed get " + objectName + " positions");
return status;
}
for (int i = 0; i < pArray.length(); i++)
{
// -----------------------------------------------
struct NoiseVector noise = new_rust_noise_vector();
gen_noise(&noise, displacementNum);
pArray[i].x += noise.x;
pArray[i].y += noise.y;
pArray[i].z += noise.z;
// -----------------------------------------------
}
status = geoIter.setAllPositions(pArray, MSpace::kWorld);
if (status != MS::kSuccess)
{
MGlobal::displayError("Failed set " + objectName + " positions");
return status;
}
MFnMesh meshFn(dagPath);
status = meshFn.updateSurface();
if (status != MS::kSuccess)
{
MGlobal::displayError("Failed update " + objectName + " surface");
return status;
}
return status;
}
在 Maya 中运行
运行以下命令,我们会得到一个凹凸不平的球体。
rustNoise -n pSphere1 -d 0.005
相关文章
- re:Invent 2020 大会直播博客:Andy Jassy 主题演讲
- 企业微信、钉钉接收 Amazon CloudWatch 告警
- 使用 Amazon EKS 轻松运行 Flink 作业
- 推出 Amazon Managed Workflows for Apache Airflow (MWAA)
- 新增功能 – 适用于 AWS Lambda 的信任和完整性控件:代码签名
- 新增功能 – AWS Single Sign-On 支持基于属性的访问控制
- 通过 Elasticsearch 构建WAF日志分析系统
- 介绍 Amazon S3 Storage Lens — 组织范围内对象存储的可见性
- 现已为 AWS 托管的 Microsoft 活动目录启用多区域复制
- AWS Network Firewall — VPC 中的新托管防火墙服务
- 在 Amazon SageMaker 中构建一套定制化推荐系统
- 规划具有 Hot-Warm 架构的 Amazon Elasticsearch Service 集群
- SOCA 帮助半导体企业快速启动 EDA 云上部署
- AWS Organizations 中组织单元的最佳实践
- 利用技术手段实现对业务运行环境的持续安全合规检测
- 使用 Amazon Textract 与 Amazon Augmented AI 配合人工循环处理 PDF 文档
- 手把手教你快速将宁盾双因素认证(MFA)与 Amazon WorkSpaces 集成
- 基于 QuickSight 的成本可视化方案
- 手把手教你快速部署 Spot 实例并配置中断邮件警告
- Windows环境下python2.7安装mysql-python