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 using System.Drawing;
00024
00025 namespace DXGfxLib
00026 {
00033 public struct InstanceInfo
00034 {
00035 public Vector4 positionRot;
00036 }
00037
00051 public class Batch : IDisposable, IDrawable
00052 {
00057 private int maxNumberFaces = 5000;
00058
00062 private EffectGroup associatedEffetGroup = null;
00063
00067 public EffectGroup AssociatedEffectGroup
00068 {
00069 get { return associatedEffetGroup; }
00070 set { associatedEffetGroup = value; }
00071 }
00072
00076 protected bool hide = false;
00077
00081 public bool Hide
00082 {
00083 get { return hide; }
00084 set { hide = value; }
00085 }
00086
00091 public Material[] meshMaterials;
00092
00096 public Texture[] meshTextures;
00097
00101 public Mesh[] meshes = null;
00102
00106 private Mesh initialMesh = null;
00107
00111 private Matrix[] worldMatrices = null;
00112
00117 public Batch()
00118 {
00119 associatedEffetGroup = DXGfxManager.GetGlobalInstance().defaultEffectGroup;
00120 }
00121
00125 public void Dispose()
00126 {
00127 if (meshes != null)
00128 {
00129 foreach (Mesh mesh in meshes)
00130 {
00131 mesh.Dispose();
00132 }
00133 }
00134 if (meshTextures != null)
00135 {
00136 foreach(Texture tex in meshTextures)
00137 {
00138 tex.Dispose();
00139 }
00140 }
00141 }
00142
00153 public void SetEffectsValues(Device d3ddevice, Effect eff, int pass)
00154 {
00155 d3ddevice.SetTransform(TransformType.World, Matrix.Identity);
00156 }
00157
00158
00164 public void Draw(Device d3ddevice)
00165 {
00166
00167
00168 for (int i = 0; i < meshMaterials.Length; i++)
00169 {
00170
00171 d3ddevice.Material = meshMaterials[i];
00172 d3ddevice.SetTexture(0, meshTextures[i]);
00173
00174
00175 foreach (Mesh mesh in meshes)
00176 {
00177 mesh.DrawSubset(i);
00178 }
00179 }
00180 }
00181
00191 public void Populate(Mesh initialMesh, Material[] materials, Texture[] textures, Matrix[] matrices)
00192 {
00193 this.initialMesh = initialMesh.Clone(initialMesh.Options.Value, CustomVertex.PositionNormalTextured.Format, initialMesh.Device);
00194 this.worldMatrices = matrices;
00195
00196 meshMaterials = materials;
00197 meshTextures = textures;
00198
00199 int max = Math.Max(initialMesh.NumberFaces, initialMesh.NumberVertices);
00200
00201 int maxInstanceInOneMesh = (int)Math.Floor((double)(maxNumberFaces / max));
00202
00203 if (matrices.Length > maxInstanceInOneMesh)
00204 {
00205 int nbIter = (int)Math.Ceiling((double)(matrices.Length / maxInstanceInOneMesh));
00206
00207 meshes = new Mesh[nbIter];
00208
00209 for (int i = 0; i < nbIter; i++)
00210 {
00211 int start = Math.Min(i * maxInstanceInOneMesh, matrices.Length);
00212 int end = Math.Min((i + 1) * maxInstanceInOneMesh, matrices.Length);
00213
00214 meshes[i] = BuildOneBigMeshForStaticInstanciating(worldMatrices, start, end);
00215 }
00216 }
00217 else
00218 {
00219 meshes = new Mesh[1];
00220 meshes[0] = BuildOneBigMeshForStaticInstanciating(worldMatrices, 0, matrices.Length);
00221 }
00222 }
00223
00234 public Mesh BuildOneBigMeshForStaticInstanciating(Matrix[] worldMatrices, int startIndex, int endIndex)
00235 {
00236 if (initialMesh == null)
00237 {
00238 throw new Exception("We need a valid initial mesh, please define one before calling this method!");
00239 }
00240
00241 int nbInstance = endIndex - startIndex;
00242 Mesh mesh = new Mesh(nbInstance * initialMesh.NumberFaces, nbInstance * initialMesh.NumberVertices, initialMesh.Options.Value,
00243 CustomVertex.PositionNormalTextured.Format, initialMesh.Device);
00244
00245 CustomVertex.PositionNormalTextured[] initialVertices = (CustomVertex.PositionNormalTextured[])initialMesh.LockVertexBuffer(typeof(CustomVertex.PositionNormalTextured),
00246 LockFlags.ReadOnly, initialMesh.NumberVertices);
00247
00248 GraphicsStream stm = mesh.LockVertexBuffer(LockFlags.NoSystemLock);
00249
00250 Int16[] initialIndices = (Int16[])initialMesh.LockIndexBuffer(typeof(Int16), LockFlags.ReadOnly, 3 * initialMesh.NumberFaces);
00251
00252 GraphicsStream stmi = mesh.LockIndexBuffer(LockFlags.None);
00253
00254 int count = 0;
00255 for (int i = startIndex; i < endIndex; i++)
00256 {
00257 Matrix mat = worldMatrices[i];
00258 CustomVertex.PositionNormalTextured[] instanceVertices = Transform(initialVertices, mat);
00259
00260 stm.Write(instanceVertices);
00261
00262
00263 Int16[] instanceIndices = AddOffset(initialIndices, (Int16)(count * initialVertices.Length));
00264
00265 stmi.Write(instanceIndices);
00266
00267 count++;
00268 }
00269
00270 initialMesh.UnlockVertexBuffer();
00271 mesh.UnlockVertexBuffer();
00272
00273 initialMesh.UnlockIndexBuffer();
00274 mesh.UnlockIndexBuffer();
00275
00276
00277
00278
00279
00280 mesh.SetAttributeTable(initialMesh.GetAttributeTable());
00281 int[] initialAttributes = initialMesh.LockAttributeBufferArray(LockFlags.ReadOnly);
00282
00283 int[] destAttributes = mesh.LockAttributeBufferArray(LockFlags.NoSystemLock);
00284
00285 count = 0;
00286 for (int i = startIndex; i < endIndex; i++)
00287 {
00288 initialAttributes.CopyTo(destAttributes, count * initialAttributes.Length);
00289 count++;
00290 }
00291
00292 initialMesh.UnlockAttributeBuffer();
00293 mesh.UnlockAttributeBuffer();
00294
00295 return mesh;
00296 }
00297
00308 public CustomVertex.PositionNormalTextured[] Transform(CustomVertex.PositionNormalTextured[] vertices, Matrix mat)
00309 {
00310 CustomVertex.PositionNormalTextured[] outVertices = new CustomVertex.PositionNormalTextured[vertices.Length];
00311 int compteur = 0;
00312
00313 foreach (CustomVertex.PositionNormalTextured vertex in vertices)
00314 {
00315 Vector3 inVec = new Vector3(vertex.X, vertex.Y, vertex.Z);
00316 Vector3 inNorm = new Vector3(vertex.Nx, vertex.Ny, vertex.Nz);
00317
00318 inVec.TransformCoordinate(mat);
00319 inNorm.TransformCoordinate(mat);
00320
00321 outVertices[compteur].X = inVec.X;
00322 outVertices[compteur].Y = inVec.Y;
00323 outVertices[compteur].Z = inVec.Z;
00324
00325 outVertices[compteur].Nx = inNorm.X;
00326 outVertices[compteur].Ny = inNorm.Y;
00327 outVertices[compteur].Nz = inNorm.Z;
00328
00329 outVertices[compteur].Tu = vertex.Tu;
00330 outVertices[compteur].Tv = vertex.Tv;
00331 compteur++;
00332 }
00333
00334 return outVertices;
00335 }
00336
00343 public Int16[] AddOffset(Int16[] inIndices, int offset)
00344 {
00345 Int16[] outIndices = new Int16[inIndices.Length];
00346 int compteur = 0;
00347
00348 foreach (Int16 index in inIndices)
00349 {
00350 outIndices[compteur] = (Int16)(index + offset);
00351 compteur++;
00352 }
00353
00354 return outIndices;
00355 }
00356
00364 public int CompareTo(Object obj)
00365 {
00366 int ret = 1;
00367 IDrawable drawable = obj as IDrawable;
00368
00369 if (drawable != null)
00370 {
00371 ret = AssociatedEffectGroup.CompareTo(drawable.AssociatedEffectGroup);
00372 }
00373 return ret;
00374 }
00375
00383 public int CompareTo(SceneObject sceneObj)
00384 {
00385 return AssociatedEffectGroup.CompareTo(sceneObj.AssociatedEffectGroup);
00386 }
00387
00395 public int CompareTo(IDrawable sceneObj)
00396 {
00397 return AssociatedEffectGroup.CompareTo(sceneObj.AssociatedEffectGroup);
00398 }
00399 }
00400 }