1/** 2 * Created by kjh on 2020-07-03. 3 */ 4var VR = function( container, textureImg, createComplete ){ 5 6 this.mode = VR.MODE_USER_CONTROL; 7 8 this.container = container; 9 this.textureImg = textureImg; 10 this.createComplete = createComplete; 11 this.onBtnHandler = null; 12 this.onReady = null; 13 this.isBtnClicked = false; 14 15 this.latitude = -0; // - ë¡ ê°ìë¡ ìëë¡ ìì§ì. 16 this.longitude = -180; // - ë¡ ê°ìë¡ ì¤ë¥¸ìª½ì¼ë¡ ìì§ì. 17 this.canvasWidth; 18 this.canvasHeight; 19 20 this.scene; 21 this.camera; 22 this.sphere; 23 this.sphereMaterial; 24 this.raycaster; 25 26 this.btnList = []; 27 this.slider; 28 this.controls; 29 this.loader; 30 this.isLandscape; 31 32 this.currentZoomSize = 0.5; 33 this.touchZoomStatus = false; 34 35 36 var deviceInfo = { 37 alpha : 0 38 ,beta : 0 39 ,gamma : 0 40 ,orient : 1 41 } 42 43 44 var PATH = WEVEN_JS_WEB_PATH ? WEVEN_JS_WEB_PATH : "../../"; 45 var _this = this; 46 47 if( VR.scriptLoaded == false ){ 48 bm.scriptLoader( function(){ 49 bm.scriptLoader( function(){ 50 VR.scriptLoaded = true; 51 _this.init(); 52 }, PATH + "libs/three/DeviceOrientationController.js" ); 53 }, PATH + "libs/three/three.js" ); 54 } 55 56 this.render = function (){ 57 __render(); 58 } 59 60 var _this = this; 61 function __render(){ 62 if( _this.mode == VR.MODE_USER_CONTROL ){ 63 _this.latitude = Math.max(-85, Math.min(85, _this.latitude)); 64 65 var x = 50 * Math.sin(THREE.Math.degToRad(90-_this.latitude)) * Math.cos(THREE.Math.degToRad(_this.longitude)); 66 var y = 50 * Math.cos(THREE.Math.degToRad(90-_this.latitude)); 67 var z = 50 * Math.sin(THREE.Math.degToRad(90-_this.latitude)) * Math.sin(THREE.Math.degToRad(_this.longitude)); 68 69 _this.camera.target.x = x; 70 _this.camera.target.y = y; 71 _this.camera.target.z = z; 72 73 _this.camera.lookAt(_this.camera.target); 74 75 }else{ 76 requestAnimationFrame( __render ); 77 _this.controls.update(); 78 } 79 80 _this.renderer.render(_this.scene, _this.camera); 81 } 82} 83VR.MODE_USER_CONTROL = "MODE_USER_CONTROL"; 84VR.MODE_DEVICE_ORIENTATION = "MODE_DEVICE_ORIENTATION"; 85VR.scriptLoaded = false; 86 87VR.prototype = { 88 89 init : function(){ 90 91 $(this.container).css( "position", "relative" ); 92 // $(container).append( '<div id="vrBtnBox" style="position:absolute; right:30px; top:20px; z-index: 99999;">' 93 // +'<div id="vrModeBtn" style=" cursor:pointer; width:110px; text-align: center; padding:7px 0; color:#ccc; border: 1px solid #666; background-color: rgba(0,0,0,0.8);">ì¬ì©ì íì 모ë</div>' 94 // +'<div id="vrZoomCon" style="margin-top: 15px; width:110px; position: relative;" >' 95 // +'<div id="vrZoomText" style="color:#ddd;">+ Zoom Control</div>' 96 // +'<div id="vrZoomBtn" style="position:relative; cursor:pointer; width:40px; margin-left:34px; z-index: 2; height:18px; padding-top: 2px; text-align: center; top: 12px; background-color: #000; border: 1px solid #666; color:#ccc;">50%</div>' 97 // +'<div id="vrZoomBar" style="position:absolute; width:100%; height:2px; background-color: #000;"></div>' 98 // +'</div>' 99 // +'</div>'); 100 101 this.renderer = new THREE.WebGLRenderer(); 102 this.renderer.setSize(this.container.offsetWidth, this.container.offsetHeight); 103 this.canvasWidth = this.container.offsetWidth; 104 this.canvasHeight = this.container.offsetHeight; 105 this.container.appendChild(this.renderer.domElement); 106 107 this.scene = new THREE.Scene(); 108 this.camera = new THREE.PerspectiveCamera(80, this.container.offsetWidth / this.container.offsetHeight, 1, 1000); 109 this.camera.target = new THREE.Vector3(0, 0, 0); 110 111 this.sphere = new THREE.SphereGeometry(100, 100, 50); 112 this.sphere.applyMatrix(new THREE.Matrix4().makeScale(-1, 1, 1)); 113 this.sphereMaterial = new THREE.MeshBasicMaterial(); 114 this.raycaster = new THREE.Raycaster(); 115 this.loader = new THREE.TextureLoader(); 116 117 this.sphereMesh = new THREE.Mesh( this.sphere, this.sphereMaterial); 118 this.scene.add( this.sphereMesh ); 119 120 this.onScreenOrientationChange(); 121 this.initLoadTexture(); 122 this.initSlider(); 123 124 if( this.createComplete ) this.createComplete(); 125 126 127 128 this.registEvent(); 129 this.registMouseEventHandler(); 130 this.registTouchEventHandler(); 131 } 132 133 ,initLoadTexture : function () { 134 var _this = this; 135 Progress.ON(); 136 this.loader.load( this.textureImg, function(tex){ 137 Progress.OFF(); 138 _this.sphereMaterial.map = tex; 139 140 if( bm.isMobile ){ 141 _this.controls = new DeviceOrientationController( _this.camera, _this.renderer.domElement ); 142 events( _this.controls ).addListener( "ZOOM_CHANGE", function(e){
143 _this.setZoom( _this.currentZoomSize + e.data.changeZoomSize, true ); 144 }) 145 _this.changeMode(VR.MODE_DEVICE_ORIENTATION ); 146 }else{ 147 _this.changeMode(VR.MODE_USER_CONTROL); 148 } 149 150 if( _this.onReady ) _this.onReady(); 151 } ); 152 } 153 154 ,initSlider : function () { 155 var _this = this; 156 this.slider = new BMSlider( "fill" ); 157 this.slider.init( $("#vrZoomBtnCon"), "#vrZoomBtn", "#vrZoomBar"); 158 this.slider.onChangeHandler = function(per){ 159 _this.zoomControl( per ); 160 } 161 } 162 163 ,registEvent : function () { 164 var _this = this; 165 166 window.addEventListener('orientationchange', function(e){ 167 _this.onScreenOrientationChange(); 168 }); 169 170 $(this.container).on("mousewheel", function(e){ 171 var delta, per; 172 173 if( e.originalEvent ) e = e.originalEvent; 174 if (e.wheelDelta) delta = e.wheelDelta / 120; /* IE/Chrome/Opera */ 175 else if (e.detail) delta = -e.detail/3; /* Mozilla case */ 176 177 if( delta > 0 ){ 178 _this.setZoom( _this.currentZoomSize + 0.1 ); 179 }else{ 180 _this.setZoom( _this.currentZoomSize - 0.1 ); 181 } 182 }); 183 if( $("#vrModeBtn").length > 0 ){ 184 mouseAdapter( $("#vrModeBtn")[0]).onDown( function(e){ 185 e.preventDefault(); 186 e.stopImmediatePropagation(); 187 if( bm.isMobile == false ) { 188 alert( "PCììë ì§ìíì§ ììµëë¤." ); 189 return; 190 } 191 if( _this.mode == VR.MODE_USER_CONTROL ){ 192 _this.changeMode( VR.MODE_DEVICE_ORIENTATION ); 193 }else{ 194 _this.changeMode( VR.MODE_USER_CONTROL ); 195 } 196 }) 197 } 198 } 199 200 ,registTouchEventHandler : function () { 201 202 var _this = this; 203 var startZoomSize; 204 var startDistance; 205 var currentDistance; 206 var touchZoomPower = 0.004; 207 208 document.addEventListener("touchstart", onTouchStart ); 209 document.addEventListener("touchmove", onTouchMove ); 210 document.addEventListener("touchend", onTouchEnd ); 211 212 function onTouchStart(e){ 213 if( _this.mode != VR.MODE_DEVICE_ORIENTATION && e.touches.length == 2 ){ 214 215 e.preventDefault(); 216 e.stopImmediatePropagation(); 217 _this.touchZoomStatus = true; 218 startDistance = Math.sqrt( Math.pow( (e.touches[1].clientX - e.touches[0].clientX), 2 ) + Math.pow( ( e.touches[1].clientY - e.touches[0].clientY ),2) ); 219 startZoomSize = _this.currentZoomSize; 220 } 221 } 222 223 function onTouchMove(e) { 224 if( _this.mode != VR.MODE_DEVICE_ORIENTATION && e.touches.length == 2 ){ 225 226 e.preventDefault(); 227 e.stopImmediatePropagation(); 228 229 _this.touchZoomStatus = true; 230 currentDistance = Math.sqrt( Math.pow( (e.touches[1].clientX - e.touches[0].clientX), 2 ) + Math.pow( ( e.touches[1].clientY - e.touches[0].clientY ),2) ); 231 _this.setZoom( startZoomSize + ( currentDistance - startDistance ) * touchZoomPower ); 232 } 233 } 234 235 function onTouchEnd(e) { 236 if ( _this.mode != VR.MODE_DEVICE_ORIENTATION && e.touches.length == 2) { 237 e.preventDefault(); 238 e.stopImmediatePropagation(); 239 } 240 241 _this.touchZoomStatus = false; 242 } 243 } 244 245 ,registMouseEventHandler : function () { 246 247 var targetDownBtn = null; 248 var touchSensorSpeed = 0.3; // 0.01 ~ 0.5 ì ë ì¬ì´ ì¶ì²í¨. 249 var sensorSpeed = 0.1; // 0.01 ~ 0.5 ì ë ì¬ì´ ì¶ì²í¨. 250 var savedX; 251 var savedY; 252 var _this = this; 253 254 mouseAdapter(this.container).onDrag(onMove, onUp, onDown); 255 window.addEventListener("mousemove", onMouseMoveHandlerForCurosr ); 256 257 function onDown( e ){ 258 259 if( _this.touchZoomStatus ) return; 260 261 var containerX, containerY; 262 containerX = $(_this.container).offset().left; 263 containerY = $(_this.container).offset().top; 264 265 var vector = new THREE.Vector3( 266 ( (e.clientX - containerX)/ _this.canvasWidth ) * 2 - 1, 267 - ( (e.clientY - containerY) / _this.canvasHeight ) * 2 + 1, 0.5 ); 268 vector.unproject( _this.camera ); 269 _this.raycaster.set( _this.camera.position, vector.sub( _this.camera.position ).normalize() ); 270 271 // ì¤ë¸ì ê° ë§ì°ì¤ ì´ë²¤í¸ì íê²ì¼ë¡ ì¡´ì¬íëì§ íì¸. 272 for( var i = 0; i<_this.btnList.length; i++){ 273 var intersects = _this.raycaster.intersectObject( _this.btnList[i] ); 274 if ( intersects.length > 0 ) { 275 targetDownBtn = _this.btnList[i]; 276 _this.isBtnClicked = true; 277 } 278 } 279 280 // íê²ì¼ë¡ ì¡´ì¬íì§ ììëë§ ë²í¼ í´ë¦ìí를 falseë¡ ë³ê²½íê³ , 281 if( !targetDownBtn ){ 282 _this.isBtnClicked = false; 283 } 284 285 if( _this.mode != VR.MODE_USER_CONTROL ) return; 286 287 e.preventDefault(); 288 289 savedX = e.clientX; 290 savedY = e.clientY; 291 292 } 293 294 function onMove( e ){ 295 if( _this.touchZoomStatus ) return; 296 if( _this.mode != VR.MODE_USER_CONTROL ) return; 297 298 _this.isBtnClicked = false; 299 300 if( bm.isMobile ){ 301 _this.longitude = (savedX - e.clientX) * touchSensorSpeed + _this.longitude; 302 _this.latitude = (e.clientY - savedY) * touchSensorSpeed + _this.latitude; 303 }else{ 304 _this.longitude = (savedX - e.clientX) * sensorSpeed + _this.longitude; 305 _this.latitude = (e.clientY - savedY) * sensorSpeed + _this.latitude; 306 } 307 308 _this.render(1);
309 310 savedX = e.clientX; 311 savedY = e.clientY; 312 } 313 314 315 function onUp( e ){ 316 317 if( _this.touchZoomStatus ) return; 318 319 if( targetDownBtn ){ 320 var containerX, containerY; 321 containerX = $(_this.container).offset().left; 322 containerY = $(_this.container).offset().top; 323 324 var vector = new THREE.Vector3( 325 ( (e.clientX - containerX)/ _this.canvasWidth ) * 2 - 1, 326 - ( (e.clientY - containerY) / _this.canvasHeight ) * 2 + 1, 0.5 ); 327 vector.unproject( _this.camera ); 328 _this.raycaster.set( _this.camera.position, vector.sub( _this.camera.position ).normalize() ); 329 330 331 for( var i = 0; i<_this.btnList.length; i++){ 332 var intersects = _this.raycaster.intersectObject( _this.btnList[i] ); 333 334 if ( intersects.length > 0 && targetDownBtn == _this.btnList[i] ) { 335 e.stopImmediatePropagation(); 336 if( _this.onBtnHandler ) _this.onBtnHandler( _this.btnList[i] ); 337 _this.isBtnClicked = false; 338 return; 339 } 340 } 341 342 targetDownBtn = null; 343 } 344 345 _this.isBtnClicked = false; 346 if( _this.mode != VR.MODE_USER_CONTROL ) return; 347 requestAnimationFrame( _this.render ); 348 } 349 350 function onMouseMoveHandlerForCurosr(e){ 351 352 var mouse = new THREE.Vector2(); 353 mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1; 354 mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1; 355 356 _this.raycaster.setFromCamera( mouse, _this.camera ); 357 358 for( var i = 0; i<_this.btnList.length; i++){ 359 var intersects = _this.raycaster.intersectObject( _this.btnList[i] ); 360 if ( intersects.length > 0 ) { 361 $("body").addClass("pointer" ); 362 break; 363 }else{ 364 $("body").removeClass("pointer" ); 365 } 366 } 367 } 368 369 } 370 371 ,changeImage : function( src ){ 372 373 var _this = this; 374 Progress.ON(); 375 loader.load( src, function(tex) { 376 Progress.OFF(); 377 _this.sphereMaterial.map = tex; 378 _this.render(); 379 }); 380 } 381 382 383 ,onScreenOrientationChange : function(e){ 384 this.isLandscape = document.documentElement.clientHeight < document.documentElement.clientWidth; 385 } 386 387 388 ,changeSize : function( width, height, realWidth, realHeight ){ 389 390 var canvas = $(this.container).find("canvas"); 391 canvas.attr("width", width+"px").attr("height", height+"px").css({width:width, height:height}); 392 393 this.canvasWidth = width; 394 this.canvasHeight = height; 395 396 realWidth = realWidth || width; 397 realHeight = realHeight || height; 398 399 this.renderer.setViewport(0, 0, realWidth, realHeight); 400 this.camera.aspect = realWidth / realHeight; 401 this.camera.updateProjectionMatrix(); 402 403 this.render(); 404 405 this.zoomControl(this.currentZoomSize); 406 } 407 408 /** 409 * ìë <=> ìë(ëë°ì´ì¤ 기ì¸ê¸°ë¡) íì 모ë ë³í 410 * @param changeMode 411 */ 412 ,changeMode : function( changeMode ){ 413 414 if( this.mode == changeMode ){ 415 this.render(); 416 return; 417 } 418 419 this.mode = changeMode; 420 if( this.mode == VR.MODE_USER_CONTROL ){ 421 $(this.container).find("#vrModeBtn").text( "ìë íì 모ë" ); 422 if( this.controls ){ 423 this.controls.disconnect(); 424 } 425 }else{ 426 $(this.container).find("#vrModeBtn").text( "ëë°ì´ì¤ íì 모ë" ); 427 this.controls.connect(); 428 } 429 430 this.render(); 431 } 432 433 ,setZoom : function( per, onlyChangeValue ){ 434 per = this.zoomControl( per, onlyChangeValue ); 435 this.slider.setValue( per ); 436 } 437 438 439 ,zoomControl : function( per, onlyChangeValue ){ 440 441 if( per > 1 ) per = 1;
442 else if( per < 0 ) per = 0; 443 444 this.currentZoomSize = per; 445 $("#vrZoomSize").text( Math.floor( per * 100 ) + "%" ); 446 447 if( $(window).width() > $(window).height() ){ 448 this.camera.fov = 55 - 20*per; 449 }else{ 450 this.camera.fov = 100 - 60*per; 451 } 452 453 this.camera.updateProjectionMatrix(); 454 455 if( !onlyChangeValue ) this.render(); 456 457 return per; 458 } 459 460 /** 461 data = { 462 imgUrl : "" 463 ,x : 0 464 ,y : 0 465 ,z : -40 466 ,rotationX : 0 467 ,rotationY : 0 468 ,width : 10 469 ,height : 10 470 ,opacity : 1 471 } 472 * @param data 473 */ 474 ,insertImg : function( data ){ 475 476 data.opacity = data.opacity === undefined ? 1 : data.opacity; 477 var textureLoader = new THREE.TextureLoader(); 478 var img = new THREE.MeshBasicMaterial({ //CHANGED to MeshBasicMaterial 479 map : textureLoader.load( data.imgUrl ) 480 ,opacity: data.opacity 481 ,transparent: data.opacity === 1 ? false : true 482 }); 483 img.map.needsUpdate = true; //ADDED 484 data.width = data.width || 3; 485 data.height = data.height || 3; 486 data.depth = data.depth || 1; 487 488 var plane = new THREE.Mesh(new THREE.PlaneGeometry(data.width, data.height, data.depth, 1, 0, 0),img); 489 plane.position.x = data.x; 490 plane.position.y = data.y; 491 plane.position.z = data.z; 492 493 plane.rotation.x = data.rotationX * Math.PI / 180; 494 plane.rotation.y = data.rotationY * Math.PI / 180; 495 496 this.scene.add(plane); 497 498 this.btnList.push( plane ); 499 return plane; 500 } 501 502 503 // ,quaternionTween : function(deg, vector, camera, time, callback){ 504 // let newQuaternion = new THREE.Quaternion(); 505 // var slerpTarget = new THREE.Quaternion().setFromAxisAngle( vector, that.getRadians(deg) ); 506 // 507 // THREE.Quaternion.slerp( sceneCamera.quaternion, slerpTarget, newQuaternion, time ); 508 // sceneCamera.applyQuaternion(newQuaternion); 509 // } 510 511 512 ,getLatLongByXYZ : function (pointX, pointY, pointZ) { 513 var pointOnSphere = new THREE.Vector3(); 514 pointOnSphere.x = pointX; 515 pointOnSphere.y = pointY; 516 pointOnSphere.z = pointZ; 517 518 var EarthRadius = 20; 519 var lat = 90 - (Math.acos(pointOnSphere.y / EarthRadius) * 180) / Math.PI; 520 var lon = ((90 + (Math.atan2(pointOnSphere.x, pointOnSphere.z) * 180) / Math.PI) % 360) - 180; 521 let latAndLongObj = { latitude: lat, longitude: lon }; 522 return latAndLongObj; 523 } 524 525 /** 526 * converts a XYZ THREE.Vector3 to longitude latitude. beware, the vector3 will be normalized! 527 * @param vector3 528 * @returns an array containing the longitude [0] & the lattitude [1] of the Vector3 529 */ 530 ,vector3toLonLat :function ( vector3 ) 531 { 532 vector3.normalize(); 533 var lng = - Math.atan2( -vector3.z, -vector3.x ) - Math.PI; 534 if( lng < - Math.PI )lng += Math.PI * 2; 535 if( lng > Math.PI )lng -= Math.PI * 2; 536 537 var p = new THREE.Vector3( vector3.x, 0, vector3.z ); 538 p.normalize(); 539 540 var lat = Math.acos( p.dot( vector3 ) ); 541 if( vector3.y < 0 ) lat *= -1; 542 543 return [ lng,lat ]; 544 545 } 546 547 /** 548 * locateCamera: orients a camera to look at another object & preserve the camera's UP axis 549 * @param target object to lookAt 550 * @param camera object (camera) to position 551 * @param camera_angle extra angle on the latitude 552 * @param camera_distance distance between the target and the camera 553 */ 554 ,locateCamera : function ( target, camera, camera_angle, camera_distance ) 555 { 556 557 var UP = new THREE.Vector3( 0,1,0 ); 558 var NORMAL = target.clone().normalize(); 559 560 var angle = Math.acos( UP.dot( NORMAL ) ); 561 angle += camera_angle || 0; 562 563 if( angle > Math.PI ) UP.y *= -1; 564 if( angle < 0 ) angle += Math.PI; 565 566 var AX = UP.crossVectors( UP, NORMAL ); 567 568 var tmp = new THREE.Vector3( 0,1,0 ); 569 tmp.applyAxisAngle( AX, angle ); 570 tmp.multiplyScalar( camera_distance ).add( target ); 571 572 camera.position.copy( tmp ); 573 camera.lookAt( target ); 574 } 575 576 577 ,getCoordinatesFromLatLng : function(latitude, longitude, radiusEarth) 578 { 579 let latitude_rad = latitude * Math.PI / 180; 580 let longitude_rad = longitude * Math.PI / 180; 581 582 let xPos= radiusEarth * Math.cos(latitude_rad) * Math.cos(longitude_rad);
583 let zPos = radiusEarth * Math.cos(latitude_rad) * Math.sin(longitude_rad); 584 let yPos = radiusEarth * Math.sin(latitude_rad); 585 586 return {x: xPos, y: yPos, z: zPos}; 587 } 588 589 , latLongToVector3: function(lat, lon, radius, heigth) { 590 var phi = (lat)*Math.PI/180; 591 var theta = (lon-180)*Math.PI/180; 592 593 var x = -(radius+heigth) * Math.cos(phi) * Math.cos(theta); 594 var y = (radius+heigth) * Math.sin(phi); 595 var z = (radius+heigth) * Math.cos(phi) * Math.sin(theta); 596 597 return new THREE.Vector3(x,y,z); 598 } 599 600} 601 602 603
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.