알쓸전컴(알아두면 쓸모있는 전자 컴퓨터)

WEB 에서 obj+mtl->gltf 컨버터 개발하기 (vue,threejs 사용) 본문

Web

WEB 에서 obj+mtl->gltf 컨버터 개발하기 (vue,threejs 사용)

백곳 2019. 1. 1. 19:21

WEB 에서 obj+mtl->gltf 컨버터 개발하기


먼저 WEB 브라우져에서는 보안 정책상 클라이언트의 로컬 파일을 직접 읽어 드릴수가 없습니다.

사용자가 웹으로 어떠한 방식이든 파일을 올려 줘야 사용 가능 합니다.

먼저 클라이언트 측에서 obj 파일과 mtl 파일 받을수 있게 콤포넌트 1개를 만들겠습니다.


<template>
<div class="home" ref="home">
<div class="UploadMain" @dragover="HandleDragOver" @drop="HandleFileSelect">
uploadfile
</div>

</div>
</template>

<script>

export default {

data(){

return {

objfile : null,

mtlfile : null,

InputFilesCount : 0
}

},

methods:{

HandleDragOver(evt){
evt.stopPropagation()
evt.preventDefault()
evt.dataTransfer.dropEffect = 'copy'
},
HandleFileSelect(evt){
evt.stopPropagation()
evt.preventDefault()
this.HandleFileLoading(evt)
},
async HandleFileLoading (evt) {
var UploadARFiles = evt.dataTransfer.files
this.InputFilesCount = UploadARFiles.length
for (var i = 0; i < this.InputFilesCount; i++) {
var LoadedFiles = await this.FileReadImage(UploadARFiles[i])
var extension = this.getExtensionOfFilename(LoadedFiles.filename)
if (extension === '.obj') {
this.objfile = LoadedFiles
} else if (extension === '.mtl') {
this.mtlfile = LoadedFiles
}
}
},
FileReadImage (FileUrl) {
return new Promise(function (resolve, reject) {
var Reader = new FileReader()
Reader.onload = function (e) {
Reader.filename = FileUrl.name
resolve(Reader)
}
Reader.readAsDataURL(FileUrl)
})
},
}
}
</script>

<style scoped>

.UploadMain{
height: 200px;
width: 200px;
border: solid 1px
}

</style>


전 위와 같이 코드를 작성 해서 일단 파일을 클라이트언트로 부터 받을 준비를 끝냈습니다.


그리고 나서 threejs 을 사용 하기 위해서


var THREE = window.THREE = require('three');
require('three/examples/js/loaders/MTLLoader');
require('three/examples/js/loaders/LoaderSupport');
require('three/examples/js/loaders/OBJLoader2');
require('three/examples/js/exporters/GLTFExporter');


var base64_arraybuffer = require('base64-arraybuffer')


이 라이브러리도 필요합니다. 추후에 base64 디코딩 할때 쓰입니다,

다음 코드를 입력 하고


data(){
return {
OBJLoader : new THREE.OBJLoader2(),
MTLLoader : new THREE.MTLLoader(),
renderer : null,
scene : null,
camera: null,
}
},


에 Loader 을 집어 넣었습니다.

IronMan.zip

IronMan.zip

IronMan.zip

그리고 이제 본격적으로 컨버팅 하기 위한 코드를 작성 하겠습니다.

밑에가 제가 사용하는 풀코드 입니다. 일부러 설명을 위해서 주석을 넣었습니다.


<template>
<div class="home" ref="home">
<div class="UploadMain" @dragover="HandleDragOver" @drop="HandleFileSelect">
uploadfile
</div>

</div>
</template>

<script>
// @ is an alias to /src
var THREE = window.THREE = require('three');
require('three/examples/js/loaders/MTLLoader');
require('three/examples/js/loaders/LoaderSupport');
require('three/examples/js/loaders/OBJLoader2');
require('three/examples/js/exporters/GLTFExporter');
var base64_arraybuffer = require('base64-arraybuffer')
export default {
name: 'home',
data(){
return {
OBJLoader : new THREE.OBJLoader2(),
MTLLoader : new THREE.MTLLoader(),
renderer : null,
scene : null,
camera: null,
}
},
methods:{
animate(){
requestAnimationFrame( this.animate );
// this.cube.rotation.x += 0.01;
// this.cube.rotation.y += 0.01;
// this.line.rotation.x += 0.01;
// this.line.rotation.y += 0.01;
this.renderer.render(this.scene,this.camera)
},
HandleDragOver(evt){
evt.stopPropagation()
evt.preventDefault()
evt.dataTransfer.dropEffect = 'copy'
},
HandleFileSelect(evt){
evt.stopPropagation()
evt.preventDefault()
this.HandleFileLoading(evt)
},
async HandleFileLoading (evt) {
var UploadARFiles = evt.dataTransfer.files
this.InputFilesCount = UploadARFiles.length
for (var i = 0; i < this.InputFilesCount; i++) {
var LoadedFiles = await this.FileReadImage(UploadARFiles[i])
var extension = this.getExtensionOfFilename(LoadedFiles.filename)
if (extension === '.obj') {
this.objfile = LoadedFiles
} else if (extension === '.mtl') {
this.mtlfile = LoadedFiles
} else if (extension === '.gltf') {
this.gltffile = LoadedFiles
}
}
//base64 코드 앞 구분자 , 앞에는 파일 타입에 대한 정보로 디코딩 할때 쓰레기 정보.
var objfilereuslt = this.objfile.result.split(",")[1]
var mtlfilereuslt = this.mtlfile.result.split(",")[1]
//OBJLoader2의 parseAsync 을 사용 하기 위해서는 text가 아닌 arraybuffer가 필요 하기 때문에 base64_arraybuffer을 사용
var decodeobjfile = base64_arraybuffer.decode(objfilereuslt)
var decodemtlfile = atob(mtlfilereuslt)
//질감 정보를 parse
var materialCreator = this.MTLLoader.parse(decodemtlfile)
//OBJLoader2에 질감을 입히기 위해서 아래 작업 필요
var materials = [];
var materialCreatorMaterials = [];
materialCreator.preload()
materialCreatorMaterials = materialCreator.materials;
        for ( var materialName in materialCreatorMaterials ) {
          if ( materialCreatorMaterials.hasOwnProperty( materialName ) ) {
            materials[ materialName ] = materialCreatorMaterials[ materialName ];
          }
}
//OBJLoader에 질감 정보 설정
this.OBJLoader.setMaterials(materials)
// 본격적으로 obj 파일 리딩
this.OBJLoader.parseAsync(decodeobjfile,async (result)=>{
// 리딩 완료후 오는 콜백 메소드
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera( 75, 500/500, 0.1, 1000 );
this.camera.position.z = 300;
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
this.scene.add( ambientLight )
var pointLight = new THREE.PointLight( 0xffffff, 0.8 );
this.camera.add( pointLight );
this.scene.add( this.camera );
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(500,500);
this.$refs.home.appendChild(this.renderer.domElement)
//gltf 파일 변환
var gltfresult = await this.GltfChange(result.detail.loaderRootNode)
this.scene.add( result.detail.loaderRootNode)
this.animate()
//파일 강제로 다운로드
this.downloadTextFile(JSON.stringify(gltfresult), 'myObj.gltf')
})
},

downloadTextFile(text, name) {
const a = document.createElement('a');
const type = name.split(".").pop();
a.href = URL.createObjectURL( new Blob([text], { type:`text/${type === "txt" ? "plain" : type}` }) );
a.download = name;
a.click();
},
GltfChange(objsrc){
//실제로 obj->gltf 로 변환
return new Promise(function(resolve,reject){
var exporter = new THREE.GLTFExporter();
exporter.parse(objsrc,(gltf)=>{
resolve(gltf)
})
})
},
FileReadImage (FileUrl) {
return new Promise(function (resolve, reject) {
var Reader = new FileReader()
Reader.onload = function (e) {
Reader.filename = FileUrl.name
resolve(Reader)
}
Reader.readAsDataURL(FileUrl)
})
},
getExtensionOfFilename (filename) {
var _fileLen = filename.length
var _lastDot = filename.lastIndexOf('.')
var _fileExt = filename.substring(_lastDot, _fileLen).toLowerCase()
return _fileExt
},
}
}
</script>
<style scoped>
.UploadMain{
height: 200px;
width: 200px;
border: solid 1px
}
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>



실행 결과 리포트 입니다.




그리고 나서 다운 받아진

gltf 을 열면

위와 같이 정상적을 컨버팅 된것을 알수 있습니다.



Comments