public MeshElement(VertexDeclaration vertexDeclaration, float[] vertexBuffer, ushort[] indexBuffer) { _vertexDeclaration = vertexDeclaration; _vertexBuffer = vertexBuffer; _indexBuffer = indexBuffer; _vertexCount = _vertexBuffer.Length / _vertexDeclaration.Stride; }
void IMeshOptimiser.Apply(float[] originalVertexBuffer, ushort[] originalIndexBuffer, MeshElement meshElement) { _vertexDeclaration = meshElement.VertexDeclaration; _meshElement = meshElement; _originalIndexBuffer = originalIndexBuffer; unsmoothedChannels = new List<VertexChannel>(); Dictionary<int, List<int>> smoothingCandidates = new Dictionary<int, List<int>>(); foreach (VertexChannel channel in _vertexDeclaration.channels) { if (channel.Name != "NORMAL" && channel.Name != "TANGENT" && channel.Name != "BITANGENT") unsmoothedChannels.Add(channel); } List<int> uniqueVertices = new List<int>(meshElement.VertexCount); for (int i = 0; i < meshElement.VertexCount; ++i) { int matching = -1; foreach (int j in uniqueVertices) { if (ChannelsMatch(i, j)) { matching = j; break; } } if (matching >= 0) { if (smoothingCandidates.ContainsKey(matching)) { smoothingCandidates[matching].Add(i); } else { smoothingCandidates.Add(matching, new List<int>()); smoothingCandidates[matching].Add(i); } } else { uniqueVertices.Add(i); } } _optimisedVertexBuffer = new float[uniqueVertices.Count * _vertexDeclaration.Stride]; _optimisedIndexBuffer = new ushort[originalIndexBuffer.Length]; for (int i = 0; i < uniqueVertices.Count; ++i) { MeshHelper.CopyFloatArray(originalVertexBuffer, uniqueVertices[i] * _vertexDeclaration.Stride, _optimisedVertexBuffer, i * _vertexDeclaration.Stride, _vertexDeclaration.Stride); ChangeIndices(uniqueVertices[i], i); if (smoothingCandidates.ContainsKey(uniqueVertices[i])) { foreach (int j in smoothingCandidates[uniqueVertices[i]]) { if (meshElement.VertexDeclaration.ContainsChannel("TANGENT")) { float[] tangent = meshElement.ReadAttribute("TANGENT", j); MeshHelper.AddFloatArray(tangent, 0, _optimisedVertexBuffer, i * _vertexDeclaration.Stride + _vertexDeclaration.GetChannel("TANGENT").Offset, 3); float[] bitangent = meshElement.ReadAttribute("BITANGENT", j); MeshHelper.AddFloatArray(bitangent, 0, _optimisedVertexBuffer, i * _vertexDeclaration.Stride + _vertexDeclaration.GetChannel("BITANGENT").Offset, 3); } float[] normal = meshElement.ReadAttribute("NORMAL", j); MeshHelper.AddFloatArray(normal, 0, _optimisedVertexBuffer, i * _vertexDeclaration.Stride + _vertexDeclaration.GetChannel("NORMAL").Offset, 3); ChangeIndices(j, i); } } MeshHelper.Normalize(_optimisedVertexBuffer, i * _vertexDeclaration.Stride + _vertexDeclaration.GetChannel("NORMAL").Offset, 3); if (meshElement.VertexDeclaration.ContainsChannel("TANGENT")) { MeshHelper.Normalize(_optimisedVertexBuffer, i * _vertexDeclaration.Stride + _vertexDeclaration.GetChannel("TANGENT").Offset, 3); MeshHelper.Normalize(_optimisedVertexBuffer, i * _vertexDeclaration.Stride + _vertexDeclaration.GetChannel("BITANGENT").Offset, 3); } } }
public Vertex(VertexDeclaration declaration) { _vertexDeclaration = declaration; _data = new float[_vertexDeclaration.Stride]; }
private void ParseMesh(XPathNavigator nav) { var sourceIterator = nav.Select("c:source", nsManager); while (sourceIterator.MoveNext()) { ParseSource(sourceIterator.Current); } var vertices = nav.SelectSingleNode("c:vertices", nsManager); string sourceNewName = vertices.GetAttribute("id", nsName); var input = nav.SelectSingleNode("c:vertices/c:input", nsManager); string sourceOldName = input.GetAttribute("source", nsName); sourceOldName = sourceOldName.Substring(1); float[] tmpData = sources[sourceOldName].data; int tmpStride = sources[sourceOldName].stride; sources.Remove(sourceOldName); sources.Add(sourceNewName, new Source(tmpData)); sources[sourceNewName].stride = tmpStride; var polylist = nav.SelectSingleNode("c:polylist", nsManager); int polyCount; if (!int.TryParse(polylist.GetAttribute("count", nsName), out polyCount)) throw new GeometryParserException("could not parse poly count!"); polyVertexCount = new int[polyCount]; var vcount = polylist.SelectSingleNode("c:vcount", nsManager); string[] parts = vcount.InnerXml.Split(' '); for (int i = 0; i < polyCount; ++i) { if (!int.TryParse(parts[i], out polyVertexCount[i])) throw new GeometryParserException("could not parse poly vertex count at element: " + i); if (polyVertexCount[i] == 3) ++triCount; else if (polyVertexCount[i] == 4) triCount += 2; else throw new GeometryParserException("can only parse tris and quads!"); } var inputIterator = polylist.Select("c:input", nsManager); int inputCount = 0; while (inputIterator.MoveNext()) { string inputSemantic = inputIterator.Current.GetAttribute("semantic", nsName); string inputSource = inputIterator.Current.GetAttribute("source", nsName).Substring(1); int inputOffset; if (!int.TryParse(inputIterator.Current.GetAttribute("offset", nsName), out inputOffset)) throw new GeometryParserException("could not parse input offset, (semantic " + inputSemantic + ")"); semantics.Add(inputSemantic, new Semantic(inputSource, inputOffset)); ++inputCount; } var indicesNode = polylist.SelectSingleNode("c:p", nsManager); parts = indicesNode.InnerXml.Split(' '); int indexCount = 0; foreach (int v in polyVertexCount) indexCount += v; indexCount *= inputCount; indices = new int[indexCount]; for (int i = 0; i < indexCount; ++i) { int.TryParse(parts[i], out indices[i]); } _vertexDeclaration = new VertexDeclaration(GetChannels()); PopulateMesh(); Console.WriteLine("Finished Parsing Mesh"); }
private void CreateArrays(bool generateTangents) { if (generateTangents && _vertexDeclaration.ContainsChannel("TEXCOORD")) { Console.WriteLine("generating tangent frames...."); List<VertexChannel> originalChannels = new List<VertexChannel>(); foreach (VertexChannel channel in _vertexDeclaration.channels) { originalChannels.Add(channel); } originalChannels.Add(new VertexChannel("TANGENT", _vertexDeclaration.Stride, 3)); originalChannels.Add(new VertexChannel("BITANGENT", _vertexDeclaration.Stride + 3, 3)); _vertexDeclaration = new VertexDeclaration(originalChannels); vertexData = new float[_vertexDeclaration.Stride * tris.Length * 3]; indexData = new ushort[tris.Length * 3]; int offset = 0; for (int i = 0; i < tris.Length; ++i) { for (int j = 0; j < 3; ++j) { tris[i][j].ToArray().CopyTo(vertexData, offset * _vertexDeclaration.Stride); indexData[i * 3 + j] = (ushort)offset; int tangentOffset = _vertexDeclaration.GetChannel("TANGENT").Offset; GenerateTangents(tris[i], j).CopyTo(vertexData, (offset * _vertexDeclaration.Stride) + tangentOffset); ++offset; } } } else { vertexData = new float[_vertexDeclaration.Stride * tris.Length * 3]; indexData = new ushort[tris.Length * 3]; int offset = 0; for (int i = 0; i < tris.Length; ++i) { for (int j = 0; j < 3; ++j) { tris[i][j].ToArray().CopyTo(vertexData, offset * _vertexDeclaration.Stride); indexData[i * 3 + j] = (ushort)offset; ++offset; } } } }