Ejemplo n.º 1
0
        private BoundingBox BuildBoundingBox(ModelMesh mesh, Matrix meshTransform)
        {
            Vector3 meshMax = new Vector3(float.MinValue);
            Vector3 meshMin = new Vector3(float.MaxValue);

            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

                VertexPositionNormalTexture[] vertexData = new VertexPositionNormalTexture[part.NumVertices];
                part.VertexBuffer.GetData(part.VertexOffset * stride, vertexData, 0, part.NumVertices, stride);

                Vector3 vertPosition = new Vector3();

                for (int i = 0; i < vertexData.Length; i++)
                {
                    vertPosition = vertexData[i].Position;

                    meshMin = Vector3.Min(meshMin, vertPosition);
                    meshMax = Vector3.Max(meshMax, vertPosition);
                }
            }

            meshMin = Vector3.Transform(meshMin, meshTransform);
            meshMax = Vector3.Transform(meshMax, meshTransform);

            BoundingBox box = new BoundingBox(meshMin, meshMax);
            return box;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This method draws a model mesh, with the given worldMatrix as viewed by the camera.
        /// </summary>
        /// <param name="mesh">The mesh to draw</param>
        /// <param name="worldMatrix">The matrix holding the position, rotation and scale of the mesh</param>
        /// <param name="camera">The camera which represents the user's current view</param>
        public void DrawModelMesh(ModelMesh mesh, Matrix worldMatrix, bool applyCustomEffects)
        {
            Cameras.Camera currentCamera = DisplayController.Display.CurrentView.Camera;
            // setup effect parameters for each effect
            foreach (BasicEffect effect in mesh.Effects)
            {
                // use default settings for now.
                effect.EnableDefaultLighting();
                effect.PreferPerPixelLighting = true;

                // the view, projection and world matrices must be setup for each effect, each frame.

                effect.View = currentCamera.ViewMatrix;
                effect.Projection = currentCamera.ProjectionMatrix;
                effect.World = worldMatrix;

                // apply custom effects (if any):
                if (applyCustomEffects) this.ApplyCustomEffects(effect);

                // propagate changes. Any changes to parameters are not applied until CommitChanges() is called.
                effect.CommitChanges();
            }

            // actually draw the model, now that all effects have been setup:
            mesh.Draw();
        }
Ejemplo n.º 3
0
        public MeshHexa(Microsoft.Xna.Framework.Graphics.Model model)
        {
            Model = model;

            Direction = new ModelMesh[6];
            for (int i = 1; i < 7; i++)
            {
                Direction[i - 1] = model.Meshes["Direction_" + i.ToString()];
            }

            Repeater = new ModelMesh[6];
            for (int i = 1; i < 7; i++)
            {
                Repeater[i - 1] = model.Meshes["Repeater_" + i.ToString()];
            }

            Speed = new ModelMesh[4];
            for (int i = 1; i < 5; i++)
            {
                Speed[i - 1] = model.Meshes["Speed_" + i.ToString()];
            }

            Icon = model.Meshes["Icon"];
            Body = model.Meshes["Body"];
        }
        //See https://electronicmeteor.wordpress.com/2011/10/25/bounding-boxes-for-your-model-meshes/
        public static BoundingBox BuildBoundingBox(ModelMesh mesh, Matrix meshTransform)
        {
            // Create initial variables to hold min and max xyz values for the mesh
            Vector3 meshMax = new Vector3(float.MinValue);
            Vector3 meshMin = new Vector3(float.MaxValue);

            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                // The stride is how big, in bytes, one vertex is in the vertex buffer
                // We have to use this as we do not know the make up of the vertex
                int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

                VertexPositionNormalTexture[] vertexData = new VertexPositionNormalTexture[part.NumVertices];
                part.VertexBuffer.GetData(part.VertexOffset * stride, vertexData, 0, part.NumVertices, stride);

                // Find minimum and maximum xyz values for this mesh part
                Vector3 vertPosition = new Vector3();

                for (int i = 0; i < vertexData.Length; i++)
                {
                    vertPosition = vertexData[i].Position;

                    // update our values from this vertex
                    meshMin = Vector3.Min(meshMin, vertPosition);
                    meshMax = Vector3.Max(meshMax, vertPosition);
                }
            }

            // transform by mesh bone matrix
            meshMin = Vector3.Transform(meshMin, meshTransform);
            meshMax = Vector3.Transform(meshMax, meshTransform);

            // Create the bounding box
            return new BoundingBox(meshMin, meshMax);
        }
        public static void ExtractModelMeshPartData(ModelMesh mm, ModelMeshPart mmp, ref Matrix xform,
            List<Vector3> vertices, List<TriangleVertexIndices> indices, string name)
        {
            int offset = vertices.Count;
            Vector3[] a = new Vector3[mmp.NumVertices];
            mm.VertexBuffer.GetData<Vector3>(mmp.StreamOffset + mmp.BaseVertex * mmp.VertexStride,
                a, 0, mmp.NumVertices, mmp.VertexStride);
            for (int i = 0; i != a.Length; ++i)
                Vector3.Transform(ref a[i], ref xform, out a[i]);
            vertices.AddRange(a);

            if (mm.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits)
                throw new Exception(
                    String.Format("Model {0} uses 32-bit indices, which are not supported.",
                                  name));
            short[] s = new short[mmp.PrimitiveCount * 3];
            mm.IndexBuffer.GetData<short>(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3);
            TriangleVertexIndices[] tvi = new TriangleVertexIndices[mmp.PrimitiveCount];
            for (int i = 0; i != tvi.Length; ++i)
            {
                tvi[i].I0 = s[i * 3 + 0] + offset;
                tvi[i].I1 = s[i * 3 + 1] + offset;
                tvi[i].I2 = s[i * 3 + 2] + offset;
            }
            indices.AddRange(tvi);
        }
Ejemplo n.º 6
0
 protected void GenericTransform(Model model, BasicEffect effect, ModelMesh mesh)
 {
     Matrix matrix = Conversion.ToXNAMatrix(Body.Orientation);
     matrix.Translation = Conversion.ToXNAVector(Body.Position) -
         Vector3.Transform(new Vector3(0, 1.0f, 0), matrix);
     effect.World = matrix;
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Get all the triangles from all mesh parts
 /// </summary>
 private static void ExtractModelMeshData(ModelMesh mesh, ref Matrix transform, List<Vector3> vertices, List<Triangle> indices)
 {
     foreach (ModelMeshPart meshPart in mesh.MeshParts)
     {
         ExtractModelMeshPartData(meshPart, ref transform, vertices, indices);
     }
 }
Ejemplo n.º 8
0
        private void DrawMesh(ModelMesh mesh)
        {
            var localWorld = Model.Transforms[mesh.ParentBone.Index] * _baseWorld;

            EnableMeshParts.Enable(View, Projection, localWorld, mesh.MeshParts);

            mesh.Draw();
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Get all the triangles from all mesh parts
 /// </summary>
 public static void ExtractModelMeshData(ModelMesh mesh, ref Matrix transform,
     List<Vector3> vertices)
 {
     foreach (ModelMeshPart meshPart in mesh.MeshParts)
     {
         ExtractModelMeshPartData(meshPart, ref transform, vertices);
     }
 }
Ejemplo n.º 10
0
        public Matrix GetWorld(ModelMesh mesh)
        {
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);
            Matrix s = Matrix.CreateScale(scale);
            Matrix trans = Matrix.CreateTranslation(translate.X, translate.Y, translate.Z);

            Matrix rotX = Matrix.CreateRotationX((rotate.X * MathHelper.Pi * 2) / 360);
            Matrix rotY = Matrix.CreateRotationY((rotate.Y * MathHelper.Pi * 2) / 360);
            Matrix rotZ = Matrix.CreateRotationZ((rotate.Z * MathHelper.Pi * 2) / 360);

            return transforms[mesh.ParentBone.Index] * s * rotX * rotY * rotZ * trans;
        }
Ejemplo n.º 11
0
        public static void CalculateBoundingBox(ModelMesh mm, out BoundingBox bb)
        {
            bb = new BoundingBox(new Vector3(float.MaxValue, float.MaxValue, float.MaxValue), new Vector3(float.MinValue, float.MinValue, float.MinValue));
            bool first = true;
            Matrix x = Matrix.Identity;
            ModelBone mb = mm.ParentBone;
            while (mb != null)
            {
                x = x * mb.Transform;
                mb = mb.Parent;
            }

            foreach (ModelMeshPart mp in mm.MeshParts)
            {

                int n = mp.NumVertices;
                if (n > tempVecs3.Length)
                    tempVecs3 = new Vector3[n + 128];
                int l = mp.PrimitiveCount * 3;
                if (l > tempUshorts.Length)
                    tempUshorts = new ushort[l + 128];
                if (n == 0 || l == 0)
                    continue;

                //mm.IndexBuffer.GetData<ushort>(tempUshorts, mp.StartIndex, l);
                //mm.VertexBuffer.GetData<Vector3>(mp.StreamOffset, tempVecs3, mp.BaseVertex, n, mp.VertexStride);
                //CONV
                mp.IndexBuffer.GetData(mp.StartIndex*sizeof(ushort),tempUshorts, 0, l);
                //mp.VertexBuffer.GetData(tempVecs3);
                //mp.VertexBuffer.GetData(0,tempVecs3, 0, n, mp.VertexBuffer.VertexDeclaration.VertexStride);
                mp.VertexBuffer.GetData(mp.VertexOffset*mp.VertexBuffer.VertexDeclaration.VertexStride,
                    tempVecs3, 0, n, mp.VertexBuffer.VertexDeclaration.VertexStride);

                if (first)
                {
                    bb.Min = Vector3.Transform(tempVecs3[tempUshorts[0]], x);
                    bb.Max = bb.Min;
                    first = false;
                }

                for (int i = 0; i != l; ++i)
                {
                    ushort us = tempUshorts[i];
                    Vector3 v = Vector3.Transform(tempVecs3[us], x);

                    Vector3.Max(ref v, ref bb.Max, out bb.Max);
                    Vector3.Min(ref v, ref bb.Min, out bb.Min);
                }
            }
        }
Ejemplo n.º 12
0
        public static BoundingBox GetBounds(ModelMesh mesh)
        {
            List<Vector3> points = new List<Vector3>();

            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                Vector3[] vb = new Vector3[part.NumVertices];
                int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

                part.VertexBuffer.GetData<Vector3>(part.VertexOffset * stride, vb, 0, vb.Length, stride);

                points.AddRange(vb);
            }
            return BoundingBox.CreateFromPoints(points);
        }
Ejemplo n.º 13
0
		public static void DrawMeshPart( ModelMesh mesh, ModelMeshPart part, Effect effect ) {
			GraphicsDevice device = Puzzle3D.Instance.GraphicsDevice;

			foreach( EffectPass pass in effect.CurrentTechnique.Passes ) {
				pass.Begin();

				device.VertexDeclaration = part.VertexDeclaration;
				device.Vertices[ 0 ].SetSource( mesh.VertexBuffer, part.StreamOffset, part.VertexStride );
				device.Indices = mesh.IndexBuffer;

				device.DrawIndexedPrimitives( PrimitiveType.TriangleList, part.BaseVertex, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount );

				pass.End();
			}
		}
Ejemplo n.º 14
0
        internal static Matrix GetAbsoluteTransform(this Microsoft.Xna.Framework.Graphics.ModelMesh mesh, Matrix world)
        {
            // In case animation changes the tranform of the node containning the model,
            // gets the ambsolute transform of the first mesh before transform to world
            // space.
            ModelBone currentBone        = mesh.ParentBone;
            Matrix    ambsoluteTransform = currentBone.Transform;

            while (currentBone.Parent != null)
            {
                currentBone        = currentBone.Parent;
                ambsoluteTransform = currentBone.Transform * ambsoluteTransform;
            }

            return(ambsoluteTransform * world);
        }
Ejemplo n.º 15
0
        public static void AddTriangles(ModelMesh mesh, List<Vector3> positions)
        {
            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                Vector3[] vb = new Vector3[part.NumVertices];
                short[] ib = new short[part.PrimitiveCount * 3];
                int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

                part.VertexBuffer.GetData<Vector3>(part.VertexOffset * stride, vb, 0, vb.Length, stride);
                part.IndexBuffer.GetData<short>(part.StartIndex * 2, ib, 0, ib.Length);

                foreach (short i in ib)
                {
                    positions.Add(vb[i]);
                }
            }
        }
Ejemplo n.º 16
0
        public override void Draw()
        {
            this.mesh = this.model.Meshes[0];
            Effect effect = this.mesh.Effects[0];

            this.camera.SetEffectParameters(effect);
            effect.CurrentTechnique = effect.Techniques["CellShading"];

            effect.Parameters["Light"].SetValue(new Vector3(50.0f, 50.0f, 50.0f));
            effect.Parameters["Camera"].SetValue(this.camera.Eye);
            effect.Parameters["World"].SetValue(this.world);
            effect.Parameters["DiffuseColor"].SetValue(Color.Red.ToVector4());
            effect.Parameters["SpecularColor"].SetValue(Color.White.ToVector4());
            effect.Parameters["SpecularIntensity"].SetValue(0.5f);
            effect.Parameters["SpecularPower"].SetValue(20000.0f);
            effect.Parameters["ShadesCount"].SetValue(2);
            this.mesh.Draw();
        }
Ejemplo n.º 17
0
        public static void ExtractModelMeshData(ModelMesh mm, ref Matrix xform,
            List<Vector3> vertices, List<TriangleVertexIndices> indices, string name, bool includeNoncoll)
        {
            foreach (ModelMeshPart mmp in mm.MeshParts)
              {

            if (!includeNoncoll)
            {
              EffectAnnotation annot = mmp.Effect.CurrentTechnique.Annotations["collide"];
              if (annot != null && annot.GetValueBoolean() == false)
              {
            Console.WriteLine("Ignoring model mesh part {0}:{1} because it's set to not collide.",
                name, mm.Name);
            continue;
              }
            }
            ExtractModelMeshPartData(mm, mmp, ref xform, vertices, indices, name);
              }
        }
Ejemplo n.º 18
0
		private static NormalBuffers GetNormalBuffers(ModelMesh mesh, ModelMeshPart meshPart, GraphicsDevice graphicsDevice, float normalLengthPercentage)
		{
			if (meshPart.VertexBuffer == null)
				return null;

			Vector3[] positions = VertexElementExtractor.GetVertexElement(meshPart, VertexElementUsage.Position);
			if (positions == null)
				return null;
			Vector3[] normals = VertexElementExtractor.GetVertexElement(meshPart, VertexElementUsage.Normal);
			if (normals == null)
				return null;

			NormalBuffers normalBuffers = new NormalBuffers();

			normalBuffers.PrimitiveCount = normals.Length;
			normalBuffers.VertexCount = normals.Length * 2;

			float size = mesh.BoundingSphere.Radius * normalLengthPercentage;

			VertexBuffer vertexBuffer = new VertexBuffer(graphicsDevice,
				typeof (VertexPositionColor), normalBuffers.VertexCount,
				BufferUsage.WriteOnly);
			VertexPositionColor[] vertices = new VertexPositionColor[normalBuffers.VertexCount];
			int counter = 0;
			for (int i = 0; i < normals.Length; ++i)
			{
				Vector3 normalColorTemp = Vector3.Normalize(normals[i]);
				normalColorTemp += Vector3.One;
				normalColorTemp *= 0.5f;
				Color normalColor = new Color(normalColorTemp);
				vertices[counter++] = new VertexPositionColor(positions[i], normalColor);
				vertices[counter++] = new VertexPositionColor(positions[i] + (normals[i] * size), normalColor);
			}
			vertexBuffer.SetData(vertices);
			normalBuffers.Vertices = vertexBuffer;

			IndexBuffer indexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, normalBuffers.VertexCount,
				BufferUsage.WriteOnly);
			indexBuffer.SetData(Enumerable.Range(0, normalBuffers.VertexCount).Select(i => (short) i).ToArray());
			normalBuffers.Indices = indexBuffer;

			return normalBuffers;
		}
Ejemplo n.º 19
0
        void drawMesh(ModelMesh mesh, Camera camera, float rot)
        {
            foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = mesh.ParentBone.Transform * GetWorld(rot);
                    effect.View = camera.view;
                    effect.Projection = camera.projection;
                    effect.TextureEnabled = true;
                    effect.Texture = tex;
                    effect.Alpha = alpha*0.6f;

                    //trying to get lighting to work, but so far the model just shows up as pure black - it was exported with a green blinn shader
                    //effect.EnableDefaultLighting(); //did not work
                    effect.LightingEnabled = true;

                }
                mesh.Draw();
                mesh.Draw();
        }
Ejemplo n.º 20
0
        public ModelMesh GetMeshByFilePath(string filePath)
        {
            if (_meshCache.ContainsKey(filePath)) return _meshCache[filePath];

            var assimpContext = new Assimp.AssimpContext();
            var assimpScene = assimpContext.ImportFile(filePath, PostProcessSteps.GenerateNormals | PostProcessSteps.GenerateUVCoords | PostProcessSteps.Triangulate);

            if (assimpScene.MeshCount > 1) throw new NotSupportedException("Currently are just single meshs supported.");

            var assimpMesh = assimpScene.Meshes.First();

            var modelMesh = new ModelMesh
            {
                Mesh = new Mesh(_device, GenerateGeometryDataFromAssimpMesh(assimpMesh)),
                Material = GenerateMaterialFromMesh(assimpMesh.MaterialIndex, assimpScene)
            };
            _meshCache.Add(filePath, modelMesh);
            return modelMesh;
        }
        /// <summary>
        /// Adds a mesh's vertices and indices to the given lists.
        /// </summary>
        /// <param name="collisionModelMesh">Model to use for the collision shape.</param>
        /// <param name="transform">Transform to apply to the mesh.</param>
        /// <param name="vertices">List to receive vertices from the mesh.</param>
        /// <param name="indices">List to receive indices from the mesh.</param>
        public static void AddMesh(ModelMesh collisionModelMesh, Matrix transform, List<Vector3> vertices, IList<int> indices)
        {
            foreach (ModelMeshPart meshPart in collisionModelMesh.MeshParts)
            {
                int startIndex = vertices.Count;
                var meshPartVertices = new Vector3[meshPart.NumVertices];
                //Grab position data from the mesh part.
                int stride = meshPart.VertexBuffer.VertexDeclaration.VertexStride;
                meshPart.VertexBuffer.GetData(
                        meshPart.VertexOffset * stride,
                        meshPartVertices,
                        0,
                        meshPart.NumVertices,
                        stride);

                //Transform it so its vertices are located in the model's space as opposed to mesh part space.
                Vector3.Transform(meshPartVertices, ref transform, meshPartVertices);
                vertices.AddRange(meshPartVertices);

                if (meshPart.IndexBuffer.IndexElementSize == IndexElementSize.ThirtyTwoBits)
                {
                    var meshIndices = new int[meshPart.PrimitiveCount * 3];
                    meshPart.IndexBuffer.GetData(meshPart.StartIndex * 4, meshIndices, 0, meshPart.PrimitiveCount * 3);
                    for (int k = 0; k < meshIndices.Length; k++)
                    {
                        indices.Add(startIndex + meshIndices[k]);
                    }
                }
                else
                {
                    var meshIndices = new ushort[meshPart.PrimitiveCount * 3];
                    meshPart.IndexBuffer.GetData(meshPart.StartIndex * 2, meshIndices, 0, meshPart.PrimitiveCount * 3);
                    for (int k = 0; k < meshIndices.Length; k++)
                    {
                        indices.Add(startIndex + meshIndices[k]);
                    }

                }
            }
        }
Ejemplo n.º 22
0
 /// <summary>
 /// Generate the current bounding box of a model.
 /// </summary>
 public static BoundingBox GenerateBoundingBox(this ModelMeshPart part, ModelMesh parentMesh)
 {
     Vector3 min = new Vector3(float.MaxValue);
     Vector3 max = new Vector3(float.MinValue);
     int stride = part.VertexStride;
     int vertexCount = part.NumVertices;
     byte[] vertexData = new byte[stride * vertexCount]; // MEMORYCHURN
     parentMesh.VertexBuffer.GetData(vertexData);
     for (int index = 0; index < vertexData.Length; index += stride)
     {
         float x = BitConverter.ToSingle(vertexData, index);
         float y = BitConverter.ToSingle(vertexData, index + 4);
         float z = BitConverter.ToSingle(vertexData, index + 8);
         if (x < min.X) min.X = x;
         if (x > max.X) max.X = x;
         if (y < min.Y) min.Y = y;
         if (y > max.Y) max.Y = y;
         if (z < min.Z) min.Z = z;
         if (z > max.Z) max.Z = z;
     }
     return new BoundingBox(min, max);
 }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="modelMesh"></param>
        /// <param name="animationTexture"></param>
        /// <param name="device"></param>
        public InstancedSkinnedModelMesh(ModelMesh modelMesh, Texture2D animationTexture, GraphicsDevice device)
        {
            this.graphicsDevice = device;
            this.mesh = modelMesh;

            // We are assuming all the mesh parts have the same vertex stride
            this.vertexCount = this.mesh.VertexBuffer.SizeInBytes / mesh.MeshParts[0].VertexStride;

            // Calculate the actual number of instances
            // We're using ushort for our instances, so we can only reference up to ushort.MaxValue
            this.maxInstances = Math.Min(ushort.MaxValue / this.vertexCount, MaxInstances);

            // Hold on to a handle to the animation texture
            this.animationTexture = animationTexture;

            // Create our temporary arrays based on the actual number of instances we can handle
            this.tempTransforms = new Matrix[this.maxInstances];
            this.tempAnimations = new int[this.maxInstances];

            // Replicate index data, as required for vfetch instancing
            this.ReplicateIndexData(this.mesh);
        }
Ejemplo n.º 24
0
		public static void DrawModelMesh( this Model model,	 ModelMesh mesh ) {
			Matrix mat = Matrix.Identity;

			GetModelMeshTransform( mesh.ParentBone, ref mat );

			Matrix View = Utility.Camera.View;
			Matrix Projection = Utility.Camera.Projection;

			for( int x = 0; x < mesh.Effects.Count; x++ ) {
				BasicEffect eff = mesh.Effects[ x ] as BasicEffect;
				if( eff != null ) {
					eff.World = mat;
					eff.View = View;
					eff.Projection = Projection;

					eff.LightingEnabled = true;
					eff.EnableDefaultLighting();
					eff.TextureEnabled = true;
					eff.VertexColorEnabled = true;
				}
			}
			mesh.Draw();
		}
Ejemplo n.º 25
0
        public static List<Vector3> ExtractVector3FromMesh(ModelMesh mesh, Matrix[] boneTransforms)
        {
            //to store all the extracted vertice positions, will be returned
            List<Vector3> vertices = new List<Vector3>();

            //the possible transform of the current mesh bone
            Matrix _transform;
            //if it has a bone then gets its matric transform
            if (mesh.ParentBone != null)
            {
                _transform = boneTransforms[mesh.ParentBone.Index];
            }
            else
            {
                //otherwise set it an Identity matrix(Scale = 1)
                _transform = Matrix.Identity;
            }

            //loop through each mesh part
            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                //create an array to match the numbers of vertices in the part
                var meshPartVertices = new Vector3[part.NumVertices];

                //use GetData to extract the positions
                part.VertexBuffer.GetData(meshPartVertices);

                //transform the vertices using the bone transform from above
                Vector3.Transform(meshPartVertices, ref _transform, meshPartVertices);

                //add to the list of vector 3, repeat
                vertices.AddRange(meshPartVertices);
            }

            return vertices;
        }
        /// <summary>
        /// Replicate the index data - we need to have indices for each of our instances, based on vfetch instancing
        /// This is sort of similar to what happens in the InstancingSample, but modified to account for ModelMeshParts
        /// </summary>
        /// <param name="mesh"></param>
        private void ReplicateIndexData(ModelMesh mesh)
        {
            List<ushort> indices = new List<ushort>();

            int size = mesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits ? 2 : 4;
            this.indexCount = mesh.IndexBuffer.SizeInBytes / size;

            ushort[] oldIndices = new ushort[indexCount];

            mesh.IndexBuffer.GetData(oldIndices);
            mesh.IndexBuffer.Dispose();

            // We have to replicate index data for each part
            // Unfortunately, since we have different meshParts we have to do this
            // If you look at the InstancingSample, they defined their own Model class.
            // This wasn't a possibility this time because I wanted to leverage the capabilities of the ModelProcessor
            // Therefore, we have to add this extra logic to deal with ModelMeshParts

            // Note that if you just replicate the whole index buffer in a pass, the instancing won't work, because
            // you have to render the instances as contiguous indices

            // So if your buffer looks like: <indices for meshPart1> <indices for meshPart2> etc.., we need to replicate it like:
            // <repeat indices for meshPart1 N times> <repeat indices for meshPart2 N times> where N is the number of instances

            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                this.ReplicateIndexData(part, indices, oldIndices);
            }

            // Create a new index buffer, and set the replicated data into it.
            this.indexBuffer = new IndexBuffer(this.graphicsDevice,
                                          sizeof(ushort) * indices.Count,
                                          BufferUsage.None,
                                          IndexElementSize.SixteenBits);

            this.indexBuffer.SetData(indices.ToArray());
        }
Ejemplo n.º 27
0
		internal void AddMesh(ModelMesh mesh)
		{
			meshes.Add(mesh);
		}
Ejemplo n.º 28
0
		public override void OnEndDrawMesh(GraphicsDevice graphicsDevice, ModelMesh mesh, Matrix bone, 
			Matrix view, Matrix projection)
		{
			if (!Active)
				return;

			foreach (ModelMeshPart meshPart in mesh.MeshParts)
			{
				NormalBuffers normalBuffers = meshPart.Tag as NormalBuffers;
				if (normalBuffers == null)
					continue;

				graphicsDevice.SetVertexBuffer(normalBuffers.Vertices);
				graphicsDevice.Indices = normalBuffers.Indices;

				_lineEffect.World = bone;
				_lineEffect.View = view;
				_lineEffect.Projection = projection;

				foreach (EffectPass pass in _lineEffect.CurrentTechnique.Passes)
				{
					pass.Apply();
					graphicsDevice.DrawIndexedPrimitives(PrimitiveType.LineList, 0, 0,
						normalBuffers.VertexCount, 0, normalBuffers.PrimitiveCount);
				}
			}
		}
        /// <summary>
        /// Create model
        /// </summary>
        /// <param name="setModelName">Set model name</param>
        public Model(string setModelName)
        {
            name = setModelName;

            xnaModel = BaseGame.Content.Load<XnaModel>(
                @"Content\" + name);

            // Get matrix transformations of the model
            // Has to be done only once because we don't use animations in our game.
            if (xnaModel != null)
            {
                transforms = new Matrix[xnaModel.Bones.Count];
                xnaModel.CopyAbsoluteBoneTransformsTo(transforms);

                // Calculate scaling for this object, used for distance comparisons.
                if (xnaModel.Meshes.Count > 0)
                    realScaling = scaling =
                        xnaModel.Meshes[0].BoundingSphere.Radius *
                        transforms[0].Right.Length();

                // For palms, laterns, holders and column holders reduce scaling
                // to reduce the number of objects we have to render.
                if (StringHelper.Compare(name,
                    new string[] { "AlphaPalm", "AlphaPalm2", "AlphaPalm3", "AlphaDeadTree",
                        //don't, looks better with more: "GuardRailHolder",
                        "RoadColumnSegment" }))
                    scaling *= 0.75f;//0.66f;

                // Hotels and windmills should always be visible (they are big)
                if (StringHelper.Compare(name,
                    new string[] { "Hotel01", "Hotel02", "Casino01", "Windmill" }))
                    scaling *= 5.0f;
                else
                    // Don't use more than 3m for scaling and checking smaller objects
                    if (scaling > 3)
                        scaling = 3;
            } // if (xnaModel)

            hasAlpha = name.StartsWith("Alpha");
            // Is this a sign or banner? Then make sure ambient is pretty high!
            bool isSign = name.StartsWith("Sign") ||
                name.StartsWith("Banner") ||
                // Also include windmills, they are too dark
                name.StartsWith("Windmill");
                //name.StartsWith("StartLight");

            isCar = name == "SpeedyRacer";

            // Go through all meshes in the model
            for (int meshNum = 0; meshNum < xnaModel.Meshes.Count; meshNum++)
            {
                ModelMesh mesh = xnaModel.Meshes[meshNum];
                int meshPartNum = 0;
                string meshName = mesh.Name;

                // Remember this mesh for animations done in Render!
                if (name == "Windmill" &&
                    meshName.StartsWith("Windmill_Wings"))
                    animatedMesh = mesh;

                // And for each effect this mesh uses (usually just 1, multimaterials
                // are nice in 3ds max, but not efficiently for rendering stuff).
                for (int effectNum = 0; effectNum < mesh.Effects.Count; effectNum++)
                {
                    Effect effect = mesh.Effects[effectNum];
                    // Store our 4 effect parameters
                    cachedEffectParameters.Add(effect.Parameters["diffuseTexture"]);
                    cachedEffectParameters.Add(effect.Parameters["ambientColor"]);
                    cachedEffectParameters.Add(effect.Parameters["diffuseColor"]);
                    cachedEffectParameters.Add(effect.Parameters["world"]);
                    cachedEffectParameters.Add(effect.Parameters["viewProj"]);
                    cachedEffectParameters.Add(effect.Parameters["viewInverse"]);
                    cachedEffectParameters.Add(effect.Parameters["lightDir"]);

                    // Store if this is a "ReflectionSpecular" technique
                    cachedIsReflectionSpecularTechnique.Add(
                        effect.CurrentTechnique.Name.Contains("ReflectionSpecular"));

                    // Increase ambient value to 0.5, 0.5, 0.5 for signs and banners!
                    if (isSign)
                        effect.Parameters["ambientColor"].SetValue(
                            new Color(128, 128, 128).ToVector4());

                    // Get technique from meshName
                    int techniqueIndex = -1;
                    if (meshName.Length > meshPartNum)
                    {
                        string techniqueNumberString = meshName.Substring(
                            meshName.Length-(1+meshPartNum), 1);
            #if !XBOX360
                        // Faster and does not throw an exception!
                        int.TryParse(techniqueNumberString, out techniqueIndex);
            #else
                        try
                        {
                            techniqueIndex = Convert.ToInt32(techniqueNumberString);
                        } // try
                        catch { } // ignore if that failed
            #endif
                    } // if (meshName.Length)

                    // No technique found or invalid?
                    if (techniqueIndex < 0 ||
                        techniqueIndex >= effect.Techniques.Count)
                    {
                        // Try to use last technique
                        techniqueIndex = effect.Techniques.Count-1;
                        // If this is NormalMapping, use DiffuseSpecular20 instead
                        // of the last technique (which is SpecularWithReflection20)
                        if (effect.Techniques[techniqueIndex].Name.Contains(
                            "SpecularWithReflection"))
                            techniqueIndex -= 2;
                        // Update: We have now 2 more techniques (ReflectionSpecular)
                        if (effect.Techniques[techniqueIndex].Name.Contains(
                            "ReflectionSpecular"))
                            techniqueIndex -= 4;
                    } // if (techniqueIndex)

                    // If the technique ends with 20, but we can't do ps20,
                    // use the technique before that (which doesn't use ps20)
                    if (BaseGame.CanUsePS20 == false &&
                        effect.Techniques[techniqueIndex].Name.EndsWith("20"))
                        techniqueIndex--;

                    // Set current technique for rendering below
                    effect.CurrentTechnique = effect.Techniques[techniqueIndex];

                    // For our car in this mod, always use the
                    // SpecularWithReflectionForCar20 technique!
                    if (isCar)
                        effect.CurrentTechnique =
                            effect.Techniques["SpecularWithReflectionForCar20"];

                    // Next mesh part
                    meshPartNum++;
                } // foreach (effect)

                // Add all mesh parts!
                for (int partNum = 0; partNum < mesh.MeshParts.Count; partNum++)
                {
                    ModelMeshPart part = mesh.MeshParts[partNum];
                    // The model mesh part is not really used, we just extract the
                    // index and vertex buffers and all the render data.
                    // Material settings are build from the effect settings.
                    // Also add this to our own dictionary for rendering.
                    renderableMeshes.Add(part, BaseGame.MeshRenderManager.Add(
                        mesh.VertexBuffer, mesh.IndexBuffer, part, part.Effect));
                } // for (partNum)
            } // foreach (mesh)

            #if DEBUG
            // Check if there are no meshes to render
            if (xnaModel.Meshes.Count == 0)
                throw new ArgumentException("Invalid model "+name+
                    ". It does not contain any meshes");
            #endif
        }
 /// <summary>
 /// Dispose
 /// </summary>
 /// <param name="disposing">Disposing</param>
 protected virtual void Dispose(bool disposing)
 {
     if (disposing)
     {
         // Just set everything to null so we stop using this!
         name = "";
         xnaModel = null;
         transforms = null;
         animatedMesh = null;
     } // if
 }
 protected GameObjectEntity(ModelMesh model)
     : base(model)
 {
 }