Skip to content

Instantly share code, notes, and snippets.

@iszn11
Last active June 2, 2023 12:16
Show Gist options
  • Save iszn11/045cee44e53b64754bcb71814651ec52 to your computer and use it in GitHub Desktop.
Save iszn11/045cee44e53b64754bcb71814651ec52 to your computer and use it in GitHub Desktop.
import * as t from "io-ts";
export type Accessor = { componentType: ComponentType, count: number, type: AccessorType, bufferView?: number, byteOffset?: number, normalized?: boolean, max?: number[], min?: number[], sparse?: AccessorSparse, extensions?: Extensions, extras?: unknown };
export type AccessorSparse = { count: number, indices: AccessorSparseIndices, values: AccessorSparseValues, extensions?: Extensions, extras?: unknown };
export type AccessorSparseIndices = { bufferView: number, componentType: IndexComponentType, byteOffset?: number, extensions?: Extensions, extras?: unknown };
export type AccessorSparseValues = { bufferView: number, byteOffset?: number, extensions?: Extensions, extras?: unknown };
export type Animation = { channels: AnimationChannel[], samplers: AnimationSampler[], name?: string, extensions?: Extensions, extras?: unknown };
export type AnimationChannel = { sampler: number, target: AnimationChannelTarget, extensions?: Extensions, extras?: unknown };
export type AnimationChannelTarget = { path: AnimationChannelTargetPath, node?: number, extensions?: Extensions, extras?: unknown };
export type AnimationSampler = { input: number, output: number, interpolation?: AnimationSamplerInterpolation, extensions?: Extensions, extras?: unknown };
export type Asset = { version: string, copyright?: string, generator?: string, minVersion?: string, extensions?: Extensions, extras?: unknown };
export type Buffer = { byteLength: number, uri?: string, name?: string, extensions?: Extensions, extras?: unknown };
export type BufferView = { buffer: number, byteLength: number, byteOffset?: number, byteStride?: number, target?: BufferViewTarget, name?: string, extensions?: Extensions, extras?: unknown };
export type CameraBase = { name?: string, extensions?: Extensions, extras?: unknown };
export type CameraOrthographic = CameraBase & { type: "orthographic", orthographic: Orthographic };
export type CameraPerspective = CameraBase & { type: "perspective", perspective: Perspective };
export type Camera = CameraOrthographic | CameraPerspective;
export type Gltf = { asset: Asset, extensionsUsed?: string[], extensionsRequired?: string[], accessors?: Accessor[], animations?: Animation[], buffers?: Buffer[], bufferViews?: BufferView[], cameras?: Camera[], images?: Image[], materials?: Material[], meshes?: Mesh[], nodes?: Node[], samplers?: Sampler[], scene?: number, scenes?: Scene[], skins?: Skin[], textures?: Texture[], extensions?: Extensions, extras?: unknown };
export type Image = { uri?: string, mimeType?: ImageMimeType, bufferView?: number, name?: string, extensions?: Extensions, extras?: unknown };
export type Material = { name?: string, extensions?: Extensions, extras?: unknown, pbrMetallicRoughness?: MaterialPbrMetallicRoughness, normalTexture?: MaterialNormalTextureInfo, occlusionTexture?: MaterialOcclusionTextureInfo, emissiveTexture?: TextureInfo, emissiveFactor?: Vector3Tuple, alphaMode?: AlphaMode, alphaCutoff?: number, doubleSided?: boolean };
export type MaterialNormalTextureInfo = { index: number, texCoord?: number, scale?: number, extensions?: Extensions, extras?: unknown };
export type MaterialOcclusionTextureInfo = { index: number, texCoord?: number, strength?: number, extensions?: Extensions, extras?: unknown };
export type MaterialPbrMetallicRoughness = { baseColorFactor?: Vector4Tuple, baseColorTexture?: TextureInfo, metallicFactor?: number, roughnessFactor?: number, metallicRoughnessTexture?: TextureInfo, extensions?: Extensions, extras?: unknown };
export type Mesh = { primitives: MeshPrimitive[], weights?: number[], name?: string, extensions?: Extensions, extras?: unknown };
export type MeshPrimitive = { attributes: Attributes, indices?: number, material?: number, mode?: PrimitiveMode, targets?: Attributes[], extensions?: Extensions, extras?: unknown };
export type Node = { camera?: number, children?: number[], skin?: number, matrix?: Matrix4x4Tuple, mesh?: number, rotation?: Vector4Tuple, scale?: Vector3Tuple, translation?: Vector3Tuple, weights?: number[], name?: string, extensions?: Extensions, extras?: unknown };
export type Sampler = { magFilter?: MagFilter, minFilter?: MinFilter, wrapS?: WrappingMode, wrapT?: WrappingMode, name?: string, extensions?: Extensions, extras?: unknown };
export type Scene = { nodes?: number[], name?: string, extensions?: Extensions, extras?: unknown };
export type Skin = { inverseBindMatrices?: number, skeleton?: number, name?: string, extensions?: Extensions, extras?: unknown };
export type Texture = { sampler?: number, source?: number, name?: string, extensions?: Extensions, extras?: unknown };
export type TextureInfo = { index: number, texCoord?: number, extensions?: Extensions, extras?: unknown };
export type AlphaMode = "OPAQUE" | "MASK" | "BLEND";
export type AnimationChannelTargetPath = "translation" | "rotation" | "scale" | "weights";
export type AccessorType = "SCALAR" | "VEC2" | "VEC3" | "VEC4" | "MAT2" | "MAT3" | "MAT4";
export type AnimationSamplerInterpolation = "LINEAR" | "STEP" | "CUBICSPLINE";
export type Attributes = Record<string, number>;
export enum BufferViewTarget { VertexBuffer = 34962, IndexBuffer = 34963 }
export enum ComponentType { SignedByte = 5120, UnsignedByte = 5121, SignedShort = 5122, UnsignedShort = 5123, UnsignedInt = 5125, Float = 5126 }
export enum IndexComponentType { UnsignedByte = 5121, UnsignedShort = 5123, UnsignedInt = 5125 }
export type ImageMimeType = "image/jpeg" | "image/png";
export enum MagFilter { Nearest = 9728, Linear = 9729 }
export enum MinFilter { Nearest = 9728, Linear = 9729, NearestMipmapNearest = 9984, LinearMipmapNearest = 9985, NearestMipmapLinear = 9986, LinearMipmapLinear = 9987 }
export type Orthographic = { xmag: number, ymag: number, zfar: number, znear: number, extensions?: Extensions, extras?: unknown };
export type Perspective = { yfov: number, znear: number, aspectRatio?: number, zfar?: number, extensions?: Extensions, extras?: unknown };
export enum PrimitiveMode { Points = 0, Lines = 1, LineLoop = 2, LineStrip = 3, Triangles = 4, TriangleStrip = 5, TriangleFan = 6 }
export type Vector2Tuple = [number, number];
export type Vector3Tuple = [number, number, number];
export type Vector4Tuple = [number, number, number, number];
export type Matrix4x4Tuple = number[];
export enum WrappingMode { ClampToEdge = 33071, MirroredRepeat = 33648, Repeat = 10497 }
export type Extensions = Record<string, unknown>;
export const Accessor: t.Type<Accessor> = t.recursion("Accessor", () => t.intersection([t.strict({ componentType: ComponentType$enum, count: t.Integer, type: AccessorType }), t.exact(t.partial({ bufferView: t.Integer, byteOffset: t.Integer, normalized: t.boolean, max: t.array(t.number), min: t.array(t.number), sparse: AccessorSparse, extensions: Extensions, extras: t.unknown }))]));
export const AccessorSparse: t.Type<AccessorSparse> = t.recursion("AccessorSparse", () => t.intersection([t.strict({ count: t.Integer, indices: AccessorSparseIndices, values: AccessorSparseValues }), t.exact(t.partial({ extensions: Extensions, extras: t.unknown }))]));
export const AccessorSparseIndices: t.Type<AccessorSparseIndices> = t.recursion("AccessorSparseIndices", () => t.intersection([t.strict({ bufferView: t.Integer, componentType: IndexComponentType$enum }), t.exact(t.partial({ byteOffset: t.Integer, extensions: Extensions, extras: t.unknown }))]));
export const AccessorSparseValues: t.Type<AccessorSparseValues> = t.recursion("AccessorSparseValues", () => t.intersection([t.strict({ bufferView: t.Integer }), t.exact(t.partial({ byteOffset: t.Integer, extensions: Extensions, extras: t.unknown }))]));
export const Animation: t.Type<Animation> = t.recursion("Animation", () => t.intersection([t.strict({ channels: t.array(AnimationChannel), samplers: t.array(AnimationSampler) }), t.exact(t.partial({ name: t.string, extensions: Extensions, extras: t.unknown }))]));
export const AnimationChannel: t.Type<AnimationChannel> = t.recursion("AnimationChannel", () => t.intersection([t.strict({ sampler: t.Integer, target: AnimationChannelTarget }), t.exact(t.partial({ extensions: Extensions, extras: t.unknown }))]));
export const AnimationChannelTarget: t.Type<AnimationChannelTarget> = t.recursion("AnimationChannelTarget", () => t.intersection([t.strict({ path: AnimationChannelTargetPath }), t.exact(t.partial({ node: t.Integer, extensions: Extensions, extras: t.unknown }))]));
export const AnimationSampler: t.Type<AnimationSampler> = t.recursion("AnimationSampler", () => t.intersection([t.strict({ input: t.Integer, output: t.Integer }), t.exact(t.partial({ interpolation: AnimationSamplerInterpolation, extensions: Extensions, extras: t.unknown }))]));
export const Asset: t.Type<Asset> = t.recursion("Asset", () => t.intersection([t.strict({ version: t.string }), t.exact(t.partial({ copyright: t.string, generator: t.string, minVersion: t.string, extensions: Extensions, extras: t.unknown }))]));
export const Buffer: t.Type<Buffer> = t.recursion("Buffer", () => t.intersection([t.strict({ byteLength: t.Integer }), t.exact(t.partial({ uri: t.string, name: t.string, extensions: Extensions, extras: t.unknown }))]));
export const BufferView: t.Type<BufferView> = t.recursion("BufferView", () => t.intersection([t.strict({ buffer: t.Integer, byteLength: t.Integer }), t.exact(t.partial({ byteOffset: t.Integer, byteStride: t.Integer, target: BufferViewTarget$enum, name: t.string, extensions: Extensions, extras: t.unknown }))]));
export const CameraBase: t.Type<CameraBase> = t.recursion("CameraBase", () => t.exact(t.partial({ name: t.string, extensions: Extensions, extras: t.unknown })));
export const CameraOrthographic: t.Type<CameraOrthographic> = t.recursion("CameraOrthographic", () => t.intersection([CameraBase, t.strict({ type: t.literal("orthographic"), orthographic: Orthographic })]));
export const CameraPerspective: t.Type<CameraPerspective> = t.recursion("CameraPerspective", () => t.intersection([CameraBase, t.strict({ type: t.literal("perspective"), perspective: Perspective })]));
export const Camera: t.Type<Camera> = t.recursion("Camera", () => t.union([CameraOrthographic, CameraPerspective]));
export const Gltf: t.Type<Gltf> = t.recursion("Gltf", () => t.intersection([t.strict({ asset: Asset }), t.exact(t.partial({ extensionsUsed: t.array(t.string), extensionsRequired: t.array(t.string), accessors: t.array(Accessor), animations: t.array(Animation), buffers: t.array(Buffer), bufferViews: t.array(BufferView), cameras: t.array(Camera), images: t.array(Image), materials: t.array(Material), meshes: t.array(Mesh), nodes: t.array(Node), samplers: t.array(Sampler), scene: t.Integer, scenes: t.array(Scene), skins: t.array(Skin), textures: t.array(Texture), extensions: Extensions, extras: t.unknown }))]));
export const Image: t.Type<Image> = t.recursion("Image", () => t.exact(t.partial({ uri: t.string, mimeType: ImageMimeType, bufferView: t.Integer, name: t.string, extensions: Extensions, extras: t.unknown })));
export const Material: t.Type<Material> = t.recursion("Material", () => t.exact(t.partial({ name: t.string, extensions: Extensions, extras: t.unknown, pbrMetallicRoughness: MaterialPbrMetallicRoughness, normalTexture: MaterialNormalTextureInfo, occlusionTexture: MaterialOcclusionTextureInfo, emissiveTexture: TextureInfo, emissiveFactor: Vector3Tuple, alphaMode: AlphaMode, alphaCutoff: t.number, doubleSided: t.boolean })));
export const MaterialNormalTextureInfo: t.Type<MaterialNormalTextureInfo> = t.recursion("MaterialNormalTextureInfo", () => t.intersection([t.strict({ index: t.Integer }), t.exact(t.partial({ texCoord: t.Integer, scale: t.number, extensions: Extensions, extras: t.unknown }))]));
export const MaterialOcclusionTextureInfo: t.Type<MaterialOcclusionTextureInfo> = t.recursion("MaterialOcclusionTextureInfo", () => t.intersection([t.strict({ index: t.Integer }), t.exact(t.partial({ texCoord: t.Integer, strength: t.number, extensions: Extensions, extras: t.unknown }))]));
export const MaterialPbrMetallicRoughness: t.Type<MaterialPbrMetallicRoughness> = t.recursion("MaterialPbrMetallicRoughness", () => t.exact(t.partial({ baseColorFactor: Vector4Tuple, baseColorTexture: TextureInfo, metallicFactor: t.number, roughnessFactor: t.number, metallicRoughnessTexture: TextureInfo, extensions: Extensions, extras: t.unknown })));
export const Mesh: t.Type<Mesh> = t.recursion("Mesh", () => t.intersection([t.strict({ primitives: t.array(MeshPrimitive) }), t.exact(t.partial({ weights: t.array(t.number), name: t.string, extensions: Extensions, extras: t.unknown }))]));
export const MeshPrimitive: t.Type<MeshPrimitive> = t.recursion("MeshPrimitive", () => t.intersection([t.strict({ attributes: Attributes }), t.exact(t.partial({ indices: t.Integer, material: t.Integer, mode: PrimitiveMode$enum, targets: t.array(Attributes), extensions: Extensions, extras: t.unknown }))]));
export const Node: t.Type<Node> = t.recursion("Node", () => t.exact(t.partial({ camera: t.Integer, children: t.array(t.Integer), skin: t.Integer, matrix: Matrix4x4Tuple, mesh: t.Integer, rotation: Vector4Tuple, scale: Vector3Tuple, translation: Vector3Tuple, weights: t.array(t.number), name: t.string, extensions: Extensions, extras: t.unknown })));
export const Sampler: t.Type<Sampler> = t.recursion("Sampler", () => t.exact(t.partial({ magFilter: MagFilter$enum, minFilter: MinFilter$enum, wrapS: WrappingMode$enum, wrapT: WrappingMode$enum, name: t.string, extensions: Extensions, extras: t.unknown })));
export const Scene: t.Type<Scene> = t.recursion("Scene", () => t.exact(t.partial({ nodes: t.array(t.Integer), name: t.string, extensions: Extensions, extras: t.unknown })));
export const Skin: t.Type<Skin> = t.recursion("Skin", () => t.exact(t.partial({ inverseBindMatrices: t.Integer, skeleton: t.Integer, name: t.string, extensions: Extensions, extras: t.unknown })));
export const Texture: t.Type<Texture> = t.recursion("Texture", () => t.exact(t.partial({ sampler: t.Integer, source: t.Integer, name: t.string, extensions: Extensions, extras: t.unknown })));
export const TextureInfo: t.Type<TextureInfo> = t.recursion("TextureInfo", () => t.intersection([t.strict({ index: t.Integer }), t.exact(t.partial({ texCoord: t.Integer, extensions: Extensions, extras: t.unknown }))]));
export const AlphaMode: t.Type<AlphaMode> = t.recursion("AlphaMode", () => t.union([t.literal("OPAQUE"), t.literal("MASK"), t.literal("BLEND")]));
export const AnimationChannelTargetPath: t.Type<AnimationChannelTargetPath> = t.recursion("AnimationChannelTargetPath", () => t.union([t.literal("translation"), t.literal("rotation"), t.literal("scale"), t.literal("weights")]));
export const AccessorType: t.Type<AccessorType> = t.recursion("AccessorType", () => t.union([t.literal("SCALAR"), t.literal("VEC2"), t.literal("VEC3"), t.literal("VEC4"), t.literal("MAT2"), t.literal("MAT3"), t.literal("MAT4")]));
export const AnimationSamplerInterpolation: t.Type<AnimationSamplerInterpolation> = t.recursion("AnimationSamplerInterpolation", () => t.union([t.literal("LINEAR"), t.literal("STEP"), t.literal("CUBICSPLINE")]));
export const Attributes: t.Type<Attributes> = t.recursion("Attributes", () => t.record(t.string, t.Integer));
export const BufferViewTarget$enum: t.Type<BufferViewTarget> = t.recursion("BufferViewTarget", () => t.union([t.literal(34962), t.literal(34963)]));
export const ComponentType$enum: t.Type<ComponentType> = t.recursion("ComponentType", () => t.union([t.literal(5120), t.literal(5121), t.literal(5122), t.literal(5123), t.literal(5125), t.literal(5126)]));
export const IndexComponentType$enum: t.Type<IndexComponentType> = t.recursion("IndexComponentType", () => t.union([t.literal(5121), t.literal(5123), t.literal(5125)]));
export const ImageMimeType: t.Type<ImageMimeType> = t.recursion("ImageMimeType", () => t.union([t.literal("image/jpeg"), t.literal("image/png")]));
export const MagFilter$enum: t.Type<MagFilter> = t.recursion("MagFilter", () => t.union([t.literal(9728), t.literal(9729)]));
export const MinFilter$enum: t.Type<MinFilter> = t.recursion("MinFilter", () => t.union([t.literal(9728), t.literal(9729), t.literal(9984), t.literal(9985), t.literal(9986), t.literal(9987)]));
export const Orthographic: t.Type<Orthographic> = t.recursion("Orthographic", () => t.intersection([t.strict({ xmag: t.number, ymag: t.number, zfar: t.number, znear: t.number }), t.exact(t.partial({ extensions: Extensions, extras: t.unknown }))]));
export const Perspective: t.Type<Perspective> = t.recursion("Perspective", () => t.intersection([t.strict({ yfov: t.number, znear: t.number }), t.exact(t.partial({ aspectRatio: t.number, zfar: t.number, extensions: Extensions, extras: t.unknown }))]));
export const PrimitiveMode$enum: t.Type<PrimitiveMode> = t.recursion("PrimitiveMode", () => t.union([t.literal(0), t.literal(1), t.literal(2), t.literal(3), t.literal(4), t.literal(5), t.literal(6)]));
export const Vector2Tuple: t.Type<Vector2Tuple> = t.recursion("Vector2Tuple", () => t.tuple([t.number, t.number]));
export const Vector3Tuple: t.Type<Vector3Tuple> = t.recursion("Vector3Tuple", () => t.tuple([t.number, t.number, t.number]));
export const Vector4Tuple: t.Type<Vector4Tuple> = t.recursion("Vector4Tuple", () => t.tuple([t.number, t.number, t.number, t.number]));
export const Matrix4x4Tuple: t.Type<Matrix4x4Tuple> = t.recursion("Matrix4x4Tuple", () => t.array(t.number));
export const WrappingMode$enum: t.Type<WrappingMode> = t.recursion("WrappingMode", () => t.union([t.literal(33071), t.literal(33648), t.literal(10497)]));
export const Extensions: t.Type<Extensions> = t.recursion("Extensions", () => t.record(t.string, t.unknown));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment