Exemplo n.º 1
0
 public static void SafeSkip(this Stream stream, int byteLength)
 {
     if (byteLength < 0)
     {
         ThrowHelper.ThrowArgOutOfRange(nameof(byteLength));
     }
     if (stream.CanSeek)
     {
         var pos = stream.Position + byteLength;
         if (pos > stream.Length)
         {
             stream.Position = stream.Length;
             ThrowEOS();
         }
         stream.Position = pos;
     }
     else
     {
         if (byteLength > 128)
         {
             using var buf = new UnsafeRawArray <byte>(byteLength, false);
             SafeRead(stream, buf.AsSpan());
         }
         else
         {
             Span <byte> buf = stackalloc byte[byteLength];
             SafeRead(stream, buf);
         }
     }
 }
Exemplo n.º 2
0
        public static Icon Parse(Stream stream)
        {
            if (stream is null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            UnsafeEx.SkipInitIfPossible(out ICONDIR icondir);   // 6 bytes
            stream.SafeRead(UnsafeEx.AsBytes(ref icondir));

            if (icondir.idCount < 0)
            {
                ThrowHelper.ThrowFormatException();
            }

            using var entries = new UnsafeRawArray <ICONDIRENTRY>(icondir.idCount, false);
            stream.SafeRead(entries.AsBytes());

            return(Icon.Create(icondir.idCount, (stream, entries), static (images, state) =>
            {
                var(stream, entries) = state;
                for (int i = 0; i < images.Length; i++)
                {
                    images[i] = ParseImage(stream, entries[i]);
                }
            }));
        }
Exemplo n.º 3
0
            static UnsafeRawArray <T> Decode <T>(Reader reader, int arrayLength, int compressedSize) where T : unmanaged
            {
                const int deflateMetaDataSize = 2;

                reader.Int16(out var _);            // deflateMetaData (not be used)

                // read compressed data
                using var buf = new UnsafeRawArray <byte>(compressedSize - deflateMetaDataSize);
                reader.Read(buf.AsSpan());

                // decompress data
                var ptr = (byte *)buf.Ptr;

                using var ms = (_ms is null) ? (_ms = new MemoryStreamUM(ptr, buf.Length)) : _ms.RefreshInstance(ptr, buf.Length);
                using var ds = new DeflateStream(ms, CompressionMode.Decompress);
                var decoded = new UnsafeRawArray <T>(arrayLength);

                try {
                    ds.Read(MemoryMarshal.Cast <T, byte>(decoded.AsSpan()));
                }
                catch {
                    decoded.Dispose();
                    throw;
                }
                return(decoded);
            }
Exemplo n.º 4
0
        private static UnsafeRawArray <Components.Bone> GetBones(PMXObject pmx)
        {
            var pmxBones = pmx.BoneList.AsSpan();
            var bones    = new UnsafeRawArray <Components.Bone>(pmxBones.Length, false);

            try {
                for (int i = 0; i < pmxBones.Length; i++)
                {
                    var     parentBone = pmxBones[i].ParentBone >= 0 ? pmxBones[i].ParentBone : (int?)null;
                    Vector3 boneVec;
                    var     c = pmxBones[i].ConnectedBone;
                    if (c >= 0)
                    {
                        boneVec = pmxBones[c].Position.ToVector3() - pmxBones[i].Position.ToVector3();
                    }
                    else
                    {
                        boneVec = pmxBones[i].PositionOffset.ToVector3();
                    }

                    bones[i] = new Components.Bone();
                }
            }
            catch {
                bones.Dispose();
                throw;
            }
            return(bones);
        }
Exemplo n.º 5
0
 internal FbxSemanticsUnsafe([MaybeNull] ref FbxObject fbx,
                             ref UnsafeRawArray <int> indices,
                             ref UnsafeRawArray <TVertex> vertices,
                             ref ValueTypeRentMemory <RawString> texture,
                             ref SkeletonDataList skeletons)
 {
     (_fbx, fbx)             = (fbx, default);
     (_textures, texture)    = (texture, default);
     (_indices, indices)     = (indices, default);
     (_vertices, vertices)   = (vertices, default);
     (_skeletons, skeletons) = (skeletons, default);
 }
Exemplo n.º 6
0
        public DeformerList(FbxNode objectsNode)
        {
            using var buf = new UnsafeRawArray <int>(objectsNode.Children.Count, false);
            var count = objectsNode.FindChildIndexAll(FbxConstStrings.Deformer(), buf.AsSpan());

            _dic = new BufferPooledDictionary <long, FbxNode>(count);
            foreach (var index in buf.AsSpan(0, count))
            {
                var deformer = objectsNode.Children[index];
                var id       = deformer.Properties[0].AsInt64();
                _dic.Add(id, deformer);
            }
        }
Exemplo n.º 7
0
        private static UnsafeRawArray <SkinnedVertex> GetVertices(PMXObject pmx)
        {
            // build vertices
            var pmxVertices = pmx.VertexList.AsSpan();
            var vertices    = new UnsafeRawArray <SkinnedVertex>(pmxVertices.Length, false);

            try {
                for (int i = 0; i < pmxVertices.Length; i++)
                {
                    vertices[i] = pmxVertices[i].ToRigVertex();
                }
            }
            catch {
                vertices.Dispose();
                throw;
            }
            return(vertices);
        }
Exemplo n.º 8
0
        private static void GenerateMesh(out UnsafeRawArray <Vertex> vertices, out UnsafeRawArray <int> indices)
        {
            const float r = 1;
            const int   a = 16;
            const int   b = 16;

            vertices = new UnsafeRawArray <Vertex>((a + 1) * (b + 1), false);
            indices  = new UnsafeRawArray <int>(a * b * 6, false);

            // 'UnsafeRawArray' does not check boundary of index accessing. Be careful!

            for (int j = 0; j < a + 1; j++)
            {
                var phi = MathTool.PiOver2 - MathTool.Pi / a * j;
                for (int i = 0; i < b + 1; i++)
                {
                    var theta    = MathTool.TwoPi / b * i;
                    var cosPhi   = MathF.Cos(phi);
                    var cosTheta = MathF.Cos(theta);
                    var sinPhi   = MathF.Sin(phi);
                    var sinTheta = MathF.Sin(theta);
                    var pos      = new Vector3((float)(r * cosPhi * cosTheta), (float)(r * sinPhi), (float)(r * cosPhi * sinTheta));
                    var normal   = -pos.Normalized();
                    var uv       = new Vector2((float)i / b, 1 - (float)j / a);
                    vertices[(b + 1) * j + i] = new Vertex(pos, normal, uv);
                }
            }
            for (int j = 0; j < a; j++)
            {
                for (int i = 0; i < b; i++)
                {
                    var l = (b * j + i) * 6;
                    indices[l]     = (b + 1) * j + i;
                    indices[l + 1] = (b + 1) * (j + 1) + i;
                    indices[l + 2] = (b + 1) * (j + 1) + (i + 1) % (b + 1);
                    indices[l + 3] = (b + 1) * j + i;
                    indices[l + 4] = (b + 1) * (j + 1) + (i + 1) % (b + 1);
                    indices[l + 5] = (b + 1) * j + (i + 1) % (b + 1);
                }
            }
        }
Exemplo n.º 9
0
 public UnsafeRawArrayDebuggerTypeProxy(UnsafeRawArray <T> entity) => _entity = entity;
Exemplo n.º 10
0
        private unsafe static void ParseProperty(Reader reader, ref FbxProperty property)
        {
            reader.Byte(out var propertyType);
            switch (propertyType)
            {
            case INT16_PROPERTY: {
                reader.Int16(out var value);
                property.SetInt16(value);
                break;
            }

            case BOOL_PROPERTY: {
                reader.Byte(out var value);
                // two types format exist. (Oh my gosh !! Fuuuuuuuu*k !!)
                // blender             -> true/false = 0x01/0x00
                // Autodesk production -> true/false = 'Y'/'T' = 0x59/0x54
                property.SetBool(value != 0x00 && value != 0x54);
                break;
            }

            case INT32_PROPERTY: {
                reader.Int32(out var value);
                property.SetInt32(value);
                break;
            }

            case FLOAT_PROPERTY: {
                reader.Float(out var value);
                property.SetFloat(value);
                break;
            }

            case DOUBLE_PROPERTY: {
                reader.Double(out var value);
                property.SetDouble(value);
                break;
            }

            case INT64_PROPERTY: {
                reader.Int64(out var value);
                property.SetInt64(value);
                break;
            }

            case STRING_PROPERTY: {
                reader.Int32(out var len);
                RawStringMem str = default;
                try {
                    str = new RawStringMem(len);
                    reader.Read(str.AsSpan());
                    SanitizeString(str.AsSpan());
                    property.SetString((byte *)str.Ptr, str.ByteLength);
                }
                catch {
                    str.Dispose();
                    throw;
                }
                break;
            }

            case BOOL_ARRAY_PROPERTY: {
                reader.Int32(out var len);
                reader.UInt32(out var encoded);
                reader.UInt32(out var compressedSize);
                UnsafeRawArray <bool> array = default;               // Don't dispose
                try {
                    if (encoded != 0)
                    {
                        array = Decode <bool>(reader, len, (int)compressedSize);
                    }
                    else
                    {
                        array = new UnsafeRawArray <bool>((int)compressedSize);
                        reader.Read(MemoryMarshal.Cast <bool, byte>(array.AsSpan()));
                    }
                    property.SetBoolArray((bool *)array.Ptr, array.Length);
                }
                catch {
                    array.Dispose();
                    throw;
                }
                break;
            }

            case INT32_ARRAY_PROPERTY: {
                reader.Int32(out var len);
                reader.UInt32(out var encoded);
                reader.UInt32(out var compressedSize);
                UnsafeRawArray <int> array = default;               // Don't dispose
                try {
                    if (encoded != 0)
                    {
                        array = Decode <int>(reader, len, (int)compressedSize);
                    }
                    else
                    {
                        array = new UnsafeRawArray <int>((int)compressedSize / sizeof(int));
                        reader.Read(MemoryMarshal.Cast <int, byte>(array.AsSpan()));
                    }
                    property.SetInt32Array((int *)array.Ptr, array.Length);
                }
                catch {
                    array.Dispose();
                    throw;
                }
                break;
            }

            case FLOAT_ARRAY_PROPERTY: {
                reader.Int32(out var len);
                reader.UInt32(out var encoded);
                reader.UInt32(out var compressedSize);
                UnsafeRawArray <float> array = default;               // Don't dispose
                try {
                    if (encoded != 0)
                    {
                        array = Decode <float>(reader, len, (int)compressedSize);
                    }
                    else
                    {
                        array = new UnsafeRawArray <float>((int)compressedSize / sizeof(float));
                        reader.Read(MemoryMarshal.Cast <float, byte>(array.AsSpan()));
                    }
                    property.SetFloatArray((float *)array.Ptr, array.Length);
                }
                catch {
                    array.Dispose();
                    throw;
                }
                break;
            }

            case DOUBLE_ARRAY_PROPERTY: {
                reader.Int32(out var len);
                reader.UInt32(out var encoded);
                reader.UInt32(out var compressedSize);
                UnsafeRawArray <double> array = default;
                try {
                    if (encoded != 0)
                    {
                        array = Decode <double>(reader, len, (int)compressedSize);
                    }
                    else
                    {
                        array = new UnsafeRawArray <double>((int)compressedSize / sizeof(double));
                        reader.Read(MemoryMarshal.Cast <double, byte>(array.AsSpan()));
                    }
                    property.SetDoubleArray((double *)array.Ptr, array.Length);
                }
                catch {
                    array.Dispose();
                    throw;
                }
                break;
            }

            case INT64_ARRAY_PROPERTY: {
                reader.Int32(out var len);
                reader.UInt32(out var encoded);
                reader.UInt32(out var compressedSize);
                UnsafeRawArray <long> array = default;
                try {
                    if (encoded != 0)
                    {
                        array = Decode <long>(reader, len, (int)compressedSize);
                    }
                    else
                    {
                        array = new UnsafeRawArray <long>((int)compressedSize / sizeof(long));
                        reader.Read(MemoryMarshal.Cast <long, byte>(array.AsSpan()));
                    }
                    property.SetInt64Array((long *)array.Ptr, array.Length);
                }
                catch {
                    array.Dispose();
                    throw;
                }
                break;
            }

            case RAW_BINARY_PROPERTY: {
                reader.Int32(out var len);
                var buf = new UnsafeRawArray <byte>(len);
                try {
                    reader.Read(buf.AsSpan());
                    property.SetByteArray((byte *)buf.Ptr, buf.Length);
                }
                catch {
                    buf.Dispose();
                    throw;
                }
                break;
            }

            default: {
                Debug.WriteLine($"[Skip Unknow Type Property] Position : {reader.BaseStream.Position}, type : {propertyType}");
                break;
            }
            }
Exemplo n.º 11
0
        private static UniTask BuildTexture(PMXObject pmx, ResourceFile pmxFile, Model3D model, UnsafeRawArray <SkinnedVertex> vertices, CancellationToken ct)
        {
            var arrayTexture = new ArrayTexture(TextureConfig.BilinearRepeat);

            model.AddComponent(arrayTexture);

            var dir             = ResourcePath.GetDirectoryName(pmxFile.Name);
            var textureNames    = pmx.TextureList.AsSpan();
            var resourcePackage = pmxFile.Package;

            var materials = pmx.MaterialList.AsSpan();

            using var matTexMem = new ValueTypeRentMemory <int>(materials.Length, true);
            var matTex = matTexMem.AsSpan();

            for (int i = 0; i < materials.Length; i++)
            {
                matTex[i] = materials[i].Texture;
            }
            matTex.Sort();
            var texCount = 0;

            if (matTex.Length > 0)
            {
                texCount = 1;
                for (int i = 1; i < matTex.Length; i++)
                {
                    if (matTex[i - 1] != matTex[i])
                    {
                        texCount++;
                    }
                }
            }

            using var textureUsed = new ValueTypeRentMemory <bool>(textureNames.Length, true);

            var size   = new Vector2i(1024, 1024);  // TODO:
            var count  = 0;
            var buffer = new ValueTypeRentMemory <ColorByte>(size.X * size.Y * texCount, false);

            try {
                for (int i = 0; i < textureNames.Length; i++)
                {
                    if (matTex.Contains(i) == false)
                    {
                        continue;
                    }

                    using var _ = GetTexturePath(dir, textureNames[i], out var texturePath, out var ext);
                    var path = texturePath.ToString();

                    // Some pmx have the texture paths that don't exist. (Nobody references them.)
                    // So skip them.
                    if (resourcePackage.TryGetStream(path, out var stream) == false)
                    {
                        continue;
                    }
                    textureUsed[i] = true;
                    var dest = buffer.AsSpan(count * size.X * size.Y);
                    try {
                        using var image = Image.LoadToImageSource(stream, Image.GetTypeFromExt(ext));
                        if (image.Width != size.X || image.Height != size.Y)
                        {
                            using var resized = Image.Resized(image, size);
                            resized.GetPixels().CopyTo(dest);
                        }
                        else
                        {
                            image.GetPixels().CopyTo(dest);
                        }
                        count++;
                    }
                    finally {
                        stream.Dispose();
                    }
                }

                // Calculate texture index of each vertex
                {
                    var indices = pmx.SurfaceList.AsSpan().MarshalCast <Surface, int>();
                    int i       = 0;
                    foreach (var mat in materials)
                    {
                        for (int j = 0; j < mat.VertexCount; j++)
                        {
                            var unusedCount = 0;
                            foreach (var isUsed in textureUsed.AsSpan(0, mat.Texture))
                            {
                                if (isUsed == false)
                                {
                                    unusedCount++;
                                }
                            }
                            vertices[indices[i++]].TextureIndex = mat.Texture - unusedCount;
                        }
                    }
                }
            }
            catch {
                buffer.Dispose();
                throw;
            }
            return(BackToMainThread(arrayTexture, new Vector3i(size.X, size.Y, count), buffer, model.Screen !.TimingPoints.Update, ct));