J'en profite alors pour mettre en ligne un autre code plus récent, mieux commenté.
Il y a pas mal de dépendances, mais il est tout de même assez simple à comprendre.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using IrrlichtNETCP;
using IrrlichtNETCP.Inheritable;
namespace AGE
{
// Mesh loader chargeant le format DXS (DeleD)
public class DXSMeshLoader : IMeshLoader
{
// Chemin des textures
static public string TexturePath = "";
// Liste des materiaux
Dictionary<int, Material> Materials = new Dictionary<int, Material>();
// Charge le mesh
public Mesh Load(string file)
{
Mesh mesh = new Mesh();
XML.File xml = new AGE.XML.File(file);
XML.Node NScene = xml.Root.GetChild(0);
this.LoadMaterials(NScene.GetChild("materials"));
this.LoadPrimitives(NScene.GetChild("primitives") , mesh);
return mesh;
}
// Charge les primitives
void LoadPrimitives(XML.Node NPrimitives , Mesh mesh)
{
// Parcours toutes les primitives
foreach (XML.Node NPrimitive in NPrimitives.Childs)
{
// Tag (ex: eau, escaladable, destructible, etc)
string Tag = NPrimitive.GetChild("tag").Text;
// Parcours les vertices
List<Vector3D> VerticesPosition = new List<Vector3D>();
foreach (XML.Node NVertex in NPrimitive.GetChild("vertices").Childs)
{
Vector3D position = new Vector3D();
position.X = Tools.ValF(NVertex.GetAttribute("x").Value);
position.Y = Tools.ValF(NVertex.GetAttribute("y").Value);
position.Z = -Tools.ValF(NVertex.GetAttribute("z").Value);
VerticesPosition.Add(position);
}
// Parcours les polygones
int OldMaterialID = -1;
Primitive Primitive = null;
foreach (XML.Node NPolygon in NPrimitive.GetChild("polygons").Childs)
{
// Identifiant du materiau à utiliser
int MaterialID = Convert.ToInt32(NPolygon.GetAttribute("mid").Value);
// Changement de matériau
if (MaterialID != OldMaterialID)
{
// Creer une nouvelle primitive
Primitive = new Primitive();
}
// Recupère le materiau dans la liste
if (Materials.ContainsKey(MaterialID))
Primitive.Material = Materials[MaterialID];
// Parcours les vertices
int VertexNbr = 0;
foreach (XML.Node NVertex in NPolygon.Childs)
{
// Identifiant de la position du vertex
int VertexID = Convert.ToInt32(NVertex.GetAttribute("vid").Value);
// Coordonnées UV
float U0 = Tools.ValF(NVertex.GetAttribute("u0").Value);
float V0 = Tools.ValF(NVertex.GetAttribute("v0").Value);
float U1 = U0;
float V1 = V0;
if (NVertex.GetAttribute("u1") != null && NVertex.GetAttribute("v1") != null)
{
U1 = Tools.ValF(NVertex.GetAttribute("u1").Value);
V1 = Tools.ValF(NVertex.GetAttribute("v1").Value);
}
// Position du vertex
Vector3D Position = VerticesPosition[VertexID];
// Creer un vertex
Vertex3DT2 vertex = new Vertex3DT2(Position, new Vector3D(), new Color(255, 255, 255, 255), new Vector2D(U0, V0), new Vector2D(U1, V1));
Primitive.AddVertex(vertex);
VertexNbr++;
}
// Indices
int High = VertexNbr - 1; // High, Low, Center
int Low = 0;
int Center = 0;
int IndexOffset = Primitive.MeshBuffer.VertexCount;
for (int v = 0; v < VertexNbr - 2; ++v)
{
// Calcul les indices
if ((v & 1) > 0) Center = High - 1;
else Center = Low + 1;
// Ajoute les indices
Primitive.AddIndex(IndexOffset + High);
Primitive.AddIndex(IndexOffset + Low);
Primitive.AddIndex(IndexOffset + Center);
// Retrouve les vertices concernés
Vertex3DT2 VertexCenter = Primitive.GetVertex(Center);
Vertex3DT2 VertexLow = Primitive.GetVertex(Low);
Vertex3DT2 VertexHigh = Primitive.GetVertex(High);
// Calcul de la normale
Vector3D Normal = this.GetFaceNormal(VertexHigh.Position, VertexLow.Position, VertexCenter.Position);
// Corrige les normales des vertices
VertexCenter.Normal += Normal;
VertexLow.Normal += Normal;
VertexHigh.Normal += Normal;
if ((v & 1) > 0) High--;
else Low++;
}
Primitive.RemadeMeshBuffer();
// Changement de matériau, c'est donc une nouvelle primitive
if (MaterialID != OldMaterialID)
{
// L'ajoute au mesh
mesh.AddPrimitive(Primitive);
OldMaterialID = MaterialID;
}
}
}
}
// Charge les matériaux
void LoadMaterials(XML.Node NMaterials)
{
// Parcours toutes les catégories
foreach (XML.Node NCategory in NMaterials.Childs)
{
// Parcours tous les matériaux d'une catégorie
foreach (XML.Node NMaterial in NCategory.Childs)
{
Material Material = new Material();
Material.Lighting = false;
int ID = Convert.ToInt32(NMaterial.GetAttribute("id").Value);
// Parcours les layers du matérial
foreach (XML.Node NLayer in NMaterial.Childs)
{
// Charge le fichier image
string type = NLayer.GetAttribute("type").Value;
string file = NLayer.GetChild("texture").GetAttribute("file").Value;
file = DXSMeshLoader.TexturePath + file;
if (type == "texture")
Material.Texture1 = GraphicManager.Instance.Driver.GetTexture(file);
else if (type == "lightmap")
{
// Présence d'une lightmap
Material.Texture2 = GraphicManager.Instance.Driver.GetTexture(file);
Material.MaterialType = MaterialType.Lightmap;
}
}
// Ajoute le material à la liste
Materials.Add(ID, Material);
}
}
}
// Renvoit la normale d'une face
Vector3D GetFaceNormal(Vector3D a, Vector3D b, Vector3D c)
{
Vector3D o = new Vector3D();
Vector3D v1 = new Vector3D();
Vector3D v2 = new Vector3D();
v1 = a - b;
v2 = b - c;
o.X = (v1.Y * v2.Z) - (v1.Z * v2.Y);
o.Y = (v1.Z * v2.X) - (v1.X * v2.Z);
o.Z = (v1.X * v2.Y) - (v1.Y * v2.X);
float dist = (o.X * o.X) + (o.Y * o.Y) + (o.Z * o.Z);
dist = (float)System.Math.Sqrt(dist);
if (dist == 0.0f) dist = 0.001f;
o /= dist;
return o;
}
}
}