{"id":13393523,"url":"https://github.com/pmndrs/gltfjsx","last_synced_at":"2025-05-13T17:13:22.608Z","repository":{"id":37687876,"uuid":"210546047","full_name":"pmndrs/gltfjsx","owner":"pmndrs","description":"🎮 Turns GLTFs into JSX components","archived":false,"fork":false,"pushed_at":"2024-11-04T16:51:26.000Z","size":7685,"stargazers_count":5319,"open_issues_count":110,"forks_count":348,"subscribers_count":43,"default_branch":"master","last_synced_at":"2025-05-09T06:28:35.814Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://gltf.pmnd.rs","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pmndrs.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"drcmda","open_collective":"react-three-fiber"}},"created_at":"2019-09-24T08:02:27.000Z","updated_at":"2025-05-08T18:13:26.000Z","dependencies_parsed_at":"2024-11-07T11:36:01.154Z","dependency_job_id":null,"html_url":"https://github.com/pmndrs/gltfjsx","commit_stats":{"total_commits":451,"total_committers":32,"mean_commits":14.09375,"dds":"0.10864745011086474","last_synced_commit":"d7c2cf2a7cb3b33b560a7d8e4870e8dcbc9c09ea"},"previous_names":[],"tags_count":118,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fgltfjsx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fgltfjsx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fgltfjsx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fgltfjsx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmndrs","download_url":"https://codeload.github.com/pmndrs/gltfjsx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253981008,"owners_count":21994186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T17:00:55.047Z","updated_at":"2025-05-13T17:13:22.542Z","avatar_url":"https://github.com/pmndrs.png","language":"JavaScript","funding_links":["https://github.com/sponsors/drcmda","https://opencollective.com/react-three-fiber"],"categories":["JavaScript","Assets","Three.js","3D","Libraries"],"sub_categories":["GLTF \u0026 KTX2","SVG Animations","JavaScript"],"readme":"https://user-images.githubusercontent.com/2223602/126318148-99da7ed6-a578-48dd-bdd2-21056dbad003.mp4\n\n\u003cbr /\u003e\n\u003cbr/\u003e\n\n[![Version](https://img.shields.io/npm/v/gltfjsx?style=flat\u0026colorA=000000\u0026colorB=000000)](https://www.npmjs.com/package/gltfjsx) [![Discord Shield](https://img.shields.io/discord/740090768164651008?style=flat\u0026colorA=000000\u0026colorB=000000\u0026label=discord\u0026logo=discord\u0026logoColor=ffffff)](https://discord.gg/ZZjjNvJ)\n\nA small command-line tool that turns GLTF assets into declarative and re-usable [react-three-fiber](https://github.com/pmndrs/react-three-fiber) JSX components.\n\n### The GLTF workflow on the web is not ideal ...\n\n- GLTF is thrown whole into the scene which prevents re-use, in threejs objects can only be mounted once\n- Contents can only be found by traversal which is cumbersome and slow\n- Changes to queried nodes are made by mutation, which alters the source data and prevents re-use\n- Re-structuring content, making nodes conditional or adding/removing is cumbersome\n- Model compression is complex and not easily achieved\n- Models often have unnecessary nodes that cause extra work and matrix updates\n\n### GLTFJSX fixes that\n\n- 🧑‍💻 It creates a virtual graph of all objects and materials. Now you can easily alter contents and re-use.\n- 🏎️ The graph gets pruned (empty groups, unnecessary transforms, ...) and will perform better.\n- ⚡️ It will optionally compress your model with up to 70%-90% size reduction.\n\n## Usage\n\n```text\nUsage\n  $ npx gltfjsx [Model.glb] [options]\n\nOptions\n  --output, -o        Output file name/path\n  --types, -t         Add Typescript definitions\n  --keepnames, -k     Keep original names\n  --keepgroups, -K    Keep (empty) groups, disable pruning\n  --bones, -b         Lay out bones declaratively (default: false)\n  --meta, -m          Include metadata (as userData)\n  --shadows, s        Let meshes cast and receive shadows\n  --printwidth, w     Prettier printWidth (default: 120)\n  --precision, -p     Number of fractional digits (default: 3)\n  --draco, -d         Draco binary path\n  --root, -r          Sets directory from which .gltf file is served\n  --instance, -i      Instance re-occuring geometry\n  --instanceall, -I   Instance every geometry (for cheaper re-use)\n  --exportdefault, -E Use default export\n  --transform, -T     Transform the asset for the web (draco, prune, resize)\n    --resolution, -R  Resolution for texture resizing (default: 1024)\n    --keepmeshes, -j  Do not join compatible meshes\n    --keepmaterials, -M Do not palette join materials\n    --format, -f      Texture format (default: \"webp\")\n    --simplify, -S    Mesh simplification (default: false)\n      --ratio         Simplifier ratio (default: 0)\n      --error         Simplifier error threshold (default: 0.0001)\n  --console, -c       Log JSX to console, won't produce a file\n  --debug, -D         Debug output\n```\n\n### A typical use-case\n\nFirst you run your model through gltfjsx. `npx` allows you to use npm packages without installing them.\n\n```bash\nnpx gltfjsx model.gltf --transform\n```\n\nThis will create a `Model.jsx` file that plots out all of the assets contents.\n\n```jsx\n/*\nauto-generated by: https://github.com/pmdrs/gltfjsx\nauthor: abcdef (https://sketchfab.com/abcdef)\nlicense: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)\nsource: https://sketchfab.com/models/...\ntitle: Model\n*/\n\nimport { useGLTF, PerspectiveCamera } from '@react-three/drei'\n\nexport function Model(props) {\n  const { nodes, materials } = useGLTF('/model-transformed.glb')\n  return (\n    \u003cgroup {...props} dispose={null}\u003e\n      \u003cPerspectiveCamera name=\"camera\" fov={40} near={10} far={1000} position={[10, 0, 50]} /\u003e\n      \u003cpointLight intensity={10} position={[100, 50, 100]} rotation={[-Math.PI / 2, 0, 0]} /\u003e\n      \u003cgroup position={[10, -5, 0]}\u003e\n        \u003cmesh geometry={nodes.robot.geometry} material={materials.metal} /\u003e\n        \u003cmesh geometry={nodes.rocket.geometry} material={materials.wood} /\u003e\n      \u003c/group\u003e\n    \u003c/group\u003e\n  )\n}\n\nuseGLTF.preload('/model.gltf')\n```\n\nAdd your model to your `/public` folder as you would normally do. With the `--transform` flag it has created a compressed copy of it (in the above case `model-transformed.glb`). Without the flag just copy the original model.\n\n```text\n/public\n  model-transformed.glb\n```\n\nThe component can now be dropped into your scene.\n\n```jsx\nimport { Canvas } from '@react-three/fiber'\nimport { Model } from './Model'\n\nfunction App() {\n  return (\n    \u003cCanvas\u003e\n      \u003cModel /\u003e\n```\n\nYou can re-use it, it will re-use geometries and materials out of the box:\n\n```jsx\n\u003cModel position={[0, 0, 0]} /\u003e\n\u003cModel position={[10, 0, -10]} /\u003e\n```\n\nOr make the model dynamic. Change its colors for example:\n\n```jsx\n\u003cmesh geometry={nodes.robot.geometry} material={materials.metal} material-color=\"green\" /\u003e\n```\n\nOr exchange materials:\n\n```jsx\n\u003cmesh geometry={nodes.robot.geometry}\u003e\n  \u003cmeshPhysicalMaterial color=\"hotpink\" /\u003e\n\u003c/mesh\u003e\n```\n\nMake contents conditional:\n\n```jsx\n{condition \u0026\u0026 \u003cmesh geometry={nodes.robot.geometry} material={materials.metal} /\u003e}\n```\n\nAdd events:\n\n```jsx\n\u003cmesh geometry={nodes.robot.geometry} material={materials.metal} onClick={handleClick} /\u003e\n```\n\n## Features\n\n#### ⚡️ Draco and meshopt compression ootb\n\nYou don't need to do anything if your models are draco compressed, since `useGLTF` defaults to a [draco CDN](https://www.gstatic.com/draco/v1/decoders/). By adding the `--draco` flag you can refer to [local binaries](https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/draco/gltf) which must reside in your /public folder.\n\n#### ⚡️ Preload your assets for faster response\n\nThe asset will be preloaded by default, this makes it quicker to load and reduces time-to-paint. Remove the preloader if you don't need it.\n\n```jsx\nuseGLTF.preload('/model.gltf')\n```\n\n#### ⚡️ Auto-transform (compression, resize)\n\nWith the `--transform` flag it creates a binary-packed, draco-compressed, texture-resized (1024x1024), webp compressed, deduped, instanced and pruned *.glb ready to be consumed on a web site. It uses [glTF-Transform](https://github.com/donmccurdy/glTF-Transform). This can reduce the size of an asset by 70%-90%.\n\nIt will not alter the original but create a copy and append `[modelname]-transformed.glb`.\n\n#### ⚡️ Type-safety\n\nAdd the `--types` flag and your GLTF will be typesafe.\n\n```tsx\ntype GLTFResult = GLTF \u0026 {\n  nodes: { robot: THREE.Mesh; rocket: THREE.Mesh }\n  materials: { metal: THREE.MeshStandardMaterial; wood: THREE.MeshStandardMaterial }\n}\n\nexport default function Model(props: JSX.IntrinsicElements['group']) {\n  const { nodes, materials } = useGLTF\u003cGLTFResult\u003e('/model.gltf')\n```\n\n#### ⚡️ Easier access to animations\n\nIf your GLTF contains animations it will add [drei's](https://github.com/pmndrs/drei) `useAnimations` hook, which extracts all clips and prepares them as actions:\n\n```jsx\nconst { nodes, materials, animations } = useGLTF('/model.gltf')\nconst { actions } = useAnimations(animations, group)\n```\n\nIf you want to play an animation you can do so at any time:\n\n```jsx\n\u003cmesh onClick={(e) =\u003e actions.jump.play()} /\u003e\n```\n\nIf you want to blend animations:\n\n```jsx\nconst [name, setName] = useState(\"jump\")\n...\nuseEffect(() =\u003e {\n  actions[name].reset().fadeIn(0.5).play()\n  return () =\u003e actions[name].fadeOut(0.5)\n}, [name])\n```\n\n#### ⚡️ Auto-instancing\n\nUse the `--instance` flag and it will look for similar geometry and create instances of them. Look into [drei/Merged](https://github.com/pmndrs/drei#instances) to understand how it works. It does not matter if you instanced the model previously in Blender, it creates instances for each mesh that has a specific geometry and/or material.\n\n`--instanceall` will create instances of all the geometry. This allows you to re-use the model with the smallest amount of drawcalls.\n\nYour export will look like something like this:\n\n```jsx\nconst context = createContext()\nexport function Instances({ children, ...props }) {\n  const { nodes } = useGLTF('/model-transformed.glb')\n  const instances = useMemo(() =\u003e ({ Screw1: nodes['Screw1'], Screw2: nodes['Screw2'] }), [nodes])\n  return (\n    \u003cMerged meshes={instances} {...props}\u003e\n      {(instances) =\u003e \u003ccontext.Provider value={instances} children={children} /\u003e}\n    \u003c/Merged\u003e\n  )\n}\n\nexport function Model(props) {\n  const instances = useContext(context)\n  return (\n    \u003cgroup {...props} dispose={null}\u003e\n      \u003cinstances.Screw1 position={[-0.42, 0.04, -0.08]} rotation={[-Math.PI / 2, 0, 0]} /\u003e\n      \u003cinstances.Screw2 position={[-0.42, 0.04, -0.08]} rotation={[-Math.PI / 2, 0, 0]} /\u003e\n    \u003c/group\u003e\n  )\n}\n```\n\nNote that similar to `--transform` it also has to transform the model. In order to use and re-use the model import both `Instances` and `Model`. Put all your models into the `Instances` component (you can nest).\n\nThe following will show the model three times, but you will only have 2 drawcalls tops.\n\n```jsx\nimport { Instances, Model } from './Model'\n\n\u003cInstances\u003e\n  \u003cModel position={[10,0,0]}\u003e\n  \u003cModel position={[-10,0,0]}\u003e\n  \u003cModel position={[-10,10,0]}\u003e\n\u003c/Instance\u003e\n```\n\n## Using the parser stand-alone\n\n```jsx\nimport { parse } from 'gltfjsx'\nimport { GLTFLoader, DRACOLoader } from 'three-stdlib'\n\nconst gltfLoader = new GLTFLoader()\nconst dracoloader = new DRACOLoader()\ndracoloader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/')\ngltfLoader.setDRACOLoader(dracoloader)\n\ngltfLoader.load(url, (gltf) =\u003e {\n  const jsx = parse(gltf, optionalConfig)\n})\n```\n\n## Using the parser stand-alone for scenes (object3d's)\n\n```jsx\nconst jsx = parse(scene, optionalConfig)\n```\n\n## Using GLTFStructureLoader stand-alone\n\nThe GLTFStructureLoader can come in handy while testing gltf assets. It allows you to extract the structure without the actual binaries and textures making it possible to run in a testing environment.\n\n```jsx\nimport { GLTFStructureLoader } from 'gltfjsx'\nimport fs from 'fs/promises'\n\nit('should have a scene with a blue mesh', async () =\u003e {\n  const loader = new GLTFStructureLoader()\n  const data = await fs.readFile('./model.glb')\n  const { scene } = await new Promise((res) =\u003e loader.parse(data, '', res))\n  expect(() =\u003e scene.children.length).toEqual(1)\n  expect(() =\u003e scene.children[0].type).toEqual('mesh')\n  expect(() =\u003e scene.children[0].material.color).toEqual('blue')\n})\n```\n\n## Requirements\n\n- Nodejs must be installed\n- The GLTF file has to be present in your projects `/public` folder\n- [three](https://github.com/mrdoob/three.js/) (\u003e= 122.x)\n- [@react-three/fiber](https://github.com/pmndrs/react-three-fiber) (\u003e= 5.x)\n- [@react-three/drei](https://github.com/pmndrs/drei) (\u003e= 2.x)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmndrs%2Fgltfjsx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmndrs%2Fgltfjsx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmndrs%2Fgltfjsx/lists"}