public SMMesh(IEnumerable <SMVertex> vertices, IEnumerable <SMTriangle> triangles, DICTObjShape shape, int vertexBufferIndex, SMTexture texture) { Vertices = vertices.ToList(); Triangles = triangles.ToList(); Shape = shape; VertexBufferIndex = vertexBufferIndex; Texture = texture; }
public static PICAVertex[] GetVertices(DICTObjShape shape, int vertexBufferIndex) { if (!(shape.VertexBuffers[vertexBufferIndex] is VertexBufferInterleaved)) { throw new InvalidOperationException($"Currently only supports VertexBufferInterleaved, but this is a {shape.VertexBuffers[vertexBufferIndex].GetType().Name}"); } var vertexBuffer = (VertexBufferInterleaved)shape.VertexBuffers[vertexBufferIndex]; if (vertexBuffer.RawBuffer.Length == 0) { return(new PICAVertex[0]); } float[] Elems = new float[4]; PICAVertex[] Output = new PICAVertex[vertexBuffer.RawBuffer.Length / vertexBuffer.VertexStride]; using (MemoryStream MS = new MemoryStream(vertexBuffer.RawBuffer)) { BinaryReader Reader = new BinaryReader(MS); for (int Index = 0; Index < Output.Length; Index++) { PICAVertex Out = new PICAVertex(); MS.Seek(Index * vertexBuffer.VertexStride, SeekOrigin.Begin); int bi = 0; int wi = 0; foreach (PICAAttribute Attrib in vertexBuffer.Attributes.Select(a => PICAAttribute.GetPICAAttribute(a))) { AlignStream(MS, Attrib.Format); for (int Elem = 0; Elem < Attrib.Elements; Elem++) { switch (Attrib.Format) { case PICAAttributeFormat.Byte: Elems[Elem] = Reader.ReadSByte(); break; case PICAAttributeFormat.Ubyte: Elems[Elem] = Reader.ReadByte(); break; case PICAAttributeFormat.Short: Elems[Elem] = Reader.ReadInt16(); break; case PICAAttributeFormat.Float: Elems[Elem] = Reader.ReadSingle(); break; } } Vector4 v = new Vector4(Elems[0], Elems[1], Elems[2], Elems[3]); v *= Attrib.Scale; if (Attrib.Name == VertexBuffer.PICAAttributeName.Position) { v.X += shape.PositionOffset.X; v.Y += shape.PositionOffset.Y; v.Z += shape.PositionOffset.Z; } switch (Attrib.Name) { case VertexBuffer.PICAAttributeName.Position: Out.Position = v; break; case VertexBuffer.PICAAttributeName.Normal: Out.Normal = v; break; case VertexBuffer.PICAAttributeName.Tangent: Out.Tangent = v; break; case VertexBuffer.PICAAttributeName.Color: Out.Color = v; break; case VertexBuffer.PICAAttributeName.TexCoord0: Out.TexCoord0 = v; break; case VertexBuffer.PICAAttributeName.TexCoord1: Out.TexCoord1 = v; break; case VertexBuffer.PICAAttributeName.TexCoord2: Out.TexCoord2 = v; break; case VertexBuffer.PICAAttributeName.BoneIndex: Out.Indices[bi++] = (int)v.X; if (Attrib.Elements == 1) { break; } Out.Indices[bi++] = (int)v.Y; if (Attrib.Elements == 2) { break; } Out.Indices[bi++] = (int)v.Z; if (Attrib.Elements == 3) { break; } Out.Indices[bi++] = (int)v.W; break; case VertexBuffer.PICAAttributeName.BoneWeight: Out.Weights[wi++] = v.X; if (Attrib.Elements == 1) { break; } Out.Weights[wi++] = v.Y; if (Attrib.Elements == 2) { break; } Out.Weights[wi++] = v.Z; if (Attrib.Elements == 3) { break; } Out.Weights[wi++] = v.W; break; } } // TODO -- missing FixedAttribute support //if (Mesh.FixedAttributes != null) //{ // bool HasFixedIndices = Mesh.FixedAttributes.Any(x => x.Name == VertexBuffer.PICAAttributeName.BoneIndex); // bool HasFixedWeights = Mesh.FixedAttributes.Any(x => x.Name == VertexBuffer.PICAAttributeName.BoneWeight); // if (HasFixedIndices || HasFixedWeights) // { // foreach (PICAFixedAttribute Attr in Mesh.FixedAttributes) // { // switch (Attr.Name) // { // case VertexBuffer.PICAAttributeName.BoneIndex: // Out.Indices[0] = (int)Attr.Value.X; // Out.Indices[1] = (int)Attr.Value.Y; // Out.Indices[2] = (int)Attr.Value.Z; // break; // case VertexBuffer.PICAAttributeName.BoneWeight: // Out.Weights[0] = Attr.Value.X; // Out.Weights[1] = Attr.Value.Y; // Out.Weights[2] = Attr.Value.Z; // break; // } // } // } //} Output[Index] = Out; } } return(Output); }