#0 

20-06-2007 14:43:38

Aranoth
Abonné
Lieu: Toulouse
Date d'inscription: 25-09-2006
Messages: 242
Site web

Yo à tous !

On me l'avait demandé, je l'avais promis, et je l'ai fait ! Hahaha...

Plus sérieusement, j'aurais aimé fournir un travail un peu mieux fait que ça, mais bon...

C'est pour ça que je suis prêt à répondre à toutes les questions, alors n'hésitez pas.

Vous trouverez le code source ainsi que quelques explications ici :
http://aranoth.keogratuit.com/?p=5

Ou si le baratin ne vous intéresse pas :
http://aranoth.keogratuit.com/LoaderDXS.rar


Voilà big_smile

En espérant que ça puisse aider certains malgré l'aspect chaotique du code...

Hors ligne


#1 

20-06-2007 19:18:31

izguit
Administrateur
Lieu: 127.0.0.1
Date d'inscription: 14-09-2006
Messages: 306
Site web

yop
'peut être très utile pour les .NETeux
bon boulot smile


Athlon 64 3000+ // 1Go RAM // Geforce 6600GT 128Mo
Turion 64 X2 // 1Go RAM // ATI X1250

Hors ligne


#2 

23-06-2007 10:54:58

Ravine
Membre
Date d'inscription: 09-12-2006
Messages: 61

hehe, merci beaucoup Aranoth. Avec ça et le loader de ilbuzzo (celui en C++) je devrais pouvoir me dépatouiller pour intégrer ça a mon projet. smile


EDIT : bon je vais passer pour un grincheux, mais je vais te donner un conseil "pour plus tard" : prends l'habitude de commenter ton code. Pas juste des summary sur les fields des classes. exemple : un "// Identifiant" sur un "public int Id" par exemple est inutile. Deja parce que le nom du field est "autodescriptif" (dans la mesure du possible), donc ce commentaire est redondant, et n'apporte aucune indication sur l'utilité du champ.

Ensuite, toutes tes méthodes ne sont pas commentées. En tant que développeur, j'aime bien ne pas perdre du temps a lire le code pour savoir ce qu'il fait. C'est là qu'un ///<summary> serait le bienvenu, pour décrire rapidos le fonctionnement de la méthode, expliquer succintement comment tu geres tel ou tel truc.

Je dis pas que c'est du mauvais code, mais reviens y dans un an, et tu vas etre réticent a te replonger dedans pour lire ton code pour essayer de te souvenir comment tu as fait. Le commentaire est là pour te servir, et pour servir à ceux qui te liront.

Sinon le code ? J'y retourne. Et comme j'avais deja ecrit des trucs pour ça, je vais etudier les sections sur l'intégration dans irrlicht, et retoucher mes classes smile.


tiens, un exemple de code "bien" commenté (extrait des sources du wrapper .NetCP)

Code:

        /// <summary>
        /// Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. 
        /// This is useful if you want to draw tangent space normal mapped geometry because it calculates the tangent and binormal data which is needed there. 
        /// </summary>
        /// <param name="baseMesh">Input mesh</param>
        /// <returns>Mesh consiting only of S3DVertexTangents vertices.</returns>
        public Mesh CreateMeshWithTangents(Mesh baseMesh)
        {
            return (Mesh)
                NativeElement.GetObject(MeshManipulator_CreateMeshWithTangents(_raw, baseMesh.Raw),
                                        typeof(Mesh));
        }

d'autant plus interessant qu'il prends en compte les spécificités de .Net et de ses capacité de gestion de création de documentation. Le summary apparaitra dans l'intellisense. Les <param name> feront apparaitre la descrition des parametres formels dans l'intellisense quand on navigue dans les parametres. Là, j'ai pas besoin de lire le code pour savoir comment l'utiliser ni pour savoir ce que ça fait smile

No offense hein, mais bon, je suis en croisade contre les codes non commentés smile

Dernière modification par Ravine (23-06-2007 12:45:20)

Hors ligne


#3 

24-06-2007 14:50:11

Aranoth
Abonné
Lieu: Toulouse
Date d'inscription: 25-09-2006
Messages: 242
Site web

Héhé, justement j'ai rajouté les <summary> vite fait sans prendre le temps de réellement me replonger dans le code (si on met pas de <summary> le compilo crache un Warning...).
Oui c'était absolument pas commenté, je l'ai dit : il aurait fallut que j'écrive ce code en pensant dès le début à diffuser les sources.

Comme tu l'as dit, y revenir après c'est dur, et pas besoin d'attendre un an. J'ai pas pu m'y replonger correctement, les dépendances ont été enlevées vite fait, le code est vraiment pas utilisable en l'état.

C'est pour ça que je suis pret à répondre à toutes les questions, parce que j'ai bien conscience que ce code n'est exploitable tel quel.

Hors ligne


#4 

24-06-2007 17:32:43

Ravine
Membre
Date d'inscription: 09-12-2006
Messages: 61

huhu  pas de soucis. Deja de mon coté j'avais réalisé une grosse part du boulot. Je charge un DXS dans une classe perso (identifier tous les bidules du format DXS ça représente un sacré boulot mine de rien smile ). Mais il me manquait concretement toute la partie "envoi dans irrlicht". Mais je note, et n'hesiterai pas a te harceler smile

Hors ligne


#5 

27-06-2007 01:37:01

Ravine
Membre
Date d'inscription: 09-12-2006
Messages: 61

Ah bah nous y voilà. Bon j'ai maté ton code et j'avoue que j'ai juste super rien a dire sur le code en lui meme smile

C'est propre et tout. Quelques questions cependant

Code:

                ArrayList Vertices = new ArrayList();
                foreach (AGE.XML.Node vert in vertices.Childs)
                {
                    int id = Convert.ToInt32(vert.GetAttribute("id").Value);
                    float x = this.ValF(vert.GetAttribute("x").Value);
                    float y = this.ValF(vert.GetAttribute("y").Value);
                    float z = -this.ValF(vert.GetAttribute("z").Value);
                    Vertices.Add(new vector3d(x, y, z));
                }

1- Une raison particuliere au choix d'un ArrayList plutot que toute autre implémentation de type list ? (juste pour info, ça m'interesse)

2- un petit détail interessant : le float z que tu multiplie par -1. Je suppose que c'est pour une obscure raison de changement de repere (main droite / main gauche), mais j'avoue que je preferai l'explication plutot que mes vagues considérations là dessus smile

Dernière modification par Ravine (27-06-2007 01:37:21)

Hors ligne


#6 

27-06-2007 08:21:00

DeusXL
Abonné
Lieu: Paris
Date d'inscription: 27-09-2006
Messages: 174

Peut-être que, list<> étant dans les Generics (donc dans la version 2.0 du framework), il a choisi de rester avec des librairies de 1.1 !
Bon le choix est étrange quand on sait que le wrapper est fait pour la 2.0...

Sinon je ne vois pas de raison possible à l'utilisation des ArrayList pour contenir un seul type d'objet, les list typées sont plus rapides, plus sûres et plus efficaces !


Fanatique d'Irrlicht + Fanatique de Mono + Fanatique de Linux => Créateur d'Irrlicht .NET CP bien sûr !
Version actuelle d'Irrlicht .NET CP : 0.8, Version en test : 0.9.

Hors ligne


#7 

27-06-2007 14:15:09

Aranoth
Abonné
Lieu: Toulouse
Date d'inscription: 25-09-2006
Messages: 242
Site web

Pour le signe moins devant la coordonnée Z c'est effectivement un changement de repère (ceux d'Irrlicht et de DeleD sont différents).

Pour le ArrayList Vertices, cela viens de là :

Code:

vector3d vect = (vector3d)Vertices[vid];

J'ai besoin d'accéder à une entrée par son ID, d'où le choix de l'ArrayList.

Mais comme j'ai appris le C# sur le tas, il est possible qu'il y ai une meilleur solution, c'est juste que dans ma tête l'ArrayList est l'équivalant du std::vector du C++.

Hors ligne


#8 

27-06-2007 21:52:23

Ravine
Membre
Date d'inscription: 09-12-2006
Messages: 61

Les list<T> feront l'affaire : gestion d'un IndexOf(T item) (renvoi l'index de l'item si trouvé, -1 sinon), gestion des indexes. Comme le fait remarquer DeusXL, la classe générique list<T> est bien plus performante que les ArrayList (je viens de le lire dans ma bible .net /C# ^^ )

Hors ligne


#9 

07-08-2007 17:36:52

Ravine
Membre
Date d'inscription: 09-12-2006
Messages: 61

Je profite d'avoir uploadé ma version du loader sur mon blog (un referer me signalait que quelqu'un cherchait des infos sur les fichiers Dxs et comment les lire) pour bumper ici et balancer le meme lien.

http://ravine.blog.free.fr/blog/wp-cont … Loader.zip

le Dxs.cs contient des bouts de code d'un peu partout, donc je ne sais pas quelle licence lui mettre, mais les autres fichiers .cs sont placés sous licence MIT.

et le manuel

Code:

            // on créée une instance d'un dxs
            Dxs myDxs = new Dxs();
 
            // on fait appel a LoadFromFile pour lire le Dxs et le charger en mémoire.
            // (ici, je fais appel directement au fichier car il est dans le rep courant de l'application
            // et que le workingDirectory de irrlicht est mis à "./"
            myDxs.LoadFromFile("moyen.dxs");
 
            // CreateMesh(IrrlichtDevice device, string texturePath) renvoie un Mesh tout propre, créé a partir des listes de myDxs
            Mesh dxsMesh = myDxs.CreateMesh(device, "");
 
            // et hop, on l'ajoute au scene manager (dans un octree, etant donné que le mesh est statique.
            // C'est plus performant selon des personnes plus calées, y'a donc pas de raison de ne pas les écouter)
            SceneNode node = smgr.AddOctTreeSceneNode(dxsMesh, null, 24, 1);

Hors ligne


#10 

13-08-2007 21:53:31

Aranoth
Abonné
Lieu: Toulouse
Date d'inscription: 25-09-2006
Messages: 242
Site web

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.

Code:

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;
        }
    }
}

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
882 membres
1429 sujets
11119 messages
Dernier membre inscrit: LiseBuisson96
17 invités en ligne
Aucun membre connecté
RSS Feed