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; }
/// <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(); }
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); }
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; }
/// <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); } }
private void DrawMesh(ModelMesh mesh) { var localWorld = Model.Transforms[mesh.ParentBone.Index] * _baseWorld; EnableMeshParts.Enable(View, Projection, localWorld, mesh.MeshParts); mesh.Draw(); }
/// <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); } }
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; }
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); } } }
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); }
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(); } }
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); }
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]); } } }
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(); }
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); } }
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; }
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(); }
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]); } } } }
/// <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); }
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(); }
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()); }
internal void AddMesh(ModelMesh mesh) { meshes.Add(mesh); }
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) { }