static int FindDuplicate(List <int> hashes, List <VertexPositionNormalDiffuseTextureTwo> buf, int startIndex, ref VertexPositionNormalDiffuseTextureTwo search, int hash) { for (int i = startIndex; i < buf.Count; i++) { if (hashes[i] != hash) { continue; } if (buf[i].Position != search.Position) { continue; } if (buf[i].Normal != search.Normal) { continue; } if (buf[i].TextureCoordinate != search.TextureCoordinate) { continue; } if (buf[i].Diffuse != search.Diffuse) { continue; } if (buf[i].TextureCoordinateTwo != search.TextureCoordinateTwo) { continue; } return(i); } return(-1); }
public static int HashVert(ref VertexPositionNormalDiffuseTextureTwo vert) { unchecked { int hash = (int)2166136261; hash = hash * 16777619 ^ vert.Position.GetHashCode(); hash = hash * 16777619 ^ vert.Normal.GetHashCode(); hash = hash * 16777619 ^ vert.TextureCoordinate.GetHashCode(); hash = hash * 16777619 ^ vert.TextureCoordinateTwo.GetHashCode(); hash = hash * 16777619 ^ vert.Diffuse.GetHashCode(); return(hash); } }
static VMeshDump ProcessRef(VMeshRef vms, ResourceManager resources) { var d = new VMeshDump(); List <VertexPositionNormalDiffuseTextureTwo> verts = new List <VertexPositionNormalDiffuseTextureTwo>(); List <int> hashes = new List <int>(); for (int meshi = vms.StartMesh; meshi < vms.StartMesh + vms.MeshCount; meshi++) { var m = vms.Mesh.Meshes[meshi]; var dc = new VmsDrawcall(); LibreLancer.Utf.Mat.Material mat; if ((mat = resources.FindMaterial(m.MaterialCrc)) != null) { dc.Material = new ExportMaterial() { Name = mat.Name, Dc = mat.Dc }; } else { dc.Material = new ExportMaterial() { Name = string.Format("material_0x{0:X8}", m.MaterialCrc), Dc = Color4.White }; } List <int> indices = new List <int>(m.NumRefVertices); for (int i = m.TriangleStart; i < m.TriangleStart + m.NumRefVertices; i++) { int idx = vms.Mesh.Indices[i] + m.StartVertex + vms.StartVertex; VertexPositionNormalDiffuseTextureTwo vert; if (vms.Mesh.verticesVertexPosition != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPosition[idx].Position } } ; else if (vms.Mesh.verticesVertexPositionNormal != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormal[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormal[idx].Normal }; } else if (vms.Mesh.verticesVertexPositionTexture != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionTexture[idx].Position, TextureCoordinate = vms.Mesh.verticesVertexPositionTexture[idx].TextureCoordinate }; } else if (vms.Mesh.verticesVertexPositionNormalTexture != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormalTexture[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormalTexture[idx].Normal, TextureCoordinate = vms.Mesh.verticesVertexPositionNormalTexture[idx].TextureCoordinate }; } else if (vms.Mesh.verticesVertexPositionNormalTextureTwo != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].Normal, TextureCoordinate = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].TextureCoordinate, TextureCoordinateTwo = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx] .TextureCoordinateTwo }; } else if (vms.Mesh.verticesVertexPositionNormalDiffuseTexture != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Normal, Diffuse = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Diffuse, TextureCoordinate = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx] .TextureCoordinate }; } else if (vms.Mesh.verticesVertexPositionNormalDiffuseTextureTwo != null) { vert = vms.Mesh.verticesVertexPositionNormalDiffuseTextureTwo[idx]; } else { throw new Exception("something in state is real bad"); //Never called } var hash = HashVert(ref vert); int newIndex = FindDuplicate(hashes, verts, 0, ref vert, hash); if (newIndex == -1) { newIndex = verts.Count; verts.Add(vert); hashes.Add(hash); } indices.Add(newIndex); } dc.Indices = indices.ToArray(); d.Drawcalls.Add(dc); } d.Vertices = verts.ToArray(); d.FVF = vms.Mesh.OriginalFVF; return(d); }
static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo, CL.library_materials matlib, CL.library_effects fxlib) { var conv = new ColladaGeometry() { FVF = D3DFVF.XYZ }; conv.Name = string.IsNullOrEmpty(geo.name) ? geo.id : geo.name; var msh = geo.Item as CL.mesh; if (msh == null) { return(null); } List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>(); List <int> hashes = new List <int>(); List <ushort> indices = new List <ushort>(); List <ColladaDrawcall> drawcalls = new List <ColladaDrawcall>(); Dictionary <string, GeometrySource> sources = new Dictionary <string, GeometrySource>(); Dictionary <string, float[]> arrays = new Dictionary <string, float[]>(); Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>(); int placeHolderIdx = 0; //Get arrays foreach (var acc in msh.source) { var arr = acc.Item as CL.float_array; arrays.Add(arr.id, FloatArray(arr.Text)); } //Accessors foreach (var acc in msh.source) { sources.Add(acc.id, new GeometrySource(acc, arrays)); } //Process geometry foreach (var item in msh.Items) { if (!(item is CL.triangles || item is CL.polylist || item is CL.polygons)) { FLLog.Warning("Collada", "Ignoring " + item.GetType().Name + " element."); } } int totalTriangles = 0; foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons)) { if (item is CL.triangles) { totalTriangles += (int)((CL.triangles)item).count; } else if (item is CL.polylist plist) { totalTriangles += (int)plist.count; } else { totalTriangles += (int)((CL.polygons)item).count; } } if (totalTriangles > 21845) { throw new Exception(string.Format( "Overflow!\nCollada geometry {0} has {1} triangles\nVMeshData has limit of 21845", string.IsNullOrEmpty(geo.name) ? geo.id : geo.name, totalTriangles)); } foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons)) { CL.InputLocalOffset[] inputs; int[] pRefs; int indexCount; string materialRef; ColladaMaterial material; if (item is CL.triangles) { var triangles = (CL.triangles)item; indexCount = (int)(triangles.count * 3); pRefs = IntArray(triangles.p); inputs = triangles.input; materialRef = triangles.material; } else if (item is CL.polygons polygons) { indexCount = (int)(polygons.count * 3); int j = 0; pRefs = new int[indexCount]; foreach (var arr in polygons.Items) { if (!(arr is string)) { throw new Exception("Polygons: ph element unsupported"); } var ints = IntArray((string)arr); if (ints.Length != 3) { throw new Exception("Polygons: non-triangle geometry not supported"); } pRefs[j] = ints[0]; pRefs[j + 1] = ints[1]; pRefs[j + 2] = ints[2]; j += 3; } inputs = polygons.input; materialRef = polygons.material; } else { var plist = (CL.polylist)item; pRefs = IntArray(plist.p); foreach (var c in IntArray(plist.vcount)) { if (c != 3) { throw new Exception("Polylist: non-triangle geometry"); } } materialRef = plist.material; inputs = plist.input; indexCount = (int)(plist.count * 3); } if (indexCount == 0) { continue; //Skip empty } material = ParseMaterial(materialRef, matlib, fxlib); int pStride = 0; foreach (var input in inputs) { pStride = Math.Max((int)input.offset, pStride); } pStride++; GeometrySource sourceXYZ = null; int offXYZ = int.MinValue; GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue; GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue; GeometrySource sourceUV1 = null; int offUV1 = int.MinValue; GeometrySource sourceUV2 = null; int offUV2 = int.MinValue; int texCount = 0; int startIdx = indices.Count; foreach (var input in inputs) { switch (input.semantic) { case SEM_VERTEX: if (CheckURI(input.source) != msh.vertices.id) { throw new Exception("VERTEX doesn't match mesh vertices"); } foreach (var ip2 in msh.vertices.input) { switch (ip2.semantic) { case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(ip2.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(ip2.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(ip2.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } break; case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(input.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(input.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(input.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } int vertexOffset = vertices.Count; for (int i = 0; i < indexCount; i++) { int idx = i * pStride; var vert = new VertexPositionNormalDiffuseTextureTwo( VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])), offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])), offCOLOR == int.MinValue ? (uint)Color4.White.ToRgba() : (uint)sourceCOLOR.GetColor(pRefs[idx + offCOLOR]).ToRgba(), offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]), offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2]) ); var hash = HashVert(ref vert); var vertIdx = FindDuplicate(hashes, vertices, vertexOffset, ref vert, hash); if (indices.Count >= ushort.MaxValue) { throw new Exception("Too many indices"); } if (vertIdx == -1) { if (vertices.Count + 1 >= ushort.MaxValue) { throw new Exception("Too many vertices"); } indices.Add((ushort)(vertices.Count - vertexOffset)); vertices.Add(vert); hashes.Add(hash); } else { indices.Add((ushort)(vertIdx - vertexOffset)); } } drawcalls.Add(new ColladaDrawcall() { StartIndex = startIdx, StartVertex = vertexOffset, EndVertex = vertices.Count - 1, TriCount = (indices.Count - startIdx) / 3, Material = material }); } conv.Indices = indices.ToArray(); conv.Vertices = vertices.ToArray(); conv.Drawcalls = drawcalls.ToArray(); conv.CalculateDimensions(); return(conv); }
public VMeshData(byte[] data, ILibFile materialLibrary, string name) { if (data == null) { throw new ArgumentNullException("data"); } if (materialLibrary == null) { throw new ArgumentNullException("materialLibrary"); } vmsname = name; ready = false; using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) { // Read the data header. MeshType = reader.ReadUInt32(); SurfaceType = reader.ReadUInt32(); MeshCount = reader.ReadUInt16(); IndexCount = reader.ReadUInt16(); FlexibleVertexFormat = (D3DFVF)reader.ReadUInt16(); VertexCount = reader.ReadUInt16(); // Read the mesh headers. Meshes = new List <TMeshHeader>(); int triangleStartOffset = 0; for (int count = 0; count < MeshCount; count++) { TMeshHeader item = new TMeshHeader(reader, triangleStartOffset, materialLibrary); triangleStartOffset += item.NumRefVertices; Meshes.Add(item); } // Read the triangle data Indices = new ushort[IndexCount]; for (int i = 0; i < IndexCount; i++) { Indices[i] = reader.ReadUInt16(); } // Read the vertex data. // The FVF defines what fields are included for each vertex. switch (FlexibleVertexFormat) { case D3DFVF.XYZ: //(D3DFVF)0x0002: verticesVertexPosition = new VertexPosition[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPosition[i] = new VertexPosition(reader); } break; case D3DFVF.XYZ | D3DFVF.NORMAL: //(D3DFVF)0x0012: verticesVertexPositionNormal = new VertexPositionNormal[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPositionNormal[i] = new VertexPositionNormal(reader); } break; case D3DFVF.XYZ | D3DFVF.TEX1: //(D3DFVF)0x0102: verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount]; for (int i = 0; i < VertexCount; i++) { Vector3 position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, Vector3.Zero, textureCoordinate); } CalculateNormals(verticesVertexPositionNormalTexture); FlexibleVertexFormat |= D3DFVF.NORMAL; break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX1: //(D3DFVF)0x0112: verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount]; for (int i = 0; i < VertexCount; i++) { Vector3 position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector3 normal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, normal, textureCoordinate); } break; case D3DFVF.XYZ | D3DFVF.DIFFUSE | D3DFVF.TEX1: //(D3DFVF)0x0142: verticesVertexPositionNormalColorTexture = new VertexPositionNormalColorTexture[VertexCount]; for (int i = 0; i < VertexCount; i++) { Vector3 position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); int r = reader.ReadByte(); int g = reader.ReadByte(); int b = reader.ReadByte(); int a = reader.ReadByte(); Color4 diffuse = new Color4(r / 255f, g / 255f, b / 255f, a / 255f); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalColorTexture[i] = new VertexPositionNormalColorTexture(position, Vector3.Zero, diffuse, textureCoordinate); } FlexibleVertexFormat |= D3DFVF.NORMAL; CalculateNormals(verticesVertexPositionNormalColorTexture); break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX1: //(D3DFVF)0x0152: verticesVertexPositionNormalColorTexture = new VertexPositionNormalColorTexture[VertexCount]; for (int i = 0; i < VertexCount; i++) { //verticesVertexPositionNormalDiffuseTexture[i] = new VertexPositionNormalDiffuseTexture(reader); var position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var normal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); int r = reader.ReadByte(); int g = reader.ReadByte(); int b = reader.ReadByte(); int a = reader.ReadByte(); Color4 diffuse = new Color4(r / 255f, g / 255f, b / 255f, a / 255f); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalColorTexture[i] = new VertexPositionNormalColorTexture(position, normal, diffuse, textureCoordinate); } break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX2: //(D3DFVF)0x0212: verticesVertexPositionNormalTextureTwo = new VertexPositionNormalTextureTwo[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPositionNormalTextureTwo[i] = new VertexPositionNormalTextureTwo(reader); } break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX2: //(D3DFVF)0x0252: verticesVertexPositionNormalDiffuseTextureTwo = new VertexPositionNormalDiffuseTextureTwo[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPositionNormalDiffuseTextureTwo[i] = new VertexPositionNormalDiffuseTextureTwo(reader); } break; /*case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX4: //(D3DFVF)0x0412: * for (int i = 0; i < VertexCount; i++) vertices[i] = new VertexPositionNormalTextureTangentBinormal(reader); * break;*/ default: throw new FileContentException("UTF:VMeshData", "FVF 0x" + FlexibleVertexFormat + " not supported."); } } }
public VMeshData(ArraySegment <byte> data, ILibFile materialLibrary, string name) { if (data == null) { throw new ArgumentNullException("data"); } if (materialLibrary == null) { throw new ArgumentNullException("materialLibrary"); } vmsname = name; ready = false; using (BinaryReader reader = new BinaryReader(data.GetReadStream())) { // Read the data header. MeshType = reader.ReadUInt32(); SurfaceType = reader.ReadUInt32(); MeshCount = reader.ReadUInt16(); IndexCount = reader.ReadUInt16(); FlexibleVertexFormat = (D3DFVF)reader.ReadUInt16(); OriginalFVF = FlexibleVertexFormat; VertexCount = reader.ReadUInt16(); // Read the mesh headers. Meshes = new List <TMeshHeader>(); int triangleStartOffset = 0; for (int count = 0; count < MeshCount; count++) { TMeshHeader item = new TMeshHeader(reader, triangleStartOffset, materialLibrary); if (item.NumRefVertices < 3) { FLLog.Warning("Vms", $"{name} mesh {count} references 0 triangles"); } triangleStartOffset += item.NumRefVertices; Meshes.Add(item); } // Read the triangle data Indices = new ushort[IndexCount]; for (int i = 0; i < IndexCount; i++) { Indices[i] = reader.ReadUInt16(); } // Read the vertex data. // The FVF defines what fields are included for each vertex. switch (FlexibleVertexFormat) { case D3DFVF.XYZ: //(D3DFVF)0x0002: verticesVertexPosition = new VertexPosition[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPosition[i] = new VertexPosition(reader); } break; case D3DFVF.XYZ | D3DFVF.NORMAL: //(D3DFVF)0x0012: verticesVertexPositionNormal = new VertexPositionNormal[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPositionNormal[i] = new VertexPositionNormal(reader); } break; case D3DFVF.XYZ | D3DFVF.TEX1: //(D3DFVF)0x0102: verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount]; for (int i = 0; i < VertexCount; i++) { Vector3 position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, Vector3.One, textureCoordinate); } FlexibleVertexFormat |= D3DFVF.NORMAL; break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX1: //(D3DFVF)0x0112: verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount]; for (int i = 0; i < VertexCount; i++) { Vector3 position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector3 normal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, normal, textureCoordinate); } break; case D3DFVF.XYZ | D3DFVF.DIFFUSE | D3DFVF.TEX1: //(D3DFVF)0x0142: verticesVertexPositionNormalDiffuseTexture = new VertexPositionNormalDiffuseTexture[VertexCount]; Diffuse = new uint[VertexCount]; for (int i = 0; i < VertexCount; i++) { Vector3 position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Diffuse[i] = reader.ReadUInt32(); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalDiffuseTexture[i] = new VertexPositionNormalDiffuseTexture(position, Vector3.One, Diffuse[i], textureCoordinate); } FlexibleVertexFormat |= D3DFVF.NORMAL; break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX1: //(D3DFVF)0x0152: verticesVertexPositionNormalDiffuseTexture = new VertexPositionNormalDiffuseTexture[VertexCount]; Diffuse = new uint[VertexCount]; for (int i = 0; i < VertexCount; i++) { var position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var normal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Diffuse[i] = reader.ReadUInt32(); Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle()); verticesVertexPositionNormalDiffuseTexture[i] = new VertexPositionNormalDiffuseTexture(position, normal, Diffuse[i], textureCoordinate); } break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX2: //(D3DFVF)0x0212: verticesVertexPositionNormalTextureTwo = new VertexPositionNormalTextureTwo[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPositionNormalTextureTwo[i] = new VertexPositionNormalTextureTwo(reader); } break; case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX2: //(D3DFVF)0x0252: verticesVertexPositionNormalDiffuseTextureTwo = new VertexPositionNormalDiffuseTextureTwo[VertexCount]; for (int i = 0; i < VertexCount; i++) { verticesVertexPositionNormalDiffuseTextureTwo[i] = new VertexPositionNormalDiffuseTextureTwo(reader); } break; /*case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX4: //(D3DFVF)0x0412: * for (int i = 0; i < VertexCount; i++) vertices[i] = new VertexPositionNormalTextureTangentBinormal(reader); * break;*/ default: throw new FileContentException("UTF:VMeshData", "FVF 0x" + FlexibleVertexFormat + " not supported."); } } }
static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo) { var conv = new ColladaGeometry() { FVF = D3DFVF.XYZ }; var msh = geo.Item as CL.mesh; if (msh == null) { return(null); } List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>(); List <ushort> indices = new List <ushort>(); List <ColladaDrawcall> drawcalls = new List <ColladaDrawcall>(); Dictionary <string, GeometrySource> sources = new Dictionary <string, GeometrySource>(); Dictionary <string, float[]> arrays = new Dictionary <string, float[]>(); Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>(); //Get arrays foreach (var acc in msh.source) { var arr = acc.Item as CL.float_array; arrays.Add(arr.id, FloatArray(arr.Text)); } //Accessors foreach (var acc in msh.source) { sources.Add(acc.id, new GeometrySource(acc, arrays)); } //Process geometry if (msh.Items.Where(x => x is CL.triangles || x is CL.polylist).Count() != msh.Items.Length) { throw new Exception("Non-triangle geometry"); } foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist)) { CL.InputLocalOffset[] inputs; int[] pRefs; int triangleCount; string material; if (item is CL.triangles) { var triangles = (CL.triangles)item; pRefs = IntArray(triangles.p); inputs = triangles.input; triangleCount = (int)(triangles.count * 3); material = triangles.material; } else { var plist = (CL.polylist)item; pRefs = IntArray(plist.p); foreach (var c in IntArray(plist.vcount)) { if (c != 3) { throw new Exception("Polylist: non-triangle geometry"); } } material = plist.material; inputs = plist.input; triangleCount = (int)(plist.count * 3); } int pStride = 0; foreach (var input in inputs) { pStride = Math.Max((int)input.offset, pStride); } pStride++; GeometrySource sourceXYZ = null; int offXYZ = int.MinValue; GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue; GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue; GeometrySource sourceUV1 = null; int offUV1 = int.MinValue; GeometrySource sourceUV2 = null; int offUV2 = int.MinValue; int texCount = 0; int startIdx = indices.Count; foreach (var input in inputs) { switch (input.semantic) { case SEM_VERTEX: if (CheckURI(input.source) != msh.vertices.id) { throw new Exception("VERTEX doesn't match mesh vertices"); } foreach (var ip2 in msh.vertices.input) { switch (ip2.semantic) { case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(ip2.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(ip2.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(ip2.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } break; case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(input.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(input.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(input.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } for (int i = 0; i < triangleCount; i++) { int idx = i * pStride; var vert = new VertexPositionNormalDiffuseTextureTwo( VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])), offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])), offCOLOR == int.MinValue ? Color4.White : sourceCOLOR.GetColor(pRefs[idx + offCOLOR]), offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]), offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2]) ); var vertIdx = vertices.IndexOf(vert); if (indices.Count >= ushort.MaxValue) { throw new Exception("Too many indices"); } if (vertIdx == -1) { if (vertices.Count + 1 >= ushort.MaxValue) { throw new Exception("Overflow"); } indices.Add((ushort)vertices.Count); vertices.Add(vert); } else { indices.Add((ushort)vertIdx); } } drawcalls.Add(new ColladaDrawcall() { Start = startIdx, TriCount = (indices.Count - startIdx) / 3, Material = string.IsNullOrEmpty(material) ? "NullMaterial" : material }); } conv.Indices = indices.ToArray(); conv.Vertices = vertices.ToArray(); conv.Drawcalls = drawcalls.ToArray(); conv.CalculateDimensions(); return(conv); }