Giter VIP home page Giter VIP logo

gltf-js-utils's Introduction

gltf-js-utils

Helper library for creating glTF 2.0 models with JavaScript.

Usage

Creating glTF from scratch

Create a GLTFAsset structure using the provided types.

import {
  GLTFAsset, Scene, Node, Material, Texture, Mesh, Vertex, WrappingMode
} from "gltf-js-utils";

const asset = new GLTFAsset();
const scene = new Scene();
asset.addScene(scene);

const node = new Node();
node.setTranslation(x, y, z);
node.setRotationRadians(x, y, z);
node.setScale(x, y, z);
scene.addNode(node);

const material = new Material();
// Supported texture types: HTMLImageElement | HTMLCanvasElement | ArrayBuffer (PNG) | Data URL (PNG)
const texture = new Texture(image);
texture.wrapS = WrappingMode.CLAMP_TO_EDGE;
texture.wrapT = WrappingMode.REPEAT;
material.pbrMetallicRoughness.baseColorTexture = texture;

const mesh = new Mesh();
mesh.material = [material];
node.mesh = mesh;

const v1 = new Vertex();
v1.x = 1;
v1.y = 1;
v1.z = 1;
v1.u = 0;
v1.v = 0;
const v2 = new Vertex();
// ...

const faceColor = undefined;
const faceMaterialIndex = 0;
mesh.addFace(v1, v2, v3, faceColor, faceMaterialIndex);
mesh.addFace(v4, v5, v6, faceColor, faceMaterialIndex);
// ...
Create Animation
import { Node, Animation, InterpolationMode, Transformation } from "gltf-js-utils";

const node = new Node();
scene.addNode(node);
const nodeAnim = new Animation(Transformation.TRANSLATION);
nodeAnim.keyframes = [
    {
        time: 0,
        value: [1, 2, 3],
        interpType: InterpolationMode.LINEAR
    },
    {
        time: 0.3,
        value: [4, 5, 6],
        interpType: InterpolationMode.LINEAR
    }
];
// or add keyframes via addKeyframe function
nodeAnim1.addKeyframe(0.8, [7, 8, 9], InterpolationMode.STEP);
node.animations = [nodeAnim];
Export to a collection of individual files/data

With the default options, you'll receive an object keyed with the glTF JSON and binary buffers.

import { exportGLTF } from "gltf-js-utils";

const gltfFiles = await exportGLTF(asset);
// {
//   "model.gltf": string /* JSON glTF string */
//   "data1.bin": ArrayBuffer /* ArrayBuffer of buffer data */
//   "data2.bin": ArrayBuffer,
//   "data3.bin": ArrayBuffer,
//   ...
//   "img1.png": ArrayBuffer /* Texture image */
//   "img2.png": ArrayBuffer
//   ...
// }
Export using data URIs

Buffers and/or images can be embedded within the JSON as data URIs.

import { exportGLTF, BufferOutputType } from "gltf-js-utils";

const gltfFiles = await exportGLTF(asset, {
  bufferOutputType: BufferOutputType.DataURI,
  imageOutputType: BufferOutputType.DataURI,
});
// {
//   "model.gltf": string /* JSON glTF string, all data embedded */
// }
Export to a ZIP file

Requires a JSZip reference. The result will be a ZIP blob.

import * as JSZip from "jszip";
import { exportGLTFZip } from "gltf-js-utils";

exportGLTFZip(asset, JSZip).then(blob => {
  // Use FileSaver as an example.
  saveAs(blob, "model.zip");
});

Create glTF from Three.js object

Use the separate gtlf-js-utils-three package to create glTF models from Three.js models. See the gtlf-js-utils-three documentation for more details.

import { exportGLTF } from "gltf-js-utils";
import { glTFAssetFromTHREE } from "gltf-js-utils-three";

// Create a Three.js Scene or Object3D structure...
const scene = new THREE.Scene();
...

const gltfFiles = await exportGLTF(glTFAssetFromTHREE(scene));

Create a GLB container

Calling exportGLB will produce a single GLB model in an ArrayBuffer.

import { exportGLB } from "gltf-js-utils";

const glbArrayBuffer = await exportGLB(asset);

You can also use exportGLTF with the GLB output type to selectively keep some assets external.

import { exportGLTF, BufferOutputType } from "gltf-js-utils";

const gltfFiles = await exportGLTF(asset, {
  bufferOutputType: BufferOutputType.GLB,
  imageOutputType: BufferOutputType.External,
});
// {
//   "model.glb": ArrayBuffer
//   ...
//   // Only images follow, data bins are in the GLB file
//   "img1.png": ArrayBuffer /* Texture image */
//   "img2.png": ArrayBuffer
// }

Limitations

  • No support for camera yet.

Development

To build:

npm install
npm run build

To test:

npm run test

License

MIT

gltf-js-utils's People

Contributors

cesswairimu avatar mrlooi avatar rkaravia avatar wnayes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gltf-js-utils's Issues

Issues with mesh and vertex interface

I'm struggling to export a mesh correctly without materials or face colors, and I think this comes down to how the mesh and vertex interfaces are structured. In this example, face colors and material index are both required arguments to addFace. When I export and validate the result (using http://github.khronos.org/glTF-Validator/) the model has some issues:

Errors:

Code Message Pointer
VALUE_NOT_IN_RANGE Value 0 is out of range. /bufferViews/3/byteLength
BUFFER_VIEW_TOO_LONG BufferView does not fit buffer (0) byteLength (1152). /bufferViews/3/byteOffset
MESH_PRIMITIVE_POSITION_ACCESSOR_WITHOUT_BOUNDS accessor.min and accessor.max must be defined for POSITION attribute accessor. /meshes/0/primitives/0/attributes/POSITION
ACCESSOR_NON_UNIT 36 accessor elements not of unit length: 0. [AGGREGATED] /accessors/1

Info:

Code Message Pointer
MESH_PRIMITIVE_UNUSED_TEXCOORD Material does not use texture coordinates sets with indices (0). /meshes/0/primitives/0/material
UNUSED_OBJECT This object may be unused. /bufferViews/3

I have a few suggestions, but they're pretty opinionated so I wasn't necessarily sure if you would agree or accept a PR:

ACCESSOR_VECTOR3_NON_UNIT error on GLTF validator

Hey, I'm generating a single triangle test using the code below and running into ACCESSOR_VECTOR3_NON_UNIT in the glTF validator on https://gltf-viewer.donmccurdy.com/

import fs from "fs";
import {
    Scene, Node, Material, Mesh, Vertex, RGBColor, exportGLB 
 } from "gltf-js-utils";

const asset = new GLTFAsset();
const scene = new Scene();
asset.addScene(scene);

const node = new Node();
node.setTranslation(0, 0, 0);
node.setRotationRadians(0, 0, 0);
node.setScale(1, 1, 1);
scene.addNode(node);

const mesh = new Mesh();
mesh.material = [new Material()];
node.mesh = mesh;

const v1 = new Vertex();
v1.x = 0;
v1.y = 0;
v1.z = 0;
v1.u = 0;
v1.v = 0;

const v2 = new Vertex();
v2.x = 5;
v2.y = 5;
v2.z = 5;
v2.u = 0;
v2.v = 0;

const v3 = new Vertex();
v3.x = 5;
v3.y = 0;
v3.z = 0;
v3.u = 0;
v3.v = 0;

const faceColor = new RGBColor();
faceColor.r = 1.0;
faceColor.g = 1.0;
faceColor.b = 1.0;
const faceMaterialIndex = 0;

mesh.addFace(v1, v2, v3, faceColor, faceMaterialIndex);

( async () => {
    const glbArrayBuffer = await exportGLB(asset);
    fs.writeFileSync('./model.glb', Buffer.from(glbArrayBuffer))
})()

Am I doing something wrong?

Produced *.gltf file extracted using glTF VS code extension:

{
  "asset": {
    "version": "2.0",
    "copyright": "",
    "generator": "glTF-js-utils"
  },
  "scene": 0,
  "buffers": [
    {
      "uri": "model_data.bin",
      "byteLength": 96
    }
  ],
  "scenes": [
    {
      "nodes": [
        0
      ]
    }
  ],
  "nodes": [
    {
      "mesh": 0
    }
  ],
  "meshes": [
    {
      "primitives": [
        {
          "attributes": {
            "POSITION": 0,
            "NORMAL": 1,
            "TEXCOORD_0": 2
          },
          "mode": 4,
          "material": 0
        }
      ]
    }
  ],
  "materials": [
    {}
  ],
  "bufferViews": [
    {
      "buffer": 0,
      "byteLength": 36,
      "byteStride": 12,
      "byteOffset": 0
    },
    {
      "buffer": 0,
      "byteLength": 36,
      "byteStride": 12,
      "byteOffset": 36
    },
    {
      "buffer": 0,
      "byteLength": 24,
      "byteStride": 8,
      "byteOffset": 72
    }
  ],
  "accessors": [
    {
      "bufferView": 0,
      "byteOffset": 0,
      "componentType": 5126,
      "count": 3,
      "type": "VEC3",
      "min": [
        0,
        0,
        0
      ],
      "max": [
        5,
        5,
        5
      ]
    },
    {
      "bufferView": 1,
      "byteOffset": 0,
      "componentType": 5126,
      "count": 3,
      "type": "VEC3",
      "min": [
        0,
        0,
        0
      ],
      "max": [
        0,
        0,
        0
      ]
    },
    {
      "bufferView": 2,
      "byteOffset": 0,
      "componentType": 5126,
      "count": 3,
      "type": "VEC2",
      "min": [
        0,
        0
      ],
      "max": [
        0,
        0
      ]
    }
  ]
}

Error report:

{
    "uri": "model.glb",
    "mimeType": "model/gltf-binary",
    "validatorVersion": "2.0.0-dev.3.8",
    "validatedAt": "2022-11-10T18:22:19.726Z",
    "issues": {
        "numErrors": 3,
        "numWarnings": 0,
        "numInfos": 1,
        "numHints": 3,
        "messages": [
            {
                "code": "BUFFER_VIEW_TARGET_MISSING",
                "message": "bufferView.target should be set for vertex or index data.",
                "severity": 3,
                "pointer": "/meshes/0/primitives/0/attributes/POSITION"
            },
            {
                "code": "BUFFER_VIEW_TARGET_MISSING",
                "message": "bufferView.target should be set for vertex or index data.",
                "severity": 3,
                "pointer": "/meshes/0/primitives/0/attributes/NORMAL"
            },
            {
                "code": "BUFFER_VIEW_TARGET_MISSING",
                "message": "bufferView.target should be set for vertex or index data.",
                "severity": 3,
                "pointer": "/meshes/0/primitives/0/attributes/TEXCOORD_0"
            },
            {
                "code": "UNUSED_OBJECT",
                "message": "This object may be unused.",
                "severity": 2,
                "pointer": "/meshes/0/primitives/0/attributes/TEXCOORD_0"
            },
            {
                "code": "ACCESSOR_VECTOR3_NON_UNIT",
                "message": "Vector3 at accessor indices 0..2 is not of unit length: 0.",
                "severity": 0,
                "pointer": "/meshes/0/primitives/0/attributes/NORMAL"
            },
            {
                "code": "ACCESSOR_VECTOR3_NON_UNIT",
                "message": "Vector3 at accessor indices 3..5 is not of unit length: 0.",
                "severity": 0,
                "pointer": "/meshes/0/primitives/0/attributes/NORMAL"
            },
            {
                "code": "ACCESSOR_VECTOR3_NON_UNIT",
                "message": "Vector3 at accessor indices 6..8 is not of unit length: 0.",
                "severity": 0,
                "pointer": "/meshes/0/primitives/0/attributes/NORMAL"
            }
        ],
        "truncated": false
    },
    "info": {
        "version": "2.0",
        "generator": "glTF-js-utils",
        "resources": [
            {
                "pointer": "/buffers/0",
                "mimeType": "application/gltf-buffer",
                "storage": "glb",
                "byteLength": 96
            }
        ],
        "animationCount": 0,
        "materialCount": 1,
        "hasMorphTargets": false,
        "hasSkins": false,
        "hasTextures": false,
        "hasDefaultScene": true,
        "drawCallCount": 1,
        "totalVertexCount": 3,
        "totalTriangleCount": 1,
        "maxUVs": 1,
        "maxInfluences": 0,
        "maxAttributes": 3
    }
}

Module on npm is out of date

There's an error related to vertexColors that it looks like you've already fixed. Would you mind pushing a new version of your library to npm?

I'm using glTF-js-utils to generate glTF models on the fly in Aardvark: https://github.com/aardvarkxr/aardvark

It's been very helpful. Thanks for building it.

.glb file did not generated

I want .glb files. How can I export the model below as a .glb file? Thanks.

ArrayBuffer {
  [Uint8Contents]: <67 6c 54 46 02 00 00 00 20 01 00 00 04 01 00 00 4a 53 4f 4e 7b 22 61 73 73 65 74 22 3a 7b 22 76 65 72 73 69 6f 6e 22 3a 22 32 2e 30 22 2c 22 63 6f 70 79 72 69 67 68 74 22 3a 22 22 2c 22 67 65 6e 65 72 61 74 6f 72 22 3a 22 67 6c 54 46 2d 6a 73 2d 75 74 69 6c 73 22 7d 2c 22 73 63 65 6e 65 22 3a 30 2c ... 188 more bytes>,
  byteLength: 288
}

npm package has invalid entrypoint

Hi, thanks for publishing this utility to npm! There seems to be an issue with the main entrypoint in package.json though. I'm not familiar with publishing transpiled TypeScript modules, but I assume "main": ".src/index.js" should be "main": "dist/index.js"?

Image as Texture

Is it possible to use image like png buffer (not html image tag) for texture? I need that as Node js doesn't support html tags.

Point cloud

Hi, Is there a way to export a point cloud in Gltf?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.