private ModelMeshContent ProcessMesh(MeshContent mesh, ModelBoneContent parent, ContentProcessorContext context) { var bounds = new BoundingSphere(); var parts = new List <ModelMeshPartContent>(); var vertexBuffer = new VertexBufferContent(); var indexBuffer = new IndexCollection(); var startVertex = 0; foreach (var geometry in mesh.Geometry) { var vertices = geometry.Vertices; var vertexCount = vertices.VertexCount; var geomBuffer = geometry.Vertices.CreateVertexBuffer(); vertexBuffer.Write(vertexBuffer.VertexData.Length, 1, geomBuffer.VertexData); var startIndex = indexBuffer.Count; indexBuffer.AddRange(geometry.Indices); var partContent = new ModelMeshPartContent(vertexBuffer, indexBuffer, startVertex, vertexCount, startIndex, geometry.Indices.Count / 3); partContent.Material = geometry.Material; parts.Add(partContent); // Update mesh bounding box bounds = BoundingSphere.CreateMerged(bounds, BoundingSphere.CreateFromPoints(geometry.Vertices.Positions)); // Geoms are supposed to all have the same decl, so just steal one of these vertexBuffer.VertexDeclaration = geomBuffer.VertexDeclaration; startVertex += vertexCount; } return(new ModelMeshContent(mesh.Name, mesh, parent, bounds, parts)); }
private ModelMeshContent ProcessMesh(MeshContent mesh, ModelBoneContent parent, ContentProcessorContext context) { var parts = new List <ModelMeshPartContent>(); var vertexBuffer = new VertexBufferContent(); var indexBuffer = new IndexCollection(); if (GenerateTangentFrames) { context.Logger.LogMessage("Generating tangent frames."); foreach (GeometryContent geom in mesh.Geometry) { if (!geom.Vertices.Channels.Contains(VertexChannelNames.Normal(0))) { MeshHelper.CalculateNormals(geom, true); } if (!geom.Vertices.Channels.Contains(VertexChannelNames.Tangent(0)) || !geom.Vertices.Channels.Contains(VertexChannelNames.Binormal(0))) { MeshHelper.CalculateTangentFrames(geom, VertexChannelNames.TextureCoordinate(0), VertexChannelNames.Tangent(0), VertexChannelNames.Binormal(0)); } } } var startVertex = 0; foreach (var geometry in mesh.Geometry) { var vertices = geometry.Vertices; var vertexCount = vertices.VertexCount; ModelMeshPartContent partContent; if (vertexCount == 0) { partContent = new ModelMeshPartContent(); } else { var geomBuffer = geometry.Vertices.CreateVertexBuffer(); vertexBuffer.Write(vertexBuffer.VertexData.Length, 1, geomBuffer.VertexData); var startIndex = indexBuffer.Count; indexBuffer.AddRange(geometry.Indices); partContent = new ModelMeshPartContent(vertexBuffer, indexBuffer, startVertex, vertexCount, startIndex, geometry.Indices.Count / 3); // Geoms are supposed to all have the same decl, so just steal one of these vertexBuffer.VertexDeclaration = geomBuffer.VertexDeclaration; startVertex += vertexCount; } partContent.Material = geometry.Material; parts.Add(partContent); } var bounds = new BoundingSphere(); if (mesh.Positions.Count > 0) { bounds = BoundingSphere.CreateFromPoints(mesh.Positions); } return(new ModelMeshContent(mesh.Name, mesh, parent, bounds, parts)); }
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)); }
/// <summary> /// Construye la información de nodos del terreno /// </summary> /// <param name="vertList">Lista de vértices</param> /// <param name="width">Anchura del terreno</param> /// <param name="deep">Profundidad del terreno</param> /// <param name="levels">Niveles distintos de detalle</param> /// <returns>Devuelve la información de nodos del terreno</returns> public static SceneryNodeInfo Build( VertexMultitextured[] vertList, int width, int deep, int levels) { // Lista resultante de nodos List <SceneryTriangleNode> nodes = new List <SceneryTriangleNode>(); // Diccionario de índices Dictionary <LOD, IndexCollection> indices = new Dictionary <LOD, IndexCollection>(); IndexCollection highIndices = new IndexCollection(); IndexCollection mediumIndices = new IndexCollection(); IndexCollection lowIndices = new IndexCollection(); // Tamaño de la cuadrícula int totalCellsX = width; int totalCellsZ = deep; // Número de divisiones int divisions = Convert.ToInt32(Math.Pow(4, levels)); int divisionsX = divisions / 2; int divisionsZ = divisions / 2; // Número de vértices en X y en Z int numVertexesX = (totalCellsX / divisionsX); int numVertexesZ = (totalCellsZ / divisionsZ); // Número total de vértices, triángulos e índices int totalVertices = totalCellsX * totalCellsZ; int totalTriangles = (totalCellsX - 1) * (totalCellsZ - 1) * 2; int totalIndices = totalTriangles * 3; for (int x = 0; x < divisionsX; x++) { int offsetX = x * numVertexesX; int cellsX = numVertexesX; for (int z = 0; z < divisionsZ; z++) { int offsetZ = z * numVertexesZ; int cellsZ = numVertexesZ; // Crear índices para generar la lista de triángulos de colisión int[] collisionIndices = SceneryNodeInfo.CreateCollisionIndices( offsetX, offsetZ, cellsX, cellsZ, totalCellsX, totalCellsZ); // Crear la lista de triángulos Triangle[] quadTriangles = SceneryNodeInfo.BuildPrimitiveList(vertList, collisionIndices); // Crear los índices para alta resolución SceneryNodeIndexInfo quadHighInfo = null; Int32[] quadHighIndices = Build( LOD.High, highIndices.Count, offsetX, offsetZ, cellsX, cellsZ, totalCellsX, totalCellsZ, out quadHighInfo); // Crear los índices para media resolución SceneryNodeIndexInfo quadMediumInfo = null; Int32[] quadMediumIndices = Build( LOD.Medium, mediumIndices.Count, offsetX, offsetZ, cellsX, cellsZ, totalCellsX, totalCellsZ, out quadMediumInfo); // Crear los índices para baja resolución SceneryNodeIndexInfo quadLowInfo = null; Int32[] quadLowIndices = Build( LOD.Low, lowIndices.Count, offsetX, offsetZ, cellsX, cellsZ, totalCellsX, totalCellsZ, out quadLowInfo); // Añadir los índices a la colección de índices para cada resolución highIndices.AddRange(quadHighIndices); mediumIndices.AddRange(quadMediumIndices); lowIndices.AddRange(quadLowIndices); Dictionary <LOD, SceneryNodeIndexInfo> info = new Dictionary <LOD, SceneryNodeIndexInfo>(); info.Add(LOD.High, quadHighInfo); info.Add(LOD.Medium, quadMediumInfo); info.Add(LOD.Low, quadLowInfo); // Crear el nodo con los triángulos para la colisión, los índices de inicio y el número de triángulos para cada resolución SceneryTriangleNode newQuadNode = new SceneryTriangleNode(quadTriangles, info); nodes.Add(newQuadNode); } } // Crear el diccionario de buffers de índices para cada resolución indices = new Dictionary <LOD, IndexCollection>(); indices.Add(LOD.High, highIndices); indices.Add(LOD.Medium, mediumIndices); indices.Add(LOD.Low, lowIndices); // Devolver la información de nodos del escenario return(new SceneryNodeInfo() { Nodes = nodes.ToArray(), Indices = indices, }); }