diff --git a/.gitignore b/.gitignore index 9376a72..cbb1d0a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ ehthumbs.db Desktop.ini $RECYCLE.BIN/ .DS_Store -.vscode .docz/ package-lock.json coverage/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..2576a6f --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "davidanson.vscode-markdownlint"] +} diff --git a/readme.md b/readme.md index 731d335..928671c 100644 --- a/readme.md +++ b/readme.md @@ -1,13 +1,12 @@ -https://user-images.githubusercontent.com/2223602/126318148-99da7ed6-a578-48dd-bdd2-21056dbad003.mp4 - -
-
+# GLTFJSX [![Version](https://img.shields.io/npm/v/gltfjsx?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/gltfjsx) [![Discord Shield](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=ffffff)](https://discord.gg/ZZjjNvJ) + + A 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. -### The GLTF workflow on the web is not ideal ... +## The GLTF workflow on the web is not ideal - GLTF is thrown whole into the scene which prevents re-use, in threejs objects can only be mounted once - Contents can only be found by traversal which is cumbersome and slow @@ -136,7 +135,9 @@ Or exchange materials: Make contents conditional: ```jsx -{condition && } +{ + condition ? : null +} ``` Add events: @@ -147,11 +148,11 @@ Add events: ## Features -#### ⚡️ Draco and meshopt compression ootb +### ⚡️ Draco and meshopt compression ootb You 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. -#### ⚡️ Preload your assets for faster response +### ⚡️ Preload your assets for faster response The 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. @@ -159,13 +160,13 @@ The asset will be preloaded by default, this makes it quicker to load and reduce useGLTF.preload('/model.gltf') ``` -#### ⚡️ Auto-transform (compression, resize) +### ⚡️ Auto-transform (compression, resize) -With 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%. +With 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%. It will not alter the original but create a copy and append `[modelname]-transformed.glb`. -#### ⚡️ Type-safety +### ⚡️ Type-safety Add the `--types` flag and your GLTF will be typesafe. @@ -179,7 +180,7 @@ export default function Model(props: JSX.IntrinsicElements['group']) { const { nodes, materials } = useGLTF('/model.gltf') ``` -#### ⚡️ Easier access to animations +### ⚡️ Easier access to animations If 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: @@ -205,7 +206,7 @@ useEffect(() => { }, [name]) ``` -#### ⚡️ Auto-instancing +### ⚡️ Auto-instancing Use 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. diff --git a/src/bin/GLTFLoader.js b/src/bin/GLTFLoader.js index 8a924ab..ea09ff2 100644 --- a/src/bin/GLTFLoader.js +++ b/src/bin/GLTFLoader.js @@ -1164,18 +1164,18 @@ function addMorphTargets(geometry, targets, parser) { } } - return Promise.all([Promise.all(pendingPositionAccessors), Promise.all(pendingNormalAccessors)]).then(function ( - accessors - ) { - var morphPositions = accessors[0] - var morphNormals = accessors[1] + return Promise.all([Promise.all(pendingPositionAccessors), Promise.all(pendingNormalAccessors)]).then( + function (accessors) { + var morphPositions = accessors[0] + var morphNormals = accessors[1] - if (hasMorphPosition) geometry.morphAttributes.position = morphPositions - if (hasMorphNormal) geometry.morphAttributes.normal = morphNormals - geometry.morphTargetsRelative = true + if (hasMorphPosition) geometry.morphAttributes.position = morphPositions + if (hasMorphNormal) geometry.morphAttributes.normal = morphNormals + geometry.morphTargetsRelative = true - return geometry - }) + return geometry + } + ) } function createPrimitiveKey(primitiveDef) { @@ -2211,7 +2211,7 @@ GLTFParser.prototype.loadMesh = function (meshIndex) { throw new Error('THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode) } - if (meshDef.hasMorphAttributes) { + if (meshDef.hasMorphAttributes) { // Just flag the mesh, so that parser.js can link morphTarget dictionaries and influences // This prevented a crash relating to morphTarget definitions mesh.morphTargetDictionary = true diff --git a/src/utils/parser.js b/src/utils/parser.js index a05be52..1eeaace 100644 --- a/src/utils/parser.js +++ b/src/utils/parser.js @@ -502,9 +502,11 @@ ${parseExtras(gltf.parser.json.asset && gltf.parser.json.asset.extras)}*/` hasAnimations ? `const group = ${options.types ? 'React.useRef()' : 'React.useRef()'};` : '' } ${ !options.instanceall - ? `const { ${!hasPrimitives ? `nodes, materials` : 'scene'} ${hasAnimations ? ', animations' : ''}} = useGLTF('${url}'${ - options.draco ? `, ${JSON.stringify(options.draco)}` : '' - })${!hasPrimitives && options.types ? ' as GLTFResult' : ''}${ + ? `const { ${!hasPrimitives ? `nodes, materials` : 'scene'} ${ + hasAnimations ? ', animations' : '' + }} = useGLTF('${url}'${options.draco ? `, ${JSON.stringify(options.draco)}` : ''})${ + !hasPrimitives && options.types ? ' as GLTFResult' : '' + }${ hasPrimitives ? `\nconst clone = React.useMemo(() => SkeletonUtils.clone(scene), [scene]) const { nodes, materials } = useGraph(clone) ${options.types ? ' as GLTFResult' : ''}` diff --git a/src/utils/transform.js b/src/utils/transform.js index 25c7005..bc57f51 100644 --- a/src/utils/transform.js +++ b/src/utils/transform.js @@ -57,8 +57,8 @@ async function transform(file, output, config = {}) { } functions.push( - // Weld vertices - weld(), + // Weld vertices + weld() ) if (config.simplify) {