Files
AR-Menu/Library/PackageCache/com.unity.cloud.gltfast@db5a82ec0b47/Runtime/Scripts/Schema/MeshPrimitive.cs
2025-11-30 08:35:03 +02:00

446 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors
// SPDX-License-Identifier: Apache-2.0
using System;
namespace GLTFast.Schema
{
/// <summary>
/// The topology type of primitives to render
/// </summary>
/// <seealso href="https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode"/>
public enum DrawMode
{
/// <summary>Points</summary>
Points = 0,
/// <summary>Lines</summary>
Lines = 1,
/// <summary>Line loop</summary>
LineLoop = 2,
/// <summary>Line strip</summary>
LineStrip = 3,
/// <summary>Triangles</summary>
Triangles = 4,
/// <summary>Triangle strip</summary>
TriangleStrip = 5,
/// <summary>Triangle fan</summary>
TriangleFan = 6
}
/// <inheritdoc />
[Serializable]
public class MeshPrimitive : MeshPrimitiveBase<MeshPrimitiveExtensions> { }
/// <inheritdoc />
/// <typeparam name="TExtensions">Mesh primitive extensions type</typeparam>
[Serializable]
public class MeshPrimitiveBase<TExtensions> : MeshPrimitiveBase
where TExtensions : MeshPrimitiveExtensions
{
/// <inheritdoc cref="Extensions"/>
public TExtensions extensions;
/// <inheritdoc />
public override MeshPrimitiveExtensions Extensions => extensions;
/// <inheritdoc />
internal override void UnsetExtensions()
{
extensions = null;
}
}
/// <summary>
/// Geometry to be rendered with the given material.
/// </summary>
[Serializable]
public abstract class MeshPrimitiveBase : ICloneable, IMaterialsVariantsSlot
{
/// <summary>
/// A dictionary object, where each key corresponds to mesh attribute semantic
/// and each value is the index of the accessor containing attribute's data.
/// </summary>
public Attributes attributes;
/// <summary>
/// The index of the accessor that contains mesh indices.
/// When this is not defined, the primitives should be rendered without indices
/// using `drawArrays()`. When defined, the accessor must contain indices:
/// the `bufferView` referenced by the accessor must have a `target` equal
/// to 34963 (ELEMENT_ARRAY_BUFFER); a `byteStride` that is tightly packed,
/// i.e., 0 or the byte size of `componentType` in bytes;
/// `componentType` must be 5121 (UNSIGNED_BYTE), 5123 (UNSIGNED_SHORT)
/// or 5125 (UNSIGNED_INT), the latter is only allowed
/// when `OES_element_index_uint` extension is used; `type` must be `\"SCALAR\"`.
/// </summary>
public int indices = -1;
/// <summary>
/// The index of the material to apply to this primitive when rendering.
/// </summary>
public int material = -1;
/// <summary>
/// The type of primitives to render. All valid values correspond to WebGL enums.
/// </summary>
public DrawMode mode = DrawMode.Triangles;
/// <summary>
/// An array of Morph Targets, each Morph Target is a dictionary mapping
/// attributes to their deviations
/// in the Morph Target (index of the accessor containing the attribute
/// displacements' data).
/// </summary>
public MorphTarget[] targets;
/// <inheritdoc cref="MeshPrimitiveExtensions"/>
public abstract MeshPrimitiveExtensions Extensions { get; }
/// <inheritdoc />
public int GetMaterialIndex(int variantIndex)
{
var mapping = Extensions?.KHR_materials_variants;
if (mapping != null && mapping.TryGetMaterialIndex(variantIndex, out var materialIndex))
{
return materialIndex;
}
return material;
}
/// <summary>`
/// Sets <see cref="Extensions"/> to null.
/// </summary>
internal abstract void UnsetExtensions();
#if DRACO_IS_INSTALLED
public bool IsDracoCompressed => Extensions!=null && Extensions.KHR_draco_mesh_compression != null;
#endif
/// <summary>
/// Determines whether two object instances are equal.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
// TODO: Remove upon next major release. This serves no purpose anymore except keeping the API intact.
public override bool Equals(object obj)
{
// ReSharper disable once BaseObjectEqualsIsObjectEquals
return base.Equals(obj);
}
/// <summary>
/// Default hash function.
/// </summary>
/// <returns>A hash code for the current object.</returns>
// TODO: Remove upon next major release. This serves no purpose anymore except keeping the API intact.
public override int GetHashCode()
{
// ReSharper disable once BaseObjectGetHashCodeCallInGetHashCode
return base.GetHashCode();
}
/// <summary>
/// Clones the object
/// </summary>
/// <returns>Member-wise clone</returns>
public object Clone()
{
return MemberwiseClone();
}
internal void GltfSerialize(JsonWriter writer)
{
writer.AddObject();
if (attributes != null)
{
writer.AddProperty("attributes");
attributes.GltfSerialize(writer);
}
if (indices >= 0)
{
writer.AddProperty("indices", indices);
}
if (material >= 0)
{
writer.AddProperty("material", material);
}
if (mode != DrawMode.Triangles)
{
writer.AddProperty("mode", (int)mode);
}
if (targets != null)
{
writer.AddArray("targets");
foreach (var target in targets)
{
target.GltfSerialize(writer);
}
writer.CloseArray();
}
if (Extensions != null)
{
writer.AddProperty("extensions");
Extensions.GltfSerialize(writer);
}
writer.Close();
}
}
/// <summary>
/// Mesh vertex attribute collection. Each property value is the index of
/// the accessor containing attributes data.
/// </summary>
[Serializable]
public class Attributes
{
// Names are identical to glTF specified property names, that's why
// inconsistent names are ignored.
// ReSharper disable InconsistentNaming
/// <summary>Vertex position accessor index.</summary>
public int POSITION = -1;
/// <summary>Vertex normals accessor index.</summary>
public int NORMAL = -1;
/// <summary>Vertex tangents accessor index.</summary>
public int TANGENT = -1;
/// <summary>Texture coordinates accessor index.</summary>
public int TEXCOORD_0 = -1;
/// <summary>Texture coordinates accessor index (second UV set).</summary>
public int TEXCOORD_1 = -1;
/// <summary>Texture coordinates accessor index (third UV set).</summary>
public int TEXCOORD_2 = -1;
/// <summary>Texture coordinates accessor index (fourth UV set).</summary>
public int TEXCOORD_3 = -1;
/// <summary>Texture coordinates accessor index (fifth UV set).</summary>
public int TEXCOORD_4 = -1;
/// <summary>Texture coordinates accessor index (sixth UV set).</summary>
public int TEXCOORD_5 = -1;
/// <summary>Texture coordinates accessor index (seventh UV set).</summary>
public int TEXCOORD_6 = -1;
/// <summary>Texture coordinates accessor index (eighth UV set).</summary>
public int TEXCOORD_7 = -1;
/// <summary>Texture coordinates accessor index (ninth UV set).</summary>
public int TEXCOORD_8 = -1;
/// <summary>Vertex color accessor index.</summary>
public int COLOR_0 = -1;
/// <summary>Bone joints accessor index.</summary>
public int JOINTS_0 = -1;
/// <summary>Bone weights accessor index.</summary>
public int WEIGHTS_0 = -1;
// ReSharper restore InconsistentNaming
/// <summary>
/// Determines whether two object instances are equal.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
// TODO: Remove upon next major release. This serves no purpose anymore except keeping the API intact.
public override bool Equals(object obj)
{
// ReSharper disable once BaseObjectEqualsIsObjectEquals
return base.Equals(obj);
}
/// <summary>
/// Default hash function.
/// </summary>
/// <returns>A hash code for the current object.</returns>
// TODO: Remove upon next major release. This serves no purpose anymore except keeping the API intact.
public override int GetHashCode()
{
// ReSharper disable once BaseObjectGetHashCodeCallInGetHashCode
return base.GetHashCode();
}
/// <summary>
/// Calculates the texture coordinate set quantity.
/// </summary>
/// <returns>Texture coordinate set quantity.</returns>
public int GetTexCoordsCount()
{
if (TEXCOORD_0 < 0) return 0;
if (TEXCOORD_1 < 0) return 1;
if (TEXCOORD_2 < 0) return 2;
if (TEXCOORD_3 < 0) return 3;
if (TEXCOORD_4 < 0) return 4;
if (TEXCOORD_5 < 0) return 5;
if (TEXCOORD_6 < 0) return 6;
if (TEXCOORD_7 < 0) return 7;
return TEXCOORD_8 < 0 ? 8 : 9;
}
/// <summary>
/// Tries to consolidate all `TEXCOORD_*` accessor fields into a single array.
/// </summary>
/// <param name="uvAccessors">Resulting array of accessor indices.</param>
/// <param name="limitExceeded">If true, the glTF has more UV sets than glTFast supports.</param>
/// <returns>True if there's one or more UV sets and the result is valid. False otherwise.</returns>
public bool TryGetAllUVAccessors(out int[] uvAccessors, out bool limitExceeded)
{
if (TEXCOORD_0 >= 0)
{
var uvCount = GetTexCoordsCount();
uvAccessors = new int[uvCount];
uvAccessors[0] = TEXCOORD_0;
if (TEXCOORD_1 >= 0)
{
uvAccessors[1] = TEXCOORD_1;
}
if (TEXCOORD_2 >= 0)
{
uvAccessors[2] = TEXCOORD_2;
}
if (TEXCOORD_3 >= 0)
{
uvAccessors[3] = TEXCOORD_3;
}
if (TEXCOORD_4 >= 0)
{
uvAccessors[4] = TEXCOORD_4;
}
if (TEXCOORD_5 >= 0)
{
uvAccessors[5] = TEXCOORD_5;
}
if (TEXCOORD_6 >= 0)
{
uvAccessors[6] = TEXCOORD_6;
}
if (TEXCOORD_7 >= 0)
{
uvAccessors[7] = TEXCOORD_7;
}
limitExceeded = TEXCOORD_8 >= 0;
return true;
}
uvAccessors = null;
limitExceeded = false;
return false;
}
internal void GltfSerialize(JsonWriter writer)
{
writer.AddObject();
if (POSITION >= 0) writer.AddProperty("POSITION", POSITION);
if (NORMAL >= 0) writer.AddProperty("NORMAL", NORMAL);
if (TANGENT >= 0) writer.AddProperty("TANGENT", TANGENT);
if (TEXCOORD_0 >= 0) writer.AddProperty("TEXCOORD_0", TEXCOORD_0);
if (TEXCOORD_1 >= 0) writer.AddProperty("TEXCOORD_1", TEXCOORD_1);
if (TEXCOORD_2 >= 0) writer.AddProperty("TEXCOORD_2", TEXCOORD_2);
if (TEXCOORD_3 >= 0) writer.AddProperty("TEXCOORD_3", TEXCOORD_3);
if (TEXCOORD_4 >= 0) writer.AddProperty("TEXCOORD_4", TEXCOORD_4);
if (TEXCOORD_5 >= 0) writer.AddProperty("TEXCOORD_5", TEXCOORD_5);
if (TEXCOORD_6 >= 0) writer.AddProperty("TEXCOORD_6", TEXCOORD_6);
if (TEXCOORD_7 >= 0) writer.AddProperty("TEXCOORD_7", TEXCOORD_7);
if (COLOR_0 >= 0) writer.AddProperty("COLOR_0", COLOR_0);
if (JOINTS_0 >= 0) writer.AddProperty("JOINTS_0", JOINTS_0);
if (WEIGHTS_0 >= 0) writer.AddProperty("WEIGHTS_0", WEIGHTS_0);
writer.Close();
}
}
/// <summary>
/// Mesh primitive extensions
/// </summary>
[Serializable]
public class MeshPrimitiveExtensions
{
#if DRACO_IS_INSTALLED
// ReSharper disable once InconsistentNaming
public MeshPrimitiveDracoExtension KHR_draco_mesh_compression;
#endif
/// <inheritdoc cref="MaterialsVariantsMeshPrimitiveExtension"/>
// ReSharper disable once InconsistentNaming
public MaterialsVariantsMeshPrimitiveExtension KHR_materials_variants;
internal void GltfSerialize(JsonWriter writer)
{
writer.AddObject();
#if DRACO_IS_INSTALLED
if (KHR_draco_mesh_compression != null) {
writer.AddProperty("KHR_draco_mesh_compression");
KHR_draco_mesh_compression.GltfSerialize(writer);
}
#endif
if (KHR_materials_variants != null)
{
writer.AddProperty("KHR_materials_variants");
KHR_materials_variants.GltfSerialize(writer);
}
writer.Close();
}
}
#if DRACO_IS_INSTALLED
[Serializable]
public class MeshPrimitiveDracoExtension {
public int bufferView;
public Attributes attributes;
internal void GltfSerialize(JsonWriter writer) {
writer.AddObject();
writer.AddProperty("bufferView", bufferView);
writer.AddProperty("attributes");
attributes.GltfSerialize(writer);
writer.Close();
}
}
#endif
/// <summary>
/// Morph target (blend shape)
/// </summary>
[Serializable]
public class MorphTarget
{
// Names are identical to glTF specified property names, that's why
// inconsistent names are ignored.
// ReSharper disable InconsistentNaming
/// <summary>Vertex position deviation accessor index.</summary>
public int POSITION = -1;
/// <summary>Vertex normal deviation accessor index.</summary>
public int NORMAL = -1;
/// <summary>Vertex tangent deviation accessor index.</summary>
public int TANGENT = -1;
// ReSharper restore InconsistentNaming
/// <summary>
/// Determines whether two object instances are equal.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
// TODO: Remove upon next major release. This serves no purpose anymore except keeping the API intact.
public override bool Equals(object obj)
{
// ReSharper disable once BaseObjectEqualsIsObjectEquals
return base.Equals(obj);
}
/// <summary>
/// Default hash function.
/// </summary>
/// <returns>A hash code for the current object.</returns>
// TODO: Remove upon next major release. This serves no purpose anymore except keeping the API intact.
public override int GetHashCode()
{
// ReSharper disable once BaseObjectGetHashCodeCallInGetHashCode
return base.GetHashCode();
}
internal void GltfSerialize(JsonWriter writer)
{
if (POSITION >= 0) writer.AddProperty("POSITION", POSITION);
if (NORMAL >= 0) writer.AddProperty("NORMAL", NORMAL);
if (TANGENT >= 0) writer.AddProperty("TANGENT", TANGENT);
}
}
}