MagosX.com
April 23, 2014, 09:06:55 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: The only true wisdom is in knowing you know nothing!
 
  Home   Forum   Files Programs Help Search Login Register  
Pages: [1]
  Print  
Author Topic: MdxLib  (Read 24195 times)
Magos
Godlike
Administrator
Jr. Member
*****
Offline Offline

Posts: 98



View Profile WWW
« on: August 02, 2008, 02:46:17 PM »

MdxLib v1.04

MdxLib is a .NET 3.5 Class Library to handle WarCraft 3 models. It's mainly aimed for programmers to be used in tools and similar. It was written in C#, but can be used by any of the .NET languages (and perhaps by other languages if you have some skillz).

  • An object oriented approach to handling and editing WarCraft 3 models. You handle objects and references, not raw data and ID's.
  • Automation - if a component is removed from a model, all references to it are nullified instead of being invalid.
  • Lazy initialization - some parts of the model are only created if neccessary.
  • Buildt-in support for MDL, MDX and XML model formats.
  • Buildt-in undo/redo system.
  • Metadata - store your own custom data in the models (and still have them work properly in WarCraft 3).

Download it here:
MdxLib.zip

Source code (released under GPL):
MdxLibSource.zip

MDX file format:
MagosMdxFormat.txt
« Last Edit: August 26, 2009, 10:08:59 AM by Magos » Logged

Magos
Godlike
Administrator
Jr. Member
*****
Offline Offline

Posts: 98



View Profile WWW
« Reply #1 on: August 02, 2008, 02:50:14 PM »

Example 1 - Converting between formats

In 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.

Code:
//
// 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 system

The 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.

Code:
//
// 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):

Code:
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 LINQ

You 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.

Code:
//
// 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 screen

This 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.

Code:
//
// 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);
}
« Last Edit: February 11, 2009, 04:28:11 PM by Magos » Logged

pha0001
Newbie
*
Offline Offline

Posts: 18

Andy Phan - VB.Net Programmer


View Profile
« Reply #2 on: October 16, 2008, 05:15:52 AM »

Can't wait until the next version. Keep up the good work Magos, as it works pretty stable, and its one of the best class modding files I seen.

Andy Phan. Grin
Logged
Magos
Godlike
Administrator
Jr. Member
*****
Offline Offline

Posts: 98



View Profile WWW
« Reply #3 on: February 11, 2009, 04:29:56 PM »

New version. Only some minor changes though. Added a Tag-attribute to all objects (like winforms has) so you can attach arbitrary data to each component.
Logged

pha0001
Newbie
*
Offline Offline

Posts: 18

Andy Phan - VB.Net Programmer


View Profile
« Reply #4 on: February 13, 2009, 11:48:29 PM »

New version. Only some minor changes though. Added a Tag-attribute to all objects (like winforms has) so you can attach arbitrary data to each component.

Nice, I'm going to try it, and keep up with the good work. Haven't seen you for a while, but now your back, its nice to keep it rolling.

Andy Phan.
Logged
blau
Newbie
*
Offline Offline

Posts: 3


View Profile
« Reply #5 on: May 18, 2009, 03:59:50 PM »

Hi,

You should update the mdx specs file with your INFO STRUCT,  Wink

is this ok?


Code:
//+-----------------------------------------------------------------------------
//| Chunk information
//+-----------------------------------------------------------------------------
struct InfoChunk
{
  DWORD 'INFO';
  DWORD InfoSize;

  CHAR[InfoSize] Info;                     
 };


Logged
Magos
Godlike
Administrator
Jr. Member
*****
Offline Offline

Posts: 98



View Profile WWW
« Reply #6 on: May 19, 2009, 10:47:46 AM »

Heh. Yeah, that looks correct.
Logged

Magos
Godlike
Administrator
Jr. Member
*****
Offline Offline

Posts: 98



View Profile WWW
« Reply #7 on: August 24, 2009, 09:34:31 AM »

Source code released (under GPL). See the first post.
Logged

lights
Newbie
*
Offline Offline

Posts: 1


View Profile
« Reply #8 on: June 06, 2010, 02:36:31 AM »

 Grin
Thanks.
This's a very useful.
I'm coding with XNA4,and I'll use this for my opensource project。
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.12 | SMF © 2006-2009, Simple Machines LLC
TinyPortal v0.9.8 © Bloc
Valid XHTML 1.0! Valid CSS!
Page created in 0.068 seconds with 20 queries.