이어서 추출된 glTF 정보를 .glb 파일(바이너리) 또는 .gltf 파일(JSON)로 다운로드하여 저장할 수 있게 헤보겠습니다.
glTF 정보를 스크립트에서 다운로드하기 위해서는 URL.createObjectURL() 메서드를 사용하면 됩니다.
URL.createObjectURL() 메서드에 대한 영문 설명은 다음과 같습니다.
The URL.createObjectURL() static method creates a string containing a URL representing the object given in the parameter.
번역해 보면 URL.createObjectURL() 정적 메서드는 파라미터로 전달받은 객체를 가리키는 URL이 포함된 문자열을 생성합니다.
URL.createObjectURL(object)
- object: File, Blob, MediaSource 객체입니다.
즉, File 객체 또는 Blob 객체 또는 MediaSource 객체를 URL로 접근할 수 있게 아래와 같이 Blob URL를 생성하여 리턴하게 됩니다.
blob:http://localhost:5173/c95eb15c-3c2d-4ca1-b327-8e25a8bfe73e
그리고 URL.createObjectURL() 정적 메서드를 사용할 때마다 새로운 Blob URL를 생성되기 때문에 생성된 Blob URL은 URL.revokeObjectURL() 정적 메서드를 사용하여 해제해줘야 합니다.
그러나 생성된 Blob URL를 해제하지 않아도 웹 브라우저가 unload(다른 경로로 이동하거나 웹 브라우저가 종료될 때)가 되면 웹 브라우저가 자동으로 해제해 줍니다.
추가적으로 URL.createObjectURL()와 URL.revokeObjectURL() 정적 메서드로 blob URL를 생성하고 해제하는 방법은 W3C의 Creating and Revoking a blob URL를 참고하시기 바랍니다.
URL.createObjectURL() 정적 메서드로 Blob URL를 생성하기 위해서는 먼저 glTF 정보를 Blob 객체로 만들어야 합니다.
Blob(Binary Large Object, 비랍/블랍)은 대용량의 바이너리로 저장된 객체입니다.
new Blob(array, options)
- array: ArrayBuffer[] 또는 TypedArray[] 또는 DataView[] 또는 USVString(UTF-8로 인코딩 된 string[]) 또는 다른 Blob 배열 객체이거나 객체 또는 여러 개의 타입이 혼합된 배열 객체입니다.
- options: 데이터의 type과 endings을 설정하는 옵셥입니다.
options은 다음과 같이 설정할 수 있습니다.
- type: 저장될 데이터의 MIME 타입입니다. 기본값 ""(빈 문자열)
- endings(transparent, native): array 타입이 USVString(UTF-8로 인코딩 된 string[])일 때 개행 문자("\n")를 사용 중인 OS에 맞춰서 개행 문자를 변환할지(native) 아니면 변환하지 않을지(transparent) 선택합니다. 기본값 transparent
그럼 추출된 glTF 정보를 Blob(Binary Large Object, 비랍/블랍)으로 만들고 Blob URL를 생성하여 파일로 다운로드해 보겠습니다.
1. 추출된 glTF 정보를 파라미터로 받아 바이너리 형식과 JSON 형식의 Blob 객체를 만드는 함수를 만듭니다.
바이너리 형식으로 변환하기 위해서 options의 type를 "application/octet-stream"으로 설정합니다.
// 바이너리 형식으로 변환
function downloadBinary(buffer) {
const blob = new Blob([buffer], {type: 'application/octet-stream'});
console.log("Blob:", blob);
}
JSON 형식으로 변환하기 위해서 추출된 glTF 정보를 JSON 문자열로 변환하고 options의 type를 "application/json"으로 설정합니다.
// JSON 형식으로 변환
function downloadJSON(buffer) {
const blob = new Blob([JSON.stringify(buffer)], {type: 'application/json'});
console.log("Blob:", blob);
}
2. 기존 ExportglTF() 함수에 downloadBinary()와 downloadJSON()를 추가합니다. glTF 정보가 ArrayBuffer[]이면 downloadBinary() 함수를 호출하고 그렇지 않으면 downloadJSON() 함수를 호출하게 합니다.
function ExportglTF() {
// GLTF익스포트 생성
const exporter = new GLTFExporter();
// GLTF익스포트 옵션 - 바이너리 형식으로 추출
const options = {
binary: false
};
exporter.parse(
box2,
function (gltf) {
if (gltf instanceof ArrayBuffer) {
console.log("export gltf:", gltf);
downloadBinary(gltf);
} else {
console.log("export gltf:", gltf);
downloadJSON(gltf);
}
},
function (error) {
console.error("exporter error:", error);
},
options
);
}
Controls에서 "Export" 버튼을 클릭하면 콘솔에 Blob 객체 정보가 출력됩니다.
만약 glTF 익스포트 옵션의 binry가 flase이면 JSON 형식으로 다음과 같이 콘솔에 출력됩니다.
// GLTF익스포트 옵션 - JSON 형식으로 추출
const options = {
binary: false
};
3. 파일로 다운로드하기 위해서 Blob 객체를 파라미터로 받는 다운로드 함수를 만듭니다.
다운로드 URL를 생성하기 위해서 URL.createObjectURL() 메서드를 사용합니다.
// 다운로드
function download(blob) {
const blobURL = URL.createObjectURL(blob);
console.log(blobURL);
}
기존 downloadBinary()와 downloadJSON()에 다운로드 함수를 추가합니다.
// 바이너리 형식으로 변환
function downloadBinary(buffer) {
const blob = new Blob([buffer], {type: 'application/octet-stream'});
console.log("Blob:", blob);
download(blob);
}
// JSON 형식으로 변환
function downloadJSON(buffer) {
const blob = new Blob([JSON.stringify(buffer)], {type: 'application/json'});
console.log("Blob:", blob);
download(blob);
}
Controls에서 "Export" 버튼을 클릭하면 콘솔에 Blob URL이 출력됩니다.
blob:http://localhost:5173/b8c1b2f5-f4ee-4a9d-b286-7aed8af4dd47
만약 glTF 익스포트 옵션의 binry가 flase이면 JSON 형식으로 다음과 같이 Blob URL이 콘솔에 출력됩니다.
// GLTF익스포트 옵션 - JSON 형식으로 추출
const options = {
binary: false
};
blob:http://localhost:5173/b86e8950-8d45-4b8c-8822-16703dc678c2
4. 생성된 Blob URL로 다운로드하기 위해서 A 태그를 생성하고 href 속성 값으로 Blob URL를 설정합니다. 그리고 생성된 A 태그를 페이지에 추가하고 click() 메서드로 A 태그를 클릭하여 다운로드하게 합니다. 다운로드 후 생성된 Blob URL를 해제하고 페이지에 추가된 A 태그를 삭제합니다.
// 다운로드
function download(blob) {
const blobURL = URL.createObjectURL(blob);
console.log(blobURL);
// 다운로드를 하기위해 Blob URL로 A 태그 생성
const link = document.createElement('a');
link.href = blobURL;
// 다운로드 파일 명
link.download = "test.glb";
// A 태그 추가
document.body.appendChild(link);
// A 태그를 클릭하여 다운로드
link.click();
// 다운로드 후 Blob URL 해제
URL.revokeObjectURL(blobURL);
// A 태그 삭제
document.body.removeChild(link);
}
Controls에서 "Export" 버튼을 클릭하면 콘솔에 glTF 파일이 다운로드됩니다.
그럼 glTF 익스포트 옵션과 다운로드되는 파일 명을 변경할 수 있게 처리해 보겠습니다.
5. Controls에서 glTF 익스포트 옵션을 변경하고 다운로드 파일명을 변경할 수 있게 객체(exporter1)에 추가합니다.
const exporter1 = {
ExportglTFFileName : 'test.glb',
ExportglTFFilebinary : true,
ExportglTFFunction : ExportglTF
};
그리고 glTF 익스포트 옵션의 binary를 exporter1의 ExportglTFFilebinary로 설정합니다.
function ExportglTF() {
// GLTF익스포트 생성
const exporter = new GLTFExporter();
// GLTF익스포트 옵션 - 바이너리/JSON 형식으로 추출
const options = {
binary: exporter1.ExportglTFFilebinary
};
exporter.parse(
box2,
function (gltf) {
if (gltf instanceof ArrayBuffer) {
console.log("export gltf:", gltf);
downloadBinary(gltf);
} else {
console.log("export gltf:", gltf);
downloadJSON(gltf);
}
},
function (error) {
console.error("exporter error:", error);
},
options
);
}
그리고 다운로드 함수에서 다운로드 파일명을 exporter1의 ExportglTFFileName으로 설정합니다.
// 다운로드
function download(blob) {
const blobURL = URL.createObjectURL(blob);
console.log(blobURL);
// 다운로드를 하기위해 Blob URL로 A 태그 생성
const link = document.createElement('a');
link.href = blobURL;
// 다운로드 파일 명
link.download = exporter1.ExportglTFFileName;
// A 태그 추가
document.body.appendChild(link);
// A 태그를 클릭하여 다운로드
link.click();
// 다운로드 후 Blob URL 해제
URL.revokeObjectURL(blobURL);
// A 태그 삭제
document.body.removeChild(link);
}
그리고 Controls에 추가합니다.
folder2.add(exporter1, 'ExportglTFFileName');
folder2.add(exporter1, 'ExportglTFFilebinary');
folder2.add(exporter1, 'ExportglTFFunction').name('Export');
그리고 Controls에 ExportglTFFileName과 ExportglTFFilebinary가 추가됩니다.
6. ExportglTFFilebinary가 체크되면 ExportglTFFileName의 확장자를 ".glb"로 변경시키고 ExportglTFFilebinary가 체크되지 않으면 ExportglTFFileName의 확장자를 ".gltf"로 변경되게 함수를 만듭니다.
// 파일 저장 형식에 따른 파일 확장자 변경
function updatesglTFFileName() {
let fileName = exporter1.ExportglTFFileName;
const pos = fileName.lastIndexOf('.');
if (pos > 0) {
if (exporter1.ExportglTFFilebinary) {
exporter1.ExportglTFFileName = fileName.substring(0, pos) + ".glb";
} else {
exporter1.ExportglTFFileName = fileName.substring(0, pos) + ".gltf";
}
}
}
확장자를 변경하는 함수를 ExportglTFFilebinary에서 onChange()로 처리되게 추가하고 Controls에 있는 ExportglTFFileName이 변경된 확장로 변경되도록 listen() 함수를 추가합니다.
folder2.add(exporter1, 'ExportglTFFileName').listen();
folder2.add(exporter1, 'ExportglTFFilebinary').onChange(updatesglTFFileName);
folder2.add(exporter1, 'ExportglTFFunction').name('Export');
Controls에서 ExportglTFFilebinary를 선택할 때마다 ExportglTFFileName의 확장자가 변경되는 것을 확인할 수 있습니다.
그리고 Controls에서 "Export" 버튼을 클릭하면 변경된 확장자로 다운로드되는 것을 확인할 수 있습니다.
'Three.js > 기초튼튼' 카테고리의 다른 글
three.js 3D 모델 추출하기(glTF JSON or Binary) - GLTFExporter (0) | 2023.10.10 |
---|---|
three.js 3D 모델 불러오기(glTF 파일 로드) - GLTFLoader (0) | 2023.09.10 |
three.js GUI Controls - lil-gui, addFolder, geometry.dispose (0) | 2023.08.27 |
three.js GUI Controls - lil-gui, gui.add (0) | 2023.08.20 |
three.js 텍스처 매핑, 알파 맵과 알파 테스트로 이미지 자르기와 그림자 처리 - alphaMap, alphaTest (0) | 2023.08.14 |