00001
00002
00003
00004
00005
00006
00007
00008 using System;
00009 using Microsoft.DirectX;
00010 using Microsoft.DirectX.Direct3D;
00011
00012 namespace Microsoft.Samples.DirectX.UtilityToolkit
00013 {
00015 public sealed class FrameworkMesh : IDisposable
00016 {
00017 #region Instance Data
00018 private string meshFileName;
00019 private Mesh systemMemoryMesh = null;
00020 private Mesh localMemoryMesh = null;
00021
00022 private Material[] meshMaterials = null;
00023 private BaseTexture[] meshTextures = null;
00024 private bool isUsingMeshMaterials = true;
00025
00027 public Mesh SystemMesh { get { return systemMemoryMesh; } }
00029 public Mesh LocalMesh { get { return localMemoryMesh; } }
00031 public bool IsUsingMaterials{ get { return isUsingMeshMaterials; } set { isUsingMeshMaterials = value; } }
00033 public int NumberMaterials { get { return meshMaterials.Length; } }
00035 public BaseTexture GetTexture(int index) { return meshTextures[index]; }
00037 public Material GetMaterial(int index) { return meshMaterials[index]; }
00038 #endregion
00039
00040 #region Creation
00042 public FrameworkMesh(Device device, string name)
00043 {
00044 meshFileName = name;
00045 Create(device, meshFileName);
00046 }
00048 public FrameworkMesh() : this(null, "FrameworkMeshFile_Mesh") {}
00049
00051 public void Create(Device device, string name)
00052 {
00053
00054 System.Diagnostics.Debug.Assert(device != null, "Device should not be null.");
00055 device.DeviceLost += new EventHandler(OnLostDevice);
00056 device.DeviceReset += new EventHandler(OnResetDevice);
00057 device.Disposing += new EventHandler(OnDeviceDisposing);
00058
00059 GraphicsStream adjacency;
00060 ExtendedMaterial[] materials;
00061
00062
00063 string path = string.Empty;
00064 try
00065 {
00066 path = Utility.FindMediaFile(name);
00067 }
00068 catch(MediaNotFoundException)
00069 {
00070
00071 if (System.IO.File.Exists(name))
00072 {
00073 path = name;
00074 }
00075 else
00076 {
00077
00078 throw new MediaNotFoundException();
00079 }
00080 }
00081
00082
00083 systemMemoryMesh = Mesh.FromFile(path, MeshFlags.SystemMemory, device, out adjacency,
00084 out materials);
00085
00086 using (adjacency)
00087 {
00088
00089 systemMemoryMesh.OptimizeInPlace(MeshFlags.OptimizeVertexCache | MeshFlags.OptimizeCompact |
00090 MeshFlags.OptimizeAttributeSort, adjacency);
00091
00092
00093 string folder = Utility.AppendDirectorySeparator(new System.IO.FileInfo(path).DirectoryName);
00094
00095
00096 CreateMaterials(folder, device, adjacency, materials);
00097 }
00098
00099
00100 OnResetDevice(device, EventArgs.Empty);
00101 }
00102
00103
00105 public void CreateMaterials(string folder, Device device, GraphicsStream adjacency, ExtendedMaterial[] materials)
00106 {
00107
00108 if ((materials != null) && (materials.Length > 0))
00109 {
00110
00111 meshMaterials = new Material[materials.Length];
00112 meshTextures = new BaseTexture[materials.Length];
00113
00114
00115 for(int i = 0; i < materials.Length; i++)
00116 {
00117
00118 meshMaterials[i] = materials[i].Material3D;
00119
00120
00121 if ((materials[i].TextureFilename == null) || (materials[i].TextureFilename.Length == 0) )
00122 continue;
00123
00124 ImageInformation info = new ImageInformation();
00125 string textureFile = folder + materials[i].TextureFilename;
00126 try
00127 {
00128
00129 info = TextureLoader.ImageInformationFromFile(textureFile);
00130 }
00131 catch
00132 {
00133 try
00134 {
00135
00136 textureFile = Utility.FindMediaFile(materials[i].TextureFilename);
00137 info = TextureLoader.ImageInformationFromFile(textureFile);
00138 }
00139 catch (MediaNotFoundException)
00140 {
00141
00142 continue;
00143 }
00144 }
00145 switch (info.ResourceType)
00146 {
00147 case ResourceType.Textures:
00148 meshTextures[i] = TextureLoader.FromFile(device, textureFile);
00149 break;
00150 case ResourceType.CubeTexture:
00151 meshTextures[i] = TextureLoader.FromCubeFile(device, textureFile);
00152 break;
00153 case ResourceType.VolumeTexture:
00154 meshTextures[i] = TextureLoader.FromVolumeFile(device, textureFile);
00155 break;
00156 }
00157 }
00158 }
00159 }
00160 #endregion
00161
00162 #region Class Methods
00164 public void SetVertexFormat(Device device, VertexFormats format)
00165 {
00166 Mesh tempSystemMesh = null;
00167 Mesh tempLocalMesh = null;
00168 VertexFormats oldFormat = VertexFormats.None;
00169 using(systemMemoryMesh)
00170 {
00171 using (localMemoryMesh)
00172 {
00173
00174 if (systemMemoryMesh != null)
00175 {
00176 oldFormat = systemMemoryMesh.VertexFormat;
00177 tempSystemMesh = systemMemoryMesh.Clone(systemMemoryMesh.Options.Value,
00178 format, device);
00179 }
00180 if (localMemoryMesh != null)
00181 {
00182 tempLocalMesh = localMemoryMesh.Clone(localMemoryMesh.Options.Value,
00183 format, device);
00184 }
00185 }
00186 }
00187
00188
00189 systemMemoryMesh = tempSystemMesh;
00190 localMemoryMesh = tempLocalMesh;
00191
00192
00193 if ( ((oldFormat & VertexFormats.Normal) == 0) && (format != 0) )
00194 {
00195 if (systemMemoryMesh != null)
00196 systemMemoryMesh.ComputeNormals();
00197 if (localMemoryMesh != null)
00198 localMemoryMesh.ComputeNormals();
00199 }
00200 }
00202 public void SetVertexDeclaration(Device device, VertexElement[] decl)
00203 {
00204 Mesh tempSystemMesh = null;
00205 Mesh tempLocalMesh = null;
00206 VertexElement[] oldDecl = null;
00207 using(systemMemoryMesh)
00208 {
00209 using (localMemoryMesh)
00210 {
00211
00212 if (systemMemoryMesh != null)
00213 {
00214 oldDecl = systemMemoryMesh.Declaration;
00215 tempSystemMesh = systemMemoryMesh.Clone(systemMemoryMesh.Options.Value,
00216 decl, device);
00217 }
00218 if (localMemoryMesh != null)
00219 {
00220 tempLocalMesh = localMemoryMesh.Clone(localMemoryMesh.Options.Value,
00221 decl, device);
00222 }
00223 }
00224 }
00225
00226
00227 systemMemoryMesh = tempSystemMesh;
00228 localMemoryMesh = tempLocalMesh;
00229
00230 bool hadNormal = false;
00231
00232 for(int i = 0; i < oldDecl.Length; i++)
00233 {
00234 if (oldDecl[i].DeclarationUsage == DeclarationUsage.Normal)
00235 {
00236 hadNormal = true;
00237 break;
00238 }
00239 }
00240
00241 bool hasNormalNow = false;
00242 for(int i = 0; i < decl.Length; i++)
00243 {
00244 if (decl[i].DeclarationUsage == DeclarationUsage.Normal)
00245 {
00246 hasNormalNow = true;
00247 break;
00248 }
00249 }
00250
00251
00252 if ( !hadNormal && hasNormalNow )
00253 {
00254 if (systemMemoryMesh != null)
00255 systemMemoryMesh.ComputeNormals();
00256 if (localMemoryMesh != null)
00257 localMemoryMesh.ComputeNormals();
00258 }
00259 }
00260
00262 private void OnResetDevice(object sender, EventArgs e)
00263 {
00264 Device device = sender as Device;
00265 if (systemMemoryMesh == null)
00266 throw new InvalidOperationException("There is no system memory mesh. Nothing to do here.");
00267
00268
00269
00270 localMemoryMesh = systemMemoryMesh.Clone((systemMemoryMesh.Options.Value & ~MeshFlags.SystemMemory),
00271 systemMemoryMesh.VertexFormat, device);
00272 }
00273
00275 private void OnLostDevice(object sender, EventArgs e)
00276 {
00277 if (localMemoryMesh != null)
00278 localMemoryMesh.Dispose();
00279
00280 localMemoryMesh = null;
00281 }
00283 public void Render(Device device, bool canDrawOpaque, bool canDrawAlpha)
00284 {
00285 if (localMemoryMesh == null)
00286 throw new InvalidOperationException("No local memory mesh.");
00287
00288
00289 if (canDrawOpaque)
00290 {
00291 for (int i = 0; i < meshMaterials.Length; i++)
00292 {
00293 if (isUsingMeshMaterials)
00294 {
00295 if (meshMaterials[i].DiffuseColor.Alpha < 1.0f)
00296 continue;
00297
00298
00299 device.Material = meshMaterials[i];
00300 device.SetTexture(0, meshTextures[i]);
00301 }
00302 localMemoryMesh.DrawSubset(i);
00303 }
00304 }
00305
00306
00307 if (canDrawAlpha)
00308 {
00309 for (int i = 0; i < meshMaterials.Length; i++)
00310 {
00311 if (meshMaterials[i].DiffuseColor.Alpha == 1.0f)
00312 continue;
00313
00314
00315 device.Material = meshMaterials[i];
00316 device.SetTexture(0, meshTextures[i]);
00317 localMemoryMesh.DrawSubset(i);
00318 }
00319 }
00320 }
00322 public void Render(Device device) { Render(device, true, true); }
00323
00324
00325
00327 public float ComputeBoundingSphere(out Vector3 center)
00328 {
00329 if (systemMemoryMesh == null)
00330 throw new InvalidOperationException("There is no system memory mesh. Nothing to do here.");
00331
00332
00333 int strideSize = VertexInformation.GetFormatSize(systemMemoryMesh.VertexFormat);
00334
00335
00336 GraphicsStream data = null;
00337 try
00338 {
00339 data = systemMemoryMesh.LockVertexBuffer(LockFlags.ReadOnly);
00340
00341 return Geometry.ComputeBoundingSphere(data, systemMemoryMesh.NumberVertices,
00342 systemMemoryMesh.VertexFormat, out center);
00343 }
00344 finally
00345 {
00346
00347 if (data != null)
00348 systemMemoryMesh.UnlockVertexBuffer();
00349 }
00350 }
00351 #endregion
00352
00353 #region IDisposable Members
00354
00356 public void Dispose()
00357 {
00358 OnLostDevice(null, EventArgs.Empty);
00359 if (meshTextures != null)
00360 {
00361 for(int i = 0; i < meshTextures.Length; i++)
00362 {
00363 if (meshTextures[i] != null)
00364 meshTextures[i].Dispose();
00365 }
00366 }
00367 meshTextures = null;
00368 meshMaterials = null;
00369
00370 if (systemMemoryMesh != null)
00371 systemMemoryMesh.Dispose();
00372
00373 systemMemoryMesh = null;
00374
00375 }
00376
00378 private void OnDeviceDisposing(object sender, EventArgs e)
00379 {
00380
00381 Dispose();
00382 }
00383 #endregion
00384
00385 }
00386 }