UNPKG

@gltf-transform/core

Version:

glTF 2.0 SDK for JavaScript and TypeScript, on Web and Node.js.

207 lines (183 loc) 7.22 kB
import { RefMap, RefSet } from 'property-graph'; import { BufferViewUsage, type Nullable, PropertyType } from '../constants.js'; import type { GLTF } from '../types/gltf.js'; import type { Accessor } from './accessor.js'; import { ExtensibleProperty, type IExtensibleProperty } from './extensible-property.js'; import type { Material } from './material.js'; import type { PrimitiveTarget } from './primitive-target.js'; interface IPrimitive extends IExtensibleProperty { mode: GLTF.MeshPrimitiveMode; material: Material; indices: Accessor; attributes: RefMap<Accessor>; targets: RefSet<PrimitiveTarget>; } /** * *Primitives are individual GPU draw calls comprising a {@link Mesh}.* * * Meshes typically have only a single Primitive, although various cases may require more. Each * primitive may be assigned vertex attributes, morph target attributes, and a material. Any of * these properties should be reused among multiple primitives where feasible. * * Primitives cannot be moved independently of other primitives within the same mesh, except * through the use of morph targets and skinning. If independent movement or other runtime * behavior is necessary (like raycasting or collisions) prefer to assign each primitive to a * different mesh. The number of GPU draw calls is typically not affected by grouping or * ungrouping primitives to a mesh. * * Each primitive may optionally be deformed by one or more morph targets, stored in a * {@link PrimitiveTarget}. * * Usage: * * ```ts * const primitive = doc.createPrimitive() * .setAttribute('POSITION', positionAccessor) * .setAttribute('TEXCOORD_0', uvAccessor) * .setMaterial(material); * mesh.addPrimitive(primitive); * node.setMesh(mesh); * ``` * * References: * - [glTF → Geometry](https://github.com/KhronosGroup/gltf/blob/main/specification/2.0/README.md#geometry) * * @category Properties */ export class Primitive extends ExtensibleProperty<IPrimitive> { public declare propertyType: PropertyType.PRIMITIVE; /********************************************************************************************** * Constants. */ /** Type of primitives to render. All valid values correspond to WebGL enums. */ public static Mode: Record<string, GLTF.MeshPrimitiveMode> = { /** Draw single points. */ POINTS: 0, /** Draw lines. Each vertex connects to the one after it. */ LINES: 1, /** * Draw lines. Each set of two vertices is treated as a separate line segment. * @deprecated See {@link https://github.com/KhronosGroup/glTF/issues/1883 KhronosGroup/glTF#1883}. */ LINE_LOOP: 2, /** Draw a connected group of line segments from the first vertex to the last, */ LINE_STRIP: 3, /** Draw triangles. Each set of three vertices creates a separate triangle. */ TRIANGLES: 4, /** Draw a connected strip of triangles. */ TRIANGLE_STRIP: 5, /** * Draw a connected group of triangles. Each vertex connects to the previous and the first * vertex in the fan. * @deprecated See {@link https://github.com/KhronosGroup/glTF/issues/1883 KhronosGroup/glTF#1883}. */ TRIANGLE_FAN: 6, }; /********************************************************************************************** * Instance. */ protected init(): void { this.propertyType = PropertyType.PRIMITIVE; } protected getDefaults(): Nullable<IPrimitive> { return Object.assign(super.getDefaults() as IExtensibleProperty, { mode: Primitive.Mode.TRIANGLES, material: null, indices: null, attributes: new RefMap<Accessor>(), targets: new RefSet<PrimitiveTarget>(), }); } /********************************************************************************************** * Primitive data. */ /** Returns an {@link Accessor} with indices of vertices to be drawn. */ public getIndices(): Accessor | null { return this.getRef('indices'); } /** * Sets an {@link Accessor} with indices of vertices to be drawn. In `TRIANGLES` draw mode, * each set of three indices define a triangle. The front face has a counter-clockwise (CCW) * winding order. */ public setIndices(indices: Accessor | null): this { return this.setRef('indices', indices, { usage: BufferViewUsage.ELEMENT_ARRAY_BUFFER }); } /** Returns a vertex attribute as an {@link Accessor}. */ public getAttribute(semantic: string): Accessor | null { return this.getRefMap('attributes', semantic); } /** * Sets a vertex attribute to an {@link Accessor}. All attributes must have the same vertex * count. */ public setAttribute(semantic: string, accessor: Accessor | null): this { return this.setRefMap('attributes', semantic, accessor, { usage: BufferViewUsage.ARRAY_BUFFER }); } /** * Lists all vertex attribute {@link Accessor}s associated with the primitive, excluding any * attributes used for morph targets. For example, `[positionAccessor, normalAccessor, * uvAccessor]`. Order will be consistent with the order returned by {@link .listSemantics}(). */ public listAttributes(): Accessor[] { return this.listRefMapValues('attributes'); } /** * Lists all vertex attribute semantics associated with the primitive, excluding any semantics * used for morph targets. For example, `['POSITION', 'NORMAL', 'TEXCOORD_0']`. Order will be * consistent with the order returned by {@link .listAttributes}(). */ public listSemantics(): string[] { return this.listRefMapKeys('attributes'); } /** Returns the material used to render the primitive. */ public getMaterial(): Material | null { return this.getRef('material'); } /** Sets the material used to render the primitive. */ public setMaterial(material: Material | null): this { return this.setRef('material', material); } /********************************************************************************************** * Mode. */ /** * Returns the GPU draw mode (`TRIANGLES`, `LINES`, `POINTS`...) as a WebGL enum value. * * Reference: * - [glTF → `primitive.mode`](https://github.com/KhronosGroup/gltf/blob/main/specification/2.0/README.md#primitivemode) */ public getMode(): GLTF.MeshPrimitiveMode { return this.get('mode'); } /** * Sets the GPU draw mode (`TRIANGLES`, `LINES`, `POINTS`...) as a WebGL enum value. * * Reference: * - [glTF → `primitive.mode`](https://github.com/KhronosGroup/gltf/blob/main/specification/2.0/README.md#primitivemode) */ public setMode(mode: GLTF.MeshPrimitiveMode): this { return this.set('mode', mode); } /********************************************************************************************** * Morph targets. */ /** Lists all morph targets associated with the primitive. */ public listTargets(): PrimitiveTarget[] { return this.listRefs('targets'); } /** * Adds a morph target to the primitive. All primitives in the same mesh must have the same * number of targets. */ public addTarget(target: PrimitiveTarget): this { return this.addRef('targets', target); } /** * Removes a morph target from the primitive. All primitives in the same mesh must have the same * number of targets. */ public removeTarget(target: PrimitiveTarget): this { return this.removeRef('targets', target); } }