#1 

20-06-2007 12:43:38

Aranoth
Membres
Avatar de Aranoth
Date d'inscription:
Messages: 242
IP: 86.201.128.213
Courriel  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


#2 

20-06-2007 17:18:31

izguit
Administrateurs
Avatar de izguit
Date d'inscription:
Messages: 306
IP: 83.153.59.133
Courriel  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


#3 

23-06-2007 08:54:58

Ravine
Membres
Date d'inscription:
Messages: 61
IP: 82.240.209.43
Courriel

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)

        /// <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


Hors ligne


#4 

24-06-2007 12:50:11

Aranoth
Membres
Avatar de Aranoth
Date d'inscription:
Messages: 242
IP: 86.221.104.127
Courriel  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


#5 

24-06-2007 15:32:43

Ravine
Membres
Date d'inscription:
Messages: 61
IP: 82.240.209.43
Courriel

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


#6 

26-06-2007 23:37:01

Ravine
Membres
Date d'inscription:
Messages: 61
IP: 82.240.209.43
Courriel

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

				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


Hors ligne


#7 

27-06-2007 06:21:00

DeusXL
Membres
Avatar de DeusXL
Date d'inscription:
Messages: 174
IP: 82.66.209.23
Courriel

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


#8 

27-06-2007 12:15:09

Aranoth
Membres
Avatar de Aranoth
Date d'inscription:
Messages: 242
IP: 86.201.56.28
Courriel  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à :

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


#9 

27-06-2007 19:52:23

Ravine
Membres
Date d'inscription:
Messages: 61
IP: 82.240.209.43
Courriel

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


#10 

07-08-2007 15:36:52

Ravine
Membres
Date d'inscription:
Messages: 61
IP: 82.65.48.32
Courriel

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-content/2007/07/DxsSharpLoader.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

            // 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


#11 

13-08-2007 19:53:31

Aranoth
Membres
Avatar de Aranoth
Date d'inscription:
Messages: 242
IP: 86.201.187.164
Courriel  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.

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é
Préférences cookies
Corrections
irrlicht
irrklang
irredit
irrxml
Propulsé par Django
xhtml 1.0
css 2.1
884 membres
1440 sujets
11337 messages
Dernier membre inscrit: Saidov17
115 invités en ligne
membre en ligne: -
RSS Feed