/*
*Copyright © 2017 mxreality.js authors
*/
var VR=function (scene,renderer,container,cameraPara,cameraPosition) {
AVR.initDomStyle(container);
AVR.setCameraPara(this,cameraPara,cameraPosition);
this.vrbox={"radius":2, "widthSegments":180, "heightSegments":180,"width":2,"height":2,"depth":2};
this.scene=scene;
this.renderer=renderer;
this.container=container;
this.video=null;
this.audio=null;
this.videoToolBar=null;
this.autoplayPanoImg=false;
this.clock = new THREE.Clock();
this.VRObject=new THREE.Object3D();
this.defaultAutoHideLeftTime=3;
this.defaultVoiceHideLeftTime=2;
this.defaultVolume=0.3;
this.sliceSegment=0;
this._controlTarget={x:0.0001,y:0,z:0};
this.resType={"video":"video","box":"box","slice":"slice"};
this.asteroidConfig={enable:false,assteroidFPS:36,assteroidFov:135,asteroidForwardTime:2000,asteroidWaitTime:1000,asteroidDepressionRate:0.5,asteroidTop:1,cubeResolution:2048};
this.VRhint="请取消屏幕翻转锁定后装入VR盒子中";
this.camera=new THREE.PerspectiveCamera(this.cameraPara.fov,this.cameraPara.aspect , this.cameraPara.near, this.cameraPara.far);
//this.camera=new THREE.OrthographicCamera(window.innerWidth / -16, window.innerWidth / 16, window.innerHeight / 16, window.innerHeight / -16, -200, 500);
this.camera.position.set(this.cameraPosition.x, this.cameraPosition.y, this.cameraPosition.z);
this.loadProgressManager=new THREE.LoadingManager(function (xhr){
console.log("loaded");
},function(item, loaded, total){
console.log("item=",item,"loaded",loaded,"total=",total);
},function (xhr,cl) {
console.log(xhr,cl);
});
this.scene.add(this.camera);
this.scene.add(this.VRObject);
//this.renderer.setPixelRatio( window.devicePixelRatio );
this.effect = AVR.stereoEffect(this.renderer);
}
VR.prototype.init=function () {
var that=this;
function render() {
var width = that.container.offsetWidth;
var height = that.container.offsetHeight;
that.camera.aspect = width / height;
if((AVR.isMobileDevice() && AVR.isCrossScreen())) {
that.effect.setSize(width, height);
that.effect.render(that.scene, that.camera);
}else{
that.renderer.setSize(width, height);
that.renderer.setClearColor(new THREE.Color(0xffffff));
that.renderer.render(that.scene, that.camera);
}
that.camera.updateProjectionMatrix();
if(that.controls){
that.controls.update(that.clock.getDelta());
}
}
function animate() {
requestAnimationFrame(animate);
render();
}
animate();
//if you don't use an asteroid view,you need to initialize the controller after the asteroid view.
if(!that.asteroidConfig.enable){
AVR.bindOrientationEnevt(that,that._controlTarget);
}
window.addEventListener('resize', function () {
AVR.bindOrientationEnevt(that,that._controlTarget);
}, false);
};
VR.prototype.playPanorama=function (recUrl,resType,objName) {
objName=objName||"__panoContainer";
var that = this;
that._containerRadius=(that.resType.box == resType|| that.resType.slice==resType) ? (that.vrbox.width / 2.1) : that.vrbox.radius;
that.autoHideLeftTime = that.defaultAutoHideLeftTime;
that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
that.videoToolBar = AVR.videoToolBar(that.container);
that.container.addEventListener("click", function () {
that.autoHideLeftTime = that.defaultAutoHideLeftTime;
that.videoToolBar.toolbar.style.display = "block";
});
that.videoToolBar.gyroBtn.addEventListener("click", function () {
if (!this.getAttribute("active")) {
that.controls.gyroFreeze();
btnActive(this);
btnActive(that.videoToolBar.circle1);
btnActive(that.videoToolBar.circle2);
this.setAttribute("active", "active");
} else {
that.controls.gyroUnfreeze();
this.removeAttribute("active");
btnInactive(this);
btnInactive(that.videoToolBar.circle1);
btnInactive(that.videoToolBar.circle2);
}
}, false);
that.videoToolBar.vrBtn.addEventListener("click", function (e) {
if (AVR.isMobileDevice()) {
if (AVR.OS.isWeixin() && !AVR.OS.isiOS()) {
if (that.video.getAttribute('x5-video-orientation') == "landscape") {
that.video.setAttribute('x5-video-orientation', 'portraint');
btnInactive(this);
} else {
that.video.setAttribute('x5-video-orientation', 'landscape');
btnActive(this);
}
} else {
if (!AVR.isCrossScreen()) {
btnInactive(this);
AVR.msgBox(that.VRhint, 5, that.container);
} else {
btnActive(this);
AVR.fullscreen(that.container);
}
}
} else {
if (!this.getAttribute("fullscreen")) {
btnActive(this);
this.setAttribute("fullscreen", "true");
} else {
btnInactive(this);
this.removeAttribute("fullscreen");
}
AVR.fullscreen(that.container);
}
}, false);
that.renderer.domElement.addEventListener( 'wheel', function(e) {
var delta = e.deltaY > 0 ? 15 : -15;
if (that.camera.fov + delta * 0.05 >= 10 && that.camera.fov + delta * 0.05 <= 120) {
fovChange(delta);
}
}, false );
function fovChange(delta){
that.camera.fov += delta * 0.05;
that.camera.updateProjectionMatrix();
}
window.addEventListener('resize', function () {
if (!AVR.isFullscreen()) {
if (AVR.OS.isWeixin() && !AVR.OS.isiOS()) {
if (that.video.getAttribute('x5-video-orientation') == "landscape") {
btnActive(that.videoToolBar.vrBtn);
} else {
btnInactive(that.videoToolBar.vrBtn);
}
AVR.isCrossScreen(function (ret) {
if (ret) {
btnActive(that.videoToolBar.vrBtn);
} else {
btnInactive(that.videoToolBar.vrBtn);
}
});
} else {
AVR.isCrossScreen(function (ret) {
if (ret) {
btnActive(that.videoToolBar.vrBtn);
} else {
btnInactive(that.videoToolBar.vrBtn);
}
});
btnInactive(that.videoToolBar.vrBtn);
}
} else {
if (AVR.isMobileDevice()) {
AVR.isCrossScreen(function (ret) {
if (ret) {
btnActive(that.videoToolBar.vrBtn);
} else {
btnInactive(that.videoToolBar.vrBtn);
}
});
} else {
btnActive(that.videoToolBar.vrBtn);
}
}
bindVolumeEvent();
}, false);
function btnActive(obj) {
obj.style.borderColor = "green";
obj.style.color = "green";
}
function btnInactive(obj) {
obj.style.borderColor = "white";
obj.style.color = "white";
}
that._play=function() {
that.videoToolBar.btn.style.border = "none";
that.videoToolBar.btn.style.fontWeight = 800;
that.videoToolBar.btn.innerHTML = "||";
}
that._pause=function() {
that.videoToolBar.btn.innerText = "";
that.videoToolBar.btn.style.borderTop = "0.6rem solid transparent";
that.videoToolBar.btn.style.borderLeft = "1rem solid white";
that.videoToolBar.btn.style.borderBottom = "0.6rem solid transparent";
}
if (that.resType.box == resType) {
var textures = [];
var materials = [];
var imageObj = new Image();
imageObj.src = recUrl;
imageObj.onload = function () {
var canvas, context;
var tileWidth = imageObj.height;
for (var i = 0; i < 6; i++) {
textures[i] = new THREE.Texture();
canvas = document.createElement('canvas');
context = canvas.getContext('2d');
canvas.height = tileWidth;
canvas.width = tileWidth;
context.drawImage(imageObj, tileWidth * i, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth);
textures[i].image = canvas;
textures[i].needsUpdate = true;
materials.push(new THREE.MeshBasicMaterial({map: textures[i]}));
}
var Box = new THREE.Mesh(new THREE.CubeGeometry(that.vrbox.width, that.vrbox.height, that.vrbox.depth), new THREE.MultiMaterial(materials));
Box.applyMatrix(new THREE.Matrix4().makeScale(1, 1, -1));
Box.visible=false;
Box.name = objName;
that.VRObject.add(Box);
that.loadProgressManager.onLoad();
}
imgPanoToolBar();
}else if(that.resType.slice==resType){
var cubeGeometry = new THREE.CubeGeometry(that.vrbox.width, that.vrbox.height, that.vrbox.depth, that.sliceSegment, that.sliceSegment, that.sliceSegment);
//cubeGeometry.scale(-1, 1, 1)
var textureLoader = new THREE.TextureLoader(that.loadProgressManager);
textureLoader.mapping = THREE.UVMapping;
var materials=[];
for(var i=0;i= video.duration) {
clearInterval(buffTimer);
}
that.videoToolBar.loadedProgress.style.width = (allBuffered / video.duration) * 100 + "%";
}, 500);
}
}, false);
that.videoToolBar.progressBar.addEventListener("click", function (e) {
video.currentTime = video.duration * (e.clientX / this.clientWidth);
}, false);
that.videoToolBar.btn.addEventListener("click", function (e) {
video.paused ? (function () {
that._play();
video.play();
})() : (function () {
that._pause();
video.pause();
})();
});
that.video = video;
var eventTester = function(e){
that.video.addEventListener(e,function(){
that.loadProgressManager.onLoad();
},false);
}
eventTester("canplay");
var texture = new THREE.VideoTexture(video);
texture.generateMipmaps = false;
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
//texture.format = THREE.RGBFormat;
texture.format = THREE.RGBAFormat;
that.VRObject.add(buildTexture(texture));
}else {
imgPanoToolBar();
new THREE.TextureLoader(that.loadProgressManager).load(recUrl, function (texture) {
that.VRObject.add(buildTexture(texture));
});
}
function buildTexture(texture) {
material = new THREE.MeshBasicMaterial({overdraw: true, map: texture});
mesh = new THREE.Mesh(geometry, material);
mesh.visible=false;
mesh.name = objName;
//mesh.material.map=;
//that.VRObject.add(mesh);
if(that.asteroidConfig.enable){
that.asteroidForward=function(callback){
asteroidForward(callback);
}
}
return mesh;
//that.renderer.setPixelRatio(window.devicePixelRatio);
}
}
function asteroidForward(callback) {
var config = that.asteroidConfig;
var defaultFov = that.camera.fov;
var s = that._containerRadius;
that.camera.position.y = s * config.asteroidTop;
that.camera.fov = config.assteroidFov;
//that.camera.lookAt(0,0,0);
var v = s / config.asteroidForwardTime * config.assteroidFPS;
var sFov = that.camera.fov - defaultFov;
var vFov = sFov / config.asteroidForwardTime * config.assteroidFPS;
var vRo = Math.PI / 2 / config.asteroidForwardTime * config.assteroidFPS;
//console.log("s=",s,"speed v=",v,"sFov=",sFov,"speed sfov=",vFov,"vRo=",vRo)
that.camera.lookAt(0, 0, AVR.isMobileDevice() ? -0.001 : 0.001);
setTimeout(function () {
var asteroidForwardTimer = setInterval(function () {
//console.log("new y=",config.asteroidTop*that.camera.position.y -v);
if (config.asteroidTop * that.camera.position.y - v <= 0) {
that.camera.position.y = 0;
that.camera.fov = defaultFov;
clearInterval(asteroidForwardTimer);
that._controlTarget={x:0.0001,y:0,z:0};
AVR.bindOrientationEnevt(that,that._controlTarget);
if(void 0 !== callback){
// Wait for the controller to initialize to complete the callback.
var controlTimer=setInterval(function () {
if(that.controls){
clearInterval(controlTimer);
callback();
}
})
}
} else {
that.camera.position.y -= (v * config.asteroidTop);
that.camera.fov -= vFov;
that.camera.rotateOnAxis(new THREE.Vector3(1, 0, 0), vRo * config.asteroidTop);
}
that.camera.updateProjectionMatrix();
}, config.assteroidFPS);
}, config.asteroidWaitTime);
}
function imgPanoToolBar() {
setInterval(function (e) {
if (that.autoHideLeftTime < 0) {
that.videoToolBar.toolbar.style.display = "none";
} else {
that.autoHideLeftTime--;
}
}, 1000);
that.videoToolBar.btn.addEventListener("click", function (e) {
that.controls.autoRotate ? that._pause() : that._play();
that.controls.autoRotate = !that.controls.autoRotate;
});
}
function bindVolumeEvent() {
var Audio=that.video || that.audio
if (Audio) {
that.videoToolBar.voice_bar.style.display = "block";
var voice_bar = that.videoToolBar.voice_bar;
var voice_slide_bar = voice_bar.firstChild;
var voice_cur_slide_bar = voice_slide_bar.firstChild;
var voice_btn = voice_cur_slide_bar.firstChild;
var mouseDown = false, touchStartY = 0, touchCurrentY = 0, tempY;
Audio.volume = that.defaultVolume;
voice_cur_slide_bar.style.height = (Audio.volume * that.container.clientHeight) + "px";
voice_bar.addEventListener("mousedown", function (e) {
voice_bar.style.opacity = 1;
}, false);
voice_slide_bar.addEventListener("click", function (e) {
e.preventDefault();
that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
voice_cur_slide_bar.style.height = this.clientHeight - e.clientY + "px";
Audio.volume = (this.clientHeight - e.clientY) / this.clientHeight;
}, false);
voice_btn.addEventListener("mousedown", function (e) {
mouseDown = true;
}, false);
voice_btn.addEventListener("mouseup", function (e) {
mouseDown = false;
}, false);
voice_bar.addEventListener("mousemove", function (e) {
that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
if (mouseDown) {
voice_cur_slide_bar.style.height = this.clientHeight - e.clientY + "px";
if ((this.clientHeight - e.clientY) / this.clientHeight <= 1)
Audio.volume = (this.clientHeight - e.clientY) / this.clientHeight;
}
}, false);
voice_bar.addEventListener("touchstart", function (e) {
e.preventDefault();
that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
tempY = voice_cur_slide_bar.clientHeight;
touchStartY = e.touches[0].pageY;
voice_bar.style.opacity = 1;
}, false);
voice_bar.addEventListener("touchmove", function (e) {
e.preventDefault();
that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
touchCurrentY = e.touches[0].pageY;
voice_cur_slide_bar.style.height = tempY + (touchStartY - touchCurrentY) + "px";
if (voice_cur_slide_bar.clientHeight / this.clientHeight <= 1)
Audio.volume = voice_cur_slide_bar.clientHeight / this.clientHeight;
}, false);
voice_bar.addEventListener("touchend", function (e) {
tempY = 0;
}, false);
setInterval(function () {
if (that.voiceHideLeftTime <= 0) {
voice_bar.style.opacity = 0;
} else {
that.voiceHideLeftTime--;
}
}, 1000);
}
}
bindVolumeEvent();
};
VR.prototype.sphere2BoxPano=function(img,w,h,callback) {
var that = this;
var fases = { 'x': 'x','nx': 'nx', 'ny': 'ny','y': 'y', 'z': 'z', 'nz': 'nz'};
var canvasArr=[],finishNum=0;
var i=0;
var image = new Image();
image.crossOrigin="anonymous";
image.src = img;
image.onload = function() {
for (var id in fases) {
var canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
canvas.id = "face_" + id;
canvasArr[i] = canvas;
var gl = canvas.getContext('webgl', {preserveDrawingBuffer: true});//获取canvas上下文
var shaderPorgram = initShaders(gl, id);//初始化着色器程序
var num = initVertexBuffers(gl, shaderPorgram);
var PI = gl.getUniformLocation(shaderPorgram, 'PI');
gl.uniform1f(PI, Math.PI);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Set texture
if (!initTextures(gl, shaderPorgram, num,image)) {
console.log('Failed to intialize the texture.');
//return;
}
i++;
}
}
//初始化纹理
function initTextures(gl,shaderPorgram,n,image){
var texture = gl.createTexture();//创建纹理对象
if(!texture){
console.log('Failed to create the texture object!');
return false;
}
var u_Sampler = gl.getUniformLocation(shaderPorgram,'u_Sampler');
loadTextures(gl,n,texture,u_Sampler,image);
return true;
}
//加载纹理图片
function loadTextures(gl,n,texture,u_Sampler,image){
if(that.asteroidConfig.enable) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, -1);//对纹理图像进行y轴反转
}
gl.activeTexture(gl.TEXTURE0);//激活纹理单元
gl.bindTexture(gl.TEXTURE_2D, texture);//绑定纹理对象
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//配置纹理对象的参数
/**
* RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.
* 大致意思是纹理没有渲染成功,因为所使用的图片的分辨率不是2的幂数,2的幂数是指2*2、4*4、8*8、16*16...256*256...;
* 需要设置图形纹理参数时设置水平垂直拉伸。
*/
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);//将纹理图像分配给纹理对象
gl.uniform1i(u_Sampler, 0);//将0号纹理传给着色器中的取样器变量
//gl.clear(gl.COLOR_BUFFER_BIT); // Clear