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); } } }
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]); } })); }
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); }
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); }
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); }
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); } }
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); }
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); } } }
public UnsafeRawArrayDebuggerTypeProxy(UnsafeRawArray <T> entity) => _entity = entity;
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; } }
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));