00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 using System;
00018 using System.Collections;
00019 using System.Collections.Generic;
00020 using System.Text;
00021 using Microsoft.DirectX;
00022 using Microsoft.DirectX.Direct3D;
00023 using Microsoft.Samples.DirectX.UtilityToolkit;
00024 using System.Drawing;
00025 using System.IO;
00026
00027 namespace DXGfxLib
00028 {
00032 public struct MaterialFromObj
00033 {
00034 public string name;
00035
00036 public Vector3 vAmbient;
00037 public Vector3 vDiffuse;
00038 public Vector3 vSpecular;
00039
00040 public int nShininess;
00041 public float fAlpha;
00042
00043 public bool bSpecular;
00044
00045 public string strTexture;
00046 public Texture texture;
00047 }
00048
00054 public class ObjectFromObj : MeshObject
00055 {
00059 private int numFaces = 0;
00063 private int numIndices = 0;
00067 private bool weHaveNormals = false;
00071 private Material defaultMat;
00072
00076 private List<MaterialFromObj> materials = null;
00077
00081 public ObjectFromObj()
00082 {
00083 materials = new List<MaterialFromObj>();
00084
00085 defaultMat = new Material();
00086 defaultMat.Ambient = Color.Aqua;
00087 defaultMat.Diffuse = Color.Azure;
00088 defaultMat.Emissive = Color.Blue;
00089 defaultMat.Specular = Color.Brown;
00090 }
00091
00097 public void Load(Device d3ddevice, string wavefrontObjFile)
00098 {
00099
00100 string meshFile = Utility.FindMediaFile(wavefrontObjFile);
00101 string mtlFile = "";
00102
00103
00104 string currentFolder = System.IO.Directory.GetCurrentDirectory();
00105 System.IO.Directory.SetCurrentDirectory(new System.IO.FileInfo(meshFile).Directory.FullName);
00106
00107 List<Int16> indices = new List<Int16>();
00108 List<Vector2> texCoords = new List<Vector2>();
00109 List<Vector3> normals = new List<Vector3>();
00110 List<int> attributes = new List<int>();
00111 List<CustomVertex.PositionNormalTextured> vertices = new List<CustomVertex.PositionNormalTextured>();
00112
00113 int currSubset = 0;
00114
00115 string line;
00116
00117
00118 StreamReader sr = new StreamReader(meshFile);
00119
00120
00121 line = sr.ReadLine();
00122
00123
00124 while (line != null)
00125 {
00126 if(line.StartsWith("#"))
00127 {
00128
00129 }
00130 else if(line.StartsWith("vt"))
00131 {
00132
00133 string tmp = line.Substring(3);
00134
00135 string[] values = FilteredSplit(tmp, null);
00136
00137 texCoords.Add(new Vector2(float.Parse(values[0]),
00138 float.Parse(values[1])));
00139 }
00140 else if(line.StartsWith("vn"))
00141 {
00142
00143 string tmp = line.Substring(3);
00144
00145 string[] values = FilteredSplit(tmp, null);
00146
00147 normals.Add(new Vector3(float.Parse(values[0]),
00148 float.Parse(values[1]),
00149 float.Parse(values[2])));
00150 }
00151 else if (line.StartsWith("v"))
00152 {
00153
00154 string tmp = line.Substring(2);
00155
00156 string[] values = FilteredSplit(tmp, null);
00157
00158 CustomVertex.PositionNormalTextured vertex = new CustomVertex.PositionNormalTextured();
00159 vertex.Position = new Vector3(float.Parse(values[0]),
00160 float.Parse(values[1]),
00161 float.Parse(values[2]));
00162 vertices.Add(vertex);
00163 }
00164 else if(line.StartsWith("f"))
00165 {
00166
00167 int iPosition, iTexCoord, iNormal;
00168 iPosition = iTexCoord = iNormal = 0;
00169 CustomVertex.PositionNormalTextured vertex;
00170
00171 string tmp = line.Substring(2);
00172 string[] values = FilteredSplit(tmp, null);
00173 if (values.Length == 3)
00174 {
00175 for (int i = 0; i < 3; i++)
00176 {
00177 string[] indexes = values[i].Split('/');
00178
00179 iPosition = int.Parse(indexes[0]);
00180 vertex = vertices[iPosition - 1];
00181
00182 indices.Add((Int16)(iPosition - 1));
00183 numIndices++;
00184
00185 if (indexes.Length > 1)
00186 {
00187 iTexCoord = int.Parse(indexes[1]);
00188 vertex.Tu = texCoords[iTexCoord - 1].X;
00189 vertex.Tv = texCoords[iTexCoord - 1].Y;
00190
00191 if (indexes.Length > 2)
00192 {
00193 weHaveNormals = true;
00194 iNormal = int.Parse(indexes[2]);
00195 vertex.Nx = normals[iNormal - 1].X;
00196 vertex.Ny = normals[iNormal - 1].Y;
00197 vertex.Nz = normals[iNormal - 1].Z;
00198 }
00199 }
00200 }
00201 numFaces++;
00202
00203 attributes.Add(currSubset);
00204 }
00205 if (values.Length == 4)
00206 {
00207 for (int i = 0; i < 4; i++)
00208 {
00209 string[] indexes = values[i].Split('/');
00210
00211 iPosition = int.Parse(indexes[0]);
00212 vertex = vertices[iPosition - 1];
00213
00214 if (i == 3)
00215 {
00216 indices.Add(indices[indices.Count - 3]);
00217 indices.Add(indices[indices.Count - 1]);
00218 indices.Add((Int16)(iPosition - 1));
00219 numIndices = +3;
00220 numFaces++;
00221 attributes.Add(currSubset);
00222 }
00223 else
00224 {
00225 indices.Add((Int16)(iPosition - 1));
00226 numIndices++;
00227 }
00228 if (indexes.Length > 1)
00229 {
00230 iTexCoord = int.Parse(indexes[1]);
00231 vertex.Tu = texCoords[iTexCoord - 1].X;
00232 vertex.Tv = texCoords[iTexCoord - 1].Y;
00233
00234 if (indexes.Length > 2)
00235 {
00236 weHaveNormals = true;
00237 iNormal = int.Parse(indexes[2]);
00238 vertex.Nx = normals[iNormal - 1].X;
00239 vertex.Ny = normals[iNormal - 1].Y;
00240 vertex.Nz = normals[iNormal - 1].Z;
00241 }
00242 }
00243 }
00244 numFaces++;
00245
00246 attributes.Add(currSubset);
00247 }
00248 }
00249 else if(line.StartsWith("mtllib"))
00250 {
00251 mtlFile = line.Substring(7);
00252
00253
00254 LoadMtl(d3ddevice, mtlFile);
00255 }
00256 else if(line.StartsWith("usemtl"))
00257 {
00258 bool found = false;
00259
00260 string matName = line.Substring(7);
00261
00262 for (int i = 0; i < materials.Count; i++)
00263 {
00264 if (matName.Equals(materials[i].name))
00265 {
00266 found = true;
00267 currSubset = i;
00268 }
00269 }
00270
00271 if (!found)
00272 {
00273 throw new Exception("Materials are already loaded so we should have it!");
00274 }
00275 }
00276
00277
00278 line = sr.ReadLine();
00279 }
00280
00281
00282 sr.Close();
00283
00284 Mesh ourMesh = new Mesh(numFaces, vertices.Count, MeshFlags.Managed, CustomVertex.PositionNormalTextured.Format,
00285 d3ddevice);
00286
00287 GraphicsStream dstVertices = ourMesh.LockVertexBuffer(LockFlags.NoSystemLock);
00288 dstVertices.Write(vertices.ToArray());
00289 ourMesh.UnlockVertexBuffer();
00290
00291 GraphicsStream dstIndices = ourMesh.LockIndexBuffer(LockFlags.NoSystemLock);
00292 dstIndices.Write(indices.ToArray());
00293 ourMesh.UnlockIndexBuffer();
00294
00295 int[] dstAttributes = ourMesh.LockAttributeBufferArray(LockFlags.NoSystemLock);
00296 attributes.CopyTo(dstAttributes);
00297 ourMesh.UnlockAttributeBuffer();
00298
00299 if (!weHaveNormals)
00300 {
00301 ourMesh.ComputeNormals();
00302 }
00303
00304
00305 base.Attach(ourMesh);
00306
00307
00308 System.IO.Directory.SetCurrentDirectory(currentFolder);
00309 }
00310
00316 public void LoadMtl(Device d3ddevice, string file)
00317 {
00318 MaterialFromObj currentMaterial = new MaterialFromObj();
00319 bool first = true;
00320
00321
00322 StreamReader sr = new StreamReader(file);
00323
00324
00325 string line = sr.ReadLine();
00326
00327
00328 while (line != null)
00329 {
00330 if (line.StartsWith("#"))
00331 {
00332
00333 }
00334 else if (line.StartsWith("newmtl"))
00335 {
00336 if (!first)
00337 {
00338 materials.Add(currentMaterial);
00339 currentMaterial = new MaterialFromObj();
00340 }
00341 first = false;
00342 currentMaterial.name = line.Substring(7);
00343 }
00344 else if (line.StartsWith("Ka"))
00345 {
00346 string tmp = line.Substring(3);
00347
00348 string[] values = FilteredSplit(tmp, null);
00349
00350
00351 currentMaterial.vAmbient = new Vector3(float.Parse(values[0]),
00352 float.Parse(values[1]),
00353 float.Parse(values[2]));
00354 }
00355 else if (line.StartsWith("Kd"))
00356 {
00357 string tmp = line.Substring(3);
00358
00359 string[] values = FilteredSplit(tmp, null);
00360
00361 currentMaterial.vDiffuse = new Vector3(float.Parse(values[0]),
00362 float.Parse(values[1]),
00363 float.Parse(values[2]));
00364 }
00365
00366 else if (line.StartsWith("Ks"))
00367 {
00368 string tmp = line.Substring(3);
00369
00370 string[] values = FilteredSplit(tmp, null);
00371
00372 currentMaterial.vSpecular = new Vector3(float.Parse(values[0]),
00373 float.Parse(values[1]),
00374 float.Parse(values[2]));
00375 }
00376 else if (line.StartsWith("map_Kd"))
00377 {
00378 string tmp = line.Substring(7);
00379
00380
00381
00382 }
00383
00384
00385 line = sr.ReadLine();
00386 }
00387 materials.Add(currentMaterial);
00388
00389
00390 sr.Close();
00391 }
00392
00397 public override void Draw(Device d3ddevice)
00398 {
00399 d3ddevice.SetTransform(TransformType.World, worldMat);
00400 d3ddevice.Material = defaultMat;
00401 for (int i = 0; i < materials.Count; i++)
00402 {
00403 d3ddevice.SetTexture(0, materials[i].texture);
00404 originalMesh.DrawSubset(i);
00405 }
00406 }
00407
00414 public string[] FilteredSplit(string strIn, char[] separator)
00415 {
00416 string[] valuesUnfiltered = strIn.Split(separator);
00417
00418
00419
00420 List<string> listOfValues = new List<string>();
00421 foreach (string str in valuesUnfiltered)
00422 {
00423 if (str != "")
00424 {
00425 listOfValues.Add(str);
00426 }
00427 }
00428 string[] values = listOfValues.ToArray();
00429
00430 return values;
00431 }
00432 }
00433 }