FrameworX renders 3D inside a Display by hosting a standard WPF Viewport3D scene in a WPF Control. You point a WPF Control at the shipped 3D host assembly (T.WpfControlParent3d.dll), build or load the 3D scene in the Display code-behind, and drive it from tags. Typical uses: robot and machine kinematics, equipment and skid models, digital-twin style visuals, and 3D representations of a process.
Autodesk 3D Studio ( |
This feature runs only on Windows (not Multiplatform), on the RichClient and SmartClient clients (WPF Only Displays). It is not available in the HTML5 / WebAssembly client — the 3D scene is an HWND-hosted WPF surface. See WPF Client overlay limitations (HWND-hosted controls) for how this control shares airspace with other WPF visuals.
TWpfControlParent3d (from T.WpfControlParent3d.dll). It exposes a Content property you set to a WPF Viewport3D.System.Windows.Media.Media3D): a Viewport3D with a camera (PerspectiveCamera), lights, and Model3D geometry. Geometry can be built in code or loaded from a model file..3ds) files imported with the Ab3d.PowerToys Reader3ds.DisplayOpening builds the scene once; DisplayIsOpen runs periodically (IsOpenInterval ms) and applies tag values to transforms (rotation / translation) or the camera.robotArm).Double tag per joint or axis.DisplayOpening — GetControl("robotArm"), create a Viewport3D, assign it to .Content, then load or build the scene.DisplayIsOpen — read the tags and apply transforms / camera updates.Info.Solution.SolutionPath.Host a viewport and load a scene in DisplayOpening:
var host = CurrentDisplay.GetControl("robotArm") as T.WpfControlParent3d.TWpfControlParent3d;
var viewport = new Viewport3D();
host.Content = viewport;
// Read the model on the server, then parse it into the viewport
System.IO.Stream model = @Script.Class.LoadFile.Get3dsModel(@Info.Solution.SolutionPath + "robotarm.3ds");
// e.g. new Ab3d.Reader3ds().ReadFile(model, viewport);
// then position the PerspectiveCamera
|
Server-side file read (a Server Script Class method):
public MemoryStream Get3dsModel(string fileName)
{
MemoryStream ms = new MemoryStream();
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
ms.Write(bytes, 0, bytes.Length);
}
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
|
Apply a tag to a transform in DisplayIsOpen (update only when the tag changes):
if (oldSlider1 != TConvert.To<int>(@Tag.slider1))
{
oldSlider1 = TConvert.To<int>(@Tag.slider1);
transformer.RotateObject("BaseMotor",
new AxisAngleRotation3D(new Vector3D(0, 1, 0), oldSlider1));
}
|
DisplayOpening (runs once) and only light per-frame updates in DisplayIsOpen.Info.Solution.SolutionPath for asset paths so the solution stays portable.The RobotArm3D solution is the worked example: five sliders drive four joint rotations plus a gripper translation on an Autodesk 3D Studio (.3ds) model, loaded through a LoadFile server class. It demonstrates the full pattern end to end.
Download Example: Display-RobotArm3D.zip |

DisplayOpening / DisplayIsOpen / DisplayClosing).