[Closed] 3DsMax to XAML (Windows.Media.Media3D) WIP
I’m in the process of developing an Im/Exporter to port 3DsMax Scenes to/from XAML format and thought I’d open a thread here to collect some ideas/wishes/oppinions.
I’ve got a Class Library written in C# and a MXS file controlling the export.
The dll contains the class definitions and their internal logic aswell as the mehods for “stringification” of the instances (currently I’m just overriding the ToString methods but in later versions I plan to move to be using XDocument/XElement classes so i can not only override but propperly manipulate the XAML resource-directories I’m building/manipulating).
Why?
Of course there are Tools like Zam3D(259,-) that do the Job but why would i pay 250 bugs for something I can write myself (and at the same time give others the possibility to use for free aswell)
Whats supported?
- Geometry Export to MeshGeometry3D (including Normals & UVs) (of course the vertCoords are *Inverse(obj.tm))
- Transformation Export to Transform3DGroup (using AxisAngleRotation3D)
What Next
- OmniLight Export
- SkyLight Export
Whats on the List?
- Materials Export
- DirectionalLight Export
- SpotLight Export
- PerspectiveCamera Export
- OrthoCamera Export
- Scene Export to ResourceDictionary file
- Replacing ToString useage with XDocument so existing ResourceDictionaries can be easily manipulated
- Transformation Animation Export to StoryBoards
And here’s the Max side of the code so far:
(
struct ExporterClasses
(
fn getAssemblyPath =
(
local p = getSourceFileName()
if p != undefined then
(
getFilenamePath(p)
)
else
(
undefined
)
),--END getAssemblyPath FN
Color,
Point2,
Point3,
AngleAxisRotation,
Transform,
Mesh,
Node,
Geometry,
OmniLight,
SkyLight,
on create do
(
if(dotNetClass "_3DsMax2Xaml.Definitions.Node") == undefined do dotnet.loadAssembly (getAssemblyPath() + @"\3DsMax2Xaml.dll")
this.Color = dotnetClass "System.Drawing.Color";
this.Point2 = dotNetClass "_3DsMax2Xaml.Definitions.Point2";
this.Point3 = dotNetClass "_3DsMax2Xaml.Definitions.Point3";
this.AngleAxisRotation = dotNetClass "_3DsMax2Xaml.Definitions.AngleAxisRotation";
this.Transform = dotNetClass "_3DsMax2Xaml.Definitions.Transform";
this.Mesh = dotNetClass "_3DsMax2Xaml.Definitions.Mesh";
this.Geometry = dotNetClass "_3DsMax2Xaml.Definitions.Geometry";
this.OmniLight = dotNetClass "_3DsMax2Xaml.Definitions.OmniLight";
this.SkyLight = dotNetClass "_3DsMax2Xaml.Definitions.SkyLight";
)
)
if ::Max2XamlExporterClasses == undefined do (global Max2XamlExporterClasses = ExporterClasses());
/* ****************************** */
/* ****************************** */
/* ****************************** */
struct GeometryCollection
(
private Classes = Max2XamlExporterClasses,
private fn getTransform tm =
(
local tmPos = tm.translationpart;
local pos = dotNetObject this.Classes.Point3 tmPos.x tmPos.y tmPos.z;
local tmRot = tm.rotationpart;
local rot = dotNetObject this.Classes.AngleAxisRotation -tmRot.angle (dotNetObject this.Classes.Point3 tmRot.axis[1] tmRot.axis[2] tmRot.axis[3]);
local tmScale = tm.scalepart;
local scale = dotNetObject this.Classes.Point3 tmScale.x tmScale.y tmScale.z;
return (dotnetObject this.Classes.Transform pos rot scale);
),--END getTransformObject FN
private fn getMesh obj =
(
with undo false
(
local tMesh = snapshotAsMesh obj;
local invTM = inverse obj.transform;
local verts=for v in tMesh.verts collect ([v.pos.x,v.pos.y,v.pos.z]*invTM);
verts=for v in verts collect(dotNetObject this.Classes.Point3 v.x v.y v.z);
local faceVerts = for f = 1 to tMesh.numfaces collect
(
local face = getFace tmesh f;
dotNetObject this.Classes.Point3 face.x face.y face.z;
)
local vertNormals = for i = 1 to tMesh.numVerts collect
(
local v = getNormal tMesh i;
dotNetObject this.Classes.Point3 v.x v.y v.z;
)
local texVerts = if getNumTVerts tMesh > 0 do
(
for f = 1 to tMesh.numVerts collect
(
local uv = getTVert tMesh f;
dotNetObject this.Classes.Point2 uv.x uv.y;
)
)
delete tmesh;
)
return (dotNetObject this.Classes.Mesh verts faceVerts vertNormals texVerts);
),--END getMeshObject FN
public objs = #(),
public Items,
on create do
(
this.Classes = ::Max2XamlExporterClasses;
this.Items = for o in objs where superclassof o == geometryclass and classof o != targetobject collect dotNetObject this.Classes.Geometry o.name (this.getTransform o.transform) (this.getMesh o);
)
)
struct LightCollection --WIP
(
private Classes = Max2XamlExporterClasses,
public objs = #(),
public Items,
on create do
(
this.Classes = ::Max2XamlExporterClasses;
this.Items = for o in objs where superclassof o == geometryclass and classof o != targetobject collect dotNetObject this.Classes.OmniLight o.name (this.Classes.Color.Point3 o.color.r o.color.g o.color.b);
)
)
local geo = GeometryCollection objs:selection
-- print geo.Items
for o in geo.Items do
(
format "%
%
" (o.ToString()) (o.Transformation.ToString());
)
-- local manager = dotNetObject "_3DsMax2Xaml.Class1";
-- manager.passTest obj
OK
)
So if you have any wishes/opinions/suggestions feel free to post them.
I started doing something like this years ago but with just Max Script. Didn’t know what I was really going to use it for so I stopped and made a tutorial from it. I wasn’t aiming it specifically at dotNet usage.
Looks cool what you have so far.
…I wasn’t aiming it specifically at dotNet usage…
I don’t think i understand what you mean with that :shrug:
Ah, in my case I’m using MeshGeometry3D for instancing purposes (wich I’ll have to implement sometime :argh: )
I attached a sample ResourceDict and the mainPage.xaml in the way i intend to implement them, maybe you got some pointers that might help with my stack overflow