|
|
@@ -21,14 +21,14 @@ namespace SharpGLTF.Geometry
|
|
|
/// </summary>
|
|
|
/// <param name="vertexIndex">The index of the vertex.</param>
|
|
|
/// <returns>If the given index has a morphed vertex, it will return it, else ir will return the base vertex.</returns>
|
|
|
- IVertexGeometry GetVertex(int vertexIndex);
|
|
|
+ IVertexBuilder GetVertex(int vertexIndex);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Gets the <see cref="VertexGeometryDelta"/> of a given vertex for a given morph target.
|
|
|
/// </summary>
|
|
|
/// <param name="vertexIndex">The index of the vertex.</param>
|
|
|
/// <returns>A Vertex delta (Morphed vertex minus base vertex).</returns>
|
|
|
- VertexGeometryDelta GetVertexDelta(int vertexIndex);
|
|
|
+ VertexBuilder<VertexGeometryDelta, VertexMaterialDelta, VertexEmpty> GetVertexDelta(int vertexIndex);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -36,30 +36,31 @@ namespace SharpGLTF.Geometry
|
|
|
/// <see cref="PrimitiveBuilder{TMaterial, TvG, TvM, TvS}._UseMorphTarget(int)"/>
|
|
|
/// </summary>
|
|
|
/// <typeparam name="TvG">The vertex fragment type with Position, Normal and Tangent.</typeparam>
|
|
|
- sealed class PrimitiveMorphTargetBuilder<TvG> : IPrimitiveMorphTargetReader
|
|
|
+ class PrimitiveMorphTargetBuilder<TvG, TvM> : IPrimitiveMorphTargetReader
|
|
|
where TvG : struct, IVertexGeometry
|
|
|
+ where TvM : struct, IVertexMaterial
|
|
|
{
|
|
|
#region lifecycle
|
|
|
|
|
|
- internal PrimitiveMorphTargetBuilder(Func<int, TvG> baseVertexFunc)
|
|
|
+ internal PrimitiveMorphTargetBuilder(Func<int, VertexBuilder<TvG, TvM, VertexEmpty>> baseVertexFunc)
|
|
|
{
|
|
|
this._BaseVertexFunc = baseVertexFunc;
|
|
|
- this._MorphVertices = new Dictionary<int, TvG>();
|
|
|
+ this._MorphVertices = new Dictionary<int, VertexBuilder<TvG, TvM, VertexEmpty>>();
|
|
|
}
|
|
|
|
|
|
- internal PrimitiveMorphTargetBuilder(Func<int, TvG> baseVertexFunc, PrimitiveMorphTargetBuilder<TvG> other)
|
|
|
+ internal PrimitiveMorphTargetBuilder(Func<int, VertexBuilder<TvG, TvM, VertexEmpty>> baseVertexFunc, PrimitiveMorphTargetBuilder<TvG, TvM> other)
|
|
|
{
|
|
|
this._BaseVertexFunc = baseVertexFunc;
|
|
|
- this._MorphVertices = new Dictionary<int, TvG>(other._MorphVertices);
|
|
|
+ this._MorphVertices = new Dictionary<int, VertexBuilder<TvG, TvM, VertexEmpty>>(other._MorphVertices);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region data
|
|
|
|
|
|
- private readonly Func<int, TvG> _BaseVertexFunc;
|
|
|
+ private readonly Func<int, VertexBuilder<TvG, TvM, VertexEmpty>> _BaseVertexFunc;
|
|
|
|
|
|
- private readonly Dictionary<int, TvG> _MorphVertices;
|
|
|
+ private readonly Dictionary<int, VertexBuilder<TvG, TvM, VertexEmpty>> _MorphVertices;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
@@ -70,54 +71,60 @@ namespace SharpGLTF.Geometry
|
|
|
return _MorphVertices.Keys;
|
|
|
}
|
|
|
|
|
|
- public VertexGeometryDelta GetVertexDelta(int vertexIndex)
|
|
|
+ public VertexBuilder<VertexGeometryDelta, VertexMaterialDelta, VertexEmpty> GetVertexDelta(int vertexIndex)
|
|
|
{
|
|
|
- if (_MorphVertices.TryGetValue(vertexIndex, out TvG value))
|
|
|
+ if (_MorphVertices.TryGetValue(vertexIndex, out VertexBuilder<TvG, TvM, VertexEmpty> value))
|
|
|
{
|
|
|
- return value.Subtract(_BaseVertexFunc(vertexIndex));
|
|
|
+ var vertex = _BaseVertexFunc(vertexIndex);
|
|
|
+ return new VertexBuilder<VertexGeometryDelta, VertexMaterialDelta, VertexEmpty>(
|
|
|
+ value.Geometry.Subtract(vertex.Geometry),
|
|
|
+ value.Material.Subtract(vertex.Material));
|
|
|
}
|
|
|
|
|
|
return default;
|
|
|
}
|
|
|
|
|
|
- public void SetVertexDelta(int vertexIndex, VertexGeometryDelta value)
|
|
|
+ public void SetVertexDelta(int vertexIndex, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta)
|
|
|
{
|
|
|
- if (object.Equals(value, default(VertexGeometryDelta)))
|
|
|
+ if (object.Equals(geometryDelta, default(VertexGeometryDelta)))
|
|
|
{
|
|
|
_RemoveVertex(vertexIndex);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var vertex = _BaseVertexFunc(vertexIndex);
|
|
|
- vertex.Add(value);
|
|
|
+
|
|
|
+ vertex.Geometry.Add(geometryDelta);
|
|
|
+ if (typeof(TvM) != typeof(VertexEmpty))
|
|
|
+ vertex.Material.Add(materialDelta);
|
|
|
|
|
|
_SetVertex(vertexIndex, vertex);
|
|
|
}
|
|
|
|
|
|
- IVertexGeometry IPrimitiveMorphTargetReader.GetVertex(int vertexIndex)
|
|
|
+ IVertexBuilder IPrimitiveMorphTargetReader.GetVertex(int vertexIndex)
|
|
|
{
|
|
|
- return _MorphVertices.TryGetValue(vertexIndex, out TvG value) ? value : _BaseVertexFunc(vertexIndex);
|
|
|
+ return _MorphVertices.TryGetValue(vertexIndex, out VertexBuilder<TvG, TvM, VertexEmpty> value) ? value : _BaseVertexFunc(vertexIndex);
|
|
|
}
|
|
|
|
|
|
- public TvG GetVertex(int vertexIndex)
|
|
|
+ public VertexBuilder<TvG, TvM, VertexEmpty> GetVertex(int vertexIndex)
|
|
|
{
|
|
|
- return _MorphVertices.TryGetValue(vertexIndex, out TvG value) ? value : _BaseVertexFunc(vertexIndex);
|
|
|
+ return _MorphVertices.TryGetValue(vertexIndex, out VertexBuilder<TvG, TvM, VertexEmpty> value) ? value : _BaseVertexFunc(vertexIndex);
|
|
|
}
|
|
|
|
|
|
- public void SetVertex(int vertexIndex, TvG value)
|
|
|
+ public void SetVertex(int vertexIndex, VertexBuilder<TvG, TvM, VertexEmpty> vertex)
|
|
|
{
|
|
|
- if (object.Equals(value, _BaseVertexFunc(vertexIndex)))
|
|
|
+ if (object.Equals(vertex, _BaseVertexFunc(vertexIndex)))
|
|
|
{
|
|
|
_RemoveVertex(vertexIndex);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- _SetVertex(vertexIndex, value);
|
|
|
+ _SetVertex(vertexIndex, vertex);
|
|
|
}
|
|
|
|
|
|
- private void _SetVertex(int vertexIndex, TvG value)
|
|
|
+ private void _SetVertex(int vertexIndex, VertexBuilder<TvG, TvM, VertexEmpty> vertex)
|
|
|
{
|
|
|
- _MorphVertices[vertexIndex] = value;
|
|
|
+ _MorphVertices[vertexIndex] = vertex;
|
|
|
}
|
|
|
|
|
|
private void _RemoveVertex(int vertexIndex)
|
|
|
@@ -129,7 +136,7 @@ namespace SharpGLTF.Geometry
|
|
|
|
|
|
#region internals
|
|
|
|
|
|
- internal void TransformVertices(Func<TvG, TvG> vertexFunc)
|
|
|
+ internal void TransformVertices(Func<VertexBuilder<TvG, TvM, VertexEmpty>, VertexBuilder<TvG, TvM, VertexEmpty>> vertexFunc)
|
|
|
{
|
|
|
foreach (var vidx in _MorphVertices.Keys)
|
|
|
{
|
|
|
@@ -141,7 +148,7 @@ namespace SharpGLTF.Geometry
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- internal void SetMorphTargets(IPrimitiveMorphTargetReader other, IReadOnlyDictionary<int, int> vertexMap, Func<IVertexGeometry, TvG> vertexFunc)
|
|
|
+ internal void SetMorphTargets(IPrimitiveMorphTargetReader other, IReadOnlyDictionary<int, int> vertexMap, Func<IVertexGeometry, VertexBuilder<TvG, TvM, VertexEmpty>> vertexFunc)
|
|
|
{
|
|
|
Guard.NotNull(vertexFunc, nameof(vertexFunc));
|
|
|
|
|
|
@@ -149,7 +156,7 @@ namespace SharpGLTF.Geometry
|
|
|
|
|
|
foreach (var srcVidx in indices)
|
|
|
{
|
|
|
- var g = vertexFunc(other.GetVertex(srcVidx));
|
|
|
+ var g = vertexFunc(other.GetVertex(srcVidx).GetGeometry());
|
|
|
|
|
|
var dstVidx = srcVidx;
|
|
|
|
|
|
@@ -182,19 +189,43 @@ namespace SharpGLTF.Geometry
|
|
|
/// <param name="morphVertex">The morphed vertex.</param>
|
|
|
void SetVertex(IVertexGeometry meshVertex, IVertexGeometry morphVertex);
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Sets an absolute morph target.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="meshVertex">The base mesh vertex to morph.</param>
|
|
|
+ /// <param name="morphVertex">The morphed vertex.</param>
|
|
|
+ /// <param name="morphMaterial">The morphed vertex material.</param>
|
|
|
+ void SetVertex(IVertexGeometry meshVertex, IVertexGeometry morphVertex, IVertexMaterial morphMaterial);
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Sets a relative morph target
|
|
|
/// </summary>
|
|
|
/// <param name="meshVertex">The base mesh vertex to morph.</param>
|
|
|
- /// <param name="delta">The offset from <paramref name="meshVertex"/> to morph.</param>
|
|
|
- void SetVertexDelta(IVertexGeometry meshVertex, VertexGeometryDelta delta);
|
|
|
+ /// <param name="geometryDelta">The offset from <paramref name="meshVertex"/> to morph.</param>
|
|
|
+ void SetVertexDelta(IVertexGeometry meshVertex, VertexGeometryDelta geometryDelta);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Sets a relative morph target
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="meshVertex">The base mesh vertex to morph.</param>
|
|
|
+ /// <param name="geometryDelta">The offset from <paramref name="meshVertex"/> to morph.</param>
|
|
|
+ /// <param name="materialDelta">The offset from <paramref name="meshVertex"/> material to morph.</param>
|
|
|
+ void SetVertexDelta(IVertexGeometry meshVertex, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Sets a relative morph target to all base mesh vertices matching <paramref name="meshPosition"/>.
|
|
|
/// </summary>
|
|
|
/// <param name="meshPosition">The base vertex position.</param>
|
|
|
- /// <param name="delta">The offset to apply to each matching vertex found.</param>
|
|
|
- void SetVertexDelta(Vector3 meshPosition, VertexGeometryDelta delta);
|
|
|
+ /// <param name="geometryDelta">The offset to apply to each matching vertex found.</param>
|
|
|
+ void SetVertexDelta(Vector3 meshPosition, VertexGeometryDelta geometryDelta);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Sets a relative morph target to all base mesh vertices matching <paramref name="meshPosition"/>.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="meshPosition">The base vertex position.</param>
|
|
|
+ /// <param name="geometryDelta">The offset to apply to each matching vertex found.</param>
|
|
|
+ /// <param name="materialDelta">The offset to apply to each matching vertex material found.</param>
|
|
|
+ void SetVertexDelta(Vector3 meshPosition, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -273,15 +304,49 @@ namespace SharpGLTF.Geometry
|
|
|
return _Positions.TryGetValue(position, out List<TvG> geos) ? (IReadOnlyList<TvG>)geos : Array.Empty<TvG>();
|
|
|
}
|
|
|
|
|
|
- public void SetVertexDelta(Vector3 key, VertexGeometryDelta delta)
|
|
|
+ public void SetVertexDelta(Vector3 key, VertexGeometryDelta geometryDelta)
|
|
|
{
|
|
|
if (_Positions.TryGetValue(key, out List<TvG> geos))
|
|
|
{
|
|
|
- foreach (var g in geos) SetVertexDelta(g, delta);
|
|
|
+ foreach (var g in geos) SetVertexDelta(g, geometryDelta, VertexMaterialDelta.Zero);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void SetVertex(TvG meshVertex, TvG morphVertex)
|
|
|
+ public void SetVertexDelta(Vector3 key, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta)
|
|
|
+ {
|
|
|
+ if (_Positions.TryGetValue(key, out List<TvG> geos))
|
|
|
+ {
|
|
|
+ foreach (var g in geos) SetVertexDelta(g, geometryDelta, materialDelta);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetVertexDelta(TvG meshVertex, VertexGeometryDelta geometryDelta)
|
|
|
+ {
|
|
|
+ if (_Vertices.TryGetValue(meshVertex, out List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)> val))
|
|
|
+ {
|
|
|
+ foreach (var entry in val)
|
|
|
+ {
|
|
|
+ entry.Item1
|
|
|
+ ._UseMorphTarget(_MorphTargetIndex)
|
|
|
+ .SetVertexDelta(entry.Item2, geometryDelta, VertexMaterialDelta.Zero);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetVertexDelta(TvG meshVertex, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta)
|
|
|
+ {
|
|
|
+ if (_Vertices.TryGetValue(meshVertex, out List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)> val))
|
|
|
+ {
|
|
|
+ foreach (var entry in val)
|
|
|
+ {
|
|
|
+ entry.Item1
|
|
|
+ ._UseMorphTarget(_MorphTargetIndex)
|
|
|
+ .SetVertexDelta(entry.Item2, geometryDelta, materialDelta);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetVertex(TvG meshVertex, VertexBuilder<TvG, TvM, VertexEmpty> morphVertex)
|
|
|
{
|
|
|
if (_Vertices.TryGetValue(meshVertex, out List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)> val))
|
|
|
{
|
|
|
@@ -294,15 +359,16 @@ namespace SharpGLTF.Geometry
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void SetVertexDelta(TvG meshVertex, VertexGeometryDelta delta)
|
|
|
+ public void SetVertex(TvG meshVertex, TvG morphVertex)
|
|
|
{
|
|
|
if (_Vertices.TryGetValue(meshVertex, out List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)> val))
|
|
|
{
|
|
|
foreach (var entry in val)
|
|
|
{
|
|
|
+ var vertexMaterial = entry.Item1.Vertices[entry.Item2].Material;
|
|
|
entry.Item1
|
|
|
._UseMorphTarget(_MorphTargetIndex)
|
|
|
- .SetVertexDelta(entry.Item2, delta);
|
|
|
+ .SetVertex(entry.Item2, new VertexBuilder<TvG, TvM, VertexEmpty>(morphVertex, vertexMaterial));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -322,12 +388,24 @@ namespace SharpGLTF.Geometry
|
|
|
|
|
|
void IMorphTargetBuilder.SetVertex(IVertexGeometry meshVertex, IVertexGeometry morphVertex)
|
|
|
{
|
|
|
- SetVertex(meshVertex.ConvertToGeometry<TvG>(), morphVertex.ConvertToGeometry<TvG>());
|
|
|
+ SetVertex(meshVertex.ConvertToGeometry<TvG>(),
|
|
|
+ new VertexBuilder<TvG, TvM, VertexEmpty>(morphVertex.ConvertToGeometry<TvG>(), default(VertexEmpty).ConvertToMaterial<TvM>()));
|
|
|
+ }
|
|
|
+
|
|
|
+ void IMorphTargetBuilder.SetVertex(IVertexGeometry meshVertex, IVertexGeometry morphVertex, IVertexMaterial morphMaterial)
|
|
|
+ {
|
|
|
+ SetVertex(meshVertex.ConvertToGeometry<TvG>(),
|
|
|
+ new VertexBuilder<TvG, TvM, VertexEmpty>(morphVertex.ConvertToGeometry<TvG>(), morphMaterial.ConvertToMaterial<TvM>()));
|
|
|
+ }
|
|
|
+
|
|
|
+ void IMorphTargetBuilder.SetVertexDelta(IVertexGeometry meshVertex, VertexGeometryDelta geometryDelta)
|
|
|
+ {
|
|
|
+ SetVertexDelta(meshVertex.ConvertToGeometry<TvG>(), geometryDelta, VertexMaterialDelta.Zero);
|
|
|
}
|
|
|
|
|
|
- void IMorphTargetBuilder.SetVertexDelta(IVertexGeometry meshVertex, VertexGeometryDelta delta)
|
|
|
+ void IMorphTargetBuilder.SetVertexDelta(IVertexGeometry meshVertex, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta)
|
|
|
{
|
|
|
- SetVertexDelta(meshVertex.ConvertToGeometry<TvG>(), delta);
|
|
|
+ SetVertexDelta(meshVertex.ConvertToGeometry<TvG>(), geometryDelta, materialDelta);
|
|
|
}
|
|
|
|
|
|
#endregion
|