public VTX1(EndianBinaryReader reader, int offset, BMDInfo modelstats = null) { Attributes = new VertexData(); StorageFormats = new SortedDictionary <GXVertexAttribute, Tuple <GXDataType, byte> >(); reader.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin); reader.SkipInt32(); int vtx1Size = reader.ReadInt32(); int attributeHeaderOffset = reader.ReadInt32(); if (modelstats != null) { modelstats.VTX1Size = vtx1Size; } int[] attribDataOffsets = new int[13]; for (int i = 0; i < 13; i++) { attribDataOffsets[i] = reader.ReadInt32(); } GXVertexAttribute attrib = (GXVertexAttribute)reader.ReadInt32(); while (attrib != GXVertexAttribute.Null) { GXComponentCount componentCount = (GXComponentCount)reader.ReadInt32(); GXDataType componentType = (GXDataType)reader.ReadInt32(); byte fractionalBitCount = reader.ReadByte(); StorageFormats.Add(attrib, new Tuple <GXDataType, byte>(componentType, fractionalBitCount)); reader.Skip(3); long curPos = reader.BaseStream.Position; int attribDataSize = 0; int attribOffset = GetAttributeDataOffset(attribDataOffsets, vtx1Size, attrib, out attribDataSize); int attribCount = GetAttributeDataCount(attribDataSize, attrib, componentType, componentCount); Attributes.SetAttributeData(attrib, LoadAttributeData(reader, offset + attribOffset, attribCount, fractionalBitCount, attrib, componentType, componentCount)); reader.BaseStream.Seek(curPos, System.IO.SeekOrigin.Begin); attrib = (GXVertexAttribute)reader.ReadInt32(); } reader.BaseStream.Seek(offset + vtx1Size, System.IO.SeekOrigin.Begin); }
private int GetAttributeDataCount(int size, GXVertexAttribute attribute, GXDataType dataType, GXComponentCount compCount) { int compCnt = 0; int compStride = 0; if (attribute == GXVertexAttribute.Color0 || attribute == GXVertexAttribute.Color1) { switch (dataType) { case GXDataType.RGB565: case GXDataType.RGBA4: compCnt = 1; compStride = 2; break; case GXDataType.RGB8: case GXDataType.RGBX8: case GXDataType.RGBA6: case GXDataType.RGBA8: compCnt = 4; compStride = 1; break; } } else { switch (dataType) { case GXDataType.Unsigned8: case GXDataType.Signed8: compStride = 1; break; case GXDataType.Unsigned16: case GXDataType.Signed16: compStride = 2; break; case GXDataType.Float32: compStride = 4; break; } switch (attribute) { case GXVertexAttribute.Position: if (compCount == GXComponentCount.Position_XY) { compCnt = 2; } else if (compCount == GXComponentCount.Position_XYZ) { compCnt = 3; } break; case GXVertexAttribute.Normal: if (compCount == GXComponentCount.Normal_XYZ) { compCnt = 3; } break; case GXVertexAttribute.Tex0: case GXVertexAttribute.Tex1: case GXVertexAttribute.Tex2: case GXVertexAttribute.Tex3: case GXVertexAttribute.Tex4: case GXVertexAttribute.Tex5: case GXVertexAttribute.Tex6: case GXVertexAttribute.Tex7: if (compCount == GXComponentCount.TexCoord_S) { compCnt = 1; } else if (compCount == GXComponentCount.TexCoord_ST) { compCnt = 2; } break; } } return(size / (compCnt * compStride)); }
private List <Color> LoadColorData(EndianBinaryReader reader, int count, GXDataType dataType) { List <Color> colorList = new List <Color>(); for (int i = 0; i < count; i++) { switch (dataType) { case GXDataType.RGB565: short colorShort = reader.ReadInt16(); int r5 = (colorShort & 0xF800) >> 11; int g6 = (colorShort & 0x07E0) >> 5; int b5 = (colorShort & 0x001F); colorList.Add(new Color((float)r5 / 255.0f, (float)g6 / 255.0f, (float)b5 / 255.0f)); break; case GXDataType.RGB8: byte r8 = reader.ReadByte(); byte g8 = reader.ReadByte(); byte b8 = reader.ReadByte(); reader.SkipByte(); colorList.Add(new Color((float)r8 / 255.0f, (float)g8 / 255.0f, (float)b8 / 255.0f)); break; case GXDataType.RGBX8: byte rx8 = reader.ReadByte(); byte gx8 = reader.ReadByte(); byte bx8 = reader.ReadByte(); reader.SkipByte(); colorList.Add(new Color((float)rx8 / 255.0f, (float)gx8 / 255.0f, (float)bx8 / 255.0f)); break; case GXDataType.RGBA4: short colorShortA = reader.ReadInt16(); int r4 = (colorShortA & 0xF000) >> 12; int g4 = (colorShortA & 0x0F00) >> 8; int b4 = (colorShortA & 0x00F0) >> 4; int a4 = (colorShortA & 0x000F); colorList.Add(new Color((float)r4 / 255.0f, (float)g4 / 255.0f, (float)b4 / 255.0f, (float)a4 / 255.0f)); break; case GXDataType.RGBA6: int colorInt = reader.ReadInt32(); int r6 = (colorInt & 0xFC0000) >> 18; int ga6 = (colorInt & 0x03F000) >> 12; int b6 = (colorInt & 0x000FC0) >> 6; int a6 = (colorInt & 0x00003F); colorList.Add(new Color((float)r6 / 255.0f, (float)ga6 / 255.0f, (float)b6 / 255.0f, (float)a6 / 255.0f)); break; case GXDataType.RGBA8: byte ra8 = reader.ReadByte(); byte ga8 = reader.ReadByte(); byte ba8 = reader.ReadByte(); byte aa8 = reader.ReadByte(); colorList.Add(new Color((float)ra8 / 255.0f, (float)ga8 / 255.0f, (float)ba8 / 255.0f, (float)aa8 / 255.0f)); break; } } return(colorList); }
private List <Vector3> LoadVec3Data(EndianBinaryReader reader, byte frac, int count, GXDataType dataType) { List <Vector3> vec3List = new List <Vector3>(); for (int i = 0; i < count; i++) { switch (dataType) { case GXDataType.Unsigned8: byte compu81 = reader.ReadByte(); byte compu82 = reader.ReadByte(); byte compu83 = reader.ReadByte(); float compu81Float = (float)compu81 / (float)(1 << frac); float compu82Float = (float)compu82 / (float)(1 << frac); float compu83Float = (float)compu83 / (float)(1 << frac); vec3List.Add(new Vector3(compu81Float, compu82Float, compu83Float)); break; case GXDataType.Signed8: sbyte comps81 = reader.ReadSByte(); sbyte comps82 = reader.ReadSByte(); sbyte comps83 = reader.ReadSByte(); float comps81Float = (float)comps81 / (float)(1 << frac); float comps82Float = (float)comps82 / (float)(1 << frac); float comps83Float = (float)comps83 / (float)(1 << frac); vec3List.Add(new Vector3(comps81Float, comps82Float, comps83Float)); break; case GXDataType.Unsigned16: ushort compu161 = reader.ReadUInt16(); ushort compu162 = reader.ReadUInt16(); ushort compu163 = reader.ReadUInt16(); float compu161Float = (float)compu161 / (float)(1 << frac); float compu162Float = (float)compu162 / (float)(1 << frac); float compu163Float = (float)compu163 / (float)(1 << frac); vec3List.Add(new Vector3(compu161Float, compu162Float, compu163Float)); break; case GXDataType.Signed16: short comps161 = reader.ReadInt16(); short comps162 = reader.ReadInt16(); short comps163 = reader.ReadInt16(); float comps161Float = (float)comps161 / (float)(1 << frac); float comps162Float = (float)comps162 / (float)(1 << frac); float comps163Float = (float)comps163 / (float)(1 << frac); vec3List.Add(new Vector3(comps161Float, comps162Float, comps163Float)); break; case GXDataType.Float32: vec3List.Add(new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle())); break; } } return(vec3List); }
private List <float> LoadSingleFloat(EndianBinaryReader reader, byte frac, int count, GXDataType dataType) { List <float> floatList = new List <float>(); for (int i = 0; i < count; i++) { switch (dataType) { case GXDataType.Unsigned8: byte compu81 = reader.ReadByte(); float compu81Float = (float)compu81 / (float)(1 << frac); floatList.Add(compu81Float); break; case GXDataType.Signed8: sbyte comps81 = reader.ReadSByte(); float comps81Float = (float)comps81 / (float)(1 << frac); floatList.Add(comps81Float); break; case GXDataType.Unsigned16: ushort compu161 = reader.ReadUInt16(); float compu161Float = (float)compu161 / (float)(1 << frac); floatList.Add(compu161Float); break; case GXDataType.Signed16: short comps161 = reader.ReadInt16(); float comps161Float = (float)comps161 / (float)(1 << frac); floatList.Add(comps161Float); break; case GXDataType.Float32: floatList.Add(reader.ReadSingle()); break; } } return(floatList); }
public object LoadAttributeData(EndianBinaryReader reader, int offset, int count, byte frac, GXVertexAttribute attribute, GXDataType dataType, GXComponentCount compCount) { reader.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin); object final = null; switch (attribute) { case GXVertexAttribute.Position: switch (compCount) { case GXComponentCount.Position_XY: final = LoadVec2Data(reader, frac, count, dataType); break; case GXComponentCount.Position_XYZ: final = LoadVec3Data(reader, frac, count, dataType); break; } break; case GXVertexAttribute.Normal: switch (compCount) { case GXComponentCount.Normal_XYZ: final = LoadVec3Data(reader, frac, count, dataType); break; case GXComponentCount.Normal_NBT: break; case GXComponentCount.Normal_NBT3: break; } break; case GXVertexAttribute.Color0: case GXVertexAttribute.Color1: final = LoadColorData(reader, count, dataType); break; case GXVertexAttribute.Tex0: case GXVertexAttribute.Tex1: case GXVertexAttribute.Tex2: case GXVertexAttribute.Tex3: case GXVertexAttribute.Tex4: case GXVertexAttribute.Tex5: case GXVertexAttribute.Tex6: case GXVertexAttribute.Tex7: switch (compCount) { case GXComponentCount.TexCoord_S: final = LoadSingleFloat(reader, frac, count, dataType); break; case GXComponentCount.TexCoord_ST: final = LoadVec2Data(reader, frac, count, dataType); break; } break; } return(final); }
public VTX1(Assimp.Scene scene, bool forceFloat32, GXDataType postype = GXDataType.Float32, byte fraction = 0) { Attributes = new VertexData(); StorageFormats = new SortedDictionary <GXVertexAttribute, Tuple <GXDataType, byte> >(); int i = -1; foreach (Assimp.Mesh mesh in scene.Meshes) { i++; Console.Write(mesh.Name); if (mesh.HasVertices) { SetAssimpPositionAttribute(mesh); if (!StorageFormats.ContainsKey(GXVertexAttribute.Position)) { StorageFormats.Add(GXVertexAttribute.Position, new Tuple <GXDataType, byte>(postype, fraction)); } } else { throw new Exception($"Mesh \"{ mesh.Name }\" ({i}) has no vertices!"); } if (mesh.HasNormals) { SetAssimpNormalAttribute(mesh); if (!StorageFormats.ContainsKey(GXVertexAttribute.Normal)) { StorageFormats.Add(GXVertexAttribute.Normal, new Tuple <GXDataType, byte>(GXDataType.Signed16, 14)); } } else { Console.WriteLine($"Mesh \"{ mesh.Name }\" ({i}) has no normals."); } if (mesh.HasVertexColors(0)) { //Console.WriteLine($"Mesh \"{ mesh.Name }\" ({i}) has vertex colors on channel 0."); SetAssimpColorAttribute(0, GXVertexAttribute.Color0, mesh); if (!StorageFormats.ContainsKey(GXVertexAttribute.Color0)) { StorageFormats.Add(GXVertexAttribute.Color0, new Tuple <GXDataType, byte>(GXDataType.RGBA8, 0)); } } //else // Console.WriteLine($"Mesh \"{ mesh.Name }\" has no colors on channel 0."); if (mesh.HasVertexColors(1)) { //Console.WriteLine($"Mesh \"{ mesh.Name }\" ({i}) has vertex colors on channel 1."); SetAssimpColorAttribute(1, GXVertexAttribute.Color1, mesh); if (!StorageFormats.ContainsKey(GXVertexAttribute.Color1)) { StorageFormats.Add(GXVertexAttribute.Color1, new Tuple <GXDataType, byte>(GXDataType.RGBA8, 0)); } } //else //Console.WriteLine($"Mesh \"{ mesh.Name }\" has no colors on channel 1."); for (int texCoords = 0; texCoords < 8; texCoords++) { if (mesh.HasTextureCoords(texCoords)) { //Console.WriteLine($"Mesh \"{ mesh.Name }\" ({i}) has texture coordinates on channel { texCoords }."); SetAssimpTexCoordAttribute(texCoords, GXVertexAttribute.Tex0 + texCoords, mesh); if (!StorageFormats.ContainsKey(GXVertexAttribute.Tex0 + texCoords)) { bool use_float = false; if (forceFloat32) { use_float = true; } else { use_float = use_float_for_texcoords(mesh, texCoords); if (use_float) { Console.WriteLine($"Mesh \"{ mesh.Name }\" ({i}) has big texture coordinate values on channel { texCoords } and will use floats."); } } if (use_float) { StorageFormats.Add(GXVertexAttribute.Tex0 + texCoords, new Tuple <GXDataType, byte>(GXDataType.Float32, 0)); } else { StorageFormats.Add(GXVertexAttribute.Tex0 + texCoords, new Tuple <GXDataType, byte>(GXDataType.Signed16, 8)); } } } //else // Console.WriteLine($"Mesh \"{ mesh.Name }\" has no texture coordinates on channel { texCoords }."); Console.Write("."); } Console.Write("✓"); Console.WriteLine(); } }