public static Geometry Polylist(string geoID, string geoName, string matName, GeometryDataType[] dataTypes, float[][] data, ulong[] channels, Semantic[] semantics, ulong[] dataSources, ulong[] sets, int[] vCount, int[] primitives) { int maxLength = Math.Min((int)data.Length, (int)dataTypes.Length); Mesh mesh = new Mesh(); mesh.source = new Source[0]; Polylist polylist = new Polylist((ulong)vCount.Length, matName, vCount, primitives); polylist.input = new InputOffset[0]; // ! ! ! ! // separate adding data and adding semantic inputs into two loops/steps // -> add a GeometryDataType enumeration to identify each data array as a specific data (Vertex, Normal, Texcoord, Colors) // -> and the Semantic which generates the "input" types for the composed vertex data which is generated by the primitive list for (int i = 0; i < maxLength; i++) { DAEGeometry.AppendDataSource(mesh, geoName, dataTypes[i], data[i], channels[i]); } for (int i = 0; i < maxLength; i++) { DAEGeometry.AppendPolylistSemantic(polylist, geoName, semantics[i], dataSources[i], sets[i]); } mesh.primitives = new object[] { polylist }; Geometry geo = new Geometry(geoID, geoName, mesh); return(geo); }
private static ulong ExpandInput(Polylist polylist) { InputOffset[] inputs = polylist.input; Array.Resize <InputOffset>(ref inputs, (int)inputs.Length + 1); polylist.input = inputs; return((ulong)(inputs.Length - 1)); }
public static Geometry Polylist(string geoID, string geoName, string matName, float[] positions, float[] normals, float[] texcoords, float[] vertexColors, int[] vCount, int[] primitive) { int numSources = 1; if (normals != null) { numSources++; } if (texcoords != null) { numSources++; } if (vertexColors != null) { numSources++; } if ((positions == null ? true : positions.Length == 0)) { throw new ArgumentException("Missing position data. Provide at least position data to use Polylist()", "positions"); } Mesh mesh = new Mesh() { source = new Source[numSources] }; Polylist polyList = new Polylist((ulong)vCount.Length, matName, vCount, primitive) { input = new InputOffset[numSources] }; mesh.primitives = new object[] { polyList }; ulong sInd = (ulong)0; mesh.source[sInd] = Source.CreatePositions(geoName, positions); polyList.input[sInd] = new InputOffset("VERTEX", string.Concat("#", geoName, "-VERTEX", sInd)); if (normals != null) { sInd++; mesh.source[sInd] = Source.CreateNormals(geoName, 0, normals); polyList.input[sInd] = new InputOffset("NORMAL", string.Concat("#", geoName, "-Normal0", sInd)); } if (texcoords != null) { sInd++; mesh.source[sInd] = Source.CreateUVs(geoName, 0, texcoords); polyList.input[sInd] = new InputOffset("TEXCOORD", string.Concat("#", geoName, "-UV", sInd)); } if (vertexColors != null) { sInd++; mesh.source[sInd] = Source.CreateVertexColors(geoName, 0, vertexColors); polyList.input[sInd] = new InputOffset("COLOR", string.Concat("#", geoName, "-VERTEX_COLOR0", sInd)); } mesh.vertices = DAEGeometry.GenerateVertices(geoName); Geometry geo = new Geometry(geoID, geoName, mesh); return(geo); }
// move to MeshDAE class (and make it an instance-method instead of static public static void AppendPolylist(string geoName, string matName, DAEGeometryInputSemanticInfo[] semanticsInfos, int[] vCount, int[] primitives, Mesh mesh) { if (mesh == null) { return; } ulong polylistIndex = DAEGeometry.ExpandItems(mesh); Polylist polylist = new Polylist((ulong)vCount.Length, matName, vCount, primitives); polylist.input = new InputOffset[0]; for (int i = 0; i < semanticsInfos.Length; i++) { DAEGeometry.AppendPolylistSemantic(polylist, geoName, semanticsInfos[i].Semantic, semanticsInfos[i].DataSourceIndex, semanticsInfos[i].SetIndex); } mesh.primitives[polylistIndex] = polylist; }
private static void AppendPolylistSemantic(Polylist polylist, string geoName, Semantic semantic, ulong dataSource, ulong set) { ulong indPolylistInput = (ulong)DAEGeometry.ExpandInput(polylist); switch (semantic) { case Semantic.VERTEX: polylist.input[indPolylistInput] = new InputOffset("VERTEX", "#" + geoName + "-VERTEX", indPolylistInput); break; case Semantic.NORMAL: polylist.input[indPolylistInput] = new InputOffset("NORMAL", "#" + geoName + "-Normal" + dataSource, indPolylistInput); break; case Semantic.TEXCOORD: polylist.input[indPolylistInput] = new InputOffset("TEXCOORD", "#" + geoName + "-UV" + dataSource, indPolylistInput, set); break; case Semantic.COLOR: polylist.input[indPolylistInput] = new InputOffset("COLOR", "#" + geoName + "-VERTEX_COLOR" + dataSource, indPolylistInput, set); break; } }
public static Geometry Polylist(string geoID, string geoName, string matName, DAEGeometryDataSourceInfo[] dataSourceInfos, float[][] data, DAEGeometryInputSemanticInfo[] semanticsInfos, int[] vCount, int[] primitives) { int maxLength = Math.Min((int)data.Length, (int)dataSourceInfos.Length); Mesh mesh = new Mesh(); mesh.source = new Source[0]; Polylist polylist = new Polylist((ulong)vCount.Length, matName, vCount, primitives); polylist.input = new InputOffset[0]; for (int i = 0; i < maxLength; i++) { DAEGeometry.AppendDataSource(mesh, geoName, dataSourceInfos[i].Type, data[i], dataSourceInfos[i].Index); } for (int i = 0; i < semanticsInfos.Length; i++) { DAEGeometry.AppendPolylistSemantic(polylist, geoName, semanticsInfos[i].Semantic, semanticsInfos[i].DataSourceIndex, semanticsInfos[i].SetIndex); } mesh.primitives = new object[] { polylist }; Geometry geo = new Geometry(geoID, geoName, mesh); return(geo); }
private Geometry GetGeometry(ModelPart part, int i, string modelName) { var id = $"{modelName}-Part-{i}"; var geometry = new Geometry { Name = id, Id = id }; var positions = GetSource("positions", part.Vertices, v => new float[] { v.Position.X, v.Position.Y, v.Position.Z }); var normals = GetSource("normals", part.Vertices, v => new float[] { v.Normal.X, v.Normal.Y, v.Normal.Z }); var uv = GetMapSource("map", part.Vertices, v => new float[] { v.U, v.V }); var vertices = new Vertices() { Id = "vertices" }; vertices.Input.Add(new InputLocal() { Semantic = "POSITION", Source = "#positions" }); var poly = new Polylist { Count = (ulong)part.Faces.Count, Vcount = string.Join(' ', Enumerable.Repeat(3, part.Faces.Count)), P = string.Join(' ', part.Faces.SelectMany(f => new string[] { f.V1.ToString(), f.V2.ToString(), f.V3.ToString() })), Material = id + "-material" }; poly.Input.Add(new InputLocalOffset() { Semantic = "VERTEX", Source = "#vertices", Offset = 0 }); poly.Input.Add(new InputLocalOffset() { Semantic = "NORMAL", Source = "#normals", Offset = 0 }); poly.Input.Add(new InputLocalOffset() { Semantic = "TEXCOORD", Source = "#map", Offset = 0 }); var mesh = new Mesh { Vertices = vertices }; mesh.Source.Add(positions); mesh.Source.Add(normals); mesh.Source.Add(uv); mesh.Polylist.Add(poly); geometry.Mesh = mesh; return(geometry); }
public static void DecodePrimitives( Geometry geo, Matrix4 bindMatrix, InfluenceDef[] infList, out VertexShaderDesc info, out List <VertexPrimitive> lines, out List <VertexPolygon> faces) { info = VertexShaderDesc.JustPositions(); lines = new List <VertexPrimitive>(); faces = new List <VertexPolygon>(); Source src; int boneCount = 0; if (infList != null) { HashSet <string> bones = new HashSet <string>(); foreach (InfluenceDef inf in infList) { for (int i = 0; i < inf.WeightCount; ++i) { bones.Add(inf.Weights[i].Bone); } } boneCount = bones.Count; } info.BoneCount = boneCount; var m = geo.MeshElement; if (m == null) { return; } Vertices vertsElem; foreach (var prim in m.PrimitiveElements) { Dictionary <ESemantic, int> semanticCounts = new Dictionary <ESemantic, int>(); Dictionary <ESemantic, Dictionary <int, Source> > inputSources = new Dictionary <ESemantic, Dictionary <int, Source> >(); Dictionary <ESemantic, Source> vertexInputSources = new Dictionary <ESemantic, Source>(); foreach (InputShared inp in prim.InputElements) { if (inp.CommonSemanticType == ESemantic.VERTEX) { vertsElem = inp.Source.GetElement <Vertices>(inp.Root); foreach (InputUnshared input in vertsElem.InputElements) { ESemantic semantic = input.CommonSemanticType; if (semanticCounts.ContainsKey(semantic)) { ++semanticCounts[semantic]; } else { semanticCounts.Add(semantic, 1); } src = input.Source.GetElement <Source>(vertsElem.Root); vertexInputSources[input.CommonSemanticType] = src; } continue; } else { ESemantic semantic = inp.CommonSemanticType; if (semanticCounts.ContainsKey(semantic)) { ++semanticCounts[semantic]; } else { semanticCounts.Add(semantic, 1); } src = inp.Source.GetElement <Source>(inp.Root); if (src != null) { if (!inputSources.ContainsKey(semantic)) { inputSources.Add(semantic, new Dictionary <int, Source>()); } int set = (int)inp.Set; if (!inputSources[semantic].ContainsKey(set)) { inputSources[semantic].Add(set, src); } else { inputSources[semantic][set] = src; } } } } info.MorphCount = 0; //Morphs are stored in separate geometry entries, so they need to be combined later info.HasNormals = semanticCounts.ContainsKey(ESemantic.NORMAL) && semanticCounts[ESemantic.NORMAL] > 0; bool hasTexBinormal = semanticCounts.ContainsKey(ESemantic.TEXBINORMAL) && semanticCounts[ESemantic.TEXBINORMAL] > 0; bool hasBinormal = semanticCounts.ContainsKey(ESemantic.BINORMAL) && semanticCounts[ESemantic.BINORMAL] > 0; info.HasBinormals = hasTexBinormal || hasBinormal; bool hasTexTangent = semanticCounts.ContainsKey(ESemantic.TEXTANGENT) && semanticCounts[ESemantic.TEXTANGENT] > 0; bool hasTangent = semanticCounts.ContainsKey(ESemantic.TANGENT) && semanticCounts[ESemantic.TANGENT] > 0; info.HasTangents = hasTexTangent || hasTangent; info.ColorCount = semanticCounts.ContainsKey(ESemantic.COLOR) ? semanticCounts[ESemantic.COLOR] : 0; info.TexcoordCount = semanticCounts.ContainsKey(ESemantic.TEXCOORD) ? semanticCounts[ESemantic.TEXCOORD] : 0; int maxSets = Math.Max(info.MorphCount + 1, Math.Max(info.ColorCount, info.TexcoordCount)); Vertex[][] vertices = new Vertex[prim.PointCount][]; int[] indices = prim?.IndicesElement?.StringContent?.Values; if (indices == null) { WriteLine("Mesh has no face indices. Mesh will be empty."); return; } Matrix4 invTranspBindMatrix = bindMatrix; if (info.HasNormals || info.HasBinormals || info.HasTangents) { invTranspBindMatrix.Invert(); invTranspBindMatrix.Transpose(); } foreach (var inp in prim.InputElements) { int set = (int)inp.Set; int offset = (int)inp.Offset; if (inp.CommonSemanticType == ESemantic.VERTEX) { foreach (ESemantic s in vertexInputSources.Keys) { src = vertexInputSources[s]; DecodeSource(src, s, offset, set, maxSets, prim, indices, vertices, infList, bindMatrix, invTranspBindMatrix); } } else { src = inputSources[inp.CommonSemanticType][set]; DecodeSource(src, inp.CommonSemanticType, offset, set, maxSets, prim, indices, vertices, infList, bindMatrix, invTranspBindMatrix); } } int setIndex = 0; switch (prim.Type) { case EColladaPrimitiveType.Lines: VertexLine[] linesTemp = new VertexLine[vertices.Length / 2]; for (int i = 0, x = 0; i < vertices.Length; i += 2, ++x) { linesTemp[x] = new VertexLine(vertices[i][setIndex], vertices[i + 1][setIndex]); } lines.AddRange(linesTemp); break; case EColladaPrimitiveType.Linestrips: lines.Add(new VertexLineStrip(false, vertices.Select(x => x[setIndex]).ToArray())); break; case EColladaPrimitiveType.Triangles: VertexTriangle[] tris = new VertexTriangle[vertices.Length / 3]; for (int i = 0, x = 0; i < vertices.Length; i += 3, ++x) { tris[x] = new VertexTriangle( vertices[i][setIndex], vertices[i + 1][setIndex], vertices[i + 2][setIndex]); } faces.AddRange(tris); break; case EColladaPrimitiveType.Trifans: faces.Add(new VertexTriangleFan(vertices.Select(x => x[setIndex]).ToArray())); break; case EColladaPrimitiveType.Tristrips: faces.Add(new VertexTriangleStrip(vertices.Select(x => x[setIndex]).ToArray())); break; case EColladaPrimitiveType.Polylist: Polylist polyListPrim = (Polylist)prim; PolyCounts countsElem = polyListPrim.PolyCountsElement; int[] counts = countsElem.StringContent.Values; VertexPolygon[] polys = new VertexPolygon[counts.Length]; for (int vtxIndex = 0, polyIndex = 0; polyIndex < counts.Length; ++polyIndex) { int count = counts[polyIndex]; Vertex[] verts = new Vertex[count]; for (int polyVtxIndex = 0; polyVtxIndex < count; ++polyVtxIndex, ++vtxIndex) { verts[polyVtxIndex] = vertices[vtxIndex][setIndex]; } polys[polyIndex] = new VertexPolygon(verts); } faces.AddRange(polys); break; default: case EColladaPrimitiveType.Polygons: WriteLine($"Primitive type '{prim.Type.ToString()}' not supported. Mesh will be empty."); break; } } }