GLTFLoader
의 Example을 따른것 같으나 GLTFLoader
에서 오류가 발생하여, GLTF파일
계열을 불러 올 수 없다(.gltf
(JSON
규격 데이터) / .glb
).SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (< anonymous >)
at GLTFLoader.parse (GLTFLoader.js:304)
at Object.onLoad (GLTFLoader.js:194)
at three.module.js:39290
<
라는 예상하지 못한 토큰이 발생된 문법 오류
이다.webpack
을 사용하라는 것이다."staticFiles":{
"staticPath": "{디폴트 경로}"
}
.parcelrc
파일을 프로젝트 최상단에 추가한다. 이는 플러그인과 관련이 있다.{
"extends": ["@parcel/config-default"],
"reporters": ["...", "parcel-reporter-static-files-copy"]
}
scene.gltf
파일에만 주목할 것'model/mobile_anti_aircraft/scene.gltf'
GLTFLoader.js
의 parse( data, path, onLoad, onError) 의 content
가 html파일
그 자체를 가리키는 것을 확인했다.JSON.parse
시도한다.content
가 무엇을 가리키는 것인지는 모르지만, 적어도 JSON
방식의 데이터이어야 할 것 같다..gltf
파일이 들어가지 않을까?)GLTFLoader
에 있는 three.js
가 제시하는 예제로 content
안에 무엇이 들어있는지 확인해 보아야 한다.GLTFLoader.js
)parse( data, path, onLoad, onError ) {
//content는 let으로 선언된 변수로
//parse함수 괄호 내에서만 유효하다.
let content;
const extensions = {};
const plugins = {};
//여러가지 분기를 거쳐 content를 결정한다.
if ( typeof data === 'string' ) {
content = data;
} else {
const magic = LoaderUtils.decodeText(
new Uint8Array( data, 0, 4 )
);
if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
try {
extensions[ EXTENSIONS.KHR_BINARY_GLTF ] =
new GLTFBinaryExtension( data );
} catch ( error ) {
if ( onError ) onError( error );
return;
}
content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;
} else {
content = LoaderUtils.decodeText( new Uint8Array( data ) );
}
}
//이 과정이 끝나면, content가 무엇인지 결정된다.
//오류가 나는 부분.
const json = JSON.parse( content );
if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {
if ( onError ) onError(
new Error(
'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.'
)
);
return;
}
//이후 생략
three.js에서 제시한 example에서의 요소들은 다음과 같다.
path
는 models/gltf/
로서, 실제 모델 glb파일이 존재하는 디렉토리까지 표시한다. 해당 파일을 직접 표시하지는 않는다.magic
은 BINARY_EXTENSION_HEADER_MAGIC
이다.content
는extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content
이다.그러나, 현재 코드에서의 요소는 다음과 같다.
path
자체에는 문제가 없이, gltf파일이 존재하는 디렉토리까지 표시한다.magic
은 BINARY_EXTENSION_HEADER_MAGIC
이 아니다.이것만으로는 판단하기 어려워, parse
를 호출하는 load
함수를 체크해본다.
load
함수는 다음과 같으며, 사용자
(개발자
)가 실제로 GLTFLoader
에서 사용하는 함수이다.
//url : 로드할 파일 경로(파일명 포함)
//onload : 로드가 완료되었을 때 호출할 콜백
//onProgress : 로드가 진행중일 때 호출할 콜백.
//로딩 진행도를 인자로 주고 콜백을 호출한다.
//onError : 오류 발생시 호출할 콜백.
//오류 정보 error를 인자로 주고 콜백을 호출한다.
load( url, onLoad, onProgress, onError ) {
const scope = this;
let resourcePath;
//GLTFLoader는 Loader를 상속받은 class이다.
//따라서 this는 현재 GLTFLoader class자체이다.
//default resourcePath를 정할 수 있는 듯.
if ( this.resourcePath !== '' ) {
resourcePath = this.resourcePath;
} else if ( this.path !== '' ) {
resourcePath = this.path;
} else {
//default? resourcePath가 없다면, 파라미터로 받아왔던 url을 extractUrlBase로 처리한 결과를 받는다.
resourcePath = LoaderUtils.extractUrlBase( url );
}
// Tells the LoadingManager to track an extra item, which resolves after
// the model is fully loaded. This means the count of items loaded will
// be incorrect, but ensures manager.onLoad() does not fire early.
this.manager.itemStart( url );
const _onError = function ( e ) {
if ( onError ) {
onError( e );
} else {
console.error( e );
}
scope.manager.itemError( url );
scope.manager.itemEnd( url );
};
const loader = new FileLoader( this.manager );
loader.setPath( this.path );
loader.setResponseType( 'arraybuffer' );
loader.setRequestHeader( this.requestHeader );
loader.setWithCredentials( this.withCredentials );
//loader에게 load를 맡긴다.
//load가 완료될시 이하 콜백함수 실행.
loader.load( url, function ( data ) {
try {
//여기서 parse가 발생한다.
//data는 콜백함수에서 전달받는 인자이다.
scope.parse( data, resourcePath, function ( gltf ) {
onLoad( gltf );
scope.manager.itemEnd( url );
}, _onError );
} catch ( e ) {
_onError( e );
}
}, onProgress, _onError );
}
url까지는 제대로 받지만, loader가 load하는 파일이 이상하다.
테스트 : 존재하지 않는 이상한 경로로 시도해본다.
경로 문제?
__filename
, __dirname
시도해보기다음과 같은 프로젝트 경로를 갖는다.
여기서 절대경로로 시도하였다.
여기서 상대경로로 시도하였다.
node.js환경에 의한 것?
three.js는 node.js에서의 사용을 권장하지 않는 편이다. 특히 three.js는 ESM(EcmaScript Module)기반인데, node.js는 자체적인 CJS(CommonJS)의 모듈을 사용하기 때문이다. 이는 공식 문서에도 기재되어있다.
프로젝트 뒤집기
시도 :
npm install -D parce-reporter-static-files-copy 명령어를 통해 일부 디렉토리에서 출력 디렉토리로 정적 파일을 복사하는 ParcelJS v2 플러그인을 설치한다.
static reader의 예시를 참고하여, .parcelrc파일을 만들어, 예제와 같게 하였다.
package.json파일을 수정하였다.
"staticFiles" 키를 만들고, "staticPath"를 "resources"로 한 것을 객체로 넣었다.
경로 수정
이제 파일의 기본 경로는 resources가 되었고,
경로를
'model/mobile_anti_aircraft/scene.gltf'
로 변경하였다.
결과 :
[.WebGL-0x29e4001a1400] GL_INVALID_OPERATION: Texture format does not support mipmap generation.