/// <summary> /// Converts design-time vertex position and channel data into a vertex buffer format that a graphics device can recognize. /// </summary> /// <returns>A packed vertex buffer.</returns> /// <exception cref="InvalidContentException"> /// One or more of the vertex channel types are invalid or an unrecognized name was passed to <see cref="VertexElementUsage"/>. /// </exception> public VertexBufferContent CreateVertexBuffer() { var vertexBuffer = new VertexBufferContent(positions.Count); var stride = SetupVertexDeclaration(vertexBuffer); // TODO: Verify enough elements in channels to match positions? // Write out data in an interleaved fashion each channel at a time, for example: // |------------------------------------------------------------| // |POSITION[0] | NORMAL[0] |TEX0[0] | POSITION[1]| NORMAL[1] | // |-----------------------------------------------|------------| // #0 |111111111111|____________|________|111111111111|____________| // #1 |111111111111|111111111111|________|111111111111|111111111111| // #2 |111111111111|111111111111|11111111|111111111111|111111111111| // #0: Write position vertices using stride to skip over the other channels: vertexBuffer.Write(0, stride, positions); var channelOffset = VertexBufferContent.SizeOf(typeof(Vector3)); foreach (var channel in Channels) { // #N: Fill in the channel within each vertex var channelType = channel.ElementType; vertexBuffer.Write(channelOffset, stride, channelType, channel); channelOffset += VertexBufferContent.SizeOf(channelType); } return(vertexBuffer); }
public GeometryDataContent(string name, VertexBufferContent vertices, IndexCollection indices, BoundingSphere bounds) { this.Name = name; this.Vertices = vertices; this.Indices = indices; this.Bounds = bounds; }
private List <DRSubmeshContent> BuildSubmeshes(MeshContent mesh, SubmeshInfo[] submeshInfos) { var submeshes = new List <DRSubmeshContent>(mesh.Geometry.Count); for (int i = 0; i < submeshInfos.Length; i++) { var submeshInfo = submeshInfos[i]; var geometry = submeshInfo.Geometry; // Append vertices to one of the _vertexBuffers. VertexBufferContent vertexBuffer = null; int vertexCount = 0; int vertexOffset = 0; if (submeshInfo.VertexBuffer.VertexData.Length > 0) { vertexBuffer = _vertexBuffers[submeshInfo.VertexBufferIndex]; if (!vertexBuffer.VertexDeclaration.VertexStride.HasValue) { string message = string.Format(CultureInfo.InvariantCulture, "Vertex declaration of \"{0}\" does not have a vertex stride.", mesh); throw new InvalidContentException(message, mesh.Identity); } vertexCount = submeshInfo.Geometry.Vertices.VertexCount; vertexOffset = vertexBuffer.VertexData.Length / vertexBuffer.VertexDeclaration.VertexStride.Value; vertexBuffer.Write(vertexBuffer.VertexData.Length, 1, submeshInfo.VertexBuffer.VertexData); } // Append indices to _indices. int startIndex = 0; int primitiveCount = 0; if (geometry.Indices.Count > 0) { startIndex = _indices.Count; primitiveCount = geometry.Indices.Count / 3; _indices.AddRange(geometry.Indices); } // Build material. object material = BuildMaterial(submeshInfo.Material); // Create Submesh. DRSubmeshContent submesh = new DRSubmeshContent { IndexBuffer = _indices, VertexCount = vertexCount, StartIndex = startIndex, PrimitiveCount = primitiveCount, VertexBuffer = vertexBuffer, StartVertex = vertexOffset, MorphTargets = submeshInfo.MorphTargets, ExternalMaterial = material as ExternalReference <DRMaterialContent>, LocalMaterial = material as DRMaterialContent, }; submeshes.Add(submesh); } return(submeshes); }
private void CopyStream(VertexBufferContent source) { var vertexBufferType = typeof(VertexBufferContent); var vertexBufferStreamField = vertexBufferType.GetField("stream", BindingFlags.Instance | BindingFlags.NonPublic); var vertexBufferStream = (MemoryStream)vertexBufferStreamField.GetValue(source); var dynamicVertexBufferStream = new MemoryStream(vertexBufferStream.ToArray()); vertexBufferStreamField.SetValue(this, dynamicVertexBufferStream); }
internal SkinnedModelMeshContent(int numVertices, int numTriangles, VertexBufferContent vertices, IndexCollection indices, MaterialContent material) { this.numVertices = numVertices; this.numTriangles = numTriangles; this.vertices = vertices; this.indices = indices; this.material = material; }
internal ModelMeshPartContent(VertexBufferContent vertexBuffer, IndexCollection indices, int vertexOffset, int numVertices, int startIndex, int primitiveCount) { _vertexBuffer = vertexBuffer; _indexBuffer = indices; _vertexOffset = vertexOffset; _numVertices = numVertices; _startIndex = startIndex; _primitiveCount = primitiveCount; }
public DynamicVertexBufferContent(VertexBufferContent source, int size = 0) : base(size) { Identity = source.Identity; Name = source.Name; foreach (var keyPair in source.OpaqueData) { OpaqueData.Add(keyPair.Key, keyPair.Value); } VertexDeclaration = source.VertexDeclaration; CopyStream(source); }
/// <summary> /// Initializes a new instance of a static model. /// </summary> public StaticModelContent() { vertexContent = new VertexBufferContent(); VertexDeclarationContent vertContent = new VertexDeclarationContent(); foreach (VertexElement element in VertexStaticModel.VertexDeclaration.GetVertexElements()) { vertContent.VertexElements.Add(element); } vertexContent.VertexDeclaration = vertContent; indexContent = new IndexCollection(); }
/// <summary> /// Helper function used by the CustomModelProcessor /// to add new ModelPart information. /// </summary> public void AddModelPart(int triangleCount, int vertexCount, VertexBufferContent vertexBufferContent, IndexCollection indexCollection, MaterialContent materialContent) { ModelPart modelPart = new ModelPart(); modelPart.TriangleCount = triangleCount; modelPart.VertexCount = vertexCount; modelPart.VertexBufferContent = vertexBufferContent; modelPart.IndexCollection = indexCollection; modelPart.MaterialContent = materialContent; modelParts.Add(modelPart); }
/// <summary> /// Converts a single piece of input geometry into our custom format. /// </summary> void ProcessGeometry(GeometryContent geometry) { int triangleCount = geometry.Indices.Count / 3; int vertexCount = geometry.Vertices.VertexCount; // Flatten the flexible input vertex channel data into // a simple GPU style vertex buffer byte array. VertexBufferContent vertexBufferContent = geometry.Vertices.CreateVertexBuffer(); // Convert the input material. MaterialContent material = ProcessMaterial(geometry.Material); // Add the new piece of geometry to our output model. outputModel.AddModelPart(triangleCount, vertexCount, vertexBufferContent, geometry.Indices, material); }
private int SetupVertexDeclaration(VertexBufferContent result) { var offset = 0; // We always have a position channel result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, VertexElementFormat.Vector3, VertexElementUsage.Position, 0)); offset += VertexElementFormat.Vector3.GetTypeSize(); // Optional channels foreach (var channel in Channels) { VertexElementFormat format; VertexElementUsage usage; // Try to determine the vertex format // TODO: Add support for additional formats as they become testable if (channel.ElementType == typeof(Vector3)) { format = VertexElementFormat.Vector3; } else if (channel.ElementType == typeof(Vector2)) { format = VertexElementFormat.Vector2; } else { throw new InvalidContentException("Unrecognized vertex content type."); } // Try to determine the vertex usage if (!VertexChannelNames.TryDecodeUsage(channel.Name, out usage)) { throw new InvalidContentException("Unknown vertex element usage."); } // Try getting the usage index var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name); result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex)); offset += format.GetTypeSize(); result.VertexDeclaration.VertexStride = offset; } return(offset); }
/// <summary> /// Helper function used by the CustomModelProcessor /// to add new ModelPart information. /// </summary> public void AddModelPart( int triangleCount, int vertexCount, int vertexStride, VertexElement[] vertexElements, VertexBufferContent vertexBufferContent, IndexCollection indexCollection, MaterialContent materialContent) { ModelPart modelPart = new ModelPart(); modelPart.TriangleCount = triangleCount; modelPart.VertexCount = vertexCount; modelPart.VertexStride = vertexStride; modelPart.VertexElements = vertexElements; modelPart.VertexBufferContent = vertexBufferContent; modelPart.IndexCollection = indexCollection; modelPart.MaterialContent = materialContent; modelParts.Add( modelPart ); }
/// <summary> /// Helper function used by the InstancedModelProcessor /// to add new ModelPart information. /// </summary> public void AddModelPart(int indexCount, int vertexCount, int vertexStride, VertexElement[] vertexElements, VertexBufferContent vertexBufferContent, IndexCollection indexCollection, MaterialContent materialContent) { ModelPart modelPart = new ModelPart(); modelPart.IndexCount = indexCount; modelPart.VertexCount = vertexCount; modelPart.VertexStride = vertexStride; modelPart.VertexElements = vertexElements; modelPart.VertexBufferContent = vertexBufferContent; modelPart.IndexCollection = indexCollection; modelPart.MaterialContent = materialContent; modelParts.Add(modelPart); }
public H3DAnimatedDynamicVertexBufferContent(VertexBufferContent source, int size = 0) : base(source, size) { }
private int SetupVertexDeclaration(VertexBufferContent result) { var offset = 0; // We always have a position channel result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, VertexElementFormat.Vector3, VertexElementUsage.Position, 0)); offset += VertexElementFormat.Vector3.GetTypeSize(); // Optional channels foreach (var channel in Channels) { VertexElementFormat format; VertexElementUsage usage; // Try to determine the vertex format // TODO: Add support for additional formats as they become testable if (channel.ElementType == typeof(Vector3)) format = VertexElementFormat.Vector3; else if (channel.ElementType == typeof(Vector2)) format = VertexElementFormat.Vector2; else throw new InvalidContentException("Unrecognized vertex content type."); // Try to determine the vertex usage if (!VertexChannelNames.TryDecodeUsage(channel.Name, out usage)) throw new InvalidContentException("Unknown vertex element usage."); // Try getting the usage index var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name); result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex)); offset += format.GetTypeSize(); result.VertexDeclaration.VertexStride = offset; } return offset; }
public PatchContent Build() { #region Local vertex buffer // create local vertex buffer for patch int numVertices = _patchSize * _patchSize; VertexBufferContent localVertexBuffer = new VertexBufferContent(numVertices); // fill vertex buffer VertexPositionNormalTexture2[] vertices = new VertexPositionNormalTexture2[numVertices]; int nStartX = _patchOffsetX * (_patchSize - 1); int nStartY = _patchOffsetY * (_patchSize - 1); int nEndX = nStartX + _patchSize; int nEndY = nStartY + _patchSize; float fMinZ = float.MaxValue, fMaxZ = float.MinValue; int index = 0; for (int y = nStartY; y < nEndY; y++) { for (int x = nStartX; x < nEndX; x++) { // write local data float fZ = _heightMap[x, y]; if (fZ < fMinZ) fMinZ = fZ; if (fZ > fMaxZ) fMaxZ = fZ; Vector2 texCoords1 = new Vector2(x / (float) (_heightMap.Width - 1), y / (float) (_heightMap.Height - 1)); Vector2 texCoords2 = texCoords1 * _detailTextureTiling; vertices[index++] = new VertexPositionNormalTexture2( new Vector3(x * _horizontalScale, fZ, y * _horizontalScale), new Vector3(0, 1, 0), texCoords1, texCoords2); } } localVertexBuffer.Write(0, VertexBufferContent.SizeOf(typeof(VertexPositionNormalTexture2)), vertices); localVertexBuffer.VertexDeclaration = new VertexDeclarationContent(); foreach (VertexElement vertexElement in VertexPositionNormalTexture2.VertexDeclaration.GetVertexElements()) localVertexBuffer.VertexDeclaration.VertexElements.Add(vertexElement); #endregion LevelContent[] levels = new LevelContent[_numLevels]; for (int i = 0; i < _numLevels; i++) { LevelContentBuilder levelContentBuilder = new LevelContentBuilder(_heightMap, _patchSize, _numLevels, i, nStartX, nEndX, nStartY, nEndY); levels[i] = levelContentBuilder.Build(); } #region Bounding box, centre, and offset BoundingBox boundingBox = new BoundingBox( new Vector3(nStartX * _horizontalScale, fMinZ, nStartY * _horizontalScale), new Vector3(nEndX * _horizontalScale, fMaxZ, nEndY * _horizontalScale)); float fAverageZ = (fMinZ + fMaxZ) / 2.0f; Vector3 center = new Vector3( (nStartX + ((_patchSize - 1) / 2.0f)) * _horizontalScale, fAverageZ, (nStartY + ((_patchSize - 1) / 2.0f)) * _horizontalScale); Vector2 offset = new Vector2( (_patchOffsetX * (_patchSize - 1)) * _horizontalScale, (_patchOffsetY * (_patchSize - 1)) * _horizontalScale); #endregion return new PatchContent { VertexBuffer = localVertexBuffer, Levels = levels, BoundingBox =boundingBox, Center = center, Offset = offset }; }
private int SetupVertexDeclaration(VertexBufferContent result) { var offset = 0; // We always have a position channel result.VertexDeclaration.VertexElements.Add( new VertexElement(offset, VertexElementFormat.Vector3, VertexElementUsage.Position, 0)); offset += VertexElementFormat.Vector3.GetSize(); // Optional channels foreach (var channel in Channels) { VertexElementFormat format; // Try to determine the vertex format if (channel.ElementType == typeof(float)) { format = VertexElementFormat.Single; } else if (channel.ElementType == typeof(Vector2)) { format = VertexElementFormat.Vector2; } else if (channel.ElementType == typeof(Vector3)) { format = VertexElementFormat.Vector3; } else if (channel.ElementType == typeof(Vector4)) { format = VertexElementFormat.Vector4; } else if (channel.ElementType == typeof(Color)) { format = VertexElementFormat.Color; } else if (channel.ElementType == typeof(Byte4)) { format = VertexElementFormat.Byte4; } else if (channel.ElementType == typeof(Short2)) { format = VertexElementFormat.Short2; } else if (channel.ElementType == typeof(Short4)) { format = VertexElementFormat.Short4; } else if (channel.ElementType == typeof(NormalizedShort2)) { format = VertexElementFormat.NormalizedShort2; } else if (channel.ElementType == typeof(NormalizedShort4)) { format = VertexElementFormat.NormalizedShort4; } else if (channel.ElementType == typeof(HalfVector2)) { format = VertexElementFormat.HalfVector2; } else if (channel.ElementType == typeof(HalfVector4)) { format = VertexElementFormat.HalfVector4; } else { throw new InvalidContentException(string.Format("Unrecognized vertex content type: '{0}'", channel.ElementType)); } // Try to determine the vertex usage if (!VertexChannelNames.TryDecodeUsage(channel.Name, out VertexElementUsage usage)) { throw new InvalidContentException(string.Format("Unknown vertex element usage for channel '{0}'", channel.Name)); } // Try getting the usage index var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name); result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex)); offset += format.GetSize(); } result.VertexDeclaration.VertexStride = offset; return(offset); }
public void CreateVertexBuffer(out VertexBufferContent vertexBuffer, out VertexElement[] vertexElements, TargetPlatform targetPlatform) { throw new NotImplementedException(); }
// From VertexBufferWriter in MonoGame.Framework.Content.Pipeline private static void Write(ContentWriter output, VertexBufferContent value) { output.WriteRawObject(value.VertexDeclaration); output.Write((uint)(value.VertexData.Length / value.VertexDeclaration.VertexStride)); output.Write(value.VertexData); }
public ModelContent ImportModel(string filename, IContentImporter importer) { if (File.Exists(filename)) { } else if (File.Exists(filename + ".fbx")) { filename += ".fbx"; } else if (next != null) { return(next(filename, importer)); } else { throw new FileNotFoundException("The file could not be found", filename); } var fimporter = new Importer(); var scene = fimporter.Import(filename); var model = new ModelContent(); model.Filename = filename; var bonesByNode = new Dictionary <Node, BoneContent>(); var nodesByBone = new Dictionary <BoneContent, Node>(); foreach (var node in scene.Nodes) { var bone = BoneFromNode(node); bonesByNode[node] = bone; nodesByBone[bone] = node; model.Bones.Add(bone); if (node == scene.GetRootNode()) { model.RootBoneIndex = model.Bones.Count - 1; bone.Transform = bone.Transform.Transposed(); } } foreach (var node in scene.Nodes) { var bone = bonesByNode[node]; if (node.GetNodeAttributeCount() > 0 && node.GetNodeAttributeByIndex(0) is Mesh) { var mesh = (Mesh)node.GetNodeAttributeByIndex(0); var mesh2 = new MeshContent(); model.Meshes.Add(mesh2); mesh2.ParentBone = bone; mesh2.Name = mesh.GetName(); bool isSkinned = true; ShaderContent vert; if (mesh.GetDeformerCount() < 1) { isSkinned = false; vert = importer.ImportShaderStage("$basic", ShaderType.Vertex, importer); } else if (mesh.GetDeformerCount() > 1) { throw new NotImplementedException(); } else { vert = importer.ImportShaderStage("$skinned", ShaderType.Vertex, importer); } var frag = importer.ImportShaderStage("$basic", ShaderType.Fragment, importer); // calculate the global transform for the mesh var meshTransform = node.EvaluateGlobalTransform(); // extract the vertex postions var vertices = Enumerable.Range(0, mesh.GetControlPointsCount()) .Select(ix => { var cp = mesh.GetControlPointAt((int)ix); var baked = meshTransform.MultNormalize(cp); var pos = baked.ToChamber().ToVectorXYZ(); return(new Vertex_PBiBwNT { Position = pos }); }) .ToList(); // extract the blend indices and weights if (mesh.GetDeformerCount() == 1) { if (!(mesh.GetDeformer(0) is Skin)) { throw new NotImplementedException("Only Skin deformers are implemented"); } var boneIndicesL = Enumerable.Range( 0, mesh.GetControlPointsCount()) .Select(x => new List <float>()) .ToList(); var boneWeightsL = Enumerable.Range( 0, mesh.GetControlPointsCount()) .Select(x => new List <float>()) .ToList(); int i; var skin = (Skin)mesh.GetDeformer(0); foreach (var cluster in skin.Clusters) { var cnode = cluster.GetLink(); var cbone = bonesByNode[cnode]; var boneIndex = model.Bones.IndexOf(cbone); for (i = 0; i < cluster.ControlPointIndices.Count; i++) { var index = cluster.ControlPointIndices[i]; var weight = cluster.ControlPointWeights[i]; if (boneIndicesL[index].Count > 4 || boneWeightsL[index].Count > 4) { throw new NotImplementedException("Too many indices or weights"); } boneIndicesL[index].Add((float)boneIndex); boneWeightsL[index].Add((float)weight); if (boneIndicesL[index].Count > 4 || boneWeightsL[index].Count > 4) { throw new NotImplementedException("Too many indices or weights"); } } } Func <List <float>, Vector4> convert = fs => { if (fs.Count == 4) { return(new Vector4(fs[0], fs[1], fs[2], fs[3])); } if (fs.Count == 3) { return(new Vector4(fs[0], fs[1], fs[2], 0)); } if (fs.Count == 2) { return(new Vector4(fs[0], fs[1], 0, 0)); } if (fs.Count == 1) { return(new Vector4(fs[0], 0, 0, 0)); } return(Vector4.Zero); }; var boneIndicesV = boneIndicesL.Select(convert).ToList(); var boneWeightsV = boneWeightsL.Select(convert).ToList(); for (i = 0; i < vertices.Count; i++) { var vertex = vertices[i]; vertex.SetBlendIndices(boneIndicesV[i]); vertex.SetBlendWeights(boneWeightsV[i]); vertices[i] = vertex; } } // construct a list of polygons // beyond this point, we don't need `vertices` until it // gets re-used to build the vertex buffer var polygons = mesh.PolygonIndexes.Select(p => new PolygonBuilder { PolygonVertexIndexes = p, Vertexes = p.Select(ix => vertices[(int)ix]).ToList(), }).ToList(); var polygonsByMaterial = new Dictionary <SurfaceMaterial, List <PolygonBuilder> >(); // organize the mesh's polygons by material var layer = mesh.GetLayer(0); var matelem = layer.GetMaterials(); var matindexes = matelem.MaterialIndexes.List;// GetIndexArray().List; if (matelem.ReferenceMode != LayerElement.EReferenceMode.IndexToDirect) { throw new NotImplementedException("A materials must have a reference mode of IndexToDirect"); } if (matelem.MappingMode == LayerElement.EMappingMode.AllSame) { // only one material var material = node.GetMaterial(matindexes[0]); polygonsByMaterial[material] = new List <PolygonBuilder>(polygons); } else if (matelem.MappingMode == LayerElement.EMappingMode.ByPolygon) { // multiple materials foreach (var mat in node.Materials) { polygonsByMaterial[mat] = new List <PolygonBuilder>(); } int i; for (i = 0; i < matindexes.Count; i++) { var mat = node.Materials[matindexes[i]]; polygonsByMaterial[mat].Add(polygons[i]); } } else { throw new NotImplementedException("Materials must have mapping modes of AllSame or ByPolygon"); } // extract the vertex normals if (layer.GetNormals() != null) { var normalElement = layer.GetNormals(); if (normalElement.MappingMode != LayerElement.EMappingMode.ByPolygonVertex) { throw new NotImplementedException("Normals layer elements must have a mapping mode of ByPolygonVertex"); } if (normalElement.ReferenceMode != LayerElement.EReferenceMode.Direct && normalElement.ReferenceMode != LayerElement.EReferenceMode.IndexToDirect) { throw new NotImplementedException("Normals layer elements must have a reference mode of Direct or IndexToDirect"); } int k = 0; foreach (var poly in polygons) { int i; for (i = 0; i < poly.Vertexes.Count; i++) { int nindex; if (normalElement.ReferenceMode == LayerElement.EReferenceMode.Direct) { nindex = k; } else { nindex = normalElement.GetIndexArray().GetAt(k); } var v = normalElement.GetDirectArray().GetAt(nindex); var vertex = poly.Vertexes[i]; vertex.Normal = meshTransform.MultNormalize(v).ToChamber().ToVectorXYZ(); poly.Vertexes[i] = vertex; k++; } } } // extract the texture coordinates if (layer.GetUVs() != null) { var uvElement = layer.GetUVs(); if (uvElement.MappingMode != LayerElement.EMappingMode.ByPolygonVertex) { throw new NotImplementedException("UV layer elements must have a mapping mode of ByPolygonVertex"); } if (uvElement.ReferenceMode != LayerElement.EReferenceMode.Direct && uvElement.ReferenceMode != LayerElement.EReferenceMode.IndexToDirect) { throw new NotImplementedException("UV layer elements must have a reference mode of Direct or IndexToDirect"); } int k = 0; foreach (var poly in polygons) { int i; for (i = 0; i < poly.Vertexes.Count; i++) { int nindex; if (uvElement.ReferenceMode == LayerElement.EReferenceMode.Direct) { nindex = k; } else { nindex = uvElement.GetIndexArray().GetAt(k); } var v = uvElement.GetDirectArray().GetAt(nindex); var vv = v.ToChamber(); var vertex = poly.Vertexes[i]; vertex.SetTextureCoords(new ChamberLib.Vector2(vv.X, 1 - vv.Y)); poly.Vertexes[i] = vertex; k++; } } } // trianglize polygons with more than three points foreach (var mat in polygonsByMaterial.Keys.ToArray()) { var polys = polygonsByMaterial[mat]; polygonsByMaterial[mat] = polys.SelectMany(p => { if (p.Vertexes.Count < 3) { throw new InvalidOperationException(); } if (p.Vertexes.Count == 3) { return(p.Yield()); } int i; var newPolys = new List <PolygonBuilder>(); for (i = 2; i < p.Vertexes.Count; i++) { var pb = new PolygonBuilder(); pb.PolygonVertexIndexes = new List <long>(); pb.PolygonVertexIndexes.Add(p.PolygonVertexIndexes[0]); pb.PolygonVertexIndexes.Add(p.PolygonVertexIndexes[i - 1]); pb.PolygonVertexIndexes.Add(p.PolygonVertexIndexes[i]); pb.Vertexes = new List <Vertex_PBiBwNT>(); pb.Vertexes.Add(p.Vertexes[0]); pb.Vertexes.Add(p.Vertexes[i - 1]); pb.Vertexes.Add(p.Vertexes[i]); newPolys.Add(pb); } return(newPolys); }).ToList(); } // construct the vertex and index buffers var vertset = new HashSet <Vertex_PBiBwNT>(); vertices.Clear(); var indices = new List <int>(); var vertexBuffer = new VertexBufferContent(); var indexBuffer = new IndexBufferContent(); model.VertexBuffers.Add(vertexBuffer); model.IndexBuffers.Add(indexBuffer); var indexByVertex = new Dictionary <Vertex_PBiBwNT, int>(); foreach (var mat in polygonsByMaterial.Keys) { var polys = polygonsByMaterial[mat]; var polyverts = polys.SelectMany(p => p.Vertexes).ToArray(); var startIndex = indices.Count; int n0 = vertices.Count; vertices.AddRange(polyverts.Except(vertset)); int n1 = vertices.Count; int i; for (i = n0; i < n1; i++) { indexByVertex[vertices[i]] = i; } var polyindices = polyverts.Select(p => indexByVertex[p]); indices.AddRange(polyindices); vertset.AddRange(polyverts); mesh2.Parts.Add(new PartContent() { Material = GetMaterialFromMaterial(mat, vert, frag, importer, filename), StartIndex = startIndex, PrimitiveCount = polys.Count, Vertexes = vertexBuffer, Indexes = indexBuffer, }); } indexBuffer.Indexes = indices.Select(ix => (short)ix).ToArray(); if (isSkinned) { vertexBuffer.Vertices = vertices.Cast <IVertex>().ToArray(); } else { vertexBuffer.Vertices = vertices.Select <Vertex_PBiBwNT, IVertex>(v => new Vertex_PNT { Position = v.Position, Normal = v.Normal, TextureCoords = v.TextureCoords, }).ToArray(); } } } foreach (var node in scene.Nodes) { var bone = bonesByNode[node]; int i; int n = node.GetChildCount(); for (i = 0; i < n; i++) { bone.ChildBoneIndexes.Add(scene.Nodes.IndexOf(node.GetChild(i))); } } if (scene.Poses.Count > 0) { var pose = scene.Poses[0]; foreach (var pi in pose.PoseInfos) { var bone = bonesByNode[pi.Node]; var m = pi.Matrix.ToChamber(); bone.Transform = m; } } // animations Dictionary <string, AnimationSequence> sequences = null; var numstacks = scene.GetSrcObjectCount <AnimStack>(); int j; for (j = 0; j < numstacks; j++) { var stack = scene.GetSrcObject <AnimStack>(j); if (sequences == null) { sequences = new Dictionary <string, AnimationSequence>(); } var timespan = stack.GetLocalTimeSpan(); var layer = (AnimLayer)stack.SrcObjects.FirstOrDefault(x => x is AnimLayer); scene.SetCurrentAnimationStack(stack); var eval = scene.GetAnimationEvaluator(); var frames = new List <AnimationFrame>(); FbxTime t; int i; var startOffset = timespan.Start.GetSecondDouble(); const int framesPerSecond = 60; const long timeStep = FbxTime.UnitsPerSecond / framesPerSecond; for (t = timespan.Start; t.Value <= timespan.Stop.Value; t = new FbxTime(t.Value + timeStep)) { var transforms = new ChamberLib.Matrix[model.Bones.Count]; for (i = 0; i < model.Bones.Count; i++) { var node = nodesByBone[model.Bones[i]]; var m = eval.GetNodeLocalTransform(node, t).ToChamber(); transforms[i] = m; } frames.Add(new AnimationFrame((float)(t.GetSecondDouble() - startOffset), transforms)); } var name = stack.Name.Replace("AnimStack::", ""); sequences.Add( name, new AnimationSequence( (float)(timespan.Stop.GetSecondDouble() - timespan.Start.GetSecondDouble()), frames.ToArray(), name)); } Matrix[] localTransforms = null; Matrix[] absoluteTransforms = null; List <int> skeletonHierarchy = null; if (model.Bones != null && model.Bones.Count > 0) { skeletonHierarchy = Enumerable.Repeat(-1, model.Bones.Count).ToList(); int i; for (i = 0; i < model.Bones.Count; i++) { foreach (var childIndex in model.Bones[i].ChildBoneIndexes) { skeletonHierarchy[childIndex] = i; } } localTransforms = new Matrix[model.Bones.Count]; var globalTransforms = model.Bones.Select(b => b.Transform).ToArray(); for (i = 0; i < model.Bones.Count; i++) { var p = skeletonHierarchy[i]; if (p < 0) { localTransforms[i] = globalTransforms[i]; } else { localTransforms[i] = globalTransforms[i] * globalTransforms[p].Inverted(); } } absoluteTransforms = new Matrix[model.Bones.Count]; for (i = 0; i < model.Bones.Count; i++) { absoluteTransforms[i] = globalTransforms[i].Inverted(); } } if (sequences != null || localTransforms != null || absoluteTransforms != null || skeletonHierarchy != null) { if (sequences == null) { sequences = new Dictionary <string, AnimationSequence>(); } if (localTransforms == null) { localTransforms = new Matrix[0]; } if (absoluteTransforms == null) { absoluteTransforms = new Matrix[0]; } if (skeletonHierarchy == null) { skeletonHierarchy = new List <int>(); } model.AnimationData = new AnimationData( sequences, localTransforms.ToList(), absoluteTransforms.ToList(), skeletonHierarchy); } return(model); }
public CpuAnimatedVertexBufferContent(VertexBufferContent source) : base(source) { }
public DynamicVertexBufferContent(VertexBufferContent source, int size) : base(size) { Source = source; }
public DynamicVertexBufferContent(VertexBufferContent source) : base() { Source = source; }
private int SetupVertexDeclaration(VertexBufferContent result) { var offset = 0; // We always have a position channel result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, VertexElementFormat.Vector3, VertexElementUsage.Position, 0)); offset += VertexElementFormat.Vector3.GetSize(); // Optional channels foreach (var channel in Channels) { VertexElementFormat format; VertexElementUsage usage; // Try to determine the vertex format if (channel.ElementType == typeof(Single)) format = VertexElementFormat.Single; else if (channel.ElementType == typeof(Vector2)) format = VertexElementFormat.Vector2; else if (channel.ElementType == typeof(Vector3)) format = VertexElementFormat.Vector3; else if (channel.ElementType == typeof(Vector4)) format = VertexElementFormat.Vector4; else if (channel.ElementType == typeof(Color)) format = VertexElementFormat.Color; else if (channel.ElementType == typeof(Byte4)) format = VertexElementFormat.Byte4; else if (channel.ElementType == typeof(Short2)) format = VertexElementFormat.Short2; else if (channel.ElementType == typeof(Short4)) format = VertexElementFormat.Short4; else if (channel.ElementType == typeof(NormalizedShort2)) format = VertexElementFormat.NormalizedShort2; else if (channel.ElementType == typeof(NormalizedShort4)) format = VertexElementFormat.NormalizedShort4; else if (channel.ElementType == typeof(HalfVector2)) format = VertexElementFormat.HalfVector2; else if (channel.ElementType == typeof(HalfVector4)) format = VertexElementFormat.HalfVector4; else throw new InvalidContentException(string.Format("Unrecognized vertex content type: '{0}'", channel.ElementType)); // Try to determine the vertex usage if (!VertexChannelNames.TryDecodeUsage(channel.Name, out usage)) throw new InvalidContentException(string.Format("Unknown vertex element usage for channel '{0}'", channel.Name)); // Try getting the usage index var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name); result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex)); offset += format.GetSize(); result.VertexDeclaration.VertexStride = offset; } return offset; }
/// <summary> /// Converts design-time vertex position and channel data into a vertex buffer format that a graphics device can recognize. /// </summary> /// <returns>A packed vertex buffer.</returns> /// <exception cref="InvalidContentException">One or more of the vertex channel types are invalid or an unrecognized name was passed to VertexElementUsage.</exception> public VertexBufferContent CreateVertexBuffer() { var vertexBuffer = new VertexBufferContent(positions.Count); var stride = SetupVertexDeclaration(vertexBuffer); // TODO: Verify enough elements in channels to match positions? // Write out data in an interleaved fashion each channel at a time, for example: // |------------------------------------------------------------| // |POSITION[0] | NORMAL[0] |TEX0[0] | POSITION[1]| NORMAL[1] | // |-----------------------------------------------|------------| // #0 |111111111111|____________|________|111111111111|____________| // #1 |111111111111|111111111111|________|111111111111|111111111111| // #2 |111111111111|111111111111|11111111|111111111111|111111111111| // #0: Write position vertices using stride to skip over the other channels: vertexBuffer.Write(0, stride, positions); var channelOffset = VertexBufferContent.SizeOf(typeof(Vector3)); foreach (var channel in Channels) { // #N: Fill in the channel within each vertex var channelType = channel.ElementType; vertexBuffer.Write(channelOffset, stride, channelType, channel); channelOffset += VertexBufferContent.SizeOf(channelType); } return vertexBuffer; }
public override ModelContent Process(SceneContent input, ContentProcessorContext context) { List <ModelMeshContent> meshes = new List <ModelMeshContent>(); VertexBufferContent vertexBuffer = new VertexBufferContent(new VertexAttribute[] { new PositionAttribute(), new NormalAttribute(), new TextureCoordinateAttribute(), }); if (Skin) { vertexBuffer.AddAttribute(new BlendWeightsAttribute()); vertexBuffer.AddAttribute(new BlendIndicesAttribute()); } BoneContent rootBone = BuildSkeleton(input.Scene.RootNode, null); MaterialContent[] materials = new MaterialContent[input.Scene.MaterialCount]; for (int i = 0; i < input.Scene.MaterialCount; i++) { Dictionary <string, object> parameters = new Dictionary <string, object>(); GetMaterialParameters(input.Scene.Materials[i], parameters, context); string materialFactory; if (!MaterialTypeFactoryReplacements.TryGetValue(i, out materialFactory)) { materialFactory = DefaultMaterialTypeFactory; } MaterialContent material = context.ContentManager.MaterialFactoryManager.GetMaterialFactory(materialFactory)(context, parameters); material.Name = input.Scene.Materials[i].HasName ? input.Scene.Materials[i].Name : string.Format("{0}_Material_{1}", input.Name, i); materials[i] = material; } uint numVertices = 0; uint numIndices = 0; for (int i = 0; i < input.Scene.MeshCount; i++) { Mesh mesh = input.Scene.Meshes[i]; uint primitiveCount = (uint)mesh.FaceCount; uint baseVertex = numVertices; uint baseIndex = numIndices; uint partNumIndices = (uint)mesh.FaceCount * 3; uint partNumVertices = (uint)mesh.VertexCount; numVertices += (uint)mesh.VertexCount; numIndices += (uint)mesh.FaceCount * 3; Dictionary <uint, List <VertexWeight> > boneVertWeights = new Dictionary <uint, List <VertexWeight> >(); if (Skin) { ExtractBoneWeights(mesh, boneVertWeights); } for (int j = 0; j < mesh.VertexCount; j++) { vertexBuffer[Minotaur.Graphics.VertexUsage.Position].AddValues(mesh, j); vertexBuffer[Minotaur.Graphics.VertexUsage.Normal].AddValues(mesh, j); vertexBuffer[Minotaur.Graphics.VertexUsage.TextureCoordinate].AddValues(mesh, j); if (Skin) { float[] weights = new float[4]; byte[] indices = new byte[4]; GetNormalizedBoneWeights(boneVertWeights[(uint)j], weights, indices); ((BlendWeightsAttribute)vertexBuffer[Minotaur.Graphics.VertexUsage.BlendWeight]).AddValues(weights); ((BlendIndicesAttribute)vertexBuffer[Minotaur.Graphics.VertexUsage.BlendIndices]).AddValues(indices); } } IndexCollection indecies = new IndexCollection(); indecies.AddRange(mesh.GetIndices().Select(k => k + (uint)baseVertex)); ModelMeshPartContent part = new ModelMeshPartContent(vertexBuffer, indecies, baseVertex, partNumVertices, baseIndex, partNumIndices, primitiveCount); Minotaur.Core.BoundingSphere boundingSphere = Minotaur.Core.BoundingSphere.CreateFromPoints( ((PositionAttribute)vertexBuffer[Minotaur.Graphics.VertexUsage.Position]).Values.Select( p => new OpenTK.Vector3(p.X, p.Y, p.Z))); ModelMeshContent modelmesh = new ModelMeshContent(mesh.Name, GetMeshParentBone(input.Scene.RootNode, i), new[] { part }, boundingSphere); meshes.Add(modelmesh); part.Material = materials[mesh.MaterialIndex]; } List <ExternalReferenceContent <BoneAnimationsContent> > animations = new List <ExternalReferenceContent <BoneAnimationsContent> >(); foreach (Animation anim in input.Scene.Animations) { if (ExportAnimations.Count == 0 || ExportAnimations.Contains(anim.Name)) { animations.Add(context.ContentManager.BuildContent <BoneAnimationsContent>(input.Name, "ModelImporter", processorName: "BoneAnimProcessor", processorData: new Dictionary <string, object>() { { "AnimationName", anim.Name }, { "NamePre", string.Format("{0}_", Path.GetFileNameWithoutExtension(input.Name)) }, }, ignoreBuildItem: true )); } } return(new ModelContent(rootBone, _bones, meshes, animations)); }
public PatchContent Build() { #region Local vertex buffer // create local vertex buffer for patch int numVertices = _patchSize * _patchSize; VertexBufferContent localVertexBuffer = new VertexBufferContent(numVertices); // fill vertex buffer VertexPositionNormalTexture2[] vertices = new VertexPositionNormalTexture2[numVertices]; int nStartX = _patchOffsetX * (_patchSize - 1); int nStartY = _patchOffsetY * (_patchSize - 1); int nEndX = nStartX + _patchSize; int nEndY = nStartY + _patchSize; float fMinZ = float.MaxValue, fMaxZ = float.MinValue; int index = 0; for (int y = nStartY; y < nEndY; y++) { for (int x = nStartX; x < nEndX; x++) { // write local data float fZ = _heightMap[x, y]; if (fZ < fMinZ) { fMinZ = fZ; } if (fZ > fMaxZ) { fMaxZ = fZ; } Vector2 texCoords1 = new Vector2(x / (float)(_heightMap.Width - 1), y / (float)(_heightMap.Height - 1)); Vector2 texCoords2 = texCoords1 * _detailTextureTiling; vertices[index++] = new VertexPositionNormalTexture2( new Vector3(x * _horizontalScale, fZ, y * _horizontalScale), new Vector3(0, 1, 0), texCoords1, texCoords2); } } localVertexBuffer.Write(0, VertexBufferContent.SizeOf(typeof(VertexPositionNormalTexture2)), vertices); localVertexBuffer.VertexDeclaration = new VertexDeclarationContent(); foreach (VertexElement vertexElement in VertexPositionNormalTexture2.VertexDeclaration.GetVertexElements()) { localVertexBuffer.VertexDeclaration.VertexElements.Add(vertexElement); } #endregion LevelContent[] levels = new LevelContent[_numLevels]; for (int i = 0; i < _numLevels; i++) { LevelContentBuilder levelContentBuilder = new LevelContentBuilder(_heightMap, _patchSize, _numLevels, i, nStartX, nEndX, nStartY, nEndY); levels[i] = levelContentBuilder.Build(); } #region Bounding box, centre, and offset BoundingBox boundingBox = new BoundingBox( new Vector3(nStartX * _horizontalScale, fMinZ, nStartY * _horizontalScale), new Vector3(nEndX * _horizontalScale, fMaxZ, nEndY * _horizontalScale)); float fAverageZ = (fMinZ + fMaxZ) / 2.0f; Vector3 center = new Vector3( (nStartX + ((_patchSize - 1) / 2.0f)) * _horizontalScale, fAverageZ, (nStartY + ((_patchSize - 1) / 2.0f)) * _horizontalScale); Vector2 offset = new Vector2( (_patchOffsetX * (_patchSize - 1)) * _horizontalScale, (_patchOffsetY * (_patchSize - 1)) * _horizontalScale); #endregion return(new PatchContent { VertexBuffer = localVertexBuffer, Levels = levels, BoundingBox = boundingBox, Center = center, Offset = offset }); }
/// <summary> /// Procesar el mapa de alturas /// </summary> /// <param name="input">Información del escenario de entrada</param> /// <param name="context">Contexto de procesado</param> /// <returns>Devuelve la información de escenario leída</returns> public override SceneryInfo Process(SceneryFile input, ContentProcessorContext context) { // Cargar la textura del mapa de alturas Texture2DContent terrain = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.HeightMapFile), null); // Obtener el mapa de alturas HeightMap heightMap = this.BuildHeightMap(terrain, input.HeightMapCellScale, context); // Generar los vértices e inicializar el buffer de vértices VertexMultitextured[] vertList = heightMap.BuildVertices( input.HeightMapCellSize, input.ProportionTexture1, input.ProportionTexture2, input.ProportionTexture3); VertexBufferContent vertexBuffer = new VertexBufferContent(VertexMultitextured.SizeInBytes * vertList.Length); vertexBuffer.Write <VertexMultitextured>(0, VertexMultitextured.SizeInBytes, vertList, context.TargetPlatform); // Generar los índices e inicializar los buffers de índices double lowOrderLevels = (Math.Sqrt(heightMap.DataLength) - 1) * 0.5f; int levelCount = Convert.ToInt32(Math.Log(lowOrderLevels, 4.0d)); SceneryNodeInfo sceneryIndexInfo = SceneryNodeInfo.Build( vertList, heightMap.Width, heightMap.Deep, levelCount); // Efecto de renderización CompiledEffect effect = Effect.CompileEffectFromFile( input.EffectFile, null, null, CompilerOptions.None, context.TargetPlatform); // Texturas del terreno Texture2DContent texture1 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture1File), null); Texture2DContent texture2 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture2File), null); Texture2DContent texture3 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture3File), null); Texture2DContent texture4 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture4File), null); Texture2DContent detailTexture1 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture1File), null); Texture2DContent detailTexture2 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture2File), null); Texture2DContent detailTexture3 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture3File), null); Texture2DContent detailTexture4 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture4File), null); CompiledEffect billboardEffect = Effect.CompileEffectFromFile( input.BillboardEffectFile, null, null, CompilerOptions.None, context.TargetPlatform); Texture2DContent billboardGrassTexture = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.BillboardGrassTextureFile), null); Texture2DContent billboardTreeTexture = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.BillboardTreeTextureFile), null); int billboardsPerTriangle = input.BillboardsPerTriangle; float billboardTreesPercent = input.BillboardTreesPercent; return(new SceneryInfo() { Terrain = terrain, TerrainBuffer = vertexBuffer, TerrainBufferVertexCount = vertList.Length, TerrainInfo = sceneryIndexInfo, Effect = effect, Texture1 = texture1, Texture2 = texture2, Texture3 = texture3, Texture4 = texture4, DetailTexture1 = detailTexture1, DetailTexture2 = detailTexture2, DetailTexture3 = detailTexture3, DetailTexture4 = detailTexture4, BillboardEffect = billboardEffect, BillboardGrass = billboardGrassTexture, BillboardTree = billboardTreeTexture, BillboardsPerTriangle = billboardsPerTriangle, BillboardTreesPercent = billboardTreesPercent, }); }