static void ReverseZ(BufferAccessor ba) { if (ba.ComponentType != AccessorValueType.FLOAT) { throw new Exception(); } if (ba.AccessorType == AccessorVectorType.VEC3) { var span = ba.GetSpan <Vector3>(); for (int i = 0; i < span.Length; ++i) { span[i] = span[i].ReverseZ(); } } else if (ba.AccessorType == AccessorVectorType.MAT4) { var span = ba.GetSpan <Matrix4x4>(); for (int i = 0; i < span.Length; ++i) { span[i] = span[i].ReverseZ(); } } else { throw new NotImplementedException(); } }
/// <summary> /// BoneSkinningもしくはMorphTargetの適用 /// <summary> public void Skinning(VertexBuffer vertexBuffer = null) { m_indexOfRoot = (ushort)Joints.IndexOf(Root); var addRoot = Root != null && m_indexOfRoot == ushort.MaxValue; if (addRoot) { m_indexOfRoot = (ushort)Joints.Count; Joints.Add(Root); } if (m_matrices == null) { m_matrices = new Matrix4x4[Joints.Count]; } if (InverseMatrices == null) { CalcInverseMatrices(); } else { if (addRoot) { var inverseArray = InverseMatrices.GetSpan <Matrix4x4>().ToArray(); InverseMatrices.Assign(inverseArray.Concat(new[] { Root.InverseMatrix }).ToArray().AsSpan()); } } var inverse = InverseMatrices.GetSpan <Matrix4x4>(); // if (Root != null) // { // var rootInverse = Root.InverseMatrix; // var root = Root.Matrix; // for (int i = 0; i < m_matrices.Length; ++i) // { // m_matrices[i] = inverse[i] * Joints[i].Matrix * rootInverse; // } // } // else { for (int i = 0; i < m_matrices.Length; ++i) { var inv = i < inverse.Length ? inverse[i] : Joints[i].InverseMatrix; m_matrices[i] = inv * Joints[i].Matrix; } } if (vertexBuffer != null) { Apply(vertexBuffer); } }
public Vector3 GetVector3(TimeSpan elapsed) { var(begin, end, ratio) = GetRange((float)elapsed.TotalSeconds); var values = Out.GetSpan <Vector3>(); if (begin == end) { return(values[begin]); } else { // TODO: curve interpolation return(Vector3.Lerp(values[begin], values[end], ratio)); } }
/// <summary> /// nullになったjointを除去して、boneweightを前に詰める /// </summary> public void FixBoneWeight(BufferAccessor jointsAccessor, BufferAccessor weightsAccessor) { var map = Joints.Select((x, i) => ValueTuple.Create(i, x)).Where(x => x.Item2 != null).ToArray(); var indexMap = Enumerable.Repeat(-1, Joints.Count).ToArray(); { for (int i = 0; i < map.Length; ++i) { indexMap[map[i].Item1] = i; } } Joints.RemoveAll(x => x == null); var joints = jointsAccessor.GetSpan <SkinJoints>(); var weights = weightsAccessor.GetSpan <Vector4>(); for (int i = 0; i < joints.Length; ++i) { var j = joints[i]; var w = weights[i]; Update(ref w.X, ref j.Joint0, indexMap); Update(ref w.Y, ref j.Joint1, indexMap); Update(ref w.Z, ref j.Joint2, indexMap); Update(ref w.W, ref j.Joint3, indexMap); joints[i] = j; weights[i] = w; } CalcInverseMatrices(); }
public void FixBoneWeight(BufferAccessor jointsAccessor, BufferAccessor weightsAccessor) { var map = Joints.Select((x, i) => ValueTuple.Create(i, x)).Where(x => x.Item2 != null).ToArray(); var indexMap = Enumerable.Repeat(-1, Joints.Count).ToArray(); { for (int i = 0; i < map.Length; ++i) { indexMap[map[i].Item1] = i; } } Joints.RemoveAll(x => x == null); var joints = jointsAccessor.GetSpan <SkinJoints>(); var weights = weightsAccessor.GetSpan <Vector4>(); for (int i = 0; i < joints.Length; ++i) { ref var j = ref joints[i]; ref var w = ref weights[i];
bool GetSubmeshOverlapped <T>() where T : struct { var indices = IndexBuffer.GetSpan <ushort>(); var offset = 0; var max = 0; foreach (var x in Submeshes) { var submeshIndices = indices.Slice(offset, x.DrawCount); var currentMax = 0; foreach (var y in submeshIndices) { if (y < max) { return(true); } currentMax = Math.Max(y, currentMax); } offset += x.DrawCount; max = currentMax; } return(false); }
ValueTuple <int, int, float> GetRange(float seconds) { var keys = In.GetSpan <float>(); if (seconds <= keys[0]) { return(0, 0, 0); } else if (seconds >= keys[keys.Length - 1]) { return(keys.Length - 1, keys.Length - 1, 0); } // search range float begin = keys[0]; float end; for (int i = 1; i < keys.Length; ++i) { end = keys[i]; if (seconds == end) { return(i, i, 0); } else if (seconds < end) { var ratio = (seconds - begin) / (end - begin); return(i - 1, i, ratio); } begin = end; } throw new Exception("not found"); }
// // Memory<byte> を新規に確保して置き換える // public void Append(BufferAccessor a, int offset = -1) { if (AccessorType != a.AccessorType) { System.Console.WriteLine(AccessorType.ToString() + "!=" + a.AccessorType.ToString()); throw new Exception("different AccessorType"); } // UNSIGNED_SHORT <-> UNSIGNED_INT の変換を許容して処理を続行 // 統合メッシュのprimitiveのIndexBufferが65,535(ushort.MaxValue)を超える場合や、変換前にindexBuffer.ComponetTypeがushortとuint混在する場合など if (ComponentType != a.ComponentType) { switch (a.ComponentType) { //ushort to uint case AccessorValueType.UNSIGNED_SHORT: { var src = a.GetSpan <UInt16>().Slice(0, a.Count); var bytes = new byte[src.Length * 4]; var dst = MemoryMarshal.Cast <byte, uint>(bytes); for (int i = 0; i < src.Length; ++i) { dst[i] = (uint)src[i]; } var accessor = new BufferAccessor(bytes, AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, a.Count); a = accessor; break; } //uint to ushort (おそらく通ることはない) case AccessorValueType.UNSIGNED_INT: { var src = a.GetSpan <UInt32>().Slice(0, a.Count); var bytes = new byte[src.Length * 2]; var dst = MemoryMarshal.Cast <byte, ushort>(bytes); for (int i = 0; i < src.Length; ++i) { dst[i] = (ushort)src[i]; } var accessor = new BufferAccessor(bytes, ComponentType, AccessorVectorType.SCALAR, a.Count); a = accessor; break; } default: throw new Exception("Cannot Convert ComponentType"); } } // 連結した新しいバッファを確保 var oldLength = Bytes.Length; ToByteLength(oldLength + a.Bytes.Length); a.Bytes.CopyTo(Bytes.Slice(oldLength)); Count += a.Count; if (offset > 0) { // 後半にoffsetを足す switch (ComponentType) { case AccessorValueType.UNSIGNED_SHORT: { var span = MemoryMarshal.Cast <byte, ushort>(Bytes.Slice(oldLength).Span); var ushortOffset = (ushort)offset; for (int i = 0; i < span.Length; ++i) { span[i] += ushortOffset; } } break; case AccessorValueType.UNSIGNED_INT: { var span = MemoryMarshal.Cast <byte, uint>(Bytes.Slice(oldLength).Span); var uintOffset = (uint)offset; for (int i = 0; i < span.Length; ++i) { span[i] += uintOffset; } } break; default: throw new NotImplementedException(); } } }