Hi there!
I’m following the sample: misc_exporter_gltf.html
And making a multiple .GLB loader in a scene. I’m following the Soldier sample.
So I construct a complex scene with 4 soldiers. GLB soldier file weight about 2.2MB.
When I download the scene, it’s weight only 2,8MB and when I upload this scene to model-viewer I see it on a very reduced dimensions
Hope you can help me!
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';
import { GLTFExporter } from "three/addons/exporters/GLTFExporter.js";
let camera, scene, renderer;
let clock;
const mixers = [];
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 2, 3, - 6 );
camera.lookAt( 0, 1, 0 );
clock = new THREE.Clock();
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
scene.fog = new THREE.Fog( 0xa0a0a0, 10, 50 );
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 20, 0 );
scene.add( hemiLight );
const dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( - 3, 10, - 10 );
dirLight.castShadow = true;
dirLight.shadow.camera.top = 4;
dirLight.shadow.camera.bottom = - 4;
dirLight.shadow.camera.left = - 4;
dirLight.shadow.camera.right = 4;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 40;
scene.add( dirLight );
// scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );
// ground
const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
const loader = new GLTFLoader();
let ferrari;
loader.load( 'models/gltf/Soldier.glb', function ( gltf ) {
gltf.scene.traverse( function ( object ) {
if ( object.isMesh ) object.castShadow = true;
} );
const model1 = SkeletonUtils.clone( gltf.scene );
const model2 = SkeletonUtils.clone( gltf.scene );
const model3 = SkeletonUtils.clone( gltf.scene );
const mixer1 = new THREE.AnimationMixer( model1 );
const mixer2 = new THREE.AnimationMixer( model2 );
const mixer3 = new THREE.AnimationMixer( model3 );
mixer1.clipAction( gltf.animations[ 0 ] ).play(); // idle
mixer2.clipAction( gltf.animations[ 1 ] ).play(); // run
mixer3.clipAction( gltf.animations[ 3 ] ).play(); // walk
model1.position.x = - 2;
model2.position.x = 0;
model3.position.x = 2;
scene.add( model1, model2, model3 );
mixers.push( mixer1, mixer2, mixer3);
animate();
} );
loader.load( 'models/gltf/Soldier.glb', function ( gltf ) {
gltf.scene.traverse( function ( object ) {
if ( object.isMesh ) object.castShadow = true;
} );
const model4 = SkeletonUtils.clone( gltf.scene );
//const mixer4 = new THREE.AnimationMixer( model4 );
//mixer4.clipAction( gltf.animations[ 0 ] ).play(); // idle
model4.position.x = -4;
scene.add(model4);
//mixers.push(mixer4);
//animate();
} );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
const delta = clock.getDelta();
for ( const mixer of mixers ) mixer.update( delta );
renderer.render( scene, camera );
}
/* DOWNLOAD */
const params = {
trs: true,
onlyVisible: false,
binary: true,
maxTextureSize: 40960000000,
forceIndices: true,
exportScene1: exportScene1,
exportScenes: exportScenes,
exportSphere: exportSphere,
exportHead: exportHead,
exportObjects: exportObjects,
exportSceneObject: exportSceneObject
};
const link = document.createElement( 'a' );
link.style.display = 'none';
document.body.appendChild( link );
function exportGLTF( input ) {
console.log(input);
const gltfExporter = new GLTFExporter();
const options = {
trs: params.trs,
onlyVisible: params.onlyVisible,
binary: params.binary,
maxTextureSize: params.maxTextureSize,
forceIndices: true
};
gltfExporter.parse(
input,
function ( result ) {
if ( result instanceof ArrayBuffer ) {
saveArrayBuffer( result, 'scene.glb' );
} else {
const output = JSON.stringify( result, null, 2 );
console.log( output );
saveString( output, 'scene.gltf' );
}
},
function ( error ) {
console.log( 'An error happened during parsing', error );
},
options
);
}
var btn = document.createElement('button');
document.body.appendChild(btn);
btn.textContent = 'Download .glb';
btn.onclick = download;
function download(){
exportGLTF( [ scene ] );
}
function save( blob, filename ) {
link.href = URL.createObjectURL( blob );
link.download = filename;
link.click();
// URL.revokeObjectURL( url ); breaks Firefox...
}
function saveString( text, filename ) {
console.log("string");
save( new Blob( [ text ], { type: 'text/plain' } ), filename );
}
function saveArrayBuffer( buffer, filename ) {
console.log("buffer");
save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
}
function exportScene1() {
exportGLTF( scene1 );
}
function exportScenes() {
exportGLTF( [ scene1, scene2 ] );
}
function exportSphere() {
exportGLTF( sphere );
}
function exportHead() {
exportGLTF( waltHead );
}
function exportObjects() {
exportGLTF( [ sphere, gridHelper ] );
}
function exportSceneObject() {
exportGLTF( [ scene1, gridHelper ] );
}