static int ExportIndices(Vrm10Storage storage, BufferAccessor x, int offset, int count, ExportArgs option) { if (x.Count <= ushort.MaxValue) { if (x.ComponentType == AccessorValueType.UNSIGNED_INT) { // ensure ushort var src = x.GetSpan <UInt32>().Slice(offset, count); var bytes = new byte[src.Length * 2]; var dst = SpanLike.Wrap <UInt16>(new ArraySegment <byte>(bytes)); for (int i = 0; i < src.Length; ++i) { dst[i] = (ushort)src[i]; } var accessor = new BufferAccessor(new ArraySegment <byte>(bytes), AccessorValueType.UNSIGNED_SHORT, AccessorVectorType.SCALAR, count); return(accessor.AddAccessorTo(storage, 0, option.sparse, null, 0, count)); } else { return(x.AddAccessorTo(storage, 0, option.sparse, null, offset, count)); } } else { return(x.AddAccessorTo(storage, 0, option.sparse, null, offset, count)); } }
public static int AddAccessorTo(this BufferAccessor self, Vrm10Storage storage, int bufferIndex, // GltfBufferTargetType targetType, bool useSparse, Action <Memory <byte>, VrmProtobuf.Accessor> minMax = null, int offset = 0, int count = 0) { if (self.ComponentType == AccessorValueType.FLOAT && self.AccessorType == AccessorVectorType.VEC3 ) { var values = self.GetSpan <Vector3>(); // 巨大ポリゴンのモデル対策にValueTupleの型をushort -> uint へ var sparseValuesWithIndex = new List <ValueTuple <int, Vector3> >(); for (int i = 0; i < values.Length; ++i) { var v = values[i]; if (v != Vector3.Zero) { sparseValuesWithIndex.Add((i, v)); } } //var status = $"{sparseIndices.Count * 14}/{values.Length * 12}"; if (useSparse && sparseValuesWithIndex.Count > 0 && // avoid empty sparse sparseValuesWithIndex.Count * 16 < values.Length * 12) { // use sparse var sparseIndexBin = new byte[sparseValuesWithIndex.Count * 4].AsMemory(); var sparseIndexSpan = MemoryMarshal.Cast <byte, int>(sparseIndexBin.Span); var sparseValueBin = new byte[sparseValuesWithIndex.Count * 12].AsMemory(); var sparseValueSpan = MemoryMarshal.Cast <byte, Vector3>(sparseValueBin.Span); for (int i = 0; i < sparseValuesWithIndex.Count; ++i) { var(index, value) = sparseValuesWithIndex[i]; sparseIndexSpan[i] = index; sparseValueSpan[i] = value; } var sparseIndexView = storage.AppendToBuffer(bufferIndex, sparseIndexBin, 4); var sparseValueView = storage.AppendToBuffer(bufferIndex, sparseValueBin, 12); var accessorIndex = storage.Gltf.Accessors.Count; var accessor = new VrmProtobuf.Accessor { ComponentType = (int)self.ComponentType, Type = EnumUtil.Cast <VrmProtobuf.Accessor.Types.accessorType>(self.AccessorType), Count = self.Count, Sparse = new VrmProtobuf.AccessorSparse { Count = sparseValuesWithIndex.Count, Indices = new VrmProtobuf.AccessorSparseIndices { ComponentType = (int)AccessorValueType.UNSIGNED_INT, BufferView = sparseIndexView, }, Values = new VrmProtobuf.AccessorSparseValues { BufferView = sparseValueView, }, } }; if (minMax != null) { minMax(sparseValueBin, accessor); } storage.Gltf.Accessors.Add(accessor); return(accessorIndex); } } var viewIndex = self.AddViewTo(storage, bufferIndex, offset, count); return(self.AddAccessorTo(storage, viewIndex, minMax, 0, count)); }
public static int AddAccessorTo(this BufferAccessor self, Vrm10Storage storage, int bufferIndex, // GltfBufferTargetType targetType, bool useSparse, Action <ArraySegment <byte>, glTFAccessor> minMax = null, int offset = 0, int count = 0) { if (self.ComponentType == AccessorValueType.FLOAT && self.AccessorType == AccessorVectorType.VEC3 ) { var values = self.GetSpan <Vector3>(); // 巨大ポリゴンのモデル対策にValueTupleの型をushort -> uint へ var sparseValuesWithIndex = new List <ValueTuple <int, Vector3> >(); for (int i = 0; i < values.Length; ++i) { var v = values[i]; if (v != Vector3.Zero) { sparseValuesWithIndex.Add((i, v)); } } //var status = $"{sparseIndices.Count * 14}/{values.Length * 12}"; if (useSparse && sparseValuesWithIndex.Count > 0 && // avoid empty sparse sparseValuesWithIndex.Count * 16 < values.Length * 12) { // use sparse var sparseIndexBin = new ArraySegment <byte>(new byte[sparseValuesWithIndex.Count * 4]); var sparseIndexSpan = SpanLike.Wrap <Int32>(sparseIndexBin); var sparseValueBin = new ArraySegment <byte>(new byte[sparseValuesWithIndex.Count * 12]); var sparseValueSpan = SpanLike.Wrap <Vector3>(sparseValueBin); for (int i = 0; i < sparseValuesWithIndex.Count; ++i) { var(index, value) = sparseValuesWithIndex[i]; sparseIndexSpan[i] = index; sparseValueSpan[i] = value; } var sparseIndexView = storage.AppendToBuffer(bufferIndex, sparseIndexBin, 4); var sparseValueView = storage.AppendToBuffer(bufferIndex, sparseValueBin, 12); var accessorIndex = storage.Gltf.accessors.Count; var accessor = new glTFAccessor { componentType = (glComponentType)self.ComponentType, type = self.AccessorType.ToString(), count = self.Count, sparse = new glTFSparse { count = sparseValuesWithIndex.Count, indices = new glTFSparseIndices { componentType = (glComponentType)AccessorValueType.UNSIGNED_INT, bufferView = sparseIndexView, }, values = new glTFSparseValues { bufferView = sparseValueView, }, } }; if (minMax != null) { minMax(sparseValueBin, accessor); } storage.Gltf.accessors.Add(accessor); return(accessorIndex); } } var viewIndex = self.AddViewTo(storage, bufferIndex, offset, count); return(self.AddAccessorTo(storage, viewIndex, minMax, 0, count)); }