;(function($){
//vrbk
jQuery.fn.vrmvViewer=function(optUser){
//options
const optDef={
src : "",
rotationY : 0
};
const opt=$.extend(optDef,optUser);
//canvas
const myCanvas=$(this);
var cv=new Canvas();
function Canvas(){
this._id =myCanvas.attr("id");
this._box =myCanvas.closest(".canvas_box");
this._loader =myCanvas.closest(".canvas_box").find(".canvas_loader");
this._start =myCanvas.closest(".canvas_box").find(".canvas_start");
this._w =this._box.width();
this._h =this._box.height();
}
myCanvas.attr({
'width' : cv._w,
'height' : cv._h
});
//three.js
var renderer;
var scene;
var camera;
var controls;
//group
var grpWorld;
var grpBase;
//video
var video;
var flag_video=false;
var flag_loader=false;
var video_totaltime="--:--:--";
//ジャイロセンサー確認
var isGyro=false;
if((window.DeviceOrientationEvent)&&('ontouchstart' in window)){
isGyro=true;
}
//PCなど非ジャイロ
if(!isGyro){
setCanvas();
//一応ジャイロ持ちデバイス
}else{
//ジャイロ動作確認
var resGyro=false;
window.addEventListener("deviceorientation",doGyro,false);
function doGyro(){
resGyro=true;
window.removeEventListener("deviceorientation",doGyro,false);
}
//数秒後に判定
setTimeout(function(){
//ジャイロが動いた
if(resGyro){
setCanvas();
//ジャイロ持ってるくせに動かなかった
}else{
//iOS13+方式ならクリックイベントを要求
if(typeof DeviceOrientationEvent.requestPermission==="function"){
//ユーザアクションを得るための要素を表示
cv._start.show();
cv._start.on("click",function(){
cv._start.hide();
DeviceOrientationEvent.requestPermission().then(res => {
//「動作と方向」が許可された
if(res==="granted"){
setCanvas();
//「動作と方向」が許可されなかった
}else{
isGyro=false;
setCanvas();
}
});
});
//iOS13+じゃない
}else{
//早くアップデートしてもらうのを祈りながら諦める
isGyro=false;
setCanvas();
}
}
},300);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Canvas
///////////////////////////////////////////////////////////////////////////////////////////
function setCanvas(){
if(!Detector.webgl){Detector.addGetWebGLMessage();}
renderer=new THREE.WebGLRenderer({
canvas : document.querySelector('#'+cv._id),
antialias : true,
alpha : true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(cv._w,cv._h);
scene=new THREE.Scene();
grpWorld=new THREE.Group();
grpBase=new THREE.Group();
//スマホなどジャイロセンサーが有効なときはDeviceOrientationControls
if(isGyro){
camera=new THREE.PerspectiveCamera(60,cv._w/cv._h,1,20000);
camera.position.set(0,0,0.01);
camera.lookAt(new THREE.Vector3(0,0,0));
controls=new THREE.DeviceOrientationControls(camera);
controls.connect();
controls.update();
//PCなどジャイロセンサーがない場合はOrbitControlsのみ
}else{
camera=new THREE.PerspectiveCamera(60,cv._w/cv._h,1,20000);
camera.position.set(0,0,0.01);
camera.lookAt(new THREE.Vector3(0,0,0));
controls=new THREE.OrbitControls(camera,renderer.domElement);
controls.autoRotate =false;
controls.enableRotate =true;
controls.rotateSpeed =-0.05;
controls.enableDamping =true;
controls.dampingFactor =0.1;
controls.enableZoom =false;
controls.enablePan =false;
}
///////////////////////////////////////////////////////////////////////
// 3Dオブジェクト配置
///////////////////////////////////////////////////////////////////////
//base
var gmBase=new THREE.SphereBufferGeometry(1000,60,40);
gmBase.scale(-1,1,1);
var mtrBase;
if(opt.src==""){
mtrBase=new THREE.MeshNormalMaterial();
}else{
flag_video=true;
video=document.createElement("video");
if(Hls.isSupported()){
var hls=new Hls();
hls.loadSource(opt.src);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function(){
video.play();
});
}else if(video.canPlayType("application/vnd.apple.mpegurl")){
video.src=opt.src;
video.addEventListener("canplay",function(){
video.play();
});
}else{
flag_video=false;
mtrBase=new THREE.MeshNormalMaterial();
alert("Failed to play video.");
}
if(flag_video){
flag_loader=true;
cv._loader.show();
video.loop=true;
video.muted=true;
video.setAttribute("webkit-playsinline","webkit-playsinline");
video.setAttribute("playsinline","playsinline");
video.setAttribute("muted","muted");
video.play();
texture=new THREE.Texture(video);
texture.minFilter=texture.magFilter=THREE.LinearFilter;
texture.format=THREE.RGBFormat;
texture.mapping=THREE.UVMapping;
mtrBase=new THREE.MeshBasicMaterial({
map : texture
});
var tm_totaltime=setInterval(function(){
if(video.readyState>0){
$("#btn_start").show();
$("#btn_stop").show();
video_totaltime=sec2timestr(video.duration);
clearInterval(tm_totaltime);
}
},300);
}
}
var base=new THREE.Mesh(gmBase,mtrBase);
base.rotation.y=(opt.rotationY*Math.PI/180);
grpBase.add(base);
grpWorld.add(grpBase);
scene.add(grpWorld);
//runAnimate
runAnimate();
function runAnimate(){
controls.update();
if(flag_video){
if(video.readyState>=video.HAVE_CURRENT_DATA){
texture.needsUpdate=true;
}
//再生中
if(!video.paused){
if(flag_loader){
if(video.currentTime>0){
flag_loader=false;
cv._loader.hide();
$("#btn_start").text("PAUSE");
}
}
set_playtime();
}
}
renderer.render(scene,camera);
requestAnimationFrame(runAnimate);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Window Resize
///////////////////////////////////////////////////////////////////////////////////////////
var timerResize=false;
$(window).on("resize",function(){
if(timerResize!==false){
clearTimeout(timerResize);
}
timerResize=setTimeout(function(){
resizeCanvas();
},500);
});
function resizeCanvas(){
cv._w=cv._box.width();
cv._h=cv._box.height();
myCanvas.attr({
'width' : cv._w,
'height' : cv._h
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(cv._w,cv._h);
camera.aspect=cv._w/cv._h;
camera.updateProjectionMatrix();
}
///////////////////////////////////////////////////////////////////////////////////////////
// 操作イベント
///////////////////////////////////////////////////////////////////////////////////////////
$("#btn_start").on("click",function(){
if(flag_video){
if(video.paused){
video.play();
$(this).text("PAUSE");
}else{
video.pause();
$(this).text("PLAY");
}
set_playtime();
}
});
$("#btn_stop").on("click",function(){
if(flag_video){
video.pause();
video.currentTime=0;
$("#btn_start").text("PLAY");
set_playtime();
}
});
function set_playtime(){
if(flag_video){
var playtime=sec2timestr(video.currentTime);
$("#time_ctrl").text(playtime+"/"+video_totaltime);
}
}
};
function sec2timestr(sec){
var time=Math.floor(sec);
var s=time;
var m=Math.floor((time/(1000*60))%60);
var h=Math.floor((time/(1000*60*60))%24);
if(s<10){
s="0"+s;
}
if(m<10){
m="0"+m;
}
if(h<10){
h="0"+h;
}
return h+":"+m+":"+s;
}
})(jQuery);