/**
 * 3D Foundation Project
 * Copyright 2019 Smithsonian Institution
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import { LoadingManager , Object3D , Scene , Group , Mesh , MeshStandardMaterial , sRGBEncoding } from "three" ; import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js' ; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js' ; import UberPBRMaterial from "../shaders/UberPBRMaterial" ; const DEFAULT_DRACO_PATH = "https://www.gstatic.com/draco/versioned/decoders/1.3.6/" ; export default class ModelReader { static readonly extensions = [ "gltf" , "glb" ] ; static readonly mimeTypes = [ "model/gltf+json" , "model/gltf-binary" ] ; protected loadingManager : LoadingManager ; protected gltfLoader ; protected customDracoPath = null ; set dracoPath ( path ) { this . customDracoPath = path ; if ( this . gltfLoader . dracoLoader !== null ) { this . gltfLoader . dracoLoader . setDecoderPath ( this . customDracoPath ) ; } } constructor ( loadingManager ) { this . loadingManager = loadingManager ; if ( ENV_DEVELOPMENT ) { console . log ( "ModelReader.constructor - DRACO path: %s" , this . customDracoPath || DEFAULT_DRACO_PATH ) ; } const dracoLoader = new DRACOLoader ( ) ; dracoLoader . setDecoderPath ( this . customDracoPath || DEFAULT_DRACO_PATH ) ; this . gltfLoader = new GLTFLoader ( loadingManager ) ; this . gltfLoader . setDRACOLoader ( dracoLoader ) ; } dispose ( ) { this . gltfLoader . dracoLoader . dispose ( ) ; this . gltfLoader . setDRACOLoader ( null ) ; this . gltfLoader = null ; } isValid ( url ) { const extension = url . split ( "." ) . pop ( ) . toLowerCase ( ) ; return ModelReader . extensions . indexOf ( extension ) >= 0 ; } isValidMimeType ( mimeType ) { return ModelReader . mimeTypes . indexOf ( mimeType ) >= 0 ; } get ( url ) { return new Promise ( ( resolve , reject ) => { this . gltfLoader . load ( url , gltf => { resolve ( this . createModelGroup ( gltf ) ) ; } , null , error => { console . error ( `failed to load '${ url }': ${ error }` ) ; reject ( new Error ( error ) ) ; } ) ; } ) ; } protected createModelGroup ( gltf ) { const scene = gltf . scene ; scene . traverse ( ( object ) => { if ( object . type === "Mesh" ) { const mesh = object ; mesh . castShadow = true ; const material = mesh . material as MeshStandardMaterial ; if ( material . map ) { material . map . encoding = sRGBEncoding ; } mesh . geometry . computeBoundingBox ( ) ; const uberMat = new UberPBRMaterial ( ) ; if ( material . type === "MeshStandardMaterial" ) { uberMat . copyStandardMaterial ( material ) ; } if ( material . userData [ "objectSpaceNormals" ] ) { uberMat . enableObjectSpaceNormalMap ( true ) ; if ( ENV_DEVELOPMENT ) { console . log ( "ModelReader.createModelGroup - objectSpaceNormals: " , true ) ; } } mesh . material = uberMat ; } } ) ; return scene ; } }