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 GraphicsBuffer adjacency = new GraphicsBuffer();
00060 MaterialList materials = new MaterialList();
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 = new Mesh(device, path, MeshFlags.SystemMemory, adjacency, materials, null);
00084
00085 using (adjacency)
00086 {
00087
00088 systemMemoryMesh.OptimizeInPlace(MeshFlags.OptimizeVertexCache | MeshFlags.OptimizeCompact |
00089 MeshFlags.OptimizeAttributeSort, adjacency);
00090
00091
00092 string folder = Utility.AppendDirectorySeparator(new System.IO.FileInfo(path).DirectoryName);
00093
00094
00095 CreateMaterials(folder, device, adjacency, materials);
00096 }
00097
00098
00099 OnResetDevice(device, EventArgs.Empty);
00100 }
00101
00102
00104 public void CreateMaterials(string folder, Device device, GraphicsBuffer adjacency, MaterialList materials)
00105 {
00106
00107 if ((materials != null) && (materials.Count > 0))
00108 {
00109
00110 meshMaterials = new Material[materials.Count];
00111 meshTextures = new BaseTexture[materials.Count];
00112
00113
00114 for (int i = 0; i < materials.Count; i++)
00115 {
00116
00117 meshMaterials[i] = materials[i].Material;
00118
00119
00120 if (string.IsNullOrEmpty(materials[i].TextureFileName))
00121 continue;
00122
00123 ImageInformation info = new ImageInformation();
00124 string textureFile = folder + materials[i].TextureFileName;
00125 try
00126 {
00127
00128 info = BaseTexture.GetImageInformationFromFile(textureFile);
00129 }
00130 catch
00131 {
00132 try
00133 {
00134
00135 textureFile = Utility.FindMediaFile(materials[i].TextureFileName);
00136 info = BaseTexture.GetImageInformationFromFile(textureFile);
00137 }
00138 catch (MediaNotFoundException)
00139 {
00140
00141 continue;
00142 }
00143 }
00144 switch (info.ResourceType)
00145 {
00146 case ResourceType.Texture:
00147 meshTextures[i] = new Texture(device, textureFile);
00148 break;
00149 case ResourceType.CubeTexture:
00150 meshTextures[i] = new CubeTexture(device, textureFile);
00151 break;
00152 case ResourceType.VolumeTexture:
00153 meshTextures[i] = new VolumeTexture(device, textureFile);
00154 break;
00155 }
00156 }
00157 }
00158 }
00159 #endregion
00160
00161 #region Class Methods
00163 public void SetVertexFormat(Device device, VertexFormats format)
00164 {
00165 Mesh tempSystemMesh = null;
00166 Mesh tempLocalMesh = null;
00167 VertexFormats oldFormat = VertexFormats.None;
00168 using (systemMemoryMesh)
00169 {
00170 using (localMemoryMesh)
00171 {
00172
00173 if (systemMemoryMesh != null)
00174 {
00175 oldFormat = systemMemoryMesh.VertexFormat;
00176 tempSystemMesh = systemMemoryMesh.Clone(device, systemMemoryMesh.Options.Value,
00177 format);
00178 }
00179 if (localMemoryMesh != null)
00180 {
00181 tempLocalMesh = localMemoryMesh.Clone(device, localMemoryMesh.Options.Value,
00182 format);
00183 }
00184 }
00185 }
00186
00187
00188 systemMemoryMesh = tempSystemMesh;
00189 localMemoryMesh = tempLocalMesh;
00190
00191
00192 if (((oldFormat & VertexFormats.Normal) == 0) && (format != 0))
00193 {
00194 if (systemMemoryMesh != null)
00195 systemMemoryMesh.ComputeNormals();
00196 if (localMemoryMesh != null)
00197 localMemoryMesh.ComputeNormals();
00198 }
00199 }
00201 public void SetVertexDeclaration(Device device, VertexElement[] decl)
00202 {
00203 Mesh tempSystemMesh = null;
00204 Mesh tempLocalMesh = null;
00205 VertexElement[] oldDecl = null;
00206 using (systemMemoryMesh)
00207 {
00208 using (localMemoryMesh)
00209 {
00210
00211 if (systemMemoryMesh != null)
00212 {
00213 oldDecl = systemMemoryMesh.GetDeclaration();
00214 tempSystemMesh = systemMemoryMesh.Clone(device, systemMemoryMesh.Options.Value,
00215 decl);
00216 }
00217 if (localMemoryMesh != null)
00218 {
00219 tempLocalMesh = localMemoryMesh.Clone(device, localMemoryMesh.Options.Value,
00220 decl);
00221 }
00222 }
00223 }
00224
00225
00226 systemMemoryMesh = tempSystemMesh;
00227 localMemoryMesh = tempLocalMesh;
00228
00229 bool hadNormal = false;
00230
00231 for (int i = 0; i < oldDecl.Length; i++)
00232 {
00233 if (oldDecl[i].DeclarationUsage == DeclarationUsage.Normal)
00234 {
00235 hadNormal = true;
00236 break;
00237 }
00238 }
00239
00240 bool hasNormalNow = false;
00241 for (int i = 0; i < decl.Length; i++)
00242 {
00243 if (decl[i].DeclarationUsage == DeclarationUsage.Normal)
00244 {
00245 hasNormalNow = true;
00246 break;
00247 }
00248 }
00249
00250
00251 if (!hadNormal && hasNormalNow)
00252 {
00253 if (systemMemoryMesh != null)
00254 systemMemoryMesh.ComputeNormals();
00255 if (localMemoryMesh != null)
00256 localMemoryMesh.ComputeNormals();
00257 }
00258 }
00259
00261 private void OnResetDevice(object sender, EventArgs e)
00262 {
00263 Device device = sender as Device;
00264 if (systemMemoryMesh == null)
00265 throw new InvalidOperationException("There is no system memory mesh. Nothing to do here.");
00266
00267
00268
00269 localMemoryMesh = systemMemoryMesh.Clone(device, (systemMemoryMesh.Options.Value & ~MeshFlags.SystemMemory),
00270 systemMemoryMesh.VertexFormat);
00271 }
00272
00274 private void OnLostDevice(object sender, EventArgs e)
00275 {
00276 if (localMemoryMesh != null)
00277 localMemoryMesh.Dispose();
00278
00279 localMemoryMesh = null;
00280 }
00282 public void Render(Device device, bool canDrawOpaque, bool canDrawAlpha)
00283 {
00284 if (localMemoryMesh == null)
00285 throw new InvalidOperationException("No local memory mesh.");
00286
00287
00288 if (canDrawOpaque)
00289 {
00290 for (int i = 0; i < meshMaterials.Length; i++)
00291 {
00292 if (isUsingMeshMaterials)
00293 {
00294 if (meshMaterials[i].DiffuseColor.Alpha < 1.0f)
00295 continue;
00296
00297
00298 device.Material = meshMaterials[i];
00299 device.SetTexture(0, meshTextures[i]);
00300 }
00301 localMemoryMesh.DrawSubset(i);
00302 }
00303 }
00304
00305
00306 if (canDrawAlpha)
00307 {
00308 for (int i = 0; i < meshMaterials.Length; i++)
00309 {
00310 if (meshMaterials[i].DiffuseColor.Alpha == 1.0f)
00311 continue;
00312
00313
00314 device.Material = meshMaterials[i];
00315 device.SetTexture(0, meshTextures[i]);
00316 localMemoryMesh.DrawSubset(i);
00317 }
00318 }
00319 }
00321 public void Render(Device device) { Render(device, true, true); }
00322
00323
00324
00326 public BoundingSphere ComputeBoundingSphere()
00327 {
00328 if (systemMemoryMesh == null)
00329 throw new InvalidOperationException("There is no system memory mesh. Nothing to do here.");
00330
00331
00332 GraphicsBuffer data = null;
00333 try
00334 {
00335 data = systemMemoryMesh.LockVertexBuffer(LockFlags.ReadOnly);
00336
00337 return Geometry.ComputeBoundingSphere(data, systemMemoryMesh.VertexCount,
00338 systemMemoryMesh.VertexFormat);
00339 }
00340 finally
00341 {
00342
00343 if (data != null)
00344 systemMemoryMesh.UnlockVertexBuffer();
00345 }
00346 }
00347 #endregion
00348
00349 #region IDisposable Members
00350
00352 public void Dispose()
00353 {
00354 OnLostDevice(null, EventArgs.Empty);
00355 if (meshTextures != null)
00356 {
00357 for (int i = 0; i < meshTextures.Length; i++)
00358 {
00359 if (meshTextures[i] != null)
00360 meshTextures[i].Dispose();
00361 }
00362 }
00363 meshTextures = null;
00364 meshMaterials = null;
00365
00366 if (systemMemoryMesh != null)
00367 systemMemoryMesh.Dispose();
00368
00369 systemMemoryMesh = null;
00370
00371 }
00372
00374 private void OnDeviceDisposing(object sender, EventArgs e)
00375 {
00376
00377 Dispose();
00378 }
00379 #endregion
00380
00381 }
00382 }