00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 using System;
00018 using System.Collections.Generic;
00019 using System.Text;
00020 using Microsoft.DirectX;
00021 using Microsoft.DirectX.Direct3D;
00022 using Microsoft.Samples.DirectX.UtilityToolkit;
00023
00024 namespace DXGfxLib
00025 {
00026 public class MeshObjectWithLOD : MeshObject
00027 {
00031 public static float near = 20.0f;
00032
00036 public static float mid = 50.0f;
00037
00042 public static float far = 250.0f;
00043
00044 public bool visible = true;
00045
00049 protected ProgressiveMesh fullMesh = null;
00050
00054 protected ProgressiveMesh[] meshes = null;
00055
00059 protected int currentMeshIndex = 0;
00060
00064 protected int[] adjacencyBuffer;
00065
00074 public virtual void AttachWithLOD(Device d3ddevice, Mesh meshToAttach, int[] adjacencyBuffer, ExtendedMaterial[] materials,
00075 EffectInstance[] effects)
00076 {
00077 Attach(meshToAttach);
00078
00079 this.adjacencyBuffer = adjacencyBuffer;
00080
00081
00082
00083 int use32Bit = (int)(originalMesh.Options.Value & MeshFlags.Use32Bit);
00084
00085
00086 int[] outAdjacency;
00087
00088 using (Mesh mesh = Mesh.Clean(CleanType.Simplification, originalMesh, adjacencyBuffer, out outAdjacency))
00089 {
00090
00091
00092 WeldEpsilons epsilons = new WeldEpsilons();
00093 int[] outAdjacency2;
00094 int[] faceRemap;
00095 GraphicsStream vertexRemap;
00096 mesh.WeldVertices(0, epsilons, outAdjacency, out outAdjacency2, out faceRemap, out vertexRemap);
00097
00098
00099 mesh.Validate(outAdjacency2);
00100
00101
00102 if (materials != null)
00103 {
00104 meshMaterials = new Material[materials.Length];
00105 meshTextures = new Texture[materials.Length];
00106
00107
00108 for (int i = 0; i < meshMaterials.Length; i++)
00109 {
00110 meshMaterials[i] = materials[i].Material3D;
00111 meshMaterials[i].AmbientColor = meshMaterials[i].DiffuseColor;
00112
00113 if ((materials[i].TextureFilename != null) && (materials[i].TextureFilename.Length > 0))
00114 {
00115
00116 meshTextures[i] = ResourceCache.GetGlobalInstance().CreateTextureFromFile(d3ddevice, materials[i].TextureFilename);
00117 }
00118 }
00119 }
00120
00121
00122 using (VertexBuffer vb = mesh.VertexBuffer)
00123 {
00124 using (GraphicsStream stm = vb.Lock(0, 0, LockFlags.NoSystemLock))
00125 {
00126 try
00127 {
00128 objectRadius = Geometry.ComputeBoundingSphere(stm,
00129 mesh.NumberVertices, mesh.VertexFormat, out objectCenter);
00130 }
00131 finally
00132 {
00133 vb.Unlock();
00134 }
00135 }
00136 }
00137
00138
00139 Mesh currentMesh = mesh;
00140 if ((mesh.VertexFormat & VertexFormats.Normal) == 0)
00141 {
00142 currentMesh = mesh.Clone(MeshFlags.Managed | (MeshFlags)use32Bit,
00143 mesh.VertexFormat | VertexFormats.Normal, d3ddevice);
00144
00145
00146 currentMesh.ComputeNormals();
00147 }
00148
00149 using (currentMesh)
00150 {
00151
00152 using (Microsoft.DirectX.Direct3D.ProgressiveMesh pMesh = new Microsoft.DirectX.Direct3D.ProgressiveMesh(currentMesh, adjacencyBuffer, null, 1, MeshFlags.SimplifyVertex))
00153 {
00154 int minVerts = pMesh.MinVertices;
00155 int maxVerts = pMesh.MaxVertices;
00156 int vertsPerMesh = (maxVerts - minVerts + 10) / 10;
00157
00158
00159
00160 int numMeshes = Math.Max(1, 3);
00161 meshes = new Microsoft.DirectX.Direct3D.ProgressiveMesh[numMeshes];
00162
00163
00164 fullMesh = pMesh.Clone(MeshFlags.Managed | MeshFlags.VbShare, pMesh.VertexFormat, d3ddevice);
00165
00166
00167 for (int iMesh = 0; iMesh < numMeshes; iMesh++)
00168 {
00169 meshes[iMesh] = pMesh.Clone(MeshFlags.Managed | MeshFlags.VbShare, pMesh.VertexFormat, d3ddevice);
00170
00171
00172 meshes[iMesh].TrimByVertices(minVerts + vertsPerMesh * iMesh, minVerts + vertsPerMesh * (iMesh + 1));
00173 meshes[iMesh].OptimizeBaseLevelOfDetail(MeshFlags.OptimizeVertexCache);
00174 }
00175
00176
00177 currentMeshIndex = numMeshes - 1;
00178 meshes[currentMeshIndex].NumberVertices = maxVerts;
00179 fullMesh.NumberVertices = maxVerts;
00180 }
00181 }
00182 }
00183 }
00184
00193 public override void Update(Frustrum frustrum, float elapsedTime, double appTime, List<IDrawable> objectsToBeRendered)
00194 {
00195 base.Update(frustrum, elapsedTime, appTime, objectsToBeRendered);
00196
00197 if (fullMesh != null)
00198 {
00199
00200 float distToNearPlane = MathUtil.SignedDistance(frustrum.NearPlane, Position);
00201
00202 if (distToNearPlane < near)
00203 {
00204 SetNumberVertices(fullMesh.MaxVertices);
00205 visible = true;
00206 }
00207 else if (distToNearPlane < mid)
00208 {
00209 SetNumberVertices((int)Math.Ceiling(0.7 * fullMesh.MaxVertices));
00210 visible = true;
00211 }
00212 else if (distToNearPlane < far)
00213 {
00214 SetNumberVertices((int)Math.Ceiling(0.4 * fullMesh.MaxVertices));
00215 visible = true;
00216 }
00217 else
00218 {
00219 SetNumberVertices(0);
00220 visible = false;
00221 }
00222 }
00223 }
00224
00230 private void SetNumberVertices(int numberVerts)
00231 {
00232
00233 fullMesh.NumberVertices = numberVerts;
00234
00235
00236 if ((numberVerts >= meshes[currentMeshIndex].MinVertices) &&
00237 (numberVerts <= meshes[currentMeshIndex].MaxVertices))
00238 {
00239 meshes[currentMeshIndex].NumberVertices = numberVerts;
00240 }
00241 else
00242 {
00243
00244 currentMeshIndex = meshes.Length - 1;
00245
00246
00247 while (currentMeshIndex > 0)
00248 {
00249
00250 if (numberVerts >= meshes[currentMeshIndex].MinVertices)
00251 break;
00252
00253 currentMeshIndex--;
00254 }
00255
00256
00257 meshes[currentMeshIndex].NumberVertices = numberVerts;
00258 }
00259 }
00260
00261 public override void Draw(Device device)
00262 {
00263 if ((fullMesh != null)&&visible)
00264 {
00265 for (int i = 0; i < originalMesh.NumberAttributes; i++)
00266 {
00267 device.SetTexture(i, meshTextures[i]);
00268 meshes[currentMeshIndex].DrawSubset(i);
00269 }
00270 }
00271 }
00272
00280 public override void DrawSubset(int index)
00281 {
00282 if (fullMesh != null)
00283 {
00284 meshes[currentMeshIndex].DrawSubset(index);
00285 }
00286 }
00287 }
00288 }