Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/lib/components/objects/GLTF.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<script context="module">
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader';

/** @type {GLTFLoader} */
let loader = null;
/** @type {DRACOLoader} */
let dracoLoader = null;
/** @type {KTX2Loader} */
let ktxLoader = null;
</script>

<script>
import { onMount } from 'svelte';

import * as THREE from 'three';
import { setup } from '../../utils/context.js';
import { transform } from '../../utils/object.js';
import * as defaults from '../../utils/defaults.js';

/** @type {string} */
export let path = '';
/** @type {string} */
export let filename = null;
export let useDraco = false;
export let useKTX2 = false;

export let position = defaults.position;
export let rotation = defaults.rotation;
export let scale = defaults.scale;
export let castShadow = false;
export let receiveShadow = false;
export let frustumCulled = true;
export let renderOrder = 0;

/** @type {THREE.Group} */
let gltfScene = null;

const { root, parent, self } = setup(new THREE.Object3D());

$: {
if(gltfScene) {
Copy link

@aewing aewing Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: Maybe worth dispatching an event on load/change as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give an example of what that might look like?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!
At the top of the file before/after the props are exported, we could create an event dispatcher:

import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();

And then on line 77 where we have successfully loaded (or failed to load) the model, we could dispatch("load", gltf); or dispatch("error", err);, etc...

My thinking was that this could provide a convenient entry point for manipulating the materials in the scene, etc...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a consumer of the component, that would look something like

<SC.GLTF {...} on:load={swapMyTexture} on:error={swapFallbackScene} />

Copy link

@aewing aewing Nov 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that dispatching on change would provide any value to me, but the implementation would be similar, just within the reactive statement.

gltfScene.traverse( function( node ) {
if ( node.isMesh ) {
node.castShadow = castShadow;
node.receiveShadow = receiveShadow;
node.frustumCulled = frustumCulled;
node.renderOrder = renderOrder;
}
} );
}

transform(self, position, rotation, scale);
root.invalidate();
}

onMount(() => {
if (loader === null) {
loader = new GLTFLoader()
}

if (useDraco && dracoLoader === null) {
dracoLoader = new DRACOLoader().setDecoderPath( '/loaders/draco/' );
loader.setDRACOLoader(dracoLoader);
}

if (useKTX2 && ktxLoader === null) {
ktxLoader = new KTX2Loader()
.setTranscoderPath( '/loaders/basis/' )
.detectSupport( root.renderer );
loader.setKTX2Loader(ktxLoader);
}

loader.setPath( path )
.load( filename, function ( gltf ) {
gltfScene = gltf.scene;
self.add(gltf.scene);
} );

return () => {};
});
</script>

<slot />
1 change: 1 addition & 0 deletions src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { default as Canvas } from './components/Canvas.svelte';
export { default as Bone } from './components/objects/Bone.svelte';
export { default as Group } from './components/objects/Group.svelte';
export { default as Mesh } from './components/objects/Mesh.svelte';
export { default as GLTF } from './components/objects/GLTF.svelte';
export { default as Skeleton } from './components/objects/Skeleton.svelte';
export { default as SkinnedMesh } from './components/objects/SkinnedMesh.svelte';
export { default as Primitive } from './components/objects/Primitive.svelte';
Expand Down
59 changes: 59 additions & 0 deletions src/routes/examples/_content/04-gltf-simple/index.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script>
import * as THREE from 'three';
import * as SC from 'svelte-cubed';
</script>

<SC.Canvas
antialias
environment={new THREE.TextureLoader().load('/textures/kiara_1_dawn.jpeg',
(tex) => {
tex.mapping = THREE.EquirectangularReflectionMapping;
tex.encoding = THREE.sRGBEncoding;
})}
background={new THREE.TextureLoader().load('/textures/kiara_1_dawn.jpeg',
(tex) => {
tex.mapping = THREE.EquirectangularReflectionMapping;
tex.encoding = THREE.sRGBEncoding;
})}
shadows
>

<SC.Group position={[0, -1, 0]}>
<SC.Mesh
geometry={new THREE.PlaneGeometry(50, 50)}
material={new THREE.MeshStandardMaterial({ color: 'burlywood' })}
rotation={[-Math.PI / 2, 0, 0]}
receiveShadow
/>
<SC.Primitive
object={new THREE.GridHelper(50, 50, 'papayawhip', 'papayawhip')}
position={[0, 0.001, 0]}
/>
</SC.Group>

<SC.GLTF path="/gltf/" filename="DamagedHelmet.glb"
position={[0, 0, 0]}
castShadow
receiveShadow />
<SC.GLTF filename="/gltf/CesiumMan.glb"
position={[-6, 0, 0]}
castShadow
receiveShadow />

<SC.GLTF filename="/gltf/waterbottle/WaterBottle.gltf"
position={[3, 0, 0]}
useDraco
castShadow
receiveShadow />
<SC.GLTF path="/gltf/stainedglasslamp-KTX2/" filename="StainedGlassLamp.gltf"
position={[-3, 0, 0]}
useKTX2
castShadow
receiveShadow />


<SC.PerspectiveCamera position={[1, 2, 6]} target={[0, 1, 0]} />
<SC.OrbitControls enableZoom={false} maxPolarAngle={Math.PI * 0.51} />
<SC.AmbientLight intensity={0.6} />
<SC.DirectionalLight intensity={0.6} position={[-2, 3, 2]} shadow={{ mapSize: [2048, 2048] }} />
</SC.Canvas>
3 changes: 3 additions & 0 deletions src/routes/examples/_content/04-gltf-simple/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"title": "glTF simple"
}
Binary file added static/example-thumbnails/gltf-simple.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/gltf/CesiumMan.glb
Binary file not shown.
Binary file not shown.
Loading