diff --git a/Unity Studio/Unity Classes/Mesh.cs b/Unity Studio/Unity Classes/Mesh.cs index 24b19eb..7bca4a8 100644 --- a/Unity Studio/Unity Classes/Mesh.cs +++ b/Unity Studio/Unity Classes/Mesh.cs @@ -326,7 +326,7 @@ namespace Unity_Studio return unpackedVectors; } - public Mesh(AssetPreloadData MeshPD) + public Mesh(AssetPreloadData MeshPD, bool readSwitch) { //Stream = new EndianStream(File.OpenRead(sourceFile.filePath), sourceFile.endianType); //Stream.endian = sourceFile.endianType; @@ -345,231 +345,98 @@ namespace Unity_Studio } m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - - if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) + + if (readSwitch) { - m_Use16BitIndices = a_Stream.ReadBoolean(); - a_Stream.Position += 3; - } - #region Index Buffer for 2.5.1 and earlier - if (version[0] == 2 && version[1] <= 5) - { - int m_IndexBuffer_size = a_Stream.ReadInt32(); - - if (m_Use16BitIndices) + if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) { - m_IndexBuffer = new uint[m_IndexBuffer_size / 2]; - for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt16(); } - a_Stream.AlignStream(4); - } - else - { - m_IndexBuffer = new uint[m_IndexBuffer_size / 4]; - for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt32(); } - } - } - #endregion - - #region subMeshes - int m_SubMeshes_size = a_Stream.ReadInt32(); - for (int s = 0; s < m_SubMeshes_size; s++) - { - m_SubMeshes.Add(new SubMesh()); - m_SubMeshes[s].firstByte = a_Stream.ReadUInt32(); - m_SubMeshes[s].indexCount = a_Stream.ReadUInt32(); //what is this in case of triangle strips? - m_SubMeshes[s].topology = a_Stream.ReadInt32(); //isTriStrip - if (version[0] < 4) - { - m_SubMeshes[s].triangleCount = a_Stream.ReadUInt32(); - } - if (version[0] >= 3) - { - m_SubMeshes[s].firstVertex = a_Stream.ReadUInt32(); - m_SubMeshes[s].vertexCount = a_Stream.ReadUInt32(); - a_Stream.Position += 24; //Axis-Aligned Bounding Box - } - } - #endregion - - #region BlendShapeData for 4.1.0 to 4.2.x, excluding 4.1.0 alpha - if (version[0] == 4 && ((version[1] == 1 && MeshPD.sourceFile.buildType[0] != "a") || - (version[1] > 1 && version[1] <= 2))) - { - int m_Shapes_size = a_Stream.ReadInt32(); - if (m_Shapes_size > 0) - { - //bool stop = true; - } - for (int s = 0; s < m_Shapes_size; s++) //untested - { - string shape_name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - a_Stream.Position += 36; //uint firstVertex, vertexCount; Vector3f aabbMinDelta, aabbMaxDelta; bool hasNormals, hasTangents + m_Use16BitIndices = a_Stream.ReadBoolean(); + a_Stream.Position += 3; } - int m_ShapeVertices_size = a_Stream.ReadInt32(); - a_Stream.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index - } - #endregion - #region BlendShapeData and BindPose for 4.3.0 and later - else if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3)) - { - int m_ShapeVertices_size = a_Stream.ReadInt32(); - if (m_ShapeVertices_size > 0) - { - //bool stop = true; - } - a_Stream.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index - - int shapes_size = a_Stream.ReadInt32(); - a_Stream.Position += shapes_size * 12; //uint firstVertex, vertexCount; bool hasNormals, hasTangents - - int channels_size = a_Stream.ReadInt32(); - for (int c = 0; c < channels_size; c++) - { - string channel_name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - a_Stream.Position += 12; //uint nameHash; int frameIndex, frameCount - } - - int fullWeights_size = a_Stream.ReadInt32(); - a_Stream.Position += fullWeights_size * 4; //floats - - m_BindPose = new float[a_Stream.ReadInt32()][,]; - for (int i = 0; i < m_BindPose.Length; i++) - { - m_BindPose[i] = new float[4,4] { - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; - } - - int m_BoneNameHashes_size = a_Stream.ReadInt32(); - a_Stream.Position += m_BoneNameHashes_size * 4; //uints - - uint m_RootBoneNameHash = a_Stream.ReadUInt32(); - } - #endregion - - #region Index Buffer for 2.6.0 and later - if (version[0] >= 3 || (version[0] == 2 && version[1] >= 6)) - { - m_MeshCompression = a_Stream.ReadByte(); - if (version[0] >= 4) - { - if (version[0] < 5) { uint m_StreamCompression = a_Stream.ReadByte(); } - bool m_IsReadable = a_Stream.ReadBoolean(); - bool m_KeepVertices = a_Stream.ReadBoolean(); - bool m_KeepIndices = a_Stream.ReadBoolean(); - } - a_Stream.AlignStream(4); - - int m_IndexBuffer_size = a_Stream.ReadInt32(); - - if (m_Use16BitIndices) - { - m_IndexBuffer = new uint[m_IndexBuffer_size / 2]; - for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt16(); } - a_Stream.AlignStream(4); - } - else - { - m_IndexBuffer = new uint[m_IndexBuffer_size / 4]; - for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt32(); } - a_Stream.AlignStream(4);//untested - } - } - #endregion - - #region Vertex Buffer for 3.4.2 and earlier - if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) - { - m_VertexCount = a_Stream.ReadInt32(); - m_Vertices = new float[m_VertexCount * 3]; - for (int v = 0; v < m_VertexCount * 3; v++) { m_Vertices[v] = a_Stream.ReadSingle(); } - - m_Skin = new List[a_Stream.ReadInt32()]; - //m_Skin = new Dictionary[a_Stream.ReadInt32()]; - for (int s = 0; s < m_Skin.Length; s++) - { - m_Skin[s] = new List(); - for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = a_Stream.ReadSingle() }); } - for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = a_Stream.ReadInt32(); } - - /*m_Skin[s] = new Dictionary(); - float[] weights = new float[4] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; - for (int i = 0; i < 4; i++) - { - int boneIndex = a_Stream.ReadInt32(); - m_Skin[s][boneIndex] = weights[i]; - }*/ - } - - m_BindPose = new float[a_Stream.ReadInt32()][,]; - for (int i = 0; i < m_BindPose.Length; i++) - { - m_BindPose[i] = new float[4, 4] { - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; - } - - int m_UV1_size = a_Stream.ReadInt32(); - m_UV1 = new float[m_UV1_size * 2]; - for (int v = 0; v < m_UV1_size * 2; v++) { m_UV1[v] = a_Stream.ReadSingle(); } - - int m_UV2_size = a_Stream.ReadInt32(); - m_UV2 = new float[m_UV2_size * 2]; - for (int v = 0; v < m_UV2_size * 2; v++) { m_UV2[v] = a_Stream.ReadSingle(); } - + #region Index Buffer for 2.5.1 and earlier if (version[0] == 2 && version[1] <= 5) { - int m_TangentSpace_size = a_Stream.ReadInt32(); - m_Normals = new float[m_TangentSpace_size * 3]; - for (int v = 0; v < m_TangentSpace_size; v++) + int m_IndexBuffer_size = a_Stream.ReadInt32(); + + if (m_Use16BitIndices) { - m_Normals[v * 3] = a_Stream.ReadSingle(); - m_Normals[v * 3 + 1] = a_Stream.ReadSingle(); - m_Normals[v * 3 + 2] = a_Stream.ReadSingle(); - a_Stream.Position += 16; //Vector3f tangent & float handedness + m_IndexBuffer = new uint[m_IndexBuffer_size / 2]; + for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt16(); } + a_Stream.AlignStream(4); + } + else + { + m_IndexBuffer = new uint[m_IndexBuffer_size / 4]; + for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt32(); } } } - else //2.6.0 and later - { - int m_Tangents_size = a_Stream.ReadInt32(); - a_Stream.Position += m_Tangents_size * 16; //Vector4f + #endregion - int m_Normals_size = a_Stream.ReadInt32(); - m_Normals = new float[m_Normals_size * 3]; - for (int v = 0; v < m_Normals_size * 3; v++) { m_Normals[v] = a_Stream.ReadSingle(); } - } - } - #endregion - #region Vertex Buffer for 3.5.0 and later - else - { - #region read vertex stream - m_Skin = new List[a_Stream.ReadInt32()]; - //m_Skin = new Dictionary[a_Stream.ReadInt32()]; - for (int s = 0; s < m_Skin.Length; s++) + #region subMeshes + int m_SubMeshes_size = a_Stream.ReadInt32(); + for (int s = 0; s < m_SubMeshes_size; s++) { - m_Skin[s] = new List(); - for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = a_Stream.ReadSingle() }); } - for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = a_Stream.ReadInt32(); } - - /*m_Skin[s] = new Dictionary(); - float[] weights = new float[4] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; - for (int i = 0; i < 4; i++) + m_SubMeshes.Add(new SubMesh()); + m_SubMeshes[s].firstByte = a_Stream.ReadUInt32(); + m_SubMeshes[s].indexCount = a_Stream.ReadUInt32(); //what is this in case of triangle strips? + m_SubMeshes[s].topology = a_Stream.ReadInt32(); //isTriStrip + if (version[0] < 4) { - int boneIndex = a_Stream.ReadInt32(); - m_Skin[s][boneIndex] = weights[i]; - }*/ + m_SubMeshes[s].triangleCount = a_Stream.ReadUInt32(); + } + if (version[0] >= 3) + { + m_SubMeshes[s].firstVertex = a_Stream.ReadUInt32(); + m_SubMeshes[s].vertexCount = a_Stream.ReadUInt32(); + a_Stream.Position += 24; //Axis-Aligned Bounding Box + } } + #endregion - - if (version[0] == 3 || (version[0] == 4 && version[1] <= 2)) + #region BlendShapeData for 4.1.0 to 4.2.x, excluding 4.1.0 alpha + if (version[0] == 4 && ((version[1] == 1 && MeshPD.sourceFile.buildType[0] != "a") || + (version[1] > 1 && version[1] <= 2))) { + int m_Shapes_size = a_Stream.ReadInt32(); + if (m_Shapes_size > 0) + { + //bool stop = true; + } + for (int s = 0; s < m_Shapes_size; s++) //untested + { + string shape_name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + a_Stream.Position += 36; //uint firstVertex, vertexCount; Vector3f aabbMinDelta, aabbMaxDelta; bool hasNormals, hasTangents + } + + int m_ShapeVertices_size = a_Stream.ReadInt32(); + a_Stream.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index + } + #endregion + #region BlendShapeData and BindPose for 4.3.0 and later + else if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3)) + { + int m_ShapeVertices_size = a_Stream.ReadInt32(); + if (m_ShapeVertices_size > 0) + { + //bool stop = true; + } + a_Stream.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index + + int shapes_size = a_Stream.ReadInt32(); + a_Stream.Position += shapes_size * 12; //uint firstVertex, vertexCount; bool hasNormals, hasTangents + + int channels_size = a_Stream.ReadInt32(); + for (int c = 0; c < channels_size; c++) + { + string channel_name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + a_Stream.Position += 12; //uint nameHash; int frameIndex, frameCount + } + + int fullWeights_size = a_Stream.ReadInt32(); + a_Stream.Position += fullWeights_size * 4; //floats + m_BindPose = new float[a_Stream.ReadInt32()][,]; for (int i = 0; i < m_BindPose.Length; i++) { @@ -579,149 +446,362 @@ namespace Unity_Studio { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; } + + int m_BoneNameHashes_size = a_Stream.ReadInt32(); + a_Stream.Position += m_BoneNameHashes_size * 4; //uints + + uint m_RootBoneNameHash = a_Stream.ReadUInt32(); } + #endregion - BitArray m_CurrentChannels = new BitArray(new int[1] { a_Stream.ReadInt32() }); - m_VertexCount = a_Stream.ReadInt32(); - //int singleStreamStride = 0;//used tor unity 5 - int streamCount = 0; - - #region streams for 3.5.0 - 3.5.7 - if (version[0] < 4) + #region Index Buffer for 2.6.0 and later + if (version[0] >= 3 || (version[0] == 2 && version[1] >= 6)) { - if (m_MeshCompression != 0 && version[2] == 0) //special case not just on platform 9 + m_MeshCompression = a_Stream.ReadByte(); + if (version[0] >= 4) { - a_Stream.Position += 12; + if (version[0] < 5) { uint m_StreamCompression = a_Stream.ReadByte(); } + bool m_IsReadable = a_Stream.ReadBoolean(); + bool m_KeepVertices = a_Stream.ReadBoolean(); + bool m_KeepIndices = a_Stream.ReadBoolean(); + } + a_Stream.AlignStream(4); + + int m_IndexBuffer_size = a_Stream.ReadInt32(); + + if (m_Use16BitIndices) + { + m_IndexBuffer = new uint[m_IndexBuffer_size / 2]; + for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt16(); } + a_Stream.AlignStream(4); } else { - m_Streams = new StreamInfo[4]; - for (int s = 0; s < 4; s++) - { - m_Streams[s] = new StreamInfo(); - m_Streams[s].channelMask = new BitArray(new int[1] { a_Stream.ReadInt32() }); - m_Streams[s].offset = a_Stream.ReadInt32(); - m_Streams[s].stride = a_Stream.ReadInt32(); - m_Streams[s].align = a_Stream.ReadUInt32(); - } + m_IndexBuffer = new uint[m_IndexBuffer_size / 4]; + for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt32(); } + a_Stream.AlignStream(4);//untested } } #endregion - #region channels and streams for 4.0.0 and later + + #region Vertex Buffer for 3.4.2 and earlier + if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) + { + m_VertexCount = a_Stream.ReadInt32(); + m_Vertices = new float[m_VertexCount * 3]; + for (int v = 0; v < m_VertexCount * 3; v++) { m_Vertices[v] = a_Stream.ReadSingle(); } + + m_Skin = new List[a_Stream.ReadInt32()]; + //m_Skin = new Dictionary[a_Stream.ReadInt32()]; + for (int s = 0; s < m_Skin.Length; s++) + { + m_Skin[s] = new List(); + for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = a_Stream.ReadSingle() }); } + for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = a_Stream.ReadInt32(); } + + /*m_Skin[s] = new Dictionary(); + float[] weights = new float[4] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; + for (int i = 0; i < 4; i++) + { + int boneIndex = a_Stream.ReadInt32(); + m_Skin[s][boneIndex] = weights[i]; + }*/ + } + + m_BindPose = new float[a_Stream.ReadInt32()][,]; + for (int i = 0; i < m_BindPose.Length; i++) + { + m_BindPose[i] = new float[4, 4] { + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; + } + + int m_UV1_size = a_Stream.ReadInt32(); + m_UV1 = new float[m_UV1_size * 2]; + for (int v = 0; v < m_UV1_size * 2; v++) { m_UV1[v] = a_Stream.ReadSingle(); } + + int m_UV2_size = a_Stream.ReadInt32(); + m_UV2 = new float[m_UV2_size * 2]; + for (int v = 0; v < m_UV2_size * 2; v++) { m_UV2[v] = a_Stream.ReadSingle(); } + + if (version[0] == 2 && version[1] <= 5) + { + int m_TangentSpace_size = a_Stream.ReadInt32(); + m_Normals = new float[m_TangentSpace_size * 3]; + for (int v = 0; v < m_TangentSpace_size; v++) + { + m_Normals[v * 3] = a_Stream.ReadSingle(); + m_Normals[v * 3 + 1] = a_Stream.ReadSingle(); + m_Normals[v * 3 + 2] = a_Stream.ReadSingle(); + a_Stream.Position += 16; //Vector3f tangent & float handedness + } + } + else //2.6.0 and later + { + int m_Tangents_size = a_Stream.ReadInt32(); + a_Stream.Position += m_Tangents_size * 16; //Vector4f + + int m_Normals_size = a_Stream.ReadInt32(); + m_Normals = new float[m_Normals_size * 3]; + for (int v = 0; v < m_Normals_size * 3; v++) { m_Normals[v] = a_Stream.ReadSingle(); } + } + } + #endregion + #region Vertex Buffer for 3.5.0 and later else { - m_Channels = new ChannelInfo[a_Stream.ReadInt32()]; - for (int c = 0; c < m_Channels.Length; c++) + #region read vertex stream + m_Skin = new List[a_Stream.ReadInt32()]; + //m_Skin = new Dictionary[a_Stream.ReadInt32()]; + for (int s = 0; s < m_Skin.Length; s++) { - m_Channels[c] = new ChannelInfo(); - m_Channels[c].stream = a_Stream.ReadByte(); - m_Channels[c].offset = a_Stream.ReadByte(); - m_Channels[c].format = a_Stream.ReadByte(); - m_Channels[c].dimension = a_Stream.ReadByte(); + m_Skin[s] = new List(); + for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = a_Stream.ReadSingle() }); } + for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = a_Stream.ReadInt32(); } - //calculate stride for Unity 5 - //singleStreamStride += m_Channels[c].dimension * (4 / (int)Math.Pow(2, m_Channels[c].format)); - - if (m_Channels[c].stream >= streamCount) { streamCount = m_Channels[c].stream + 1; } + /*m_Skin[s] = new Dictionary(); + float[] weights = new float[4] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; + for (int i = 0; i < 4; i++) + { + int boneIndex = a_Stream.ReadInt32(); + m_Skin[s][boneIndex] = weights[i]; + }*/ } - if (version[0] < 5) + + if (version[0] == 3 || (version[0] == 4 && version[1] <= 2)) { - m_Streams = new StreamInfo[a_Stream.ReadInt32()]; - for (int s = 0; s < m_Streams.Length; s++) + m_BindPose = new float[a_Stream.ReadInt32()][,]; + for (int i = 0; i < m_BindPose.Length; i++) + { + m_BindPose[i] = new float[4, 4] { + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, + { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; + } + } + + BitArray m_CurrentChannels = new BitArray(new int[1] { a_Stream.ReadInt32() }); + m_VertexCount = a_Stream.ReadInt32(); + //int singleStreamStride = 0;//used tor unity 5 + int streamCount = 0; + + #region streams for 3.5.0 - 3.5.7 + if (version[0] < 4) + { + if (m_MeshCompression != 0 && version[2] == 0) //special case not just on platform 9 + { + a_Stream.Position += 12; + } + else + { + m_Streams = new StreamInfo[4]; + for (int s = 0; s < 4; s++) + { + m_Streams[s] = new StreamInfo(); + m_Streams[s].channelMask = new BitArray(new int[1] { a_Stream.ReadInt32() }); + m_Streams[s].offset = a_Stream.ReadInt32(); + m_Streams[s].stride = a_Stream.ReadInt32(); + m_Streams[s].align = a_Stream.ReadUInt32(); + } + } + } + #endregion + #region channels and streams for 4.0.0 and later + else + { + m_Channels = new ChannelInfo[a_Stream.ReadInt32()]; + for (int c = 0; c < m_Channels.Length; c++) + { + m_Channels[c] = new ChannelInfo(); + m_Channels[c].stream = a_Stream.ReadByte(); + m_Channels[c].offset = a_Stream.ReadByte(); + m_Channels[c].format = a_Stream.ReadByte(); + m_Channels[c].dimension = a_Stream.ReadByte(); + + //calculate stride for Unity 5 + //singleStreamStride += m_Channels[c].dimension * (4 / (int)Math.Pow(2, m_Channels[c].format)); + + if (m_Channels[c].stream >= streamCount) { streamCount = m_Channels[c].stream + 1; } + } + + if (version[0] < 5) + { + m_Streams = new StreamInfo[a_Stream.ReadInt32()]; + for (int s = 0; s < m_Streams.Length; s++) + { + m_Streams[s] = new StreamInfo(); + m_Streams[s].channelMask = new BitArray(new int[1] { a_Stream.ReadInt32() }); + m_Streams[s].offset = a_Stream.ReadInt32(); + m_Streams[s].stride = a_Stream.ReadByte(); + m_Streams[s].dividerOp = a_Stream.ReadByte(); + m_Streams[s].frequency = a_Stream.ReadUInt16(); + } + } + } + #endregion + + //actual Vertex Buffer + byte[] m_DataSize = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_DataSize, 0, m_DataSize.Length); + + if (version[0] >= 5) //create streams + { + m_Streams = new StreamInfo[streamCount]; + for (int s = 0; s < streamCount; s++) { m_Streams[s] = new StreamInfo(); - m_Streams[s].channelMask = new BitArray(new int[1] { a_Stream.ReadInt32() }); - m_Streams[s].offset = a_Stream.ReadInt32(); - m_Streams[s].stride = a_Stream.ReadByte(); - m_Streams[s].dividerOp = a_Stream.ReadByte(); - m_Streams[s].frequency = a_Stream.ReadUInt16(); - } - } - } - #endregion + m_Streams[s].channelMask = new BitArray(new int[1] { 0 }); + m_Streams[s].offset = 0; + m_Streams[s].stride = 0; - //actual Vertex Buffer - byte[] m_DataSize = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_DataSize, 0, m_DataSize.Length); - - if (version[0] >= 5) //create streams - { - m_Streams = new StreamInfo[streamCount]; - for (int s = 0; s < streamCount; s++) - { - m_Streams[s] = new StreamInfo(); - m_Streams[s].channelMask = new BitArray(new int[1] { 0 }); - m_Streams[s].offset = 0; - m_Streams[s].stride = 0; - - foreach (var m_Channel in m_Channels) - { - if (m_Channel.stream == s) { m_Streams[s].stride += m_Channel.dimension * (4 / (int)Math.Pow(2, m_Channel.format)); } - } - - if (s > 0) - { - m_Streams[s].offset = m_Streams[s - 1].offset + m_Streams[s - 1].stride * m_VertexCount; - //sometimes there are 8 bytes between streams - //this is NOT an alignment, even if sometimes it may seem so - - if (streamCount == 2) { m_Streams[s].offset = m_DataSize.Length - m_Streams[s].stride * m_VertexCount; } - else + foreach (var m_Channel in m_Channels) { - m_VertexCount = 0; - return; + if (m_Channel.stream == s) { m_Streams[s].stride += m_Channel.dimension * (4 / (int)Math.Pow(2, m_Channel.format)); } } - /*var absoluteOffset = a_Stream.Position + 4 + m_Streams[s].offset; - if ((absoluteOffset % m_Streams[s].stride) != 0) + if (s > 0) { - m_Streams[s].offset += m_Streams[s].stride - (int)(absoluteOffset % m_Streams[s].stride); - }*/ + m_Streams[s].offset = m_Streams[s - 1].offset + m_Streams[s - 1].stride * m_VertexCount; + //sometimes there are 8 bytes between streams + //this is NOT an alignment, even if sometimes it may seem so + + if (streamCount == 2) { m_Streams[s].offset = m_DataSize.Length - m_Streams[s].stride * m_VertexCount; } + else + { + m_VertexCount = 0; + return; + } + + /*var absoluteOffset = a_Stream.Position + 4 + m_Streams[s].offset; + if ((absoluteOffset % m_Streams[s].stride) != 0) + { + m_Streams[s].offset += m_Streams[s].stride - (int)(absoluteOffset % m_Streams[s].stride); + }*/ + } } } - } - #endregion + #endregion - #region compute FvF - int componentByteSize = 0; - byte[] componentBytes; - float[] componentsArray; + #region compute FvF + int componentByteSize = 0; + byte[] componentBytes; + float[] componentsArray; - #region 4.0.0 and later - if (m_Channels != null) - { - //it is better to loop channels instead of streams - //because channels are likely to be sorted by vertex property - foreach (var m_Channel in m_Channels) + #region 4.0.0 and later + if (m_Channels != null) { - if (m_Channel.dimension > 0) + //it is better to loop channels instead of streams + //because channels are likely to be sorted by vertex property + foreach (var m_Channel in m_Channels) { - var m_Stream = m_Streams[m_Channel.stream]; - - for (int b = 0; b < 8; b++) + if (m_Channel.dimension > 0) { - //in the future, try to use only m_CurrentChannels - if ((version[0] < 5 && m_Stream.channelMask.Get(b)) || (version[0] >= 5 && m_CurrentChannels.Get(b))) + var m_Stream = m_Streams[m_Channel.stream]; + + for (int b = 0; b < 8; b++) { - // in Unity 4.x the colors channel has 1 dimension, as in 1 color with 4 components - if (b == 2 && m_Channel.format == 2) { m_Channel.dimension = 4; } - - componentByteSize = 4 / (int)Math.Pow(2, m_Channel.format); - - /*switch (m_Channel.format) + //in the future, try to use only m_CurrentChannels + if ((version[0] < 5 && m_Stream.channelMask.Get(b)) || (version[0] >= 5 && m_CurrentChannels.Get(b))) { - case 0: //32bit - valueBufferSize = 4; + // in Unity 4.x the colors channel has 1 dimension, as in 1 color with 4 components + if (b == 2 && m_Channel.format == 2) { m_Channel.dimension = 4; } + + componentByteSize = 4 / (int)Math.Pow(2, m_Channel.format); + + /*switch (m_Channel.format) + { + case 0: //32bit + valueBufferSize = 4; + break; + case 1: //16bit + valueBufferSize = 2; + break; + case 2: //8bit + valueBufferSize = 1; + m_Channel.dimension = 4;//in older versions this is 1, as in 1 color with 4 components + break; + }*/ + + componentBytes = new byte[componentByteSize]; + componentsArray = new float[m_VertexCount * m_Channel.dimension]; + + for (int v = 0; v < m_VertexCount; v++) + { + int vertexOffset = m_Stream.offset + m_Channel.offset + m_Stream.stride * v; + for (int d = 0; d < m_Channel.dimension; d++) + { + int componentOffset = vertexOffset + componentByteSize * d; + Buffer.BlockCopy(m_DataSize, componentOffset, componentBytes, 0, componentByteSize); + componentsArray[v * m_Channel.dimension + d] = bytesToFloat(componentBytes); + } + } + + switch (b) + { + case 0: m_Vertices = componentsArray; break; + case 1: m_Normals = componentsArray; break; + case 2: m_Colors = componentsArray; break; + case 3: m_UV1 = componentsArray; break; + case 4: m_UV2 = componentsArray; break; + case 5: + if (version[0] == 5) { m_UV3 = componentsArray; } + else { m_Tangents = componentsArray; } + break; + case 6: m_UV4 = componentsArray; break; + case 7: m_Tangents = componentsArray; break; + } + + m_Stream.channelMask.Set(b, false); + m_CurrentChannels.Set(b, false); + componentBytes = null; + componentsArray = null; + break; //go to next channel + } + } + } + } + } + #endregion + #region 3.5.0 - 3.5.7 + else if (m_Streams != null) + { + foreach (var m_Stream in m_Streams) + { + //a stream may have multiple vertex components but without channels there are no offsets, so I assume all vertex properties are in order + //Unity 3.5.x only uses floats, and that's probably why channels were introduced in Unity 4 + + ChannelInfo m_Channel = new ChannelInfo();//create my own channel so I can use the same methods + m_Channel.offset = 0; + + for (int b = 0; b < 6; b++) + { + if (m_Stream.channelMask.Get(b)) + { + switch (b) + { + case 0: + case 1: + componentByteSize = 4; + m_Channel.dimension = 3; break; - case 1: //16bit - valueBufferSize = 2; + case 2: + componentByteSize = 1; + m_Channel.dimension = 4; break; - case 2: //8bit - valueBufferSize = 1; - m_Channel.dimension = 4;//in older versions this is 1, as in 1 color with 4 components + case 3: + case 4: + componentByteSize = 4; + m_Channel.dimension = 2; break; - }*/ + case 5: + componentByteSize = 4; + m_Channel.dimension = 4; + break; + } componentBytes = new byte[componentByteSize]; componentsArray = new float[m_VertexCount * m_Channel.dimension]; @@ -731,8 +811,8 @@ namespace Unity_Studio int vertexOffset = m_Stream.offset + m_Channel.offset + m_Stream.stride * v; for (int d = 0; d < m_Channel.dimension; d++) { - int componentOffset = vertexOffset + componentByteSize * d; - Buffer.BlockCopy(m_DataSize, componentOffset, componentBytes, 0, componentByteSize); + int m_DataSizeOffset = vertexOffset + componentByteSize * d; + Buffer.BlockCopy(m_DataSize, m_DataSizeOffset, componentBytes, 0, componentByteSize); componentsArray[v * m_Channel.dimension + d] = bytesToFloat(componentBytes); } } @@ -744,479 +824,412 @@ namespace Unity_Studio case 2: m_Colors = componentsArray; break; case 3: m_UV1 = componentsArray; break; case 4: m_UV2 = componentsArray; break; - case 5: - if (version[0] == 5) { m_UV3 = componentsArray; } - else { m_Tangents = componentsArray; } - break; - case 6: m_UV4 = componentsArray; break; - case 7: m_Tangents = componentsArray; break; + case 5: m_Tangents = componentsArray; break; } + m_Channel.offset += (byte)(m_Channel.dimension * componentByteSize); //safe to cast as byte because strides larger than 255 are unlikely m_Stream.channelMask.Set(b, false); - m_CurrentChannels.Set(b, false); componentBytes = null; componentsArray = null; - break; //go to next channel } } } } + #endregion + #endregion } #endregion - #region 3.5.0 - 3.5.7 - else if (m_Streams != null) + + #region Compressed Mesh data for 2.6.0 and later - 160 bytes + if (version[0] >= 3 || (version[0] == 2 && version[1] >= 6)) { - foreach (var m_Stream in m_Streams) + //remember there can be combinations of packed and regular vertex properties + + #region m_Vertices + PackedBitVector m_Vertices_Packed = new PackedBitVector(); + m_Vertices_Packed.m_NumItems = a_Stream.ReadInt32(); + m_Vertices_Packed.m_Range = a_Stream.ReadSingle(); + m_Vertices_Packed.m_Start = a_Stream.ReadSingle(); + m_Vertices_Packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_Vertices_Packed.m_Data, 0, m_Vertices_Packed.m_Data.Length); + a_Stream.AlignStream(4); + m_Vertices_Packed.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + if (m_Vertices_Packed.m_NumItems > 0) { - //a stream may have multiple vertex components but without channels there are no offsets, so I assume all vertex properties are in order - //Unity 3.5.x only uses floats, and that's probably why channels were introduced in Unity 4 - - ChannelInfo m_Channel = new ChannelInfo();//create my own channel so I can use the same methods - m_Channel.offset = 0; - - for (int b = 0; b < 6; b++) + m_VertexCount = m_Vertices_Packed.m_NumItems / 3; + uint[] m_Vertices_Unpacked = UnpackBitVector(m_Vertices_Packed); + int bitmax = 0;//used to convert int value to float + for (int b = 0; b < m_Vertices_Packed.m_BitSize; b++) { bitmax |= (1 << b); } + m_Vertices = new float[m_Vertices_Packed.m_NumItems]; + for (int v = 0; v < m_Vertices_Packed.m_NumItems; v++) { - if (m_Stream.channelMask.Get(b)) - { - switch (b) - { - case 0: - case 1: - componentByteSize = 4; - m_Channel.dimension = 3; - break; - case 2: - componentByteSize = 1; - m_Channel.dimension = 4; - break; - case 3: - case 4: - componentByteSize = 4; - m_Channel.dimension = 2; - break; - case 5: - componentByteSize = 4; - m_Channel.dimension = 4; - break; - } - - componentBytes = new byte[componentByteSize]; - componentsArray = new float[m_VertexCount * m_Channel.dimension]; - - for (int v = 0; v < m_VertexCount; v++) - { - int vertexOffset = m_Stream.offset + m_Channel.offset + m_Stream.stride * v; - for (int d = 0; d < m_Channel.dimension; d++) - { - int m_DataSizeOffset = vertexOffset + componentByteSize * d; - Buffer.BlockCopy(m_DataSize, m_DataSizeOffset, componentBytes, 0, componentByteSize); - componentsArray[v * m_Channel.dimension + d] = bytesToFloat(componentBytes); - } - } - - switch (b) - { - case 0: m_Vertices = componentsArray; break; - case 1: m_Normals = componentsArray; break; - case 2: m_Colors = componentsArray; break; - case 3: m_UV1 = componentsArray; break; - case 4: m_UV2 = componentsArray; break; - case 5: m_Tangents = componentsArray; break; - } - - m_Channel.offset += (byte)(m_Channel.dimension * componentByteSize); //safe to cast as byte because strides larger than 255 are unlikely - m_Stream.channelMask.Set(b, false); - componentBytes = null; - componentsArray = null; - } + m_Vertices[v] = (float)((double)m_Vertices_Unpacked[v] / bitmax) * m_Vertices_Packed.m_Range + m_Vertices_Packed.m_Start; } } - } - #endregion - #endregion - } - #endregion + #endregion - #region Compressed Mesh data for 2.6.0 and later - 160 bytes - if (version[0] >= 3 || (version[0] == 2 && version[1] >= 6)) - { - //remember there can be combinations of packed and regular vertex properties + #region m_UV + PackedBitVector m_UV_Packed = new PackedBitVector(); //contains all channels + m_UV_Packed.m_NumItems = a_Stream.ReadInt32(); + m_UV_Packed.m_Range = a_Stream.ReadSingle(); + m_UV_Packed.m_Start = a_Stream.ReadSingle(); + m_UV_Packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_UV_Packed.m_Data, 0, m_UV_Packed.m_Data.Length); + a_Stream.AlignStream(4); + m_UV_Packed.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment - #region m_Vertices - PackedBitVector m_Vertices_Packed = new PackedBitVector(); - m_Vertices_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Vertices_Packed.m_Range = a_Stream.ReadSingle(); - m_Vertices_Packed.m_Start = a_Stream.ReadSingle(); - m_Vertices_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Vertices_Packed.m_Data, 0, m_Vertices_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Vertices_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - if (m_Vertices_Packed.m_NumItems > 0) - { - m_VertexCount = m_Vertices_Packed.m_NumItems / 3; - uint[] m_Vertices_Unpacked = UnpackBitVector(m_Vertices_Packed); - int bitmax = 0;//used to convert int value to float - for (int b = 0; b < m_Vertices_Packed.m_BitSize; b++) { bitmax |= (1 << b); } - m_Vertices = new float[m_Vertices_Packed.m_NumItems]; - for (int v = 0; v < m_Vertices_Packed.m_NumItems; v++) + if (m_UV_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportUVs"]) { - m_Vertices[v] = (float)((double)m_Vertices_Unpacked[v] / bitmax) * m_Vertices_Packed.m_Range + m_Vertices_Packed.m_Start; - } - } - #endregion + uint[] m_UV_Unpacked = UnpackBitVector(m_UV_Packed); + int bitmax = 0; + for (int b = 0; b < m_UV_Packed.m_BitSize; b++) { bitmax |= (1 << b); } - #region m_UV - PackedBitVector m_UV_Packed = new PackedBitVector(); //contains all channels - m_UV_Packed.m_NumItems = a_Stream.ReadInt32(); - m_UV_Packed.m_Range = a_Stream.ReadSingle(); - m_UV_Packed.m_Start = a_Stream.ReadSingle(); - m_UV_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_UV_Packed.m_Data, 0, m_UV_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_UV_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_UV1 = new float[m_VertexCount * 2]; - if (m_UV_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportUVs"]) - { - uint[] m_UV_Unpacked = UnpackBitVector(m_UV_Packed); - int bitmax = 0; - for (int b = 0; b < m_UV_Packed.m_BitSize; b++) { bitmax |= (1 << b); } - - m_UV1 = new float[m_VertexCount * 2]; - - for (int v = 0; v < m_VertexCount * 2; v++) - { - m_UV1[v] = (float)((double)m_UV_Unpacked[v] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; - } - - if (m_UV_Packed.m_NumItems >= m_VertexCount * 4) - { - m_UV2 = new float[m_VertexCount * 2]; - for (uint v = 0; v < m_VertexCount * 2; v++) + for (int v = 0; v < m_VertexCount * 2; v++) { - m_UV2[v] = (float)((double)m_UV_Unpacked[v + m_VertexCount * 2] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; + m_UV1[v] = (float)((double)m_UV_Unpacked[v] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; } - if (m_UV_Packed.m_NumItems >= m_VertexCount * 6) + if (m_UV_Packed.m_NumItems >= m_VertexCount * 4) { - m_UV3 = new float[m_VertexCount * 2]; + m_UV2 = new float[m_VertexCount * 2]; for (uint v = 0; v < m_VertexCount * 2; v++) { - m_UV3[v] = (float)((double)m_UV_Unpacked[v + m_VertexCount * 4] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; + m_UV2[v] = (float)((double)m_UV_Unpacked[v + m_VertexCount * 2] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; } - if (m_UV_Packed.m_NumItems == m_VertexCount * 8) + if (m_UV_Packed.m_NumItems >= m_VertexCount * 6) { - m_UV4 = new float[m_VertexCount * 2]; + m_UV3 = new float[m_VertexCount * 2]; for (uint v = 0; v < m_VertexCount * 2; v++) { - m_UV4[v] = (float)((double)m_UV_Unpacked[v + m_VertexCount * 6] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; + m_UV3[v] = (float)((double)m_UV_Unpacked[v + m_VertexCount * 4] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; + } + + if (m_UV_Packed.m_NumItems == m_VertexCount * 8) + { + m_UV4 = new float[m_VertexCount * 2]; + for (uint v = 0; v < m_VertexCount * 2; v++) + { + m_UV4[v] = (float)((double)m_UV_Unpacked[v + m_VertexCount * 6] / bitmax) * m_UV_Packed.m_Range + m_UV_Packed.m_Start; + } } } } } - } - #endregion + #endregion - #region m_BindPose - if (version[0] < 5) - { - PackedBitVector m_BindPoses_Packed = new PackedBitVector(); - m_BindPoses_Packed.m_NumItems = a_Stream.ReadInt32(); - m_BindPoses_Packed.m_Range = a_Stream.ReadSingle(); - m_BindPoses_Packed.m_Start = a_Stream.ReadSingle(); - m_BindPoses_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_BindPoses_Packed.m_Data, 0, m_BindPoses_Packed.m_Data.Length); + #region m_BindPose + if (version[0] < 5) + { + PackedBitVector m_BindPoses_Packed = new PackedBitVector(); + m_BindPoses_Packed.m_NumItems = a_Stream.ReadInt32(); + m_BindPoses_Packed.m_Range = a_Stream.ReadSingle(); + m_BindPoses_Packed.m_Start = a_Stream.ReadSingle(); + m_BindPoses_Packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_BindPoses_Packed.m_Data, 0, m_BindPoses_Packed.m_Data.Length); + a_Stream.AlignStream(4); + m_BindPoses_Packed.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + if (m_BindPoses_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportDeformers"]) + { + uint[] m_BindPoses_Unpacked = UnpackBitVector(m_BindPoses_Packed); + int bitmax = 0;//used to convert int value to float + for (int b = 0; b < m_BindPoses_Packed.m_BitSize; b++) { bitmax |= (1 << b); } + + m_BindPose = new float[m_BindPoses_Packed.m_NumItems / 16][,]; + + for (int i = 0; i < m_BindPose.Length; i++) + { + m_BindPose[i] = new float[4, 4]; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < 4; k++) + { + m_BindPose[i][j, k] = (float)((double)m_BindPoses_Unpacked[i * 16 + j * 4 + k] / bitmax) * m_BindPoses_Packed.m_Range + m_BindPoses_Packed.m_Start; + } + } + } + } + } + #endregion + + PackedBitVector m_Normals_Packed = new PackedBitVector(); + m_Normals_Packed.m_NumItems = a_Stream.ReadInt32(); + m_Normals_Packed.m_Range = a_Stream.ReadSingle(); + m_Normals_Packed.m_Start = a_Stream.ReadSingle(); + m_Normals_Packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_Normals_Packed.m_Data, 0, m_Normals_Packed.m_Data.Length); a_Stream.AlignStream(4); - m_BindPoses_Packed.m_BitSize = a_Stream.ReadByte(); + m_Normals_Packed.m_BitSize = a_Stream.ReadByte(); a_Stream.Position += 3; //4 byte alignment - if (m_BindPoses_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportDeformers"]) - { - uint[] m_BindPoses_Unpacked = UnpackBitVector(m_BindPoses_Packed); - int bitmax = 0;//used to convert int value to float - for (int b = 0; b < m_BindPoses_Packed.m_BitSize; b++) { bitmax |= (1 << b); } - - m_BindPose = new float[m_BindPoses_Packed.m_NumItems / 16][,]; + PackedBitVector m_Tangents_Packed = new PackedBitVector(); + m_Tangents_Packed.m_NumItems = a_Stream.ReadInt32(); + m_Tangents_Packed.m_Range = a_Stream.ReadSingle(); + m_Tangents_Packed.m_Start = a_Stream.ReadSingle(); + m_Tangents_Packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_Tangents_Packed.m_Data, 0, m_Tangents_Packed.m_Data.Length); + a_Stream.AlignStream(4); + m_Tangents_Packed.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment - for (int i = 0; i < m_BindPose.Length; i++) + PackedBitVector m_Weights = new PackedBitVector(); + m_Weights.m_NumItems = a_Stream.ReadInt32(); + m_Weights.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_Weights.m_Data, 0, m_Weights.m_Data.Length); + a_Stream.AlignStream(4); + m_Weights.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + #region m_Normals + PackedBitVector m_NormalSigns_packed = new PackedBitVector(); + m_NormalSigns_packed.m_NumItems = a_Stream.ReadInt32(); + m_NormalSigns_packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_NormalSigns_packed.m_Data, 0, m_NormalSigns_packed.m_Data.Length); + a_Stream.AlignStream(4); + m_NormalSigns_packed.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + if (m_Normals_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportNormals"]) + { + uint[] m_Normals_Unpacked = UnpackBitVector(m_Normals_Packed); + uint[] m_NormalSigns = UnpackBitVector(m_NormalSigns_packed); + int bitmax = 0; + for (int b = 0; b < m_Normals_Packed.m_BitSize; b++) { bitmax |= (1 << b); } + m_Normals = new float[m_Normals_Packed.m_NumItems / 2 * 3]; + for (int v = 0; v < m_Normals_Packed.m_NumItems / 2; v++) { - m_BindPose[i] = new float[4, 4]; - for (int j = 0; j < 4; j++) + m_Normals[v * 3] = (float)((double)m_Normals_Unpacked[v * 2] / bitmax) * m_Normals_Packed.m_Range + m_Normals_Packed.m_Start; + m_Normals[v * 3 + 1] = (float)((double)m_Normals_Unpacked[v * 2 + 1] / bitmax) * m_Normals_Packed.m_Range + m_Normals_Packed.m_Start; + m_Normals[v * 3 + 2] = (float)Math.Sqrt(1 - m_Normals[v * 3] * m_Normals[v * 3] - m_Normals[v * 3 + 1] * m_Normals[v * 3 + 1]); + if (m_NormalSigns[v] == 0) { m_Normals[v * 3 + 2] *= -1; } + } + } + #endregion + + #region m_Tangents + PackedBitVector m_TangentSigns_packed = new PackedBitVector(); + m_TangentSigns_packed.m_NumItems = a_Stream.ReadInt32(); + m_TangentSigns_packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_TangentSigns_packed.m_Data, 0, m_TangentSigns_packed.m_Data.Length); + a_Stream.AlignStream(4); + m_TangentSigns_packed.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + if (m_Tangents_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportTangents"]) + { + uint[] m_Tangents_Unpacked = UnpackBitVector(m_Tangents_Packed); + uint[] m_TangentSigns = UnpackBitVector(m_TangentSigns_packed); + int bitmax = 0; + for (int b = 0; b < m_Tangents_Packed.m_BitSize; b++) { bitmax |= (1 << b); } + m_Tangents = new float[m_Tangents_Packed.m_NumItems / 2 * 3]; + for (int v = 0; v < m_Tangents_Packed.m_NumItems / 2; v++) + { + m_Tangents[v * 3] = (float)((double)m_Tangents_Unpacked[v * 2] / bitmax) * m_Tangents_Packed.m_Range + m_Tangents_Packed.m_Start; + m_Tangents[v * 3 + 1] = (float)((double)m_Tangents_Unpacked[v * 2 + 1] / bitmax) * m_Tangents_Packed.m_Range + m_Tangents_Packed.m_Start; + m_Tangents[v * 3 + 2] = (float)Math.Sqrt(1 - m_Tangents[v * 3] * m_Tangents[v * 3] - m_Tangents[v * 3 + 1] * m_Tangents[v * 3 + 1]); + if (m_TangentSigns[v] == 0) { m_Tangents[v * 3 + 2] *= -1; } + } + } + #endregion + + #region m_FloatColors + if (version[0] >= 5) + { + PackedBitVector m_FloatColors = new PackedBitVector(); + m_FloatColors.m_NumItems = a_Stream.ReadInt32(); + m_FloatColors.m_Range = a_Stream.ReadSingle(); + m_FloatColors.m_Start = a_Stream.ReadSingle(); + m_FloatColors.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_FloatColors.m_Data, 0, m_FloatColors.m_Data.Length); + a_Stream.AlignStream(4); + m_FloatColors.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + if (m_FloatColors.m_NumItems > 0 && (bool)Properties.Settings.Default["exportColors"]) + { + uint[] m_FloatColors_Unpacked = UnpackBitVector(m_FloatColors); + int bitmax = 0; + for (int b = 0; b < m_FloatColors.m_BitSize; b++) { bitmax |= (1 << b); } + + m_Colors = new float[m_FloatColors.m_NumItems]; + + for (int v = 0; v < m_FloatColors.m_NumItems; v++) { - for (int k = 0; k < 4; k++) + m_Colors[v] = (float)m_FloatColors_Unpacked[v] / bitmax * m_FloatColors.m_Range + m_FloatColors.m_Start; + } + } + } + #endregion + + #region m_Skin + PackedBitVector m_BoneIndices = new PackedBitVector(); + m_BoneIndices.m_NumItems = a_Stream.ReadInt32(); + m_BoneIndices.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_BoneIndices.m_Data, 0, m_BoneIndices.m_Data.Length); + a_Stream.AlignStream(4); + m_BoneIndices.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + //how the hell does this work?? + if (m_BoneIndices.m_NumItems > 0 && m_BoneIndices.m_NumItems == m_Weights.m_NumItems && (bool)Properties.Settings.Default["exportDeformers"]) + { + uint[] m_Weights_Unpacked = UnpackBitVector(m_Weights); + int bitmax = 0; + for (int b = 0; b < m_Weights.m_BitSize; b++) { bitmax |= (1 << b); } + + uint[] m_BoneIndices_Unpacked = UnpackBitVector(m_BoneIndices); + + m_Skin = new List[m_BoneIndices.m_NumItems / 4]; + for (int s = 0; s < m_Skin.Length; s++) + { + m_Skin[s] = new List(); + for (int i = 0; i < 4; i++) + { + m_Skin[s].Add(new BoneInfluence() { - m_BindPose[i][j,k] = (float)((double)m_BindPoses_Unpacked[i * 16 + j * 4 + k] / bitmax) * m_BindPoses_Packed.m_Range + m_BindPoses_Packed.m_Start; + weight = (float)((double)m_Weights_Unpacked[s * 4 + i] / bitmax), + boneIndex = (int)m_BoneIndices_Unpacked[s * 4 + i] + }); + } + } + } + #endregion + + PackedBitVector m_Triangles = new PackedBitVector(); + m_Triangles.m_NumItems = a_Stream.ReadInt32(); + m_Triangles.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_Triangles.m_Data, 0, m_Triangles.m_Data.Length); + a_Stream.AlignStream(4); + m_Triangles.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + if (m_Triangles.m_NumItems > 0) { m_IndexBuffer = UnpackBitVector(m_Triangles); } + } + #endregion + + #region Colors & Collision triangles for 3.4.2 and earlier + if (version[0] <= 2 || (version[0] == 3 && version[1] <= 4)) // + { + a_Stream.Position += 24; //Axis-Aligned Bounding Box + int m_Colors_size = a_Stream.ReadInt32(); + m_Colors = new float[m_Colors_size * 4]; + for (int v = 0; v < m_Colors_size * 4; v++) { m_Colors[v] = (float)(a_Stream.ReadByte()) / 0xFF; } + + int m_CollisionTriangles_size = a_Stream.ReadInt32(); + a_Stream.Position += m_CollisionTriangles_size * 4; //UInt32 indices + int m_CollisionVertexCount = a_Stream.ReadInt32(); + } + #endregion + #region Compressed colors & Local AABB for 3.5.0 to 4.x.x + else //vertex colors are either in streams or packed bits + { + if (version[0] < 5) + { + PackedBitVector m_Colors_Packed = new PackedBitVector(); + m_Colors_Packed.m_NumItems = a_Stream.ReadInt32(); + m_Colors_Packed.m_Data = new byte[a_Stream.ReadInt32()]; + a_Stream.Read(m_Colors_Packed.m_Data, 0, m_Colors_Packed.m_Data.Length); + a_Stream.AlignStream(4); + m_Colors_Packed.m_BitSize = a_Stream.ReadByte(); + a_Stream.Position += 3; //4 byte alignment + + if (m_Colors_Packed.m_NumItems > 0) + { + if (m_Colors_Packed.m_BitSize == 32) + { + //4 x 8bit color channels + m_Colors = new float[m_Colors_Packed.m_Data.Length]; + for (int v = 0; v < m_Colors_Packed.m_Data.Length; v++) + { + m_Colors[v] = (float)m_Colors_Packed.m_Data[v] / 0xFF; + } + } + else //not tested + { + uint[] m_Colors_Unpacked = UnpackBitVector(m_Colors_Packed); + int bitmax = 0;//used to convert int value to float + for (int b = 0; b < m_Colors_Packed.m_BitSize; b++) { bitmax |= (1 << b); } + m_Colors = new float[m_Colors_Packed.m_NumItems]; + for (int v = 0; v < m_Colors_Packed.m_NumItems; v++) + { + m_Colors[v] = (float)m_Colors_Unpacked[v] / bitmax; } } } } + else { uint m_UVInfo = a_Stream.ReadUInt32(); } + + a_Stream.Position += 24; //Axis-Aligned Bounding Box } #endregion - PackedBitVector m_Normals_Packed = new PackedBitVector(); - m_Normals_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Normals_Packed.m_Range = a_Stream.ReadSingle(); - m_Normals_Packed.m_Start = a_Stream.ReadSingle(); - m_Normals_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Normals_Packed.m_Data, 0, m_Normals_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Normals_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + int m_MeshUsageFlags = a_Stream.ReadInt32(); - PackedBitVector m_Tangents_Packed = new PackedBitVector(); - m_Tangents_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Tangents_Packed.m_Range = a_Stream.ReadSingle(); - m_Tangents_Packed.m_Start = a_Stream.ReadSingle(); - m_Tangents_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Tangents_Packed.m_Data, 0, m_Tangents_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Tangents_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - PackedBitVector m_Weights = new PackedBitVector(); - m_Weights.m_NumItems = a_Stream.ReadInt32(); - m_Weights.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Weights.m_Data, 0, m_Weights.m_Data.Length); - a_Stream.AlignStream(4); - m_Weights.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - #region m_Normals - PackedBitVector m_NormalSigns_packed = new PackedBitVector(); - m_NormalSigns_packed.m_NumItems = a_Stream.ReadInt32(); - m_NormalSigns_packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_NormalSigns_packed.m_Data, 0, m_NormalSigns_packed.m_Data.Length); - a_Stream.AlignStream(4); - m_NormalSigns_packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - if (m_Normals_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportNormals"]) - { - uint[] m_Normals_Unpacked = UnpackBitVector(m_Normals_Packed); - uint[] m_NormalSigns = UnpackBitVector(m_NormalSigns_packed); - int bitmax = 0; - for (int b = 0; b < m_Normals_Packed.m_BitSize; b++) { bitmax |= (1 << b); } - m_Normals = new float[m_Normals_Packed.m_NumItems / 2 * 3]; - for (int v = 0; v < m_Normals_Packed.m_NumItems / 2; v++) - { - m_Normals[v * 3] = (float)((double)m_Normals_Unpacked[v * 2] / bitmax) * m_Normals_Packed.m_Range + m_Normals_Packed.m_Start; - m_Normals[v * 3 + 1] = (float)((double)m_Normals_Unpacked[v * 2 + 1] / bitmax) * m_Normals_Packed.m_Range + m_Normals_Packed.m_Start; - m_Normals[v * 3 + 2] = (float)Math.Sqrt(1 - m_Normals[v * 3] * m_Normals[v * 3] - m_Normals[v * 3 + 1] * m_Normals[v * 3 + 1]); - if (m_NormalSigns[v] == 0) { m_Normals[v * 3 + 2] *= -1; } - } - } - #endregion - - #region m_Tangents - PackedBitVector m_TangentSigns_packed = new PackedBitVector(); - m_TangentSigns_packed.m_NumItems = a_Stream.ReadInt32(); - m_TangentSigns_packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_TangentSigns_packed.m_Data, 0, m_TangentSigns_packed.m_Data.Length); - a_Stream.AlignStream(4); - m_TangentSigns_packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - if (m_Tangents_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportTangents"]) - { - uint[] m_Tangents_Unpacked = UnpackBitVector(m_Tangents_Packed); - uint[] m_TangentSigns = UnpackBitVector(m_TangentSigns_packed); - int bitmax = 0; - for (int b = 0; b < m_Tangents_Packed.m_BitSize; b++) { bitmax |= (1 << b); } - m_Tangents = new float[m_Tangents_Packed.m_NumItems / 2 * 3]; - for (int v = 0; v < m_Tangents_Packed.m_NumItems / 2; v++) - { - m_Tangents[v * 3] = (float)((double)m_Tangents_Unpacked[v * 2] / bitmax) * m_Tangents_Packed.m_Range + m_Tangents_Packed.m_Start; - m_Tangents[v * 3 + 1] = (float)((double)m_Tangents_Unpacked[v * 2 + 1] / bitmax) * m_Tangents_Packed.m_Range + m_Tangents_Packed.m_Start; - m_Tangents[v * 3 + 2] = (float)Math.Sqrt(1 - m_Tangents[v * 3] * m_Tangents[v * 3] - m_Tangents[v * 3 + 1] * m_Tangents[v * 3 + 1]); - if (m_TangentSigns[v] == 0) { m_Tangents[v * 3 + 2] *= -1; } - } - } - #endregion - - #region m_FloatColors if (version[0] >= 5) { - PackedBitVector m_FloatColors = new PackedBitVector(); - m_FloatColors.m_NumItems = a_Stream.ReadInt32(); - m_FloatColors.m_Range = a_Stream.ReadSingle(); - m_FloatColors.m_Start = a_Stream.ReadSingle(); - m_FloatColors.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_FloatColors.m_Data, 0, m_FloatColors.m_Data.Length); - a_Stream.AlignStream(4); - m_FloatColors.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - if (m_FloatColors.m_NumItems > 0 && (bool)Properties.Settings.Default["exportColors"]) - { - uint[] m_FloatColors_Unpacked = UnpackBitVector(m_FloatColors); - int bitmax = 0; - for (int b = 0; b < m_FloatColors.m_BitSize; b++) { bitmax |= (1 << b); } - - m_Colors = new float[m_FloatColors.m_NumItems]; - - for (int v = 0; v < m_FloatColors.m_NumItems; v++) - { - m_Colors[v] = (float)m_FloatColors_Unpacked[v] / bitmax * m_FloatColors.m_Range + m_FloatColors.m_Start; - } - } + //int m_BakedConvexCollisionMesh = a_Stream.ReadInt32(); + //a_Stream.Position += m_BakedConvexCollisionMesh; + //int m_BakedTriangleCollisionMesh = a_Stream.ReadInt32(); + //a_Stream.Position += m_BakedConvexCollisionMesh; } - #endregion - #region m_Skin - PackedBitVector m_BoneIndices = new PackedBitVector(); - m_BoneIndices.m_NumItems = a_Stream.ReadInt32(); - m_BoneIndices.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_BoneIndices.m_Data, 0, m_BoneIndices.m_Data.Length); - a_Stream.AlignStream(4); - m_BoneIndices.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - //how the hell does this work?? - if (m_BoneIndices.m_NumItems > 0 && m_BoneIndices.m_NumItems == m_Weights.m_NumItems && (bool)Properties.Settings.Default["exportDeformers"]) + #region Build face indices + for (int s = 0; s < m_SubMeshes_size; s++) { - uint[] m_Weights_Unpacked = UnpackBitVector(m_Weights); - int bitmax = 0; - for (int b = 0; b < m_Weights.m_BitSize; b++) { bitmax |= (1 << b); } + uint firstIndex = m_SubMeshes[s].firstByte / 2; + if (!m_Use16BitIndices) { firstIndex /= 2; } - uint[] m_BoneIndices_Unpacked = UnpackBitVector(m_BoneIndices); - - m_Skin = new List[m_BoneIndices.m_NumItems / 4]; - for (int s = 0; s < m_Skin.Length; s++) + if (m_SubMeshes[s].topology == 0) { - m_Skin[s] = new List(); - for (int i = 0; i < 4; i++) + for (int i = 0; i < m_SubMeshes[s].indexCount / 3; i++) { - m_Skin[s].Add(new BoneInfluence() { weight = (float)((double)m_Weights_Unpacked[s * 4 + i] / bitmax), - boneIndex = (int)m_BoneIndices_Unpacked[s * 4 + i] }); - } - } - } - #endregion - - PackedBitVector m_Triangles = new PackedBitVector(); - m_Triangles.m_NumItems = a_Stream.ReadInt32(); - m_Triangles.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Triangles.m_Data, 0, m_Triangles.m_Data.Length); - a_Stream.AlignStream(4); - m_Triangles.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - if (m_Triangles.m_NumItems > 0) { m_IndexBuffer = UnpackBitVector(m_Triangles); } - } - #endregion - - #region Colors & Collision triangles for 3.4.2 and earlier - if (version[0] <= 2 || (version[0] == 3 && version[1] <= 4)) // - { - a_Stream.Position += 24; //Axis-Aligned Bounding Box - int m_Colors_size = a_Stream.ReadInt32(); - m_Colors = new float[m_Colors_size * 4]; - for (int v = 0; v < m_Colors_size * 4; v++) { m_Colors[v] = (float)(a_Stream.ReadByte()) / 0xFF; } - - int m_CollisionTriangles_size = a_Stream.ReadInt32(); - a_Stream.Position += m_CollisionTriangles_size * 4; //UInt32 indices - int m_CollisionVertexCount = a_Stream.ReadInt32(); - } - #endregion - #region Compressed colors & Local AABB for 3.5.0 to 4.x.x - else //vertex colors are either in streams or packed bits - { - if (version[0] < 5) - { - PackedBitVector m_Colors_Packed = new PackedBitVector(); - m_Colors_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Colors_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Colors_Packed.m_Data, 0, m_Colors_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Colors_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment - - if (m_Colors_Packed.m_NumItems > 0) - { - if (m_Colors_Packed.m_BitSize == 32) - { - //4 x 8bit color channels - m_Colors = new float[m_Colors_Packed.m_Data.Length]; - for (int v = 0; v < m_Colors_Packed.m_Data.Length; v++) - { - m_Colors[v] = (float)m_Colors_Packed.m_Data[v] / 0xFF; - } - } - else //not tested - { - uint[] m_Colors_Unpacked = UnpackBitVector(m_Colors_Packed); - int bitmax = 0;//used to convert int value to float - for (int b = 0; b < m_Colors_Packed.m_BitSize; b++) { bitmax |= (1 << b); } - m_Colors = new float[m_Colors_Packed.m_NumItems]; - for (int v = 0; v < m_Colors_Packed.m_NumItems; v++) - { - m_Colors[v] = (float)m_Colors_Unpacked[v] / bitmax; - } - } - } - } - else { uint m_UVInfo = a_Stream.ReadUInt32(); } - - a_Stream.Position += 24; //Axis-Aligned Bounding Box - } - #endregion - - int m_MeshUsageFlags = a_Stream.ReadInt32(); - - if (version[0] >= 5) - { - //int m_BakedConvexCollisionMesh = a_Stream.ReadInt32(); - //a_Stream.Position += m_BakedConvexCollisionMesh; - //int m_BakedTriangleCollisionMesh = a_Stream.ReadInt32(); - //a_Stream.Position += m_BakedConvexCollisionMesh; - } - - #region Build face indices - for (int s = 0; s < m_SubMeshes_size; s++) - { - uint firstIndex = m_SubMeshes[s].firstByte / 2; - if (!m_Use16BitIndices) { firstIndex /= 2; } - - if (m_SubMeshes[s].topology == 0) - { - for (int i = 0; i < m_SubMeshes[s].indexCount / 3; i++) - { - m_Indices.Add(m_IndexBuffer[firstIndex + i * 3]); - m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 1]); - m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 2]); - m_materialIDs.Add(s); - } - } - else - { - for (int i = 0; i < m_SubMeshes[s].indexCount - 2; i++) - { - uint fa = m_IndexBuffer[firstIndex + i]; - uint fb = m_IndexBuffer[firstIndex + i + 1]; - uint fc = m_IndexBuffer[firstIndex + i + 2]; - - if ((fa!=fb) && (fa!=fc) && (fc!=fb)) - { - m_Indices.Add(fa); - if ((i % 2) == 0) - { - m_Indices.Add(fb); - m_Indices.Add(fc); - } - else - { - m_Indices.Add(fc); - m_Indices.Add(fb); - } + m_Indices.Add(m_IndexBuffer[firstIndex + i * 3]); + m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 1]); + m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 2]); m_materialIDs.Add(s); } } + else + { + for (int i = 0; i < m_SubMeshes[s].indexCount - 2; i++) + { + uint fa = m_IndexBuffer[firstIndex + i]; + uint fb = m_IndexBuffer[firstIndex + i + 1]; + uint fc = m_IndexBuffer[firstIndex + i + 2]; + + if ((fa != fb) && (fa != fc) && (fc != fb)) + { + m_Indices.Add(fa); + if ((i % 2) == 0) + { + m_Indices.Add(fb); + m_Indices.Add(fc); + } + else + { + m_Indices.Add(fc); + m_Indices.Add(fb); + } + m_materialIDs.Add(s); + } + } + } } + #endregion + } + else + { + if (m_Name != "") { MeshPD.Text = m_Name; } + else { MeshPD.Text = MeshPD.TypeString + " #" + MeshPD.uniqueID; } + MeshPD.SubItems.AddRange(new[] { MeshPD.TypeString, MeshPD.Size.ToString() }); } - #endregion } } } diff --git a/Unity Studio/Unity Studio Classes/UnityStudio.cs b/Unity Studio/Unity Studio Classes/UnityStudio.cs index 78f1985..37a3e88 100644 --- a/Unity Studio/Unity Studio Classes/UnityStudio.cs +++ b/Unity Studio/Unity Studio Classes/UnityStudio.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Drawing.Imaging; using System.Web.Script.Serialization; +using ManagedFbx; namespace Unity_Studio @@ -280,7 +281,6 @@ namespace Unity_Studio assetsFile.TransformList.Add(asset.m_PathID, m_Rect.m_Transform); break; } - //case 21: //Material case 28: //Texture2D { Texture2D m_Texture2D = new Texture2D(asset, false); @@ -324,8 +324,13 @@ namespace Unity_Studio productName = plSet.productName; break; } - case 21: //Material case 43: //Mesh + { + Mesh m_Mesh = new Mesh(asset, false); + exportable = true; + break; + } + case 21: //Material case 74: //AnimationClip case 90: //Avatar case 91: //AnimatorController @@ -920,7 +925,7 @@ namespace Unity_Studio //StatusStripUpdate("Writing Geometry"); foreach (var MeshPD in Meshes) { - Mesh m_Mesh = new Mesh(MeshPD); + Mesh m_Mesh = new Mesh(MeshPD, true); MeshFBX(m_Mesh, MeshPD.uniqueID, ob); //write data 8MB at a time @@ -951,7 +956,7 @@ namespace Unity_Studio //find a way to test if a mesh instance was loaded previously and if it uses the same skeleton, then create instance or copy var keepID = MeshPD.uniqueID; MeshPD.uniqueID = SkinnedMeshPD.uniqueID; - Mesh m_Mesh = new Mesh(MeshPD); + Mesh m_Mesh = new Mesh(MeshPD, true); MeshFBX(m_Mesh, MeshPD.uniqueID, ob); //write data 8MB at a time @@ -1734,6 +1739,111 @@ namespace Unity_Studio } } + public static void ExportMesh(Mesh m_Mesh, string exportPath) + { + Scene m_scene = Scene.CreateScene("Scene"); + SceneNode root = m_scene.RootNode; + SceneNode meshnode = Scene.CreateNode(m_scene, m_Mesh.m_Name); + SceneNode.AddChild(root, meshnode); + ManagedFbx.Mesh mesh = Scene.CreateMesh(m_scene, meshnode, "Mesh"); + if (m_Mesh.m_VertexCount > 0) + { + #region Vertices + int count = 3; + if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) + { + count = 4; + } + var vertices = new ManagedFbx.Vector3[m_Mesh.m_VertexCount]; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + vertices[v] = new ManagedFbx.Vector3( + m_Mesh.m_Vertices[v * count], + m_Mesh.m_Vertices[v * count + 1], + m_Mesh.m_Vertices[v * count + 2]); + } + mesh.Vertices = vertices; + #endregion + #region Indicies + List indices = new List(); + for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3) + { + indices.Add((int)m_Mesh.m_Indices[i]); + indices.Add((int)m_Mesh.m_Indices[i + 1]); + indices.Add((int)m_Mesh.m_Indices[i + 2]); + } + mesh.AddPolygons(indices, 0); + #endregion + #region Normals + if (m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0) + { + if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3) + { + count = 3; + } + else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4) + { + count = 4; + } + + var normals = new ManagedFbx.Vector3[m_Mesh.m_VertexCount]; + for (int n = 0; n < m_Mesh.m_VertexCount; n++) + { + normals[n] = new ManagedFbx.Vector3( + m_Mesh.m_Normals[n * count], + m_Mesh.m_Normals[n * count + 1], + m_Mesh.m_Normals[n * count + 2]); + } + mesh.Normals = normals; + } + #endregion + #region Colors + if (m_Mesh.m_Colors == null) + { + var colors = new ManagedFbx.Colour[m_Mesh.m_VertexCount]; + for (int c = 0; c < m_Mesh.m_VertexCount; c++) + { + colors[c] = new ManagedFbx.Colour( + 0.5f, 0.5f, 0.5f, 1.0f); + } + mesh.VertexColours = colors; + } + else if (m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3) + { + var colors = new ManagedFbx.Colour[m_Mesh.m_VertexCount]; + for (int c = 0; c < m_Mesh.m_VertexCount; c++) + { + colors[c] = new ManagedFbx.Colour( + m_Mesh.m_Colors[c * 4], + m_Mesh.m_Colors[c * 4 + 1], + m_Mesh.m_Colors[c * 4 + 2], + 1.0f); + } + mesh.VertexColours = colors; + } + else + { + var colors = new ManagedFbx.Colour[m_Mesh.m_VertexCount]; + for (int c = 0; c < m_Mesh.m_VertexCount; c++) + { + colors[c] = new ManagedFbx.Colour( + m_Mesh.m_Colors[c * 4], + m_Mesh.m_Colors[c * 4 + 1], + m_Mesh.m_Colors[c * 4 + 2], + m_Mesh.m_Colors[c * 4 + 3]); + } + mesh.VertexColours = colors; + } + #endregion + } + SceneNode.AddMesh(meshnode, mesh); + + m_scene.Save(exportPath); //default is .fbx + //m_scene.Save(exportPath + ".fbx"); + m_scene.Save(exportPath + ".obj"); + m_scene.Save(exportPath + ".dae"); + } + public static bool ExportFileExists(string filename) { if (File.Exists(filename)) diff --git a/Unity Studio/Unity Studio.csproj b/Unity Studio/Unity Studio.csproj index 2a1a8f2..fe1cf60 100644 --- a/Unity Studio/Unity Studio.csproj +++ b/Unity Studio/Unity Studio.csproj @@ -73,6 +73,9 @@ MinimumRecommendedRules.ruleset + + library\ManagedFbx.dll + False library\OpenTK.dll diff --git a/Unity Studio/UnityStudioForm.cs b/Unity Studio/UnityStudioForm.cs index 63b324a..81b0877 100644 --- a/Unity Studio/UnityStudioForm.cs +++ b/Unity Studio/UnityStudioForm.cs @@ -13,9 +13,9 @@ using System.Diagnostics; using System.Drawing.Text; using OpenTK; using OpenTK.Graphics.OpenGL; +using ManagedFbx; using static Unity_Studio.UnityStudio; - namespace Unity_Studio { partial class UnityStudioForm : Form @@ -50,65 +50,11 @@ namespace Unity_Studio int vboColors; int vboViewMatrix; int eboElements; - Vector3[] vertexData = - { - new Vector3(-0.5f, -0.5f, -0.5f), - new Vector3(0.5f, -0.5f, -0.5f), - new Vector3(0.5f, 0.5f, -0.5f), - new Vector3(-0.5f, 0.5f, -0.5f), - new Vector3(-0.5f, -0.5f, 0.5f), - new Vector3(0.5f, -0.5f, 0.5f), - new Vector3(0.5f, 0.5f, 0.5f), - new Vector3(-0.5f, 0.5f, 0.5f) - }; - Vector3[] normalData = - { - //left - new Vector3(-1.0f, 0.0f, 0.0f) - //back - //new Vector3(0.0f, 0.0f, -1.0f), - //right - //new Vector3(1.0f, 0.0f, 0.0f), - //top - //new Vector3(0.0f, 1.0f, 0.0f), - //front - //new Vector3(0.0f, 0.0f, 1.0f), - //bottom - //new Vector3(0.0f, -1.0f, 0.0f) - }; - Vector4[] colorData = - { - new Vector4(0.5f, 0.5f, 0.5f, 1.0f), - new Vector4(0.5f, 0.5f, 0.5f, 1.0f), - new Vector4(0.5f, 0.5f, 0.5f, 1.0f), - new Vector4(0.5f, 0.5f, 0.5f, 1.0f), - new Vector4(0.5f, 0.5f, 0.5f, 1.0f), - new Vector4(0.5f, 0.5f, 0.5f, 1.0f), - new Vector4(0.5f, 0.5f, 0.5f, 1.0f), - new Vector4(0.5f, 0.5f, 0.5f, 1.0f) - }; - Matrix4[] viewMatrixData = { Matrix4.Identity }; - int[] indiceData = - { - //left - 0,2,1, - 0,3,2, - //back - 1,2,6, - 6,5,1, - //right - 4,5,6, - 6,7,4, - //top - 2,3,6, - 6,3,7, - //front - 0,7,3, - 0,4,7, - //bottom - 0,1,5, - 0,5,4 - }; + OpenTK.Vector3[] vertexData; + OpenTK.Vector3[] normalData; + OpenTK.Vector4[] colorData; + Matrix4[] viewMatrixData; + int[] indiceData; bool wireFrameView; #endregion @@ -1021,24 +967,25 @@ namespace Unity_Studio Matrix4.Identity * Matrix4.CreateTranslation( 0.0f, -1.0f, 0.0f ) * Matrix4.CreateRotationY(-90.0f)}; - - var m_Mesh = new Mesh(asset); - + var m_Mesh = new Mesh(asset, true); if (m_Mesh.m_VertexCount > 0) { - int count = 3;//vertex components - //skip last component in vector4 - if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) { count = 4; } - - vertexData = new Vector3[m_Mesh.m_VertexCount]; + #region Vertices + int count = 3; + if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) + { + count = 4; + } + vertexData = new OpenTK.Vector3[m_Mesh.m_VertexCount]; for (int v = 0; v < m_Mesh.m_VertexCount; v++) { - vertexData[v] = new Vector3( + vertexData[v] = new OpenTK.Vector3( m_Mesh.m_Vertices[v * count], m_Mesh.m_Vertices[v * count + 1], m_Mesh.m_Vertices[v * count + 2]); } - + #endregion + #region Indicies indiceData = new int[m_Mesh.m_Indices.Count]; for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3) { @@ -1046,6 +993,8 @@ namespace Unity_Studio indiceData[i + 1] = (int)m_Mesh.m_Indices[i + 1]; indiceData[i + 2] = (int)m_Mesh.m_Indices[i + 2]; } + #endregion + #region Normals if (m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0) { if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3) @@ -1057,40 +1006,53 @@ namespace Unity_Studio count = 4; } - normalData = new Vector3[m_Mesh.m_VertexCount]; + normalData = new OpenTK.Vector3[m_Mesh.m_VertexCount]; for (int n = 0; n < m_Mesh.m_VertexCount; n++) { - normalData[n] = new Vector3( + normalData[n] = new OpenTK.Vector3( m_Mesh.m_Normals[n * count], m_Mesh.m_Normals[n * count + 1], m_Mesh.m_Normals[n * count + 2]); } } - if (m_Mesh.m_Colors == null || m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3) + #endregion + #region Colors + if (m_Mesh.m_Colors == null) { - colorData = new Vector4[m_Mesh.m_VertexCount]; + colorData = new OpenTK.Vector4[m_Mesh.m_VertexCount]; for (int c = 0; c < m_Mesh.m_VertexCount; c++) { - colorData[c] = new Vector4( + colorData[c] = new OpenTK.Vector4( 0.5f, 0.5f, 0.5f, 1.0f); } } + else if (m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3) + { + colorData = new OpenTK.Vector4[m_Mesh.m_VertexCount]; + for (int c = 0; c < m_Mesh.m_VertexCount; c++) + { + colorData[c] = new OpenTK.Vector4( + m_Mesh.m_Colors[c * 4], + m_Mesh.m_Colors[c * 4 + 1], + m_Mesh.m_Colors[c * 4 + 2], + 1.0f); + } + } else { - colorData = new Vector4[m_Mesh.m_VertexCount]; + colorData = new OpenTK.Vector4[m_Mesh.m_VertexCount]; for (int c = 0; c < m_Mesh.m_VertexCount; c++) { - colorData[c] = new Vector4( + colorData[c] = new OpenTK.Vector4( m_Mesh.m_Colors[c * 4], m_Mesh.m_Colors[c * 4 + 1], m_Mesh.m_Colors[c * 4 + 2], m_Mesh.m_Colors[c * 4 + 3]); } } + #endregion } - createVAO(); - StatusStripUpdate("Using OpenGL Version: " + GL.GetString(StringName.Version) + " | 'T'=Start/Stop Rotation | 'WASD'=Manual Rotate | " + "'Shift WASD'=Move | 'Q/E'=Zoom | 'Ctl W' =Wireframe"); @@ -1574,9 +1536,10 @@ namespace Unity_Studio } break; case 48: + Shader m_Shader = new Shader(asset, true); if (!ExportFileExists(exportpath + asset.Text + asset.extension)) { - ExportShader(new Shader(asset, true), exportpath + asset.Text + ".txt"); + ExportShader(m_Shader, exportpath + asset.Text + ".txt"); exportedCount++; } break; @@ -1603,6 +1566,15 @@ namespace Unity_Studio ExportFont(m_Font, exportpath + asset.Text + asset.extension); exportedCount++; } + break; + case 43: //Mesh + Mesh m_Mesh = new Mesh(asset, true); + if (!ExportFileExists(exportpath + asset.Text + asset.extension)) + { + ExportMesh(m_Mesh, exportpath + asset.Text); + exportedCount++; + } + break; default: if (!ExportFileExists(exportpath + asset.Text + asset.extension)) @@ -1755,24 +1727,24 @@ namespace Unity_Studio GL.DeleteShader(address); } - private void createVBO(int vboAddress, Vector3[] data, int address) + private void createVBO(int vboAddress, OpenTK.Vector3[] data, int address) { GL.GenBuffers(1, out vboAddress); GL.BindBuffer(BufferTarget.ArrayBuffer, vboAddress); - GL.BufferData(BufferTarget.ArrayBuffer, - (IntPtr)(data.Length * Vector3.SizeInBytes), + GL.BufferData(BufferTarget.ArrayBuffer, + (IntPtr)(data.Length * OpenTK.Vector3.SizeInBytes), data, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(address, 3, VertexAttribPointerType.Float, false, 0, 0); GL.EnableVertexAttribArray(address); } - private void createVBO(int vboAddress, Vector4[] data, int address) + private void createVBO(int vboAddress, OpenTK.Vector4[] data, int address) { GL.GenBuffers(1, out vboAddress); GL.BindBuffer(BufferTarget.ArrayBuffer, vboAddress); - GL.BufferData(BufferTarget.ArrayBuffer, - (IntPtr)(data.Length * Vector4.SizeInBytes), + GL.BufferData(BufferTarget.ArrayBuffer, + (IntPtr)(data.Length * OpenTK.Vector4.SizeInBytes), data, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(address, 4, VertexAttribPointerType.Float, false, 0, 0); @@ -1802,10 +1774,10 @@ namespace Unity_Studio GL.GenVertexArrays(1, out vao); GL.BindVertexArray(vao); createVBO(vboPositions, vertexData, attributeVertexPosition); + createVBO(vboNormals, normalData, attributeNormalDirection); createVBO(vboColors, colorData, attributeVertexColor); createVBO(vboViewMatrix, viewMatrixData, uniformViewMatrix); createEBO(eboElements, indiceData); - createVBO(vboNormals, normalData, attributeNormalDirection); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindVertexArray(0); } diff --git a/Unity Studio/library/ManagedFbx.dll b/Unity Studio/library/ManagedFbx.dll new file mode 100644 index 0000000..0aaa22d Binary files /dev/null and b/Unity Studio/library/ManagedFbx.dll differ