## Q&A with Mister Ray

Moderator: SecondMan

Midgardsormr
Fusionator
Posts: 1096
Joined: Wed Nov 26, 2014 8:04 pm
Location: Los Angeles, CA, USA
Been thanked: 74 times
Contact:

### Q&A with Mister Ray

Inspired by SirEdric, I thought I'd drop my own mini-tutorial thread here with answers to questions I get in non-public channels, for the good of the Empire.

Today, we have a question about pipeline from Maya to Fusion 3D:

Hi Bryan,

I found your Wordpress book and decided to reach out to you about confusion I have about importing a Maya 2019 simple walking, textured male mesh. Can you possibly give me the settings to use to export the animation (alembic) and the settings to use to export the character with the textures (fbx?). My confusion is with how to get the character into Fusion with the simple animation. If you could point me to a tutorial or a worded document to show the basic node connections in Fusion, I would greatly appreciate it. I really want to integrate Maya animation into live footage, but right now I can't find any info on how to export what from Maya and how to connect the necessary nodes in Fusion.

And a follow-up after my initial answer:

Will alembic handle fluids, ncloth, and bifrost?

I'll be working with the walking Nathan character from RenderPeople.com.

Fusion can import either Alembic or FBX, but there are some details to be aware of.

First, Alembic can't carry materials or textures, so any object with very complex texturing can't lean on Alembic alone.
Second, many Alembic exporters, Maya's included, do not export UVs by default. In Maya, you'll need to tick "UV Write" under the Advanced Options.
Third, although Alembic is intended to be a streaming format, Fusion will not treat it as such universally. Although a point cache like Nathan will update in place, camera transformations will be baked keyframe animation and will not update automatically. If you change your camera, you'll have to re-import the Alembic. Though you need not use anything but the new camera when you do so.

Fourth, on the FBX side, Fusion's FBX importer hasn't been updated for a while, so use version 2014/2015. Fusion won't load any later version.
Fifth, there is a bug where cameras and lights frequently come in rotated 90 degrees anti-clockwise. This doesn't always happen, but it's pretty persistent from both 3DS Max and PFTrack. The solution is to copy-paste the object's transforms into a new Transform3D node, then reset the transforms on the object itself and give it a 90 degree Y rotation.

Now, FBX does carry textures and basic materials, so a possible tactic is to import Alembic for the geo and FBX for the materials. So let's walk through the procedure for both:

In Maya, I've loaded up Nathan and activated the Alembic Cache Export:

mayaToFusion_001_maya-nathan.jpg

I've circled the Cache menu, where the Export to Alembic command lives because I had to look up how to do it. You'd think it would be under Export with everything else, but apparently not. I've also indicated the UV Write option I mentioned earlier. I've left all the other options at default.

To make an FBX, use the File > Export All command. The only thing I've changed in this dialog is under File Type Specific Options > Advanced Options > FBX File Format, where I've changed Version to FBX 2014/2015.

mayaToFusion_002_maya-fbx.jpg

Once both of those files have been exported, I move to Fusion, where I import them both using File > Import > Alembic Scene for the Alembic and File > Import FBX Scene for the FBX. (As an aside, the FBX import can also import a number of other formats, such as OBJ, Collada, and Vicon mocap—check the list of file types in the Open File window for the complete list.)

I haven't changed any of the defaults for this demo, but I'm not sure if any of them are sticky from previous imports.

So here we see the Alembic on the left and the FBX on the right. For some reason the Diffuse texture didn't come through on the import, but the spec and normal maps did. You can immediately see the influence of that normal map on the FBX version, which appears to have much more detail.

mayaToFusion_003_fusion-imports.jpg

All of those extra lines you can see in the Alembic's viewport are the frustra of the four cameras that come along for the ride in an Alembic from Maya. It's safe to delete front, persp, side, and top, which I have done for the rest of the demo.

Since the Diffuse didn't import, that's the first thing I'll address. It's as simple as copy-pasting the two nodes associated with the spec map, getting the Diffuse map in the Loader, and connecting the Texture2D node to the Diffuse Color input of the shader.

To apply the texture to the Alembic version of the model, plug the output of the Blinn into the Material Input of the Alembic Mesh node:

mayaToFusion_004_fusion-textures.jpg

I'm not sure how well FBX handles deforming meshes—it's the default file format for MotionBuilder, so I assume it works, but in this case none of the animation came through from that scene. It did however, come in on the Alembic, so now I have the animation from the abc and the shading from the FBX.

Now, does Alembic handle nCloth, fluids, and Bifrost? To an extent. Cloth and particle liquids are generally turned into a polygon mesh and point cached for rendering. This mesh can be cached as Alembic and imported into Fusion.

Fluids are another story; they're volumes, not geometry, so they require different handling. Usually volumes are interchanged using the OpenVDB file format. Fusion does not handle VDB, so you'll need a different solution for that. There is some research lying around here somewhere about prepping a volume from Houdini for use with Fusion's VolumeFog tool, but it's complex and inefficient.

You do not have the required permissions to view the files attached to this post.

Tags:

Midgardsormr
Fusionator
Posts: 1096
Joined: Wed Nov 26, 2014 8:04 pm
Location: Los Angeles, CA, USA
Been thanked: 74 times
Contact:

### Re: Q&A with Mister Ray

@Midgaard77
As for null objects, any node with a Center control can be used as a null. You can connect any Point control to any other animated Point. Ping me if you need guidance.

@TheDeanPhillips
Hey man, I'd love to know more about how to do this if possible (more specifically the best workflow). I'm mainly (trying) to recreate some Mograph AE tutorials inside of Fusion, which is why I need nulls

@Midgaard77
Point me toward one of the tutorials so I can see the context of what you're trying to do. It's been quite a long time since I last used AE. I'll try to find some time in the near future to write something up.

@TheDeanPhillips
Thanks man. It was mainly just practising to do something like this ( which is easy in AE but complicated in Fusion (however, hoping it's possible and just me being new to Fusion)

In the tutorial referenced, the null is being used as a 3d pivot point. Fusion doesn't have the fakey '2.5-D' workspace that AE leans on. It instead has a fully-realized, and still fast, 3D workspace, and that's what we'll use here.

So, an Ellipse and a Background can make a colored circle, and putting it on an ImagePlane3D will put it into the 3D workspace:

AE-tut_001_Middle-sphere.jpg

To make a second circle, a second Background and another ImagePlane3D, which I'll move off to one side, just as would be done in AE. A Merge3D to combine the two circles and a Renderer3D to create the output image complete the basic set-up. For this purpose, we don't even need to create a camera. The Default Camera looks down the Z axis and gives us what we need. I've adjusted the scale of the first ImagePlane3D to set up the composition while looking at the Renderer. Also, I changed the Image dimensions to create a square composition, since the implication was that this would be a texture applied to particles.

AE-tut_002_orbiter-renderer.jpg

Now the crux of the question. In the AE tutorial, the instructor used a Null to perform the orbit. An equivalent operator in Fusion is a Transform3D. Since we've left everything at the origin, the Transform's pivot is still at 0, even though the object it's going to be transforming is elsewhere. I'll add the Transform3D right after the Orbiter ImagePlane3D and animate its Y-Rotation value. Just like in AE, we'll want it to loop, so I'll pop over to the Spline View and use the Loop Out controls to determine what should happen when we run out of keyframes. Activate the animated control using the list on the left, Ctrl+F to frame the keyframes or use the Zoom to Fit button, select them both and choose either the Set Loop or Set Relative button.

AE-tut_003_loop-animation.jpg

The next step presents us with a challenge. In the AE tutorial, the instructor used the Look at Camera feature to keep the circle always facing the camera, and thus always remaining a circle. Our ImagePlane3D does have a Look At control, but it's evaluated before the Transform 3D, so the target also gets rotated, which is no good.

If we look hard at what's happening during this rotation, it should be evident that the circle's orientation is equal to the rotation it's undergoing, so to keep it facing the camera, we just need to undo that orientation change by giving it a local rotation opposite its orbital rotation. For that, we'll use an expression on its own Y-Rotation. To add an expression, you can right-click the control and choose 'Expression' or just type = in the text entry field. That will create an expression entry field under the control. The + icon next to the field is your pick-whip button. If you just click it, you'll get the scripting name of the control in the field, or you can drag it to another parameter to get that parameter's name.

In order for this to work, we'll need to have two control panels open at the same time. By default, Fusion doesn't permit that, but you can lock a panel open using the push-pin icon at the top. That will allow you to multi-select tools and see all of their parameters at the same time.

Dragging the pick-whip from the ImagePlane's Y-Rotation to the Transform's animated Y-Rotation, the two controls will be linked. To make it a counter-rotation, just negate the expression: -Transform3D1.Transform3DOp.Rotate.Y. Now the ImagePlane will rotate backward at the same rate as the Transform rotates it forward, keeping it always facing forward.

Of course, you could get around this issue by remembering that the 2.5D approach is unnecessary. If we simply use real spheres from the Shape3D, then we wouldn't have to bother with facing. But there may be occasions when you have a sprite on a card and still need to do it this way.

If you want to change the orientation or the orbital distance, as was done in the AE tutorial, simply add a second Transform3D after the first one. The Rotation controls can alter the angle, and Scale can make the orbit wider or narrower. The Echo effect seen in AE can be accomplished with the Duplicate3D tool.

Here's my finished piece, with a few additional changes:

Code: Select all

{
Tools = ordered() {
Orbiter_1 = ImagePlane3D {
NameSet = true,
Inputs = {
["Transform3DOp.Translation"] = Input { Value = 0, },
["Transform3DOp.Translate.X"] = Input { Value = 0.523891429557906, },
["Transform3DOp.Rotate.Y"] = Input {
Value = -331.56,
Expression = "Transform3D1_2.Transform3DOp.Rotate.Y * -1",
},
["Transform3DOp.Scale.X"] = Input { Value = 1.103, },
["SurfacePlaneInputs.ObjectID.ObjectID"] = Input { Value = 2, },
MaterialInput = Input {
SourceOp = "Background2",
Source = "Output",
},
["MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.921, },
["MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.843923352, },
["MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0.045129, },
["MtlStdInputs.MaterialID"] = Input { Value = 2, },
},
ViewInfo = OperatorInfo { Pos = { 385, -49.5 } },
},
Orbiter = ImagePlane3D {
NameSet = true,
Inputs = {
["Transform3DOp.Translation"] = Input { Value = 0, },
["Transform3DOp.Translate.X"] = Input { Value = 0.523891429557906, },
["Transform3DOp.Rotate.Y"] = Input {
Value = -187.884,
Expression = "Transform3D1.Transform3DOp.Rotate.Y * -1",
},
["Transform3DOp.Scale.X"] = Input { Value = 1.103, },
["SurfacePlaneInputs.ObjectID.ObjectID"] = Input { Value = 2, },
MaterialInput = Input {
SourceOp = "Background2",
Source = "Output",
},
["MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.575528, },
["MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0.453, },
["MtlStdInputs.MaterialID"] = Input { Value = 2, },
},
ViewInfo = OperatorInfo { Pos = { 385, -16.5 } },
},
Transform3D1_2 = Transform3D {
Inputs = {
SceneInput = Input {
SourceOp = "Orbiter_1",
Source = "Output",
},
["Transform3DOp.Translation"] = Input { Value = 0, },
["Transform3DOp.Rotate.Y"] = Input {
SourceOp = "Transform3D1_2YRotation",
Source = "Value",
},
["Transform3DOp.ScaleNest"] = Input { Value = 0, },
},
ViewInfo = OperatorInfo { Pos = { 495, -49.5 } },
},
Transform3D1_2YRotation = BezierSpline {
SplineColor = { Red = 128, Green = 255, Blue = 128 },
NameSet = true,
KeyFrames = {
[0] = { 0, RH = { 5.66666666666667, 120 }, Flags = { Linear = true, Loop = true } },
[17] = { 360, LH = { 11.3333333333333, 240 }, Flags = { Linear = true, Loop = true } }
}
},
Transform3D1 = Transform3D {
Inputs = {
SceneInput = Input {
SourceOp = "Orbiter",
Source = "Output",
},
["Transform3DOp.Translation"] = Input { Value = 0, },
["Transform3DOp.Rotate.Y"] = Input {
SourceOp = "Transform3D1YRotation",
Source = "Value",
},
["Transform3DOp.ScaleNest"] = Input { Value = 0, },
},
ViewInfo = OperatorInfo { Pos = { 495, -16.5 } },
},
Transform3D1YRotation = BezierSpline {
SplineColor = { Red = 128, Green = 255, Blue = 128 },
NameSet = true,
KeyFrames = {
[0] = { 0, RH = { 10, 120 }, Flags = { Linear = true, Loop = true } },
[30] = { 360, LH = { 20, 240 }, Flags = { Linear = true, Loop = true } }
}
},
Middle = ImagePlane3D {
NameSet = true,
Inputs = {
["Transform3DOp.Scale.X"] = Input { Value = 2.874, },
["SurfacePlaneInputs.ObjectID.ObjectID"] = Input { Value = 1, },
MaterialInput = Input {
SourceOp = "Background2",
Source = "Output",
},
["MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.100456, },
["MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.516911936, },
["MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0.866, },
["MtlStdInputs.MaterialID"] = Input { Value = 1, },
},
ViewInfo = OperatorInfo { Pos = { 385, 16.5 } },
},
Transform3D2 = Transform3D {
Inputs = {
SceneInput = Input {
SourceOp = "Transform3D1",
Source = "Output",
},
["Transform3DOp.Rotate.X"] = Input { Value = 17, },
["Transform3DOp.Rotate.Y"] = Input { Value = -3.4, },
["Transform3DOp.Rotate.Z"] = Input { Value = 23.8, },
["Transform3DOp.Scale.X"] = Input { Value = 0.8696, },
},
ViewInfo = OperatorInfo { Pos = { 605, -16.5 } },
},
Background2 = Background {
Inputs = {
GlobalOut = Input { Value = 60, },
Width = Input { Value = 1920, },
Height = Input { Value = 1080, },
["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
TopLeftRed = Input { Value = 1, },
TopLeftGreen = Input { Value = 1, },
TopLeftBlue = Input { Value = 1, },
SourceOp = "Ellipse1",
}
},
ViewInfo = OperatorInfo { Pos = { 275, 16.5 } },
},
Inputs = {
Filter = Input { Value = FuID { "Fast Gaussian" }, },
MaskWidth = Input { Value = 1920, },
MaskHeight = Input { Value = 1080, },
PixelAspect = Input { Value = { 1, 1 }, },
ClippingMode = Input { Value = FuID { "None" }, },
Width = Input { Value = 0.182520081763387, },
Height = Input { Value = 0.182520081763387, },
},
ViewInfo = OperatorInfo { Pos = { 165, 16.5 } },
},
Transform3D2_1 = Transform3D {
Inputs = {
SceneInput = Input {
SourceOp = "Transform3D1_2",
Source = "Output",
},
["Transform3DOp.Rotate.X"] = Input { Value = -28.9, },
["Transform3DOp.Rotate.Y"] = Input { Value = -3.4, },
["Transform3DOp.Rotate.Z"] = Input { Value = 49.3, },
["Transform3DOp.Scale.X"] = Input { Value = 0.8696, },
},
ViewInfo = OperatorInfo { Pos = { 605, -49.5 } },
},
Duplicate3D1 = Duplicate3D {
Inputs = {
LastCopy = Input { Value = 10, },
TimeOffset = Input { Value = 0.073, },
SceneInput = Input {
SourceOp = "Transform3D2_1",
Source = "Output",
},
},
ViewInfo = OperatorInfo { Pos = { 715, -49.5 } },
},
Duplicate3D1_1 = Duplicate3D {
Inputs = {
LastCopy = Input { Value = 10, },
TimeOffset = Input { Value = 0.073, },
SceneInput = Input {
SourceOp = "Transform3D2",
Source = "Output",
},
},
ViewInfo = OperatorInfo { Pos = { 715, -16.5 } },
},
Merge3D1 = Merge3D {
Inputs = {
SceneInput1 = Input {
SourceOp = "Middle",
Source = "Output",
},
SceneInput2 = Input {
SourceOp = "Duplicate3D1_1",
Source = "Data3D",
},
SceneInput3 = Input {
SourceOp = "Duplicate3D1",
Source = "Data3D",
},
},
ViewInfo = OperatorInfo { Pos = { 715, 16.5 } },
},
Renderer3D1 = Renderer3D {
CtrlWZoom = false,
CustomData = {
ToolVersion = 2,
},
Inputs = {
Quality = Input { Value = 10, },
ShutterAngle = Input { Value = 360, },
GlobalOut = Input { Value = 60, },
Width = Input { Value = 1080, },
Height = Input { Value = 1080, },
["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
SceneInput = Input {
SourceOp = "Merge3D1",
Source = "Output",
},
},
ViewInfo = OperatorInfo { Pos = { 825, 16.5 } },
}
}
}


Rather than choosing the color using the Background node, I've instead just sent a white circle into 3D and used the Material controls of each ImagePlane to choose the color. I added the second transform to modify the angle of the orbit and put in a second orbiter with a shorter period and a different color. I also put in the Duplicate3D.

I'd like to talk a little bit about linking Point controls, too, but that will have to wait for another time; I'm late for work!

You do not have the required permissions to view the files attached to this post.