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); }
public PartMaterial(ModelMeshPart part) { MeshPart = part; DefaultEffect = part.Effect; DefaultParameters = EffectParameterListSave.FromEffect(part.Effect); SetDefaults(); }
private void EnableEffect(ModelMeshPart meshPart) { var effect = (BasicEffect)meshPart.Effect; effect.World = LocalWorld; effect.View = View; effect.Projection = Projection; effect.EnableDefaultLighting(); }
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(); } }
public static Vector3[] GetVertexElement(ModelMeshPart meshPart, VertexElementUsage usage) { VertexDeclaration vd = meshPart.VertexBuffer.VertexDeclaration; VertexElement[] elements = vd.GetVertexElements(); Func<VertexElement, bool> elementPredicate = ve => ve.VertexElementUsage == usage && ve.VertexElementFormat == VertexElementFormat.Vector3; if (!elements.Any(elementPredicate)) return null; VertexElement element = elements.First(elementPredicate); Vector3[] vertexData = new Vector3[meshPart.NumVertices]; meshPart.VertexBuffer.GetData((meshPart.VertexOffset * vd.VertexStride) + element.Offset, vertexData, 0, vertexData.Length, vd.VertexStride); return vertexData; }
internal ModelMesh(string name, ModelBone parentBone, BoundingSphere boundingSphere, VertexBuffer vertexBuffer, IndexBuffer indexBuffer, ModelMeshPart[] meshParts, object tag) { this.boundingSphere = new BoundingSphere(); this.effects = new ModelEffectCollection(); this.name = name; this.parentBone = parentBone; this.boundingSphere = boundingSphere; this.vertexBuffer = vertexBuffer; this.indexBuffer = indexBuffer; this.meshParts = new ModelMeshPartCollection(meshParts); this.tag = tag; int length = meshParts.Length; for (int i = 0; i < length; i++) { ModelMeshPart part = meshParts[i]; part.parent = this; } }
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; }
private void CreateMeshPart(MODELMESHPART dstPart, MeshPrimitive srcPart, MeshNormalsFallback normalsFunc, int maxBones) { var doubleSided = srcPart.Material?.DoubleSided ?? false; var srcGeometry = new MeshPrimitiveReader(srcPart, doubleSided, normalsFunc); var eff = srcGeometry.IsSkinned ? _MatFactory.UseSkinnedEffect(srcPart.Material) : _MatFactory.UseRigidEffect(srcPart.Material); dstPart.Effect = eff; var vb = srcGeometry.IsSkinned ? CreateVertexBuffer(srcGeometry.ToXnaSkinned()) : CreateVertexBuffer(srcGeometry.ToXnaRigid()); dstPart.VertexBuffer = vb; dstPart.NumVertices = srcGeometry.VertexCount; dstPart.VertexOffset = 0; dstPart.IndexBuffer = CreateIndexBuffer(srcGeometry.TriangleIndices); dstPart.PrimitiveCount = srcGeometry.TriangleIndices.Length; dstPart.StartIndex = 0; }
public IndexArrayShort(ModelMeshPart part) : base(part) { Indices = new short[part.PrimitiveCount * 3]; part.IndexBuffer.GetData<short>(part.StartIndex * sizeof(short), Indices, 0, part.PrimitiveCount * 3); }
private static void DrawMeshPart(ModelMeshPart meshPart) { if (meshPart.NumVertices > 0) { GraphicsDevice graphicsDevice = meshPart.VertexBuffer.GraphicsDevice; graphicsDevice.SetVertexBuffer(meshPart.VertexBuffer, meshPart.VertexOffset); graphicsDevice.Indices = meshPart.IndexBuffer; graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount); } }
public IndexArray(ModelMeshPart part) { }
public virtual void PrepareShadows(ref Matrix renderMatrix) { if (!(shader is IShadowShader)) return; foreach (ModelMesh modelMesh in this.mesh) { Matrix.Multiply(ref transforms[modelMesh.ParentBone.Index], ref renderMatrix, out tmpMat1); if (animationTransforms.Count > 0 && animationTransforms.ContainsKey(modelMesh.Name)) tmpMat1 = animationTransforms[modelMesh.Name] * tmpMat1; foreach (ModelMeshPart part in modelMesh.MeshParts) { curPart = part; ((IShadowShader)shader).ShadowMap.ComputeShadow( ref tmpMat1, SubmitGeometry); } } }
private static BoundingBox? GetBoundingBox(ModelMeshPart meshPart) { if (meshPart.VertexBuffer == null) return null; Vector3[] positions = VertexElementExtractor.GetVertexElement(meshPart, VertexElementUsage.Position); if (positions == null) return null; return BoundingBox.CreateFromPoints(positions); }
private static OutlineItem CreateOutlineItem(ModelMeshPart meshPart) { var item = new OutlineItem { Text = "ModelMeshPart", Icon = MultiColorGlyphs.Mesh, UserData = meshPart, }; return item; }
public override Material CreateFromMeshPart(ModelMeshPart MeshPart) { base.CreateFromMeshPart(MeshPart); this.texture = GetTextureFromEffect(MeshPart.Effect); return this; }
private bool PartIsTranslucent(ModelMeshPart modelMeshPart) { bool result = false; if(modelMeshPart.Effect is BasicEffect){ if((double)((BasicEffect)modelMeshPart.Effect).Alpha < 1.0) result = true; } return result; }
/// <summary> /// Do the actual replication of the indices, for each ModelMeshPart /// </summary> /// <param name="part"></param> /// <param name="indices"></param> /// <param name="oldIndices"></param> private void ReplicateIndexData(ModelMeshPart part, List<ushort> indices, ushort [] oldIndices) { // Replicate one copy of the original index buffer for each instance. for (int instanceIndex = 0; instanceIndex < maxInstances; instanceIndex++) { int instanceOffset = instanceIndex * vertexCount; // Basically, keep adding the indices. We have to replicate this ModelMeshPart index for each instance we can have // Note that each time we are incrementing by instanceOffset. This is so in the vertex shader, when we divide // by the vertex count, we know exactly which index we are at. for (int i = part.StartIndex; i < part.PrimitiveCount * 3; i++) { indices.Add((ushort)(oldIndices[i] + instanceOffset)); } } }
/// <summary> /// Get all the triangles from each mesh part (Changed for XNA 4) /// </summary> public static void ExtractModelMeshPartData(ModelMeshPart meshPart, ref Matrix transform, List<Vector3> vertices, List<TriangleVertexIndices> indices) { // Before we add any more where are we starting from int offset = vertices.Count; // == Vertices (Changed for XNA 4.0) // Read the format of the vertex buffer VertexDeclaration declaration = meshPart.VertexBuffer.VertexDeclaration; VertexElement[] vertexElements = declaration.GetVertexElements(); // Find the element that holds the position VertexElement vertexPosition = new VertexElement(); foreach (VertexElement vert in vertexElements) { if (vert.VertexElementUsage == VertexElementUsage.Position && vert.VertexElementFormat == VertexElementFormat.Vector3) { vertexPosition = vert; // There should only be one break; } } // Check the position element found is valid if (vertexPosition == null || vertexPosition.VertexElementUsage != VertexElementUsage.Position || vertexPosition.VertexElementFormat != VertexElementFormat.Vector3) { throw new Exception("Model uses unsupported vertex format!"); } // This where we store the vertices until transformed Vector3[] allVertex = new Vector3[meshPart.NumVertices]; // Read the vertices from the buffer in to the array meshPart.VertexBuffer.GetData<Vector3>( meshPart.VertexOffset * declaration.VertexStride + vertexPosition.Offset, allVertex, 0, meshPart.NumVertices, declaration.VertexStride); // Transform them based on the relative bone location and the world if provided for (int i = 0; i != allVertex.Length; ++i) { Vector3.Transform(ref allVertex[i], ref transform, out allVertex[i]); } // Store the transformed vertices with those from all the other meshes in this model vertices.AddRange(allVertex); // == Indices (Changed for XNA 4) // Find out which vertices make up which triangles if (meshPart.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) { // This could probably be handled by using int in place of short but is unnecessary throw new Exception("Model uses 32-bit indices, which are not supported."); } // Each primitive is a triangle short[] indexElements = new short[meshPart.PrimitiveCount * 3]; // It looks like the same index buffer is referenced from each meshPart. meshPart.IndexBuffer.GetData<short>( meshPart.StartIndex * 2, indexElements, 0, meshPart.PrimitiveCount * 3); // Each TriangleVertexIndices holds the three indexes to each vertex that makes up a triangle TriangleVertexIndices[] tvi = new TriangleVertexIndices[meshPart.PrimitiveCount]; for (int i = 0; i != tvi.Length; ++i) { // The offset is because we are storing them all in the one array and the // vertices were added to the end of the array. tvi[i].A = indexElements[i * 3 + 0] + offset; tvi[i].B = indexElements[i * 3 + 1] + offset; tvi[i].C = indexElements[i * 3 + 2] + offset; } // Store our triangles indices.AddRange(tvi); }
private void DrawMeshPart(AccessMesh am, ModelMeshPart modelMeshPart,Matrix view, Matrix projection) { if(modelMeshPart.Effect is IEffectMatrices) { IEffectMatrices effectMatrices = modelMeshPart.Effect as IEffectMatrices; effectMatrices.Projection = projection; effectMatrices.View = view; effectMatrices.World = _meshTransform[am.MeshId] * (_model.Meshes)[am.MeshId].ParentBone.Transform * Matrix.CreateTranslation(_position); } _device.SetVertexBuffer(modelMeshPart.VertexBuffer); _device.Indices = modelMeshPart.IndexBuffer; foreach(EffectPass effectPass in modelMeshPart.Effect.CurrentTechnique.Passes) { effectPass.Apply(); _device.DrawIndexedPrimitives(PrimitiveType.TriangleList, modelMeshPart.VertexOffset, modelMeshPart.StartIndex, modelMeshPart.NumVertices, modelMeshPart.StartIndex, modelMeshPart.PrimitiveCount); } }
// Sets up material from values embedded in a MeshPart public virtual Material CreateFromMeshPart(ModelMeshPart MeshPart) { this.effect = MeshPart.Effect; return this; }
/// <summary> /// Each model part will have several datastrutures associated with it so we need an array of objects to store them all /// </summary> /// <param name="part">Model mesh part under consideration</param> private static void ConstructCollisionDetectionInfoStore(ModelMeshPart part) { part.Tag = new object[2]; }
public static bool m0001a8(ModelMeshPart p0) { foreach (VertexElement element in p0.VertexDeclaration.GetVertexElements()) { if ((element.VertexElementUsage == VertexElementUsage.BlendIndices) && (element.UsageIndex == 0)) { return true; } } return false; }
public VertexArray(ModelMeshPart part) { Vertices = new Vector3[part.NumVertices]; part.VertexBuffer.GetData<Vector3>(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, Vertices, 0, part.NumVertices, part.VertexBuffer.VertexDeclaration.VertexStride); }
private static BoundingBox? GetBoundingBox(ModelMeshPart meshPart, Matrix transform) { if (meshPart.VertexBuffer == null) return null; Vector3[] positions = GetVertexElement(meshPart, VertexElementUsage.Position); if (positions == null) return null; Vector3[] transformedPositions = new Vector3[positions.Length]; Vector3.Transform(positions, ref transform, transformedPositions); return BoundingBox.CreateFromPoints(transformedPositions); }
/// <summary> /// Attaches this <see cref="ModelMesh"/> to a parent <see cref="model"/>. /// </summary> internal void Attach(Model model, Microsoft.Xna.Framework.Graphics.ModelMesh mesh, Microsoft.Xna.Framework.Graphics.ModelMeshPart part) { if (model == null || mesh == null || part == null) { throw new ArgumentNullException(); } this.model = model; this.name = mesh.Name; var tag = part.Tag as ModelMeshPartTag; if (tag != null && tag.Textures != null && tag.Textures.Count > 0) { this.textures = tag.Textures; } this.diffuseTexture = part.Effect.GetTexture(); this.parentBoneIndex = mesh.ParentBone.Index; this.vertexBuffer = part.VertexBuffer; this.indexBuffer = part.IndexBuffer; this.vertexOffset = part.VertexOffset; this.numVertices = part.NumVertices; this.primitiveCount = part.PrimitiveCount; this.startIndex = part.StartIndex; }
// Set the required values in the shader. private void SetupEffect(Matrix[] transforms, ModelMesh mesh, ModelMeshPart part) { Effect effect = part.Effect; effect.Parameters["TranslationAmount"].SetValue(translationRate * time); effect.Parameters["RotationAmount"].SetValue(rotationRate * time); effect.Parameters["time"].SetValue(time); effect.Parameters["WorldViewProjection"].SetValue( transforms[mesh.ParentBone.Index] * view * projection); effect.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index]); effect.Parameters["eyePosition"].SetValue(cameraPosition); effect.Parameters["lightPosition"].SetValue(lightPosition); effect.Parameters["ambientColor"].SetValue(ambientColor); effect.Parameters["diffuseColor"].SetValue(diffuseColor); effect.Parameters["specularColor"].SetValue(specularColor); effect.Parameters["specularPower"].SetValue(specularPower); }
/// <summary> /// Renders the model itself as well as the minimum bounding box if showBoundingBox /// is true. By default, SimpleEffectShader is used to render the model. /// </summary> /// <remarks> /// This function is called automatically to render the model, so do not call this method /// </remarks> /// <param name="material">Material properties of this model</param> /// <param name="renderMatrix">Transform of this model</param> public virtual void Render(ref Matrix renderMatrix, Material material) { if (!UseInternalMaterials) { material.InternalEffect = null; if ((shader.CurrentMaterial != material) || material.HasChanged) { shader.SetParameters(material); foreach (IShader afterEffect in afterEffectShaders) afterEffect.SetParameters(material); material.HasChanged = false; } } BlendState origState = null; if (ContainsTransparency) { origState = State.Device.BlendState; State.AlphaBlendingEnabled = true; } // Render the actual model foreach (ModelMesh modelMesh in this.mesh) { Matrix.Multiply(ref transforms[modelMesh.ParentBone.Index], ref renderMatrix, out tmpMat1); if (animationTransforms.Count > 0 && animationTransforms.ContainsKey(modelMesh.Name)) tmpMat1 = animationTransforms[modelMesh.Name] * tmpMat1; foreach (ModelMeshPart part in modelMesh.MeshParts) { if (UseInternalMaterials) { material.InternalEffect = part.Effect; shader.SetParameters(material); } String techniqueName = technique; if (String.IsNullOrEmpty(techniqueName)) techniqueName = part.Effect.CurrentTechnique.Name; curPart = part; shader.Render( ref tmpMat1, techniqueName, SubmitGeometry); foreach (IShader afterEffect in afterEffectShaders) { if (UseInternalMaterials) afterEffect.SetParameters(material); afterEffect.Render( ref tmpMat1, "", ResubmitGeometry); } } } shader.RenderEnd(); foreach (IShader afterEffect in afterEffectShaders) afterEffect.RenderEnd(); if (ContainsTransparency) State.Device.BlendState = origState; if (showBoundingBox) RenderBoundingBox(ref renderMatrix); }
private static Int32[] LoadIndexBuffer(ModelMeshPart thisPart) { int numIndices = thisPart.IndexBuffer.IndexCount; Int32[] localIndexBuffer = new Int32[numIndices]; if (thisPart.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits) { Int16[] tmpI = new Int16[numIndices]; thisPart.IndexBuffer.GetData<Int16>(tmpI); for (int i = 0; i < numIndices; i++) localIndexBuffer[i] = (Int32)tmpI[i]; } else { thisPart.IndexBuffer.GetData<Int32>(localIndexBuffer); } return localIndexBuffer; }
/// <summary> /// DrawPart draws the actual ModelMeshPart /// </summary> /// <param name="transforms"></param> /// <param name="animations"></param> /// <param name="effect"></param> /// <param name="part"></param> private void DrawPart(Matrix [] transforms, int [] animations, Effect effect, ModelMeshPart part) { for (int i = 0; i < transforms.Length; i += maxInstances) { // How many instances can we fit into this batch? int instanceCount = transforms.Length- i; if (instanceCount > maxInstances) instanceCount = maxInstances; // Copy transform and animation data Array.Copy(transforms, i, tempTransforms, 0, instanceCount); Array.Copy(animations, i, tempAnimations, 0, instanceCount); // Send the transform and animation data to the shader effect.Parameters["InstanceTransforms"].SetValue(tempTransforms); effect.Parameters["InstanceAnimations"].SetValue(tempAnimations); effect.CommitChanges(); // Draw maxInstances copies of our geometry in a single batch. this.graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.BaseVertex, 0, part.NumVertices * instanceCount, part.StartIndex, part.PrimitiveCount * instanceCount); } }
private void drawTexturedInstancedPrimitives(Matrix[] instancesArray, Effect effect, ModelMeshPart meshPart) { if (instancesArray.Length != 0) { instanceVertexBuffer.SetData(instancesArray, 0, instancesArray.Length, SetDataOptions.Discard); // Draw all the GRASS instance copies in a single call. foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, Math.Min(1048574, instancesArray.Length)); //TODO: should have warning or something when too big } } }
/// <summary> /// Add model mesh part with the used effect to our sortedMeshes list. /// Neither the model mesh part nor the effect is directly used, /// we will extract all data from the model and only render the /// index and vertex buffers later. /// The model mesh part must use the TangentVertex format. /// </summary> /// <param name="vertexBuffer">Vertex buffer</param> /// <param name="indexBuffer">Index buffer</param> /// <param name="part">Part</param> /// <param name="effect">Effect</param> /// <returns>Renderable mesh</returns> public RenderableMesh Add(VertexBuffer vertexBuffer, IndexBuffer indexBuffer, ModelMeshPart part, Effect effect) { string techniqueName = effect.CurrentTechnique.Name; // Does this technique already exists? MeshesPerMaterialPerTechniques foundList = null; //obs: foreach (MeshesPerMaterialPerTechniques list in sortedMeshes) for (int listNum = 0; listNum < sortedMeshes.Count; listNum++) { MeshesPerMaterialPerTechniques list = sortedMeshes[listNum]; if (list.technique != null && list.technique.Name == techniqueName) { foundList = list; break; } // if (list.technique.Name) } // for (listNum) // Did not found list? Create new one if (foundList == null) { EffectTechnique technique = BaseGame.ParallaxShader.GetTechnique(techniqueName); // Make sure we always have a valid technique if (technique == null) { if (BaseGame.CanUsePS20) techniqueName = "Diffuse20";//"Specular20"; else techniqueName = "Diffuse";//"Specular"; technique = BaseGame.ParallaxShader.GetTechnique(techniqueName); } // if foundList = new MeshesPerMaterialPerTechniques(technique); sortedMeshes.Add(foundList); } // if (foundList) // Create new material from the current effect parameters. // This will create duplicate materials if the same material is used // multiple times, we check this later. Material material = new Material(effect); // Search for material inside foundList. //obs: foreach (MeshesPerMaterial innerList in foundList.meshesPerMaterials) for (int innerListNum = 0; innerListNum < foundList.meshesPerMaterials.Count; innerListNum++) { MeshesPerMaterial innerList = foundList.meshesPerMaterials[innerListNum]; // Check if this is the same material and we can use it instead. // For our purposes it is sufficiant if we check textures and colors. if (innerList.material.diffuseTexture == material.diffuseTexture && innerList.material.normalTexture == material.normalTexture && innerList.material.ambientColor == material.ambientColor && innerList.material.diffuseColor == material.diffuseColor && innerList.material.specularColor == material.specularColor && innerList.material.specularPower == material.specularPower) { // Reuse this material and quit this search material = innerList.material; break; } // if (innerList.material.diffuseTexture) } // foreach (innerList) // Build new RenderableMesh object RenderableMesh mesh = new RenderableMesh( vertexBuffer, indexBuffer, material, foundList.technique, part.VertexDeclaration, part.StreamOffset, part.VertexStride, part.BaseVertex, part.NumVertices, part.StartIndex, part.PrimitiveCount); foundList.Add(mesh); return mesh; }
public ModelExtractor(ModelMeshPart mmp, Vector3[] vecArray, VertexPositionTexture[] vpcVertexArray) { this.model = mmp; this.vectorArray = vecArray; this.vpcVerts = vpcVertexArray; }