Example 1 - Converting between formatsIn this example I first load the MDL file into a CModel object, then saving it to an MDX file. Converting files requires this middle-storage.
//
// The files to load from and save to.
//
var FromFileName = "SomeFile.mdx";
var ToFileName = "FileToSaveTo.mdl";
//
// Creates a model.
//
var Model = new MdxLib.Model.CModel();
//
// Loads the model from a file (using the MDX format).
//
using(var Stream = new System.IO.FileStream(FromFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
var ModelFormat = new MdxLib.ModelFormats.CMdx();
ModelFormat.Load(FromFileName, Stream, Model);
}
//
// Saves the model to a file (using the MDL format).
//
using(var Stream = new System.IO.FileStream(ToFileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
var ModelFormat = new MdxLib.ModelFormats.CMdl();
ModelFormat.Save(ToFileName, Stream, Model);
}
Example 2 - The Undo/Redo systemThe undo/redo system is enabled by calling the Begin/EndUndoRedoSession methods. All changes to the model between these calls will be stored in a command objects which can be undo:ed/redo:ed.
//
// The file to load from.
//
var FileName = "SomeFile.mdx";
//
// Creates a model.
//
var Model = new MdxLib.Model.CModel();
//
// Loads the model from a file (using the MDX format).
//
using(var Stream = new System.IO.FileStream(FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
var ModelFormat = new MdxLib.ModelFormats.CMdx();
ModelFormat.Load(FileName, Stream, Model);
}
//
// A helper class, making undo/redo easier.
//
var UndoRedoManager = new CUndoRedoManager();
//
// Performs some commands (all to be treated as one undo/redo step)
// - Renames the model to "Peon"
// - Renames the first sequence to "Run like hell" (if one exists)
//
Model.BeginUndoRedoSession();
Model.Name = "Peon";
if(Model.HasSequences) Model.Sequences[0].Name = "Run like hell";
UndoRedoManager.Add(Model.EndUndoRedoSession());
//
// Performs some commands (all to be treated as one undo/redo step)
// - Adds an attachment point
// - Makes the attachment point a child of the first bone (if one exists)
//
Model.BeginUndoRedoSession();
var Attachment = new MdxLib.Model.CAttachment(Model);
Attachment.Name = "Head Ref";
Model.Attachments.Add(Attachment);
if(Model.HasBones) Attachment.Parent.Attach(Model.Bones[0]);
UndoRedoManager.Add(Model.EndUndoRedoSession());
//
// Performs some commands (all to be treated as one undo/redo step)
// - Removes all textures
// - Removes all materials
//
Model.BeginUndoRedoSession();
Model.Textures.Clear();
Model.Materials.Clear();
UndoRedoManager.Add(Model.EndUndoRedoSession());
//
// Undo the last two steps, then redo the last undo:ed step.
//
UndoRedoManager.Undo();
UndoRedoManager.Undo();
UndoRedoManager.Redo();
This example used the following helper class (to make undo/redo easier):
private class CUndoRedoManager
{
public CUndoRedoManager()
{
UndoList = new System.Collections.Generic.LinkedList<MdxLib.Command.ICommand>();
RedoList = new System.Collections.Generic.LinkedList<MdxLib.Command.ICommand>();
}
public void Add(MdxLib.Command.ICommand Command)
{
UndoList.AddFirst(Command);
RedoList.Clear();
}
public void Undo()
{
if(UndoList.Count > 0)
{
var Command = UndoList.First.Value;
Command.Undo();
UndoList.RemoveFirst();
RedoList.AddFirst(Command);
}
}
public void Redo()
{
if(RedoList.Count > 0)
{
var Command = RedoList.First.Value;
Command.Do();
RedoList.RemoveFirst();
UndoList.AddFirst(Command);
}
}
private System.Collections.Generic.LinkedList<MdxLib.Command.ICommand> UndoList = null;
private System.Collections.Generic.LinkedList<MdxLib.Command.ICommand> RedoList = null;
}
Example 3 - Using LINQYou can use LINQ (LINQ to Objects) to query data from the model. Just remember to call "using System.Linq" or you can't access it.
//
// The file to load from.
//
var FileName = "SomeFile.mdx";
//
// Creates a model.
//
var Model = new MdxLib.Model.CModel();
//
// Loads the model from a file (using the MDX format).
//
using(var Stream = new System.IO.FileStream(FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
var ModelFormat = new MdxLib.ModelFormats.CMdx();
ModelFormat.Load(FileName, Stream, Model);
}
//
// Filters out all image texture (their filename).
//
var TextureFileNames = from Texture in Model.Textures where Texture.FileName != "" select Texture.FileName;
foreach(var TextureFileName in TextureFileNames)
{
//Do something with TextureFileName
}
//
// Filters out all replaceable texture (their replaceable ID).
//
var TextureResults = from Texture in Model.Textures where Texture.ReplaceableId > 0 select new { Id = Texture.ReplaceableId };
foreach(var TextureResult in TextureResults)
{
//Do something with TextureResult.Id
}
Example 4 - Creating a loading screenThis example creates the neccessary components for a loading screen. It must be saved as MDX cause MDL files doesn't seem to work in loading screens.
//
// The file to save to.
//
var FileName = "SomeFile.mdx";
//
// Creates the model, the object which is the base of everything.
// Version and BlendTime are automatically set to default values.
//
var Model = new MdxLib.Model.CModel();
Model.Name = "Loading Screen";
//
// Creates an animation sequence. Loading screens should have
// a nonlooping birth sequence.
//
var Sequence = new MdxLib.Model.CSequence(Model);
Sequence.Name = "Birth";
Sequence.IntervalStart = 1000;
Sequence.IntervalEnd = 2000;
Sequence.NonLooping = true;
Model.Sequences.Add(Sequence);
//
// Creates a texture to be used for the background. Make sure
// the path is correct (like the war3mapImported path).
//
var Texture = new MdxLib.Model.CTexture(Model);
Texture.FileName = "LoadingScreen.blp";
Model.Textures.Add(Texture);
//
// Creates a material for the background. Materials consists
// of one or several layers.
//
var Material = new MdxLib.Model.CMaterial(Model);
Material.FullResolution = true;
Model.Materials.Add(Material);
//
// Creates a layer for the material. Attaches the previously
// created texture to the layer.
//
var Layer = new MdxLib.Model.CMaterialLayer(Model);
Layer.FilterMode = MdxLib.Model.EMaterialLayerFilterMode.None;
Layer.TwoSided = true;
Layer.Unshaded = true;
Layer.Unfogged = true;
Layer.Texture.Attach(Texture);
Material.Layers.Add(Layer);
//
// Creates a geoset. A geoset is the actual geometry that you
// see (vertices, faces, etc...). The previously created material
// is attached to the geoset to define how it's rendered.
//
var Geoset = new MdxLib.Model.CGeoset(Model);
Geoset.Material.Attach(Material);
Model.Geosets.Add(Geoset);
//
// Creates a bone. No matrix transformations will be performed on
// the loading screen, however a bone is still required. The bone
// attaches the previously created geoset to itself.
//
var Bone = new MdxLib.Model.CBone(Model);
Bone.Name = "Loading Screen Bone";
Bone.Geoset.Attach(Geoset);
Model.Bones.Add(Bone);
//
// Creates a (matrix) group for the geoset. These tells which matrix
// transformations should be applied to which vertices. Each group
// contains a number of nodes, each representing a matrix.
//
var Group = new MdxLib.Model.CGeosetGroup(Model);
Geoset.Groups.Add(Group);
//
// Creates a group node. This node attaches the previously created
// bone (and its matrix) to itself.
//
var GroupNode = new MdxLib.Model.CGeosetGroupNode(Model);
GroupNode.Node.Attach(Bone);
Group.Nodes.Add(GroupNode);
//
// Creates the top left vertex. The normal points out from the screen.
// Attaches the previously created group to the vertex.
//
var Vertex1 = new MdxLib.Model.CGeosetVertex(Model);
Vertex1.Position = new MdxLib.Primitives.CVector3(0.0f, 0.6f, 0.0f);
Vertex1.Normal = new MdxLib.Primitives.CVector3(0.0f, 0.0f, 1.0f);
Vertex1.TexturePosition = new MdxLib.Primitives.CVector2(0.0f, 0.0f);
Vertex1.Group.Attach(Group);
Geoset.Vertices.Add(Vertex1);
//
// Creates the top right vertex. The normal points out from the screen.
// Attaches the previously created group to the vertex.
//
var Vertex2 = new MdxLib.Model.CGeosetVertex(Model);
Vertex2.Position = new MdxLib.Primitives.CVector3(0.8f, 0.6f, 0.0f);
Vertex2.Normal = new MdxLib.Primitives.CVector3(0.0f, 0.0f, 1.0f);
Vertex2.TexturePosition = new MdxLib.Primitives.CVector2(1.0f, 0.0f);
Vertex2.Group.Attach(Group);
Geoset.Vertices.Add(Vertex2);
//
// Creates the bottom left vertex. The normal points out from the screen.
// Attaches the previously created group to the vertex.
//
var Vertex3 = new MdxLib.Model.CGeosetVertex(Model);
Vertex3.Position = new MdxLib.Primitives.CVector3(0.0f, 0.0f, 0.0f);
Vertex3.Normal = new MdxLib.Primitives.CVector3(0.0f, 0.0f, 1.0f);
Vertex3.TexturePosition = new MdxLib.Primitives.CVector2(0.0f, 1.0f);
Vertex3.Group.Attach(Group);
Geoset.Vertices.Add(Vertex3);
//
// Creates the bottom right vertex. The normal points out from the screen.
// Attaches the previously created group to the vertex.
//
var Vertex4 = new MdxLib.Model.CGeosetVertex(Model);
Vertex4.Position = new MdxLib.Primitives.CVector3(0.8f, 0.0f, 0.0f);
Vertex4.Normal = new MdxLib.Primitives.CVector3(0.0f, 0.0f, 1.0f);
Vertex4.TexturePosition = new MdxLib.Primitives.CVector2(1.0f, 1.0f);
Vertex4.Group.Attach(Group);
Geoset.Vertices.Add(Vertex4);
//
// Creates the first face. Each face is a triangle attached to
// three vertices (one for each corner).
//
var Face1 = new MdxLib.Model.CGeosetFace(Model);
Face1.Vertex1.Attach(Vertex1);
Face1.Vertex2.Attach(Vertex2);
Face1.Vertex3.Attach(Vertex3);
Geoset.Faces.Add(Face1);
//
// Creates the second face. Each face is a triangle attached to
// three vertices (one for each corner).
//
var Face2 = new MdxLib.Model.CGeosetFace(Model);
Face2.Vertex1.Attach(Vertex2);
Face2.Vertex2.Attach(Vertex3);
Face2.Vertex3.Attach(Vertex4);
Geoset.Faces.Add(Face2);
//
// Saves the model to a file (using the MDL format).
//
using(var Stream = new System.IO.FileStream(FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
var ModelFormat = new MdxLib.ModelFormats.CMdx();
ModelFormat.Save(FileName, Stream, Model);
}