Created
June 30, 2020 11:54
-
-
Save Keshigom/2d32b05bd810a001ad768774c0b3d78d to your computer and use it in GitHub Desktop.
AR.jsのNFTでVRMモデルを表示する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | |
<!-- three.js library --> | |
<script src='lib/three.min.js'></script> | |
<!-- three.js load GLTF --> | |
<script src='lib/GLTFLoader.js'></script> | |
<!-- ar.js --> | |
<script src='lib/ar-nft.js'></script> | |
<!-- three-vrm --> | |
<script src="lib/three-vrm.min.js"></script> | |
<script>THREEx.ArToolkitContext.baseURL = '../'</script> | |
<body style='position: absolute; top: 0; left: 0; width: 100%; height: 100%; margin : 0px; overflow: hidden;'> | |
<style> | |
.arjs-loader { | |
margin: 0 auto; | |
width: 100%; | |
height: 100%; | |
position: absolute; | |
top: 0; | |
left: 0; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
.arjs-loader-spinner { | |
z-index: 10; | |
-webkit-transform: spin 1s linear infinite; | |
animation: spin 1s linear infinite; | |
border: 3px solid #ddd; | |
border-top: 3px solid #42a5f5; | |
border-radius: 50%; | |
height: 75px; | |
width: 75px; | |
} | |
@-webkit-keyframes spin { | |
to { | |
border-top-color: #42a5f5; | |
-webkit-transform: rotate(360deg); | |
transform: rotate(360deg); | |
} | |
} | |
@keyframes spin { | |
to { | |
border-top-color: #42a5f5; | |
-webkit-transform: rotate(360deg); | |
transform: rotate(360deg); | |
} | |
} | |
</style> | |
<div class="arjs-loader"> | |
<div class="arjs-loader-spinner"></div> | |
</div> | |
<script> | |
var renderer = new THREE.WebGLRenderer({ | |
antialias: true, | |
alpha: true, | |
logarithmicDepthBuffer: true, | |
}); | |
var clock = new THREE.Clock(); | |
var mixers = []; | |
renderer.setPixelRatio(window.devicePixelRatio); | |
renderer.setClearColor(new THREE.Color('lightgrey'), 0) | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
renderer.domElement.style.position = 'absolute' | |
renderer.domElement.style.top = '0px' | |
renderer.domElement.style.left = '0px' | |
document.body.appendChild(renderer.domElement); | |
var scene = new THREE.Scene(); | |
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1000, 10000); | |
scene.add(camera); | |
const light = new THREE.DirectionalLight(0xffffff); | |
light.position.set(1.0, 1.0, 1.0).normalize(); | |
scene.add(light); | |
var arToolkitSource = new THREEx.ArToolkitSource({ | |
sourceType: 'webcam', | |
sourceWidth: 480, | |
sourceHeight: 640, | |
}) | |
arToolkitSource.init(function onReady() { | |
// use a resize to fullscreen mobile devices | |
setTimeout(function () { | |
onResize() | |
}, 1000); | |
}) | |
// handle resize | |
window.addEventListener('resize', function () { | |
onResize() | |
}) | |
// listener for end loading of NFT marker | |
window.addEventListener('arjs-nft-loaded', function (ev) { | |
console.log(ev); | |
}) | |
function onResize() { | |
arToolkitSource.onResizeElement() | |
arToolkitSource.copyElementSizeTo(renderer.domElement) | |
if (arToolkitContext.arController !== null) { | |
arToolkitSource.copyElementSizeTo(arToolkitContext.arController.canvas) | |
} | |
} | |
// create atToolkitContext | |
var arToolkitContext = new THREEx.ArToolkitContext({ | |
detectionMode: 'mono', | |
canvasWidth: 480, | |
canvasHeight: 640, | |
}, { | |
sourceWidth: 480, | |
sourceHeight: 640, | |
}) | |
// initialize it | |
arToolkitContext.init(function onCompleted() { | |
// copy projection matrix to camera | |
camera.projectionMatrix.copy(arToolkitContext.getProjectionMatrix()); | |
}) | |
var root = new THREE.Group(); | |
scene.add(root); | |
// init controls for camera | |
var markerControls = new THREEx.ArMarkerControls(arToolkitContext, camera, { | |
type: 'nft', | |
descriptorsUrl: 'data/dataNFT/marker', | |
changeMatrixMode: 'cameraTransformMatrix' | |
}) | |
scene.visible = true | |
const loader = new THREE.GLTFLoader(); | |
loader.load( | |
// URL of the VRM you want to load | |
'data/model.vrm', | |
// called when the resource is loaded | |
(gltf) => { | |
// generate a VRM instance from gltf | |
THREE.VRM.from(gltf).then((vrm) => { | |
const scale = 200; | |
// add the loaded vrm to the scene | |
vrm.scene.scale.set(scale, scale, scale); | |
// root.matrixAutoUpdate = false; | |
root.add(vrm.scene); | |
vrm.scene.rotation.y = Math.PI; | |
vrm.scene.position.x = 80; | |
vrm.scene.position.z = -80; | |
loadJson("./data/data/pose.json", (json) => { | |
vrm.humanoid.setPose(json); | |
}); | |
// deal with vrm features | |
console.log(vrm); | |
}); | |
}, | |
// called while loading is progressing | |
(progress) => console.log('Loading model...', 100.0 * (progress.loaded / progress.total), '%'), | |
// called when loading has errors | |
(error) => console.error(error) | |
); | |
const animate = () => { | |
requestAnimationFrame(animate); | |
if (!arToolkitSource.ready) { | |
return; | |
} | |
arToolkitContext.update(arToolkitSource.domElement) | |
// update scene.visible if the marker is seen | |
scene.visible = camera.visible; | |
renderer.render(scene, camera); | |
}; | |
requestAnimationFrame(animate); | |
const loadJson = (path, callback) => { | |
const xhr = new XMLHttpRequest(); | |
xhr.onreadystatechange = () => { | |
if (xhr.readyState == 4 && xhr.status == 200) { | |
callback(xhr.response); | |
} | |
}; | |
xhr.responseType = 'json'; | |
xhr.open('GET', path, true); | |
xhr.send(); | |
}; | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment