@babylonjs/serializers 7.44.0 → 7.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.d.ts +3 -3
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js +10 -42
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.d.ts +32 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js +136 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js.map +1 -0
- package/glTF/2.0/Extensions/index.d.ts +1 -0
- package/glTF/2.0/Extensions/index.js +1 -0
- package/glTF/2.0/Extensions/index.js.map +1 -1
- package/glTF/2.0/bufferManager.d.ts +68 -0
- package/glTF/2.0/bufferManager.js +152 -0
- package/glTF/2.0/bufferManager.js.map +1 -0
- package/glTF/2.0/dataWriter.d.ts +5 -3
- package/glTF/2.0/dataWriter.js +30 -12
- package/glTF/2.0/dataWriter.js.map +1 -1
- package/glTF/2.0/glTFAnimation.d.ts +7 -7
- package/glTF/2.0/glTFAnimation.js +30 -51
- package/glTF/2.0/glTFAnimation.js.map +1 -1
- package/glTF/2.0/glTFExporter.d.ts +5 -4
- package/glTF/2.0/glTFExporter.js +89 -137
- package/glTF/2.0/glTFExporter.js.map +1 -1
- package/glTF/2.0/glTFExporterExtension.d.ts +14 -10
- package/glTF/2.0/glTFExporterExtension.js.map +1 -1
- package/glTF/2.0/glTFMaterialExporter.js +25 -15
- package/glTF/2.0/glTFMaterialExporter.js.map +1 -1
- package/glTF/2.0/glTFMorphTargetsUtilities.d.ts +2 -2
- package/glTF/2.0/glTFMorphTargetsUtilities.js +23 -25
- package/glTF/2.0/glTFMorphTargetsUtilities.js.map +1 -1
- package/glTF/2.0/glTFSerializer.d.ts +8 -0
- package/glTF/2.0/glTFSerializer.js.map +1 -1
- package/glTF/2.0/glTFUtilities.d.ts +11 -27
- package/glTF/2.0/glTFUtilities.js +17 -49
- package/glTF/2.0/glTFUtilities.js.map +1 -1
- package/package.json +3 -3
@@ -1,6 +1,6 @@
|
|
1
1
|
import type { INode } from "babylonjs-gltf2interface";
|
2
2
|
import type { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
|
3
|
-
import type {
|
3
|
+
import type { BufferManager } from "../bufferManager";
|
4
4
|
import { GLTFExporter } from "../glTFExporter";
|
5
5
|
import type { Nullable } from "@babylonjs/core/types.js";
|
6
6
|
import type { Node } from "@babylonjs/core/node.js";
|
@@ -28,9 +28,9 @@ export declare class EXT_mesh_gpu_instancing implements IGLTFExporterExtensionV2
|
|
28
28
|
* @param babylonNode the corresponding babylon node
|
29
29
|
* @param nodeMap map from babylon node id to node index
|
30
30
|
* @param convertToRightHanded true if we need to convert data from left hand to right hand system.
|
31
|
-
* @param
|
31
|
+
* @param bufferManager buffer manager
|
32
32
|
* @returns nullable promise, resolves with the node
|
33
33
|
*/
|
34
|
-
postExportNodeAsync(context: string, node: Nullable<INode>, babylonNode: Node, nodeMap: Map<Node, number>, convertToRightHanded: boolean,
|
34
|
+
postExportNodeAsync(context: string, node: Nullable<INode>, babylonNode: Node, nodeMap: Map<Node, number>, convertToRightHanded: boolean, bufferManager: BufferManager): Promise<Nullable<INode>>;
|
35
35
|
private _buildAccessor;
|
36
36
|
}
|
@@ -2,7 +2,6 @@ import { GLTFExporter } from "../glTFExporter.js";
|
|
2
2
|
import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
|
3
3
|
import "@babylonjs/core/Meshes/thinInstanceMesh.js";
|
4
4
|
import { TmpVectors, Quaternion, Vector3 } from "@babylonjs/core/Maths/math.vector.js";
|
5
|
-
import { VertexBuffer } from "@babylonjs/core/Buffers/buffer.js";
|
6
5
|
import { ConvertToRightHandedPosition, ConvertToRightHandedRotation } from "../glTFUtilities.js";
|
7
6
|
const NAME = "EXT_mesh_gpu_instancing";
|
8
7
|
/**
|
@@ -32,10 +31,10 @@ export class EXT_mesh_gpu_instancing {
|
|
32
31
|
* @param babylonNode the corresponding babylon node
|
33
32
|
* @param nodeMap map from babylon node id to node index
|
34
33
|
* @param convertToRightHanded true if we need to convert data from left hand to right hand system.
|
35
|
-
* @param
|
34
|
+
* @param bufferManager buffer manager
|
36
35
|
* @returns nullable promise, resolves with the node
|
37
36
|
*/
|
38
|
-
postExportNodeAsync(context, node, babylonNode, nodeMap, convertToRightHanded,
|
37
|
+
postExportNodeAsync(context, node, babylonNode, nodeMap, convertToRightHanded, bufferManager) {
|
39
38
|
return new Promise((resolve) => {
|
40
39
|
if (node && babylonNode instanceof Mesh) {
|
41
40
|
if (babylonNode.hasThinInstances && this._exporter) {
|
@@ -77,16 +76,16 @@ export class EXT_mesh_gpu_instancing {
|
|
77
76
|
};
|
78
77
|
// do we need to write TRANSLATION ?
|
79
78
|
if (hasAnyInstanceWorldTranslation) {
|
80
|
-
extension.attributes["TRANSLATION"] = this._buildAccessor(translationBuffer, "VEC3" /* AccessorType.VEC3 */, babylonNode.thinInstanceCount,
|
79
|
+
extension.attributes["TRANSLATION"] = this._buildAccessor(translationBuffer, "VEC3" /* AccessorType.VEC3 */, babylonNode.thinInstanceCount, bufferManager);
|
81
80
|
}
|
82
81
|
// do we need to write ROTATION ?
|
83
82
|
if (hasAnyInstanceWorldRotation) {
|
84
|
-
|
85
|
-
extension.attributes["ROTATION"] = this._buildAccessor(rotationBuffer, "VEC4" /* AccessorType.VEC4 */, babylonNode.thinInstanceCount,
|
83
|
+
// we decided to stay on FLOAT for now see https://github.com/BabylonJS/Babylon.js/pull/12495
|
84
|
+
extension.attributes["ROTATION"] = this._buildAccessor(rotationBuffer, "VEC4" /* AccessorType.VEC4 */, babylonNode.thinInstanceCount, bufferManager);
|
86
85
|
}
|
87
86
|
// do we need to write SCALE ?
|
88
87
|
if (hasAnyInstanceWorldScale) {
|
89
|
-
extension.attributes["SCALE"] = this._buildAccessor(scaleBuffer, "VEC3" /* AccessorType.VEC3 */, babylonNode.thinInstanceCount,
|
88
|
+
extension.attributes["SCALE"] = this._buildAccessor(scaleBuffer, "VEC3" /* AccessorType.VEC3 */, babylonNode.thinInstanceCount, bufferManager);
|
90
89
|
}
|
91
90
|
/* eslint-enable @typescript-eslint/naming-convention*/
|
92
91
|
node.extensions = node.extensions || {};
|
@@ -96,44 +95,13 @@ export class EXT_mesh_gpu_instancing {
|
|
96
95
|
resolve(node);
|
97
96
|
});
|
98
97
|
}
|
99
|
-
_buildAccessor(buffer, type, count,
|
100
|
-
// write the buffer
|
101
|
-
const bufferOffset = binaryWriter.byteOffset;
|
102
|
-
switch (componentType) {
|
103
|
-
case 5126 /* AccessorComponentType.FLOAT */: {
|
104
|
-
for (let i = 0; i != buffer.length; i++) {
|
105
|
-
binaryWriter.writeFloat32(buffer[i]);
|
106
|
-
}
|
107
|
-
break;
|
108
|
-
}
|
109
|
-
case 5120 /* AccessorComponentType.BYTE */: {
|
110
|
-
for (let i = 0; i != buffer.length; i++) {
|
111
|
-
binaryWriter.writeInt8(buffer[i] * 127);
|
112
|
-
}
|
113
|
-
break;
|
114
|
-
}
|
115
|
-
case 5122 /* AccessorComponentType.SHORT */: {
|
116
|
-
for (let i = 0; i != buffer.length; i++) {
|
117
|
-
binaryWriter.writeInt16(buffer[i] * 32767);
|
118
|
-
}
|
119
|
-
break;
|
120
|
-
}
|
121
|
-
}
|
98
|
+
_buildAccessor(buffer, type, count, bufferManager) {
|
122
99
|
// build the buffer view
|
123
|
-
const bv =
|
124
|
-
const bufferViewIndex = this._exporter._bufferViews.length;
|
125
|
-
this._exporter._bufferViews.push(bv);
|
100
|
+
const bv = bufferManager.createBufferView(buffer);
|
126
101
|
// finally build the accessor
|
127
|
-
const
|
128
|
-
const accessor = {
|
129
|
-
bufferView: bufferViewIndex,
|
130
|
-
componentType: componentType,
|
131
|
-
count: count,
|
132
|
-
type: type,
|
133
|
-
normalized: componentType == 5120 /* AccessorComponentType.BYTE */ || componentType == 5122 /* AccessorComponentType.SHORT */,
|
134
|
-
};
|
102
|
+
const accessor = bufferManager.createAccessor(bv, type, 5126 /* AccessorComponentType.FLOAT */, count);
|
135
103
|
this._exporter._accessors.push(accessor);
|
136
|
-
return
|
104
|
+
return this._exporter._accessors.length - 1;
|
137
105
|
}
|
138
106
|
}
|
139
107
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"EXT_mesh_gpu_instancing.js","sourceRoot":"","sources":["../../../../../../dev/serializers/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IBufferView, IAccessor, INode, IEXTMeshGpuInstancing } from \"babylonjs-gltf2interface\";\r\nimport { AccessorType, AccessorComponentType } from \"babylonjs-gltf2interface\";\r\nimport type { IGLTFExporterExtensionV2 } from \"../glTFExporterExtension\";\r\nimport type { DataWriter } from \"../dataWriter\";\r\nimport { GLTFExporter } from \"../glTFExporter\";\r\nimport type { Nullable } from \"core/types\";\r\nimport type { Node } from \"core/node\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport \"core/Meshes/thinInstanceMesh\";\r\nimport { TmpVectors, Quaternion, Vector3 } from \"core/Maths/math.vector\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer\";\r\nimport { ConvertToRightHandedPosition, ConvertToRightHandedRotation } from \"../glTFUtilities\";\r\n\r\nconst NAME = \"EXT_mesh_gpu_instancing\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_gpu_instancing/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_mesh_gpu_instancing implements IGLTFExporterExtensionV2 {\r\n /** Name of this extension */\r\n public readonly name = NAME;\r\n\r\n /** Defines whether this extension is enabled */\r\n public enabled = true;\r\n\r\n /** Defines whether this extension is required */\r\n public required = false;\r\n\r\n private _exporter: GLTFExporter;\r\n\r\n private _wasUsed = false;\r\n\r\n constructor(exporter: GLTFExporter) {\r\n this._exporter = exporter;\r\n }\r\n\r\n public dispose() {}\r\n\r\n /** @internal */\r\n public get wasUsed() {\r\n return this._wasUsed;\r\n }\r\n\r\n /**\r\n * After node is exported\r\n * @param context the GLTF context when loading the asset\r\n * @param node the node exported\r\n * @param babylonNode the corresponding babylon node\r\n * @param nodeMap map from babylon node id to node index\r\n * @param convertToRightHanded true if we need to convert data from left hand to right hand system.\r\n * @param dataWriter binary writer\r\n * @returns nullable promise, resolves with the node\r\n */\r\n public postExportNodeAsync(\r\n context: string,\r\n node: Nullable<INode>,\r\n babylonNode: Node,\r\n nodeMap: Map<Node, number>,\r\n convertToRightHanded: boolean,\r\n dataWriter: DataWriter\r\n ): Promise<Nullable<INode>> {\r\n return new Promise((resolve) => {\r\n if (node && babylonNode instanceof Mesh) {\r\n if (babylonNode.hasThinInstances && this._exporter) {\r\n this._wasUsed = true;\r\n\r\n const noTranslation = Vector3.Zero();\r\n const noRotation = Quaternion.Identity();\r\n const noScale = Vector3.One();\r\n\r\n // retrieve all the instance world matrix\r\n const matrix = babylonNode.thinInstanceGetWorldMatrices();\r\n\r\n const iwt = TmpVectors.Vector3[2];\r\n const iwr = TmpVectors.Quaternion[1];\r\n const iws = TmpVectors.Vector3[3];\r\n\r\n let hasAnyInstanceWorldTranslation = false;\r\n let hasAnyInstanceWorldRotation = false;\r\n let hasAnyInstanceWorldScale = false;\r\n\r\n // prepare temp buffers\r\n const translationBuffer = new Float32Array(babylonNode.thinInstanceCount * 3);\r\n const rotationBuffer = new Float32Array(babylonNode.thinInstanceCount * 4);\r\n const scaleBuffer = new Float32Array(babylonNode.thinInstanceCount * 3);\r\n\r\n let i = 0;\r\n for (const m of matrix) {\r\n m.decompose(iws, iwr, iwt);\r\n\r\n if (convertToRightHanded) {\r\n ConvertToRightHandedPosition(iwt);\r\n ConvertToRightHandedRotation(iwr);\r\n }\r\n\r\n // fill the temp buffer\r\n translationBuffer.set(iwt.asArray(), i * 3);\r\n rotationBuffer.set(iwr.normalize().asArray(), i * 4); // ensure the quaternion is normalized\r\n scaleBuffer.set(iws.asArray(), i * 3);\r\n\r\n // this is where we decide if there is any transformation\r\n hasAnyInstanceWorldTranslation = hasAnyInstanceWorldTranslation || !iwt.equalsWithEpsilon(noTranslation);\r\n hasAnyInstanceWorldRotation = hasAnyInstanceWorldRotation || !iwr.equalsWithEpsilon(noRotation);\r\n hasAnyInstanceWorldScale = hasAnyInstanceWorldScale || !iws.equalsWithEpsilon(noScale);\r\n\r\n i++;\r\n }\r\n\r\n const extension: IEXTMeshGpuInstancing = {\r\n attributes: {},\r\n };\r\n\r\n // do we need to write TRANSLATION ?\r\n if (hasAnyInstanceWorldTranslation) {\r\n extension.attributes[\"TRANSLATION\"] = this._buildAccessor(\r\n translationBuffer,\r\n AccessorType.VEC3,\r\n babylonNode.thinInstanceCount,\r\n dataWriter,\r\n AccessorComponentType.FLOAT\r\n );\r\n }\r\n // do we need to write ROTATION ?\r\n if (hasAnyInstanceWorldRotation) {\r\n const componentType = AccessorComponentType.FLOAT; // we decided to stay on FLOAT for now see https://github.com/BabylonJS/Babylon.js/pull/12495\r\n extension.attributes[\"ROTATION\"] = this._buildAccessor(rotationBuffer, AccessorType.VEC4, babylonNode.thinInstanceCount, dataWriter, componentType);\r\n }\r\n // do we need to write SCALE ?\r\n if (hasAnyInstanceWorldScale) {\r\n extension.attributes[\"SCALE\"] = this._buildAccessor(scaleBuffer, AccessorType.VEC3, babylonNode.thinInstanceCount, dataWriter, AccessorComponentType.FLOAT);\r\n }\r\n\r\n /* eslint-enable @typescript-eslint/naming-convention*/\r\n node.extensions = node.extensions || {};\r\n node.extensions[NAME] = extension;\r\n }\r\n }\r\n resolve(node);\r\n });\r\n }\r\n\r\n private _buildAccessor(buffer: Float32Array, type: AccessorType, count: number, binaryWriter: DataWriter, componentType: AccessorComponentType): number {\r\n // write the buffer\r\n const bufferOffset = binaryWriter.byteOffset;\r\n switch (componentType) {\r\n case AccessorComponentType.FLOAT: {\r\n for (let i = 0; i != buffer.length; i++) {\r\n binaryWriter.writeFloat32(buffer[i]);\r\n }\r\n break;\r\n }\r\n case AccessorComponentType.BYTE: {\r\n for (let i = 0; i != buffer.length; i++) {\r\n binaryWriter.writeInt8(buffer[i] * 127);\r\n }\r\n break;\r\n }\r\n case AccessorComponentType.SHORT: {\r\n for (let i = 0; i != buffer.length; i++) {\r\n binaryWriter.writeInt16(buffer[i] * 32767);\r\n }\r\n\r\n break;\r\n }\r\n }\r\n // build the buffer view\r\n const bv: IBufferView = { buffer: 0, byteOffset: bufferOffset, byteLength: buffer.length * VertexBuffer.GetTypeByteLength(componentType) };\r\n const bufferViewIndex = this._exporter._bufferViews.length;\r\n this._exporter._bufferViews.push(bv);\r\n\r\n // finally build the accessor\r\n const accessorIndex = this._exporter._accessors.length;\r\n const accessor: IAccessor = {\r\n bufferView: bufferViewIndex,\r\n componentType: componentType,\r\n count: count,\r\n type: type,\r\n normalized: componentType == AccessorComponentType.BYTE || componentType == AccessorComponentType.SHORT,\r\n };\r\n this._exporter._accessors.push(accessor);\r\n return accessorIndex;\r\n }\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\nGLTFExporter.RegisterExtension(NAME, (exporter) => new EXT_mesh_gpu_instancing(exporter));\r\n"]}
|
1
|
+
{"version":3,"file":"EXT_mesh_gpu_instancing.js","sourceRoot":"","sources":["../../../../../../dev/serializers/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts"],"names":[],"mappings":"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","sourcesContent":["import type { INode, IEXTMeshGpuInstancing } from \"babylonjs-gltf2interface\";\r\nimport { AccessorType, AccessorComponentType } from \"babylonjs-gltf2interface\";\r\nimport type { IGLTFExporterExtensionV2 } from \"../glTFExporterExtension\";\r\nimport type { BufferManager } from \"../bufferManager\";\r\nimport { GLTFExporter } from \"../glTFExporter\";\r\nimport type { Nullable } from \"core/types\";\r\nimport type { Node } from \"core/node\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport \"core/Meshes/thinInstanceMesh\";\r\nimport { TmpVectors, Quaternion, Vector3 } from \"core/Maths/math.vector\";\r\nimport { ConvertToRightHandedPosition, ConvertToRightHandedRotation } from \"../glTFUtilities\";\r\n\r\nconst NAME = \"EXT_mesh_gpu_instancing\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_gpu_instancing/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_mesh_gpu_instancing implements IGLTFExporterExtensionV2 {\r\n /** Name of this extension */\r\n public readonly name = NAME;\r\n\r\n /** Defines whether this extension is enabled */\r\n public enabled = true;\r\n\r\n /** Defines whether this extension is required */\r\n public required = false;\r\n\r\n private _exporter: GLTFExporter;\r\n\r\n private _wasUsed = false;\r\n\r\n constructor(exporter: GLTFExporter) {\r\n this._exporter = exporter;\r\n }\r\n\r\n public dispose() {}\r\n\r\n /** @internal */\r\n public get wasUsed() {\r\n return this._wasUsed;\r\n }\r\n\r\n /**\r\n * After node is exported\r\n * @param context the GLTF context when loading the asset\r\n * @param node the node exported\r\n * @param babylonNode the corresponding babylon node\r\n * @param nodeMap map from babylon node id to node index\r\n * @param convertToRightHanded true if we need to convert data from left hand to right hand system.\r\n * @param bufferManager buffer manager\r\n * @returns nullable promise, resolves with the node\r\n */\r\n public postExportNodeAsync(\r\n context: string,\r\n node: Nullable<INode>,\r\n babylonNode: Node,\r\n nodeMap: Map<Node, number>,\r\n convertToRightHanded: boolean,\r\n bufferManager: BufferManager\r\n ): Promise<Nullable<INode>> {\r\n return new Promise((resolve) => {\r\n if (node && babylonNode instanceof Mesh) {\r\n if (babylonNode.hasThinInstances && this._exporter) {\r\n this._wasUsed = true;\r\n\r\n const noTranslation = Vector3.Zero();\r\n const noRotation = Quaternion.Identity();\r\n const noScale = Vector3.One();\r\n\r\n // retrieve all the instance world matrix\r\n const matrix = babylonNode.thinInstanceGetWorldMatrices();\r\n\r\n const iwt = TmpVectors.Vector3[2];\r\n const iwr = TmpVectors.Quaternion[1];\r\n const iws = TmpVectors.Vector3[3];\r\n\r\n let hasAnyInstanceWorldTranslation = false;\r\n let hasAnyInstanceWorldRotation = false;\r\n let hasAnyInstanceWorldScale = false;\r\n\r\n // prepare temp buffers\r\n const translationBuffer = new Float32Array(babylonNode.thinInstanceCount * 3);\r\n const rotationBuffer = new Float32Array(babylonNode.thinInstanceCount * 4);\r\n const scaleBuffer = new Float32Array(babylonNode.thinInstanceCount * 3);\r\n\r\n let i = 0;\r\n for (const m of matrix) {\r\n m.decompose(iws, iwr, iwt);\r\n\r\n if (convertToRightHanded) {\r\n ConvertToRightHandedPosition(iwt);\r\n ConvertToRightHandedRotation(iwr);\r\n }\r\n\r\n // fill the temp buffer\r\n translationBuffer.set(iwt.asArray(), i * 3);\r\n rotationBuffer.set(iwr.normalize().asArray(), i * 4); // ensure the quaternion is normalized\r\n scaleBuffer.set(iws.asArray(), i * 3);\r\n\r\n // this is where we decide if there is any transformation\r\n hasAnyInstanceWorldTranslation = hasAnyInstanceWorldTranslation || !iwt.equalsWithEpsilon(noTranslation);\r\n hasAnyInstanceWorldRotation = hasAnyInstanceWorldRotation || !iwr.equalsWithEpsilon(noRotation);\r\n hasAnyInstanceWorldScale = hasAnyInstanceWorldScale || !iws.equalsWithEpsilon(noScale);\r\n\r\n i++;\r\n }\r\n\r\n const extension: IEXTMeshGpuInstancing = {\r\n attributes: {},\r\n };\r\n\r\n // do we need to write TRANSLATION ?\r\n if (hasAnyInstanceWorldTranslation) {\r\n extension.attributes[\"TRANSLATION\"] = this._buildAccessor(translationBuffer, AccessorType.VEC3, babylonNode.thinInstanceCount, bufferManager);\r\n }\r\n // do we need to write ROTATION ?\r\n if (hasAnyInstanceWorldRotation) {\r\n // we decided to stay on FLOAT for now see https://github.com/BabylonJS/Babylon.js/pull/12495\r\n extension.attributes[\"ROTATION\"] = this._buildAccessor(rotationBuffer, AccessorType.VEC4, babylonNode.thinInstanceCount, bufferManager);\r\n }\r\n // do we need to write SCALE ?\r\n if (hasAnyInstanceWorldScale) {\r\n extension.attributes[\"SCALE\"] = this._buildAccessor(scaleBuffer, AccessorType.VEC3, babylonNode.thinInstanceCount, bufferManager);\r\n }\r\n\r\n /* eslint-enable @typescript-eslint/naming-convention*/\r\n node.extensions = node.extensions || {};\r\n node.extensions[NAME] = extension;\r\n }\r\n }\r\n resolve(node);\r\n });\r\n }\r\n\r\n private _buildAccessor(buffer: Float32Array, type: AccessorType, count: number, bufferManager: BufferManager): number {\r\n // build the buffer view\r\n const bv = bufferManager.createBufferView(buffer);\r\n\r\n // finally build the accessor\r\n const accessor = bufferManager.createAccessor(bv, type, AccessorComponentType.FLOAT, count);\r\n this._exporter._accessors.push(accessor);\r\n return this._exporter._accessors.length - 1;\r\n }\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\nGLTFExporter.RegisterExtension(NAME, (exporter) => new EXT_mesh_gpu_instancing(exporter));\r\n"]}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import type { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
|
2
|
+
import { GLTFExporter } from "../glTFExporter";
|
3
|
+
import type { IAccessor, IMeshPrimitive } from "babylonjs-gltf2interface";
|
4
|
+
import type { BufferManager } from "../bufferManager";
|
5
|
+
/**
|
6
|
+
* [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md)
|
7
|
+
*/
|
8
|
+
export declare class KHR_draco_mesh_compression implements IGLTFExporterExtensionV2 {
|
9
|
+
/** Name of this extension */
|
10
|
+
readonly name = "KHR_draco_mesh_compression";
|
11
|
+
/** Defines whether this extension is enabled */
|
12
|
+
enabled: boolean;
|
13
|
+
/** KHR_draco_mesh_compression is required, as uncompressed fallback data is not yet implemented. */
|
14
|
+
required: boolean;
|
15
|
+
/** BufferViews used for Draco data, which may be eligible for removal after Draco encoding */
|
16
|
+
private _bufferViewsUsed;
|
17
|
+
/** Accessors that were replaced with Draco data, which may be eligible for removal after Draco encoding */
|
18
|
+
private _accessorsUsed;
|
19
|
+
/** Promise pool for Draco encoding work */
|
20
|
+
private _encodePromises;
|
21
|
+
private _wasUsed;
|
22
|
+
/** @internal */
|
23
|
+
get wasUsed(): boolean;
|
24
|
+
/** @internal */
|
25
|
+
constructor(exporter: GLTFExporter);
|
26
|
+
/** @internal */
|
27
|
+
dispose(): void;
|
28
|
+
/** @internal */
|
29
|
+
postExportMeshPrimitive(primitive: IMeshPrimitive, bufferManager: BufferManager, accessors: IAccessor[]): void;
|
30
|
+
/** @internal */
|
31
|
+
preGenerateBinaryAsync(bufferManager: BufferManager): Promise<void>;
|
32
|
+
}
|
@@ -0,0 +1,136 @@
|
|
1
|
+
import { GLTFExporter } from "../glTFExporter.js";
|
2
|
+
import { DracoEncoder } from "@babylonjs/core/Meshes/Compression/dracoEncoder.js";
|
3
|
+
import { GetFloatData, GetTypeByteLength } from "@babylonjs/core/Buffers/bufferUtils.js";
|
4
|
+
import { GetAccessorElementCount } from "../glTFUtilities.js";
|
5
|
+
import { Logger } from "@babylonjs/core/Misc/logger.js";
|
6
|
+
const NAME = "KHR_draco_mesh_compression";
|
7
|
+
function getDracoAttributeName(glTFName) {
|
8
|
+
if (glTFName === "POSITION") {
|
9
|
+
return "POSITION";
|
10
|
+
}
|
11
|
+
else if (glTFName === "NORMAL") {
|
12
|
+
return "NORMAL";
|
13
|
+
}
|
14
|
+
else if (glTFName.startsWith("COLOR")) {
|
15
|
+
return "COLOR";
|
16
|
+
}
|
17
|
+
else if (glTFName.startsWith("TEXCOORD")) {
|
18
|
+
return "TEX_COORD";
|
19
|
+
}
|
20
|
+
return "GENERIC";
|
21
|
+
}
|
22
|
+
/**
|
23
|
+
* [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md)
|
24
|
+
*/
|
25
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
26
|
+
export class KHR_draco_mesh_compression {
|
27
|
+
/** @internal */
|
28
|
+
get wasUsed() {
|
29
|
+
return this._wasUsed;
|
30
|
+
}
|
31
|
+
/** @internal */
|
32
|
+
constructor(exporter) {
|
33
|
+
/** Name of this extension */
|
34
|
+
this.name = NAME;
|
35
|
+
/** KHR_draco_mesh_compression is required, as uncompressed fallback data is not yet implemented. */
|
36
|
+
this.required = true;
|
37
|
+
/** BufferViews used for Draco data, which may be eligible for removal after Draco encoding */
|
38
|
+
this._bufferViewsUsed = new Set();
|
39
|
+
/** Accessors that were replaced with Draco data, which may be eligible for removal after Draco encoding */
|
40
|
+
this._accessorsUsed = new Set();
|
41
|
+
/** Promise pool for Draco encoding work */
|
42
|
+
this._encodePromises = [];
|
43
|
+
this._wasUsed = false;
|
44
|
+
this.enabled = exporter.options.meshCompressionMethod === "Draco" && DracoEncoder.DefaultAvailable;
|
45
|
+
}
|
46
|
+
/** @internal */
|
47
|
+
dispose() { }
|
48
|
+
/** @internal */
|
49
|
+
postExportMeshPrimitive(primitive, bufferManager, accessors) {
|
50
|
+
if (!this.enabled) {
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
if (primitive.mode !== 4 /* MeshPrimitiveMode.TRIANGLES */ && primitive.mode !== 5 /* MeshPrimitiveMode.TRIANGLE_STRIP */) {
|
54
|
+
Logger.Warn("Cannot compress primitive with mode " + primitive.mode + ".");
|
55
|
+
return;
|
56
|
+
}
|
57
|
+
// Collect bufferViews and accessors used by this primitive
|
58
|
+
const primitiveBufferViews = [];
|
59
|
+
const primitiveAccessors = [];
|
60
|
+
// Prepare indices for Draco encoding
|
61
|
+
let indices = null;
|
62
|
+
if (primitive.indices !== undefined) {
|
63
|
+
const accessor = accessors[primitive.indices];
|
64
|
+
const bufferView = bufferManager.getBufferView(accessor);
|
65
|
+
// Per exportIndices, indices must be either Uint16Array or Uint32Array
|
66
|
+
indices = bufferManager.getData(bufferView);
|
67
|
+
primitiveBufferViews.push(bufferView);
|
68
|
+
primitiveAccessors.push(accessor);
|
69
|
+
}
|
70
|
+
// Prepare attributes for Draco encoding
|
71
|
+
const attributes = [];
|
72
|
+
for (const [name, accessorIndex] of Object.entries(primitive.attributes)) {
|
73
|
+
const accessor = accessors[accessorIndex];
|
74
|
+
const bufferView = bufferManager.getBufferView(accessor);
|
75
|
+
const data = bufferManager.getData(bufferView);
|
76
|
+
const size = GetAccessorElementCount(accessor.type);
|
77
|
+
// TODO: Implement a way to preserve original data type, as Draco can handle more than just floats
|
78
|
+
// TODO: Add flag in DracoEncoder API to prevent copying data (a second time) to transferable buffer
|
79
|
+
const floatData = GetFloatData(data, size, accessor.componentType, accessor.byteOffset || 0, bufferView.byteStride || GetTypeByteLength(accessor.componentType) * size, accessor.normalized || false, accessor.count); // Because data is a TypedArray, GetFloatData will return a Float32Array
|
80
|
+
attributes.push({ kind: name, dracoName: getDracoAttributeName(name), size: GetAccessorElementCount(accessor.type), data: floatData });
|
81
|
+
primitiveBufferViews.push(bufferView);
|
82
|
+
primitiveAccessors.push(accessor);
|
83
|
+
}
|
84
|
+
// Use sequential encoding to preserve vertex order for cases like morph targets
|
85
|
+
const options = {
|
86
|
+
method: primitive.targets ? "MESH_SEQUENTIAL_ENCODING" : "MESH_EDGEBREAKER_ENCODING",
|
87
|
+
};
|
88
|
+
const promise = DracoEncoder.Default._encodeAsync(attributes, indices, options)
|
89
|
+
.then((encodedData) => {
|
90
|
+
if (!encodedData) {
|
91
|
+
Logger.Error("Draco encoding failed for primitive.");
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
const dracoInfo = {
|
95
|
+
bufferView: -1, // bufferView will be set to a real index later, when we write the binary and decide bufferView ordering
|
96
|
+
attributes: encodedData.attributeIDs,
|
97
|
+
};
|
98
|
+
const bufferView = bufferManager.createBufferView(encodedData.data);
|
99
|
+
bufferManager.setBufferView(dracoInfo, bufferView);
|
100
|
+
for (const bufferView of primitiveBufferViews) {
|
101
|
+
this._bufferViewsUsed.add(bufferView);
|
102
|
+
}
|
103
|
+
for (const accessor of primitiveAccessors) {
|
104
|
+
this._accessorsUsed.add(accessor);
|
105
|
+
}
|
106
|
+
primitive.extensions || (primitive.extensions = {});
|
107
|
+
primitive.extensions[NAME] = dracoInfo;
|
108
|
+
})
|
109
|
+
.catch((error) => {
|
110
|
+
Logger.Error("Draco encoding failed for primitive: " + error);
|
111
|
+
});
|
112
|
+
this._encodePromises.push(promise);
|
113
|
+
this._wasUsed = true;
|
114
|
+
}
|
115
|
+
/** @internal */
|
116
|
+
async preGenerateBinaryAsync(bufferManager) {
|
117
|
+
if (!this.enabled) {
|
118
|
+
return;
|
119
|
+
}
|
120
|
+
await Promise.all(this._encodePromises);
|
121
|
+
// Cull obsolete bufferViews that were replaced with Draco data
|
122
|
+
this._bufferViewsUsed.forEach((bufferView) => {
|
123
|
+
const references = bufferManager.getPropertiesWithBufferView(bufferView);
|
124
|
+
const onlyUsedByEncodedPrimitives = references.every((object) => {
|
125
|
+
return this._accessorsUsed.has(object); // has() can handle any object, but TS doesn't know that
|
126
|
+
});
|
127
|
+
if (onlyUsedByEncodedPrimitives) {
|
128
|
+
bufferManager.removeBufferView(bufferView);
|
129
|
+
}
|
130
|
+
});
|
131
|
+
this._bufferViewsUsed.clear();
|
132
|
+
this._accessorsUsed.clear();
|
133
|
+
}
|
134
|
+
}
|
135
|
+
GLTFExporter.RegisterExtension(NAME, (exporter) => new KHR_draco_mesh_compression(exporter));
|
136
|
+
//# sourceMappingURL=KHR_draco_mesh_compression.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"KHR_draco_mesh_compression.js","sourceRoot":"","sources":["../../../../../../dev/serializers/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IGLTFExporterExtensionV2 } from \"../glTFExporterExtension\";\nimport { GLTFExporter } from \"../glTFExporter\";\nimport { MeshPrimitiveMode } from \"babylonjs-gltf2interface\";\nimport type { IAccessor, IBufferView, IKHRDracoMeshCompression, IMeshPrimitive } from \"babylonjs-gltf2interface\";\nimport type { BufferManager } from \"../bufferManager\";\nimport { DracoEncoder } from \"core/Meshes/Compression/dracoEncoder\";\nimport { GetFloatData, GetTypeByteLength } from \"core/Buffers/bufferUtils\";\nimport { GetAccessorElementCount } from \"../glTFUtilities\";\nimport type { DracoAttributeName, IDracoAttributeData, IDracoEncoderOptions } from \"core/Meshes/Compression/dracoEncoder.types\";\nimport { Logger } from \"core/Misc/logger\";\nimport type { Nullable } from \"core/types\";\n\nconst NAME = \"KHR_draco_mesh_compression\";\n\nfunction getDracoAttributeName(glTFName: string): DracoAttributeName {\n if (glTFName === \"POSITION\") {\n return \"POSITION\";\n } else if (glTFName === \"NORMAL\") {\n return \"NORMAL\";\n } else if (glTFName.startsWith(\"COLOR\")) {\n return \"COLOR\";\n } else if (glTFName.startsWith(\"TEXCOORD\")) {\n return \"TEX_COORD\";\n }\n return \"GENERIC\";\n}\n\n/**\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md)\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport class KHR_draco_mesh_compression implements IGLTFExporterExtensionV2 {\n /** Name of this extension */\n public readonly name = NAME;\n\n /** Defines whether this extension is enabled */\n public enabled;\n\n /** KHR_draco_mesh_compression is required, as uncompressed fallback data is not yet implemented. */\n public required = true;\n\n /** BufferViews used for Draco data, which may be eligible for removal after Draco encoding */\n private _bufferViewsUsed: Set<IBufferView> = new Set();\n\n /** Accessors that were replaced with Draco data, which may be eligible for removal after Draco encoding */\n private _accessorsUsed: Set<IAccessor> = new Set();\n\n /** Promise pool for Draco encoding work */\n private _encodePromises: Promise<void>[] = [];\n\n private _wasUsed = false;\n\n /** @internal */\n public get wasUsed() {\n return this._wasUsed;\n }\n\n /** @internal */\n constructor(exporter: GLTFExporter) {\n this.enabled = exporter.options.meshCompressionMethod === \"Draco\" && DracoEncoder.DefaultAvailable;\n }\n\n /** @internal */\n public dispose() {}\n\n /** @internal */\n public postExportMeshPrimitive(primitive: IMeshPrimitive, bufferManager: BufferManager, accessors: IAccessor[]): void {\n if (!this.enabled) {\n return;\n }\n\n if (primitive.mode !== MeshPrimitiveMode.TRIANGLES && primitive.mode !== MeshPrimitiveMode.TRIANGLE_STRIP) {\n Logger.Warn(\"Cannot compress primitive with mode \" + primitive.mode + \".\");\n return;\n }\n\n // Collect bufferViews and accessors used by this primitive\n const primitiveBufferViews: IBufferView[] = [];\n const primitiveAccessors: IAccessor[] = [];\n\n // Prepare indices for Draco encoding\n let indices: Nullable<Uint32Array | Uint16Array> = null;\n if (primitive.indices !== undefined) {\n const accessor = accessors[primitive.indices];\n const bufferView = bufferManager.getBufferView(accessor);\n // Per exportIndices, indices must be either Uint16Array or Uint32Array\n indices = bufferManager.getData(bufferView) as Uint32Array | Uint16Array;\n\n primitiveBufferViews.push(bufferView);\n primitiveAccessors.push(accessor);\n }\n\n // Prepare attributes for Draco encoding\n const attributes: IDracoAttributeData[] = [];\n for (const [name, accessorIndex] of Object.entries(primitive.attributes)) {\n const accessor = accessors[accessorIndex];\n const bufferView = bufferManager.getBufferView(accessor);\n const data = bufferManager.getData(bufferView);\n\n const size = GetAccessorElementCount(accessor.type);\n // TODO: Implement a way to preserve original data type, as Draco can handle more than just floats\n // TODO: Add flag in DracoEncoder API to prevent copying data (a second time) to transferable buffer\n const floatData = GetFloatData(\n data,\n size,\n accessor.componentType,\n accessor.byteOffset || 0,\n bufferView.byteStride || GetTypeByteLength(accessor.componentType) * size,\n accessor.normalized || false,\n accessor.count\n ) as Float32Array; // Because data is a TypedArray, GetFloatData will return a Float32Array\n\n attributes.push({ kind: name, dracoName: getDracoAttributeName(name), size: GetAccessorElementCount(accessor.type), data: floatData });\n\n primitiveBufferViews.push(bufferView);\n primitiveAccessors.push(accessor);\n }\n\n // Use sequential encoding to preserve vertex order for cases like morph targets\n const options: IDracoEncoderOptions = {\n method: primitive.targets ? \"MESH_SEQUENTIAL_ENCODING\" : \"MESH_EDGEBREAKER_ENCODING\",\n };\n\n const promise = DracoEncoder.Default._encodeAsync(attributes, indices, options)\n .then((encodedData) => {\n if (!encodedData) {\n Logger.Error(\"Draco encoding failed for primitive.\");\n return;\n }\n\n const dracoInfo: IKHRDracoMeshCompression = {\n bufferView: -1, // bufferView will be set to a real index later, when we write the binary and decide bufferView ordering\n attributes: encodedData.attributeIDs,\n };\n const bufferView = bufferManager.createBufferView(encodedData.data);\n bufferManager.setBufferView(dracoInfo, bufferView);\n\n for (const bufferView of primitiveBufferViews) {\n this._bufferViewsUsed.add(bufferView);\n }\n for (const accessor of primitiveAccessors) {\n this._accessorsUsed.add(accessor);\n }\n\n primitive.extensions ||= {};\n primitive.extensions[NAME] = dracoInfo;\n })\n .catch((error) => {\n Logger.Error(\"Draco encoding failed for primitive: \" + error);\n });\n\n this._encodePromises.push(promise);\n\n this._wasUsed = true;\n }\n\n /** @internal */\n public async preGenerateBinaryAsync(bufferManager: BufferManager): Promise<void> {\n if (!this.enabled) {\n return;\n }\n\n await Promise.all(this._encodePromises);\n\n // Cull obsolete bufferViews that were replaced with Draco data\n this._bufferViewsUsed.forEach((bufferView) => {\n const references = bufferManager.getPropertiesWithBufferView(bufferView);\n const onlyUsedByEncodedPrimitives = references.every((object) => {\n return this._accessorsUsed.has(object as IAccessor); // has() can handle any object, but TS doesn't know that\n });\n if (onlyUsedByEncodedPrimitives) {\n bufferManager.removeBufferView(bufferView);\n }\n });\n\n this._bufferViewsUsed.clear();\n this._accessorsUsed.clear();\n }\n}\n\nGLTFExporter.RegisterExtension(NAME, (exporter) => new KHR_draco_mesh_compression(exporter));\n"]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../dev/serializers/src/glTF/2.0/Extensions/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sCAAsC,CAAC;AACrD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC","sourcesContent":["export * from \"./EXT_mesh_gpu_instancing\";\r\nexport * from \"./KHR_lights_punctual\";\r\nexport * from \"./KHR_materials_anisotropy\";\r\nexport * from \"./KHR_materials_clearcoat\";\r\nexport * from \"./KHR_materials_diffuse_transmission\";\r\nexport * from \"./KHR_materials_dispersion\";\r\nexport * from \"./KHR_materials_emissive_strength\";\r\nexport * from \"./KHR_materials_ior\";\r\nexport * from \"./KHR_materials_iridescence\";\r\nexport * from \"./KHR_materials_sheen\";\r\nexport * from \"./KHR_materials_specular\";\r\nexport * from \"./KHR_materials_transmission\";\r\nexport * from \"./KHR_materials_unlit\";\r\nexport * from \"./KHR_materials_volume\";\r\nexport * from \"./KHR_texture_transform\";\r\n"]}
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../dev/serializers/src/glTF/2.0/Extensions/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sCAAsC,CAAC;AACrD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC","sourcesContent":["export * from \"./EXT_mesh_gpu_instancing\";\r\nexport * from \"./KHR_draco_mesh_compression\";\r\nexport * from \"./KHR_lights_punctual\";\r\nexport * from \"./KHR_materials_anisotropy\";\r\nexport * from \"./KHR_materials_clearcoat\";\r\nexport * from \"./KHR_materials_diffuse_transmission\";\r\nexport * from \"./KHR_materials_dispersion\";\r\nexport * from \"./KHR_materials_emissive_strength\";\r\nexport * from \"./KHR_materials_ior\";\r\nexport * from \"./KHR_materials_iridescence\";\r\nexport * from \"./KHR_materials_sheen\";\r\nexport * from \"./KHR_materials_specular\";\r\nexport * from \"./KHR_materials_transmission\";\r\nexport * from \"./KHR_materials_unlit\";\r\nexport * from \"./KHR_materials_volume\";\r\nexport * from \"./KHR_texture_transform\";\r\n"]}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import type { TypedArray } from "@babylonjs/core/types.js";
|
2
|
+
import type { AccessorComponentType, AccessorType, IAccessor, IBufferView } from "babylonjs-gltf2interface";
|
3
|
+
type TypedArrayForglTF = Exclude<TypedArray, Float64Array | BigInt64Array | BigUint64Array>;
|
4
|
+
interface IPropertyWithBufferView {
|
5
|
+
bufferView?: number;
|
6
|
+
}
|
7
|
+
/**
|
8
|
+
* Utility class to centralize the management of binary data, bufferViews, and the objects that reference them.
|
9
|
+
* @internal
|
10
|
+
*/
|
11
|
+
export declare class BufferManager {
|
12
|
+
/**
|
13
|
+
* Maps a bufferView to its data
|
14
|
+
*/
|
15
|
+
private _bufferViewToData;
|
16
|
+
/**
|
17
|
+
* Maps a bufferView to glTF objects that reference it via a "bufferView" property (e.g. accessors, images)
|
18
|
+
*/
|
19
|
+
private _bufferViewToProperties;
|
20
|
+
/**
|
21
|
+
* Maps an accessor to its bufferView
|
22
|
+
*/
|
23
|
+
private _accessorToBufferView;
|
24
|
+
/**
|
25
|
+
* Generates a binary buffer from the stored bufferViews. Also populates the bufferViews list.
|
26
|
+
* @param bufferViews The list of bufferViews to be populated while writing the binary
|
27
|
+
* @returns The binary buffer
|
28
|
+
*/
|
29
|
+
generateBinary(bufferViews: IBufferView[]): Uint8Array;
|
30
|
+
/**
|
31
|
+
* Creates a buffer view based on the supplied arguments
|
32
|
+
* @param data a TypedArray to create the bufferView for
|
33
|
+
* @param byteStride byte distance between consecutive elements
|
34
|
+
* @returns bufferView for glTF
|
35
|
+
*/
|
36
|
+
createBufferView(data: TypedArrayForglTF, byteStride?: number): IBufferView;
|
37
|
+
/**
|
38
|
+
* Creates an accessor based on the supplied arguments and assigns it to the bufferView
|
39
|
+
* @param bufferView The glTF bufferView referenced by this accessor
|
40
|
+
* @param type The type of the accessor
|
41
|
+
* @param componentType The datatype of components in the attribute
|
42
|
+
* @param count The number of attributes referenced by this accessor
|
43
|
+
* @param byteOffset The offset relative to the start of the bufferView in bytes
|
44
|
+
* @param minMax Minimum and maximum value of each component in this attribute
|
45
|
+
* @param normalized Specifies whether integer data values are normalized before usage
|
46
|
+
* @returns accessor for glTF
|
47
|
+
*/
|
48
|
+
createAccessor(bufferView: IBufferView, type: AccessorType, componentType: AccessorComponentType, count: number, byteOffset?: number, minMax?: {
|
49
|
+
min: number[];
|
50
|
+
max: number[];
|
51
|
+
}, normalized?: boolean): IAccessor;
|
52
|
+
/**
|
53
|
+
* Assigns a bufferView to a glTF object that references it
|
54
|
+
* @param object The glTF object
|
55
|
+
* @param bufferView The bufferView to assign
|
56
|
+
*/
|
57
|
+
setBufferView(object: IPropertyWithBufferView, bufferView: IBufferView): void;
|
58
|
+
/**
|
59
|
+
* Removes buffer view from the binary data, as well as from all its known references
|
60
|
+
* @param bufferView the bufferView to remove
|
61
|
+
*/
|
62
|
+
removeBufferView(bufferView: IBufferView): void;
|
63
|
+
getBufferView(accessor: IAccessor): IBufferView;
|
64
|
+
getPropertiesWithBufferView(bufferView: IBufferView): IPropertyWithBufferView[];
|
65
|
+
getData(bufferView: IBufferView): TypedArrayForglTF;
|
66
|
+
private _verifyBufferView;
|
67
|
+
}
|
68
|
+
export {};
|
@@ -0,0 +1,152 @@
|
|
1
|
+
import { DataWriter } from "./dataWriter.js";
|
2
|
+
function getHighestByteAlignment(byteLength) {
|
3
|
+
if (byteLength % 4 === 0)
|
4
|
+
return 4;
|
5
|
+
if (byteLength % 2 === 0)
|
6
|
+
return 2;
|
7
|
+
return 1;
|
8
|
+
}
|
9
|
+
/**
|
10
|
+
* Utility class to centralize the management of binary data, bufferViews, and the objects that reference them.
|
11
|
+
* @internal
|
12
|
+
*/
|
13
|
+
export class BufferManager {
|
14
|
+
constructor() {
|
15
|
+
/**
|
16
|
+
* Maps a bufferView to its data
|
17
|
+
*/
|
18
|
+
this._bufferViewToData = new Map();
|
19
|
+
/**
|
20
|
+
* Maps a bufferView to glTF objects that reference it via a "bufferView" property (e.g. accessors, images)
|
21
|
+
*/
|
22
|
+
this._bufferViewToProperties = new Map();
|
23
|
+
/**
|
24
|
+
* Maps an accessor to its bufferView
|
25
|
+
*/
|
26
|
+
this._accessorToBufferView = new Map();
|
27
|
+
}
|
28
|
+
/**
|
29
|
+
* Generates a binary buffer from the stored bufferViews. Also populates the bufferViews list.
|
30
|
+
* @param bufferViews The list of bufferViews to be populated while writing the binary
|
31
|
+
* @returns The binary buffer
|
32
|
+
*/
|
33
|
+
generateBinary(bufferViews) {
|
34
|
+
// Construct a DataWriter with the total byte length to prevent resizing
|
35
|
+
let totalByteLength = 0;
|
36
|
+
this._bufferViewToData.forEach((data) => {
|
37
|
+
totalByteLength += data.byteLength;
|
38
|
+
});
|
39
|
+
const dataWriter = new DataWriter(totalByteLength);
|
40
|
+
// Order the bufferViews in descending order of their alignment requirements
|
41
|
+
const orderedBufferViews = Array.from(this._bufferViewToData.keys()).sort((a, b) => getHighestByteAlignment(b.byteLength) - getHighestByteAlignment(a.byteLength));
|
42
|
+
// Fill in the bufferViews list and missing bufferView index references while writing the binary
|
43
|
+
for (const bufferView of orderedBufferViews) {
|
44
|
+
bufferView.byteOffset = dataWriter.byteOffset;
|
45
|
+
bufferViews.push(bufferView);
|
46
|
+
const bufferViewIndex = bufferViews.length - 1;
|
47
|
+
const properties = this.getPropertiesWithBufferView(bufferView);
|
48
|
+
for (const object of properties) {
|
49
|
+
object.bufferView = bufferViewIndex;
|
50
|
+
}
|
51
|
+
dataWriter.writeTypedArray(this._bufferViewToData.get(bufferView));
|
52
|
+
this._bufferViewToData.delete(bufferView); // Try to free up memory ASAP
|
53
|
+
}
|
54
|
+
return dataWriter.getOutputData();
|
55
|
+
}
|
56
|
+
/**
|
57
|
+
* Creates a buffer view based on the supplied arguments
|
58
|
+
* @param data a TypedArray to create the bufferView for
|
59
|
+
* @param byteStride byte distance between consecutive elements
|
60
|
+
* @returns bufferView for glTF
|
61
|
+
*/
|
62
|
+
createBufferView(data, byteStride) {
|
63
|
+
const bufferView = {
|
64
|
+
buffer: 0,
|
65
|
+
byteOffset: undefined, // byteOffset will be set later, when we write the binary and decide bufferView ordering
|
66
|
+
byteLength: data.byteLength,
|
67
|
+
byteStride: byteStride,
|
68
|
+
};
|
69
|
+
this._bufferViewToData.set(bufferView, data);
|
70
|
+
return bufferView;
|
71
|
+
}
|
72
|
+
/**
|
73
|
+
* Creates an accessor based on the supplied arguments and assigns it to the bufferView
|
74
|
+
* @param bufferView The glTF bufferView referenced by this accessor
|
75
|
+
* @param type The type of the accessor
|
76
|
+
* @param componentType The datatype of components in the attribute
|
77
|
+
* @param count The number of attributes referenced by this accessor
|
78
|
+
* @param byteOffset The offset relative to the start of the bufferView in bytes
|
79
|
+
* @param minMax Minimum and maximum value of each component in this attribute
|
80
|
+
* @param normalized Specifies whether integer data values are normalized before usage
|
81
|
+
* @returns accessor for glTF
|
82
|
+
*/
|
83
|
+
createAccessor(bufferView, type, componentType, count, byteOffset, minMax, normalized) {
|
84
|
+
this._verifyBufferView(bufferView);
|
85
|
+
const accessor = {
|
86
|
+
bufferView: undefined, // bufferView will be set to a real index later, once we write the binary and decide bufferView ordering
|
87
|
+
componentType: componentType,
|
88
|
+
count: count,
|
89
|
+
type: type,
|
90
|
+
min: minMax?.min,
|
91
|
+
max: minMax?.max,
|
92
|
+
normalized: normalized,
|
93
|
+
byteOffset: byteOffset,
|
94
|
+
};
|
95
|
+
this.setBufferView(accessor, bufferView);
|
96
|
+
this._accessorToBufferView.set(accessor, bufferView);
|
97
|
+
return accessor;
|
98
|
+
}
|
99
|
+
/**
|
100
|
+
* Assigns a bufferView to a glTF object that references it
|
101
|
+
* @param object The glTF object
|
102
|
+
* @param bufferView The bufferView to assign
|
103
|
+
*/
|
104
|
+
setBufferView(object, bufferView) {
|
105
|
+
this._verifyBufferView(bufferView);
|
106
|
+
const properties = this.getPropertiesWithBufferView(bufferView);
|
107
|
+
properties.push(object);
|
108
|
+
}
|
109
|
+
/**
|
110
|
+
* Removes buffer view from the binary data, as well as from all its known references
|
111
|
+
* @param bufferView the bufferView to remove
|
112
|
+
*/
|
113
|
+
removeBufferView(bufferView) {
|
114
|
+
const properties = this.getPropertiesWithBufferView(bufferView);
|
115
|
+
for (const object of properties) {
|
116
|
+
if (object.bufferView !== undefined) {
|
117
|
+
delete object.bufferView;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
this._bufferViewToData.delete(bufferView);
|
121
|
+
this._bufferViewToProperties.delete(bufferView);
|
122
|
+
this._accessorToBufferView.forEach((bv, accessor) => {
|
123
|
+
if (bv === bufferView) {
|
124
|
+
// Additionally, remove byteOffset from accessor referencing this bufferView
|
125
|
+
if (accessor.byteOffset !== undefined) {
|
126
|
+
delete accessor.byteOffset;
|
127
|
+
}
|
128
|
+
this._accessorToBufferView.delete(accessor);
|
129
|
+
}
|
130
|
+
});
|
131
|
+
}
|
132
|
+
getBufferView(accessor) {
|
133
|
+
const bufferView = this._accessorToBufferView.get(accessor);
|
134
|
+
this._verifyBufferView(bufferView);
|
135
|
+
return bufferView;
|
136
|
+
}
|
137
|
+
getPropertiesWithBufferView(bufferView) {
|
138
|
+
this._verifyBufferView(bufferView);
|
139
|
+
this._bufferViewToProperties.set(bufferView, this._bufferViewToProperties.get(bufferView) ?? []);
|
140
|
+
return this._bufferViewToProperties.get(bufferView);
|
141
|
+
}
|
142
|
+
getData(bufferView) {
|
143
|
+
this._verifyBufferView(bufferView);
|
144
|
+
return this._bufferViewToData.get(bufferView);
|
145
|
+
}
|
146
|
+
_verifyBufferView(bufferView) {
|
147
|
+
if (bufferView === undefined || !this._bufferViewToData.has(bufferView)) {
|
148
|
+
throw new Error(`BufferView ${bufferView} not found in BufferManager.`);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
//# sourceMappingURL=bufferManager.js.map
|