Bladeren bron

修改了导览相关。过渡方式、缩放

xzw 4 jaren geleden
bovenliggende
commit
d775c8eb92
12 gewijzigde bestanden met toevoegingen van 1998 en 56869 verwijderingen
  1. 32 18
      css/lzb.css
  2. 56 30
      edit.html
  3. BIN
      images/rd图标.7z
  4. 720 610
      index.html
  5. 0 1
      js/ZHYHmain_2018.js
  6. 147 30
      js/edit.js
  7. 21 0
      js/lib/video.min.js
  8. 0 55920
      js/main_2018.js.bak
  9. 376 81
      js/main_2020_edit.js
  10. 458 153
      js/main_2020_show.js
  11. 68 26
      js/overlay.js
  12. 120 0
      js/stats.min.js

+ 32 - 18
css/lzb.css

@@ -895,28 +895,12 @@ ul.MenuOptions li.chosen {
 
 .toolBottom .midBottom {
     width: 100%;
-    height: 93px;
+    height: 98px;
     position: relative;
 }
 
 .confirmSnap {
-    background: #00b4ed;
-    color: #fff;
-    border-radius: 21px;
-    /* margin: 0 auto; */
-    position: absolute;
-    letter-spacing: 0.05em;
-    height: 42px;
-    text-align: center;
-    line-height: 42px;
-    font-size: 14px;
-    pointer-events: all;
-    cursor: pointer;
-    transition: background 0.2s;
-    top: 8px;
-    width: 220px;
-    left: 50%;
-    transform: translateX(-50%);
+     
 }
 
 #webgl .overlayGui.snapshotGui {
@@ -1165,6 +1149,36 @@ ul.MenuOptions li.chosen {
 }
 
 
+
+#midBtns{
+    position: absolute;
+    transform: translateX(-50%);
+    width: 220px;
+    left: 50%;
+    flex-direction: column;
+}
+#midBtns>*{
+    /* color: #fff; */
+    border-radius: 21px;
+    /* margin: 0 auto; */
+    margin: 0px 0 0 0 !important;
+    letter-spacing: 0.05em;
+    height: 38px;
+    text-align: center;
+    line-height: 42px;
+    font-size: 14px;
+    pointer-events: all;
+    cursor:pointer;
+    transition:background 0.2s;
+    width: 220px;
+}
+
+#midBtns button:nth-child(2) {
+    margin: 10px 0 0 0 !important;
+}
+
+
+
 .toolRight  .itemTitle .buttons, .toolRight .remark .buttons{
    position:absolute; right:0;
     

+ 56 - 30
edit.html

@@ -323,37 +323,37 @@
                                                 <div id="gui-modes-map" class="ui-icon double active">
                                                     <div data-original-title="导览" id="pullTab" rel="tooltip" title="">
                                                         <img class="icon icon-inside" src="images/auto.png"
-                                                            title="navigation icon" />
+                                                             />
                                                     </div>
                                                     <div data-original-title="热点列表" id="hotList" rel="tooltip" title=""
                                                         style="display: none">
                                                         <img class="icon icon-inside" src="images/hotlist.png"
-                                                            title="navigation icon" />
+                                                             />
                                                     </div>
                                                     <div data-original-title="全景漫游" id="gui-modes-inside" rel="tooltip"
                                                         title="" class="">
                                                         <img class="icon icon-inside" src="images/inside.png"
-                                                            title="navigation icon" />
+                                                             />
                                                     </div>
                                                     <div data-original-title="迷你模型" id="gui-modes-dollhouse"
                                                         rel="tooltip" title="" class="">
                                                         <img class="icon icon-inside" src="images/dollhouse.png"
-                                                            title="navigation icon" />
+                                                             />
                                                     </div>
                                                     <div data-original-title="俯视图" id="gui-modes-floorplan"
                                                         rel="tooltip" title="">
                                                         <img class="icon icon-inside" src="images/floor.png"
-                                                            title="navigation icon" />
+                                                             />
                                                     </div>
                                                     <div data-original-title="VR" id="vr" rel="tooltip" title=""
                                                         style="display: none;">
                                                         <img class="icon icon-inside" src="images/VR.png"
-                                                            title="navigation icon" />
+                                                             />
                                                     </div>
                                                     <div data-original-title="消除外壳" id="gui-remove-face" rel="tooltip"
                                                         title="" style="display: none; float: left;">
                                                         <img class="icon icon-inside" src="images/face.jpg"
-                                                            title="navigation icon" />
+                                                             />
                                                     </div>
                                                 </div>
                                             </div>
@@ -855,7 +855,7 @@
                                                     <img class="keyboard">
                                                 </div> -->
                                             <div class="nav-icon">
-                                                <img src="images/pc_step1.png" class="icon" title="navigation icon"
+                                                <img src="images/pc_step1.png" class="icon" 
                                                     data-page="1">
                                                 <div class="nav-help-button">
                                                     <div class="next-button nav-help-page" data-id="plus"></div>
@@ -892,9 +892,14 @@
                     </div>
                 </div>
                 <div class="midBottom hasPad">
-                    <!-- 中间下部 -->
-                    <div class="confirmSnap innerBtn hide" id="camera-start">点此设置为初始画面</div>
-                    <!--  <div class="innerBtn hide cancel" data-lang="">隐藏该点</div>  -->
+                    <!-- 中间下部 --> 
+                    
+                    <div id="midBtns" class="buttons">
+						<button class="confirmSnap hide innerBtn" id="camera-start">保存当前设置</button> 
+						<button class="innerBtn hide cancel" function="hide">隐藏该点位置</button> 				 
+                    
+                    </div>
+                    
                 </div>
             </div>
             <div class="toolRight">
@@ -1415,12 +1420,16 @@
                                     <li>
                                         <div class="itemTitle">
                                             <span>选择导览过渡效果</span>
-                                        </div>
-                                        <ul id="folderTourSwitch" class="switch clearfix hotStyle-item colorWrap">
-                                            <label><input class="mui-switch mui-switch-animbg" type="checkbox">
-                                                启用瞬间过渡
-                                            </label>
+                                        </div> 
+                                        
+                                        <ul id="folderTourSwitch"  class="MenuOptions innerBtn" >
+                                            <li class="halfCell" index="default" data-lang="">同外层</li>
+                                            <li class="halfCell" index="walk" data-lang="">行走</li>
+                                            <li class="halfCell chosen" index="black" data-lang="">瞬间</li>
                                         </ul>
+                                        
+                                        
+                                        
                                     </li>
                                     <li class="snapATourView">
                                         <div class="buttons begin">
@@ -1479,6 +1488,16 @@
                                             </div>
                                         </div>
                                     </li>
+                                    <li>
+                                        <div class="itemTitle">
+                                            <span>飞向该片段的过渡效果</span>
+                                        </div> 
+                                        <ul id="tourSwitch_Slice"  class="MenuOptions innerBtn" >
+                                            <li class="halfCell" index="default" data-lang="">同外层</li>
+                                            <li class="halfCell" index="walk" data-lang="">行走</li>
+                                            <li class="halfCell chosen" index="black" data-lang="">瞬间</li>
+                                        </ul>  
+                                    </li>
                                     <li id="tourRenew" class="info"> 
                                         <div class="name itemMargin">
                                             <div class="buttons begin">
@@ -1607,22 +1626,29 @@
     </div>
 
     <script>
+        window.isEdit = true
+    
+        if(window.location.href.includes('&localTest')){
+            //本地:
+            // var token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOm51bGwsIm1hbmFnZXIiOm51bGwsImlkIjoxLCJ1c2VyTmFtZSI6ImFkbWluIiwiZXhwIjoxNjE2NTc1MjU5LCJpYXQiOjE2MTY0ODg4NTksImp0aSI6ImJjZGNhZmQxLTU2NGItNGVhMC1hYTE5LWY1ZWRjZThjZTM3ZiJ9.ODMw__rU7GfuGNZNKo14ll7HnOYEG-yNM3Rqh-XYqw4"
+            var ceshi = 'http://47.112.166.173:8105/';
+            var token = ''
+        }else{
+             //大场景: 
+           var ceshi = '';
+           var token = window.localStorage.dcj_token 
+           if (!token) {
+              window.location.href = '../list/index.html'
+           } 
+        
+        }
+ 
+        
+ 
 
-        //本地:
-        // var token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOm51bGwsIm1hbmFnZXIiOm51bGwsImlkIjoxLCJ1c2VyTmFtZSI6ImFkbWluIiwiZXhwIjoxNjE2NTc1MjU5LCJpYXQiOjE2MTY0ODg4NTksImp0aSI6ImJjZGNhZmQxLTU2NGItNGVhMC1hYTE5LWY1ZWRjZThjZTM3ZiJ9.ODMw__rU7GfuGNZNKo14ll7HnOYEG-yNM3Rqh-XYqw4"
-        var ceshi = 'http://47.112.166.173:8105/';
-        var token = ''
+      
+      
        
-
-
-       /*
-       //大场景: 
-       var ceshi = '';
-       var token = window.localStorage.dcj_token 
-       if (!token) {
-          window.location.href = '../list/index.html'
-       } 
-       */
         /*
         //军史馆:
         var ceshi = "http://192.168.0.44:8101/"

BIN
images/rd图标.7z


File diff suppressed because it is too large
+ 720 - 610
index.html


File diff suppressed because it is too large
+ 0 - 1
js/ZHYHmain_2018.js


+ 147 - 30
js/edit.js

@@ -75,6 +75,14 @@ EditTools.prototype.init = function() {
     $("body").on("click", function() {
         $(".DelConfirm").removeClass("active");
     })
+    
+    
+    
+    $(" .MenuOptions li").on("click", (e)=>{ 
+        var $elem = $(e.target);
+        $elem.closest('.MenuOptions').find('li').removeClass("chosen");
+        $elem.addClass("chosen"); 
+    })
 
 }
 //点击的时候激活状态
@@ -361,9 +369,13 @@ SceneInformation.prototype.init = function(data, data2) {
     if (data.showHotListSta) {
         hotListSwitch.prop('checked', true);
     }
-    if (data.hotIconScale && parseFloat(data.hotIconScale) <= 1.5 && parseFloat(data.hotIconScale) >= 0.3) {
+    
+    if (data.hotIconScale) {
         hotIconScale.val(parseFloat(data.hotIconScale));
     }
+    hotIconScale.on('change',(e)=>{
+        e.target.value = THREE.Math.clamp(parseFloat(e.target.value), 0.3, 1.5)
+    })
     if (data.supportsVR) {
         VRSwitch.prop('checked', true);
     }
@@ -961,8 +973,7 @@ $("#hotpointDetail .style .MenuOptions li").on("click", (e)=>{
     } else {
         $("#userUploadStyle").removeClass("hide")
     }
-    $("#hotpointDetail .style .MenuOptions li").removeClass("chosen");
-    $(e.target).addClass("chosen")
+    
 }
 )
 
@@ -1337,13 +1348,13 @@ Hotpoint.prototype.initSaveHot = function() {
 
     })
     
-    $(".webPage .MenuOptions li").on("click", (e)=>{ //链接打开方式切换 
+   /*  $(".webPage .MenuOptions li").on("click", (e)=>{ //链接打开方式切换 
         _this.editSpot.linkType = $(e.target).attr("index") 
         $(".webPage .MenuOptions li").removeClass("chosen");
         $(e.target).addClass("chosen")
         
     })
-    
+     */
     $("#noAction").on("change", function(e) {
         _this.editSpot.noAction = this.checked;
     })
@@ -1499,7 +1510,7 @@ EditGuide.prototype.init = function(data, data2) {
         that.tourDetail.addClass("atRight");
     }); */
     
- 
+    
 
     
     //导览目录
@@ -1643,6 +1654,11 @@ EditGuide.prototype.init = function(data, data2) {
         
     }) */
      
+     
+     
+    
+     
+     
 }
 
 
@@ -1785,7 +1801,12 @@ EditGuide.prototype.editFolder = function(folderDom){
     
     $("#tourFolderEdit").removeClass('atRight');
     $("#tourFolderEdit .tourName input").val( $(folderDom).find('.title').text()||'');
-    $("#folderTourSwitch input").prop('checked', folderDom.tourData.momentTour === 'black');
+    //$("#folderTourSwitch input").prop('checked', folderDom.tourData.momentTour === 'black');
+    
+    var momentTour = folderDom.tourData.momentTour || "default"
+    $("#folderTourSwitch li").removeClass('chosen')
+    $("#folderTourSwitch li[index="+ momentTour +"]").addClass('chosen');
+    
     
     folderDom.tourItemDoms.forEach(li=>{
         $("#tourItemList>ul").append(li)
@@ -1829,15 +1850,19 @@ EditGuide.prototype.editItem = function(li) {
     $('#tourItemEdit').removeClass('atRight');
     $('#tourItemEdit .tourName input').val( $(li).find('.guide-name').text() );
     
+    var momentTour = li.tourData.momentTour || "default"
+    $("#tourSwitch_Slice li").removeClass('chosen')
+    $("#tourSwitch_Slice li[index="+ momentTour +"]").addClass('chosen');
+    
     var metadata = JSON.parse(li.tourData.metadata);
     if(metadata.scan_id != 'outside'){
         var pano = player.model.panos.index[metadata.scan_id]
         if(pano){ 
-            var q = new THREE.Quaternion().copy(metadata.camera_quaternion);
-            var lookAtPoint = new THREE.Vector3(0,0,-1).applyQuaternion(q).add(pano.position);
+            var q = new THREE.Quaternion().copy(metadata.camera_quaternion); 
             player.flyToPano({
-                pano: pano,
-                lookAtPoint: lookAtPoint
+                pano: pano, 
+                quaternion: q,
+                zoomLevel: metadata.zoom
             })
         }
     }
@@ -1871,7 +1896,12 @@ EditGuide.prototype.completeFolder = function(){//点击完成
     
     var tourName = $('#tourFolderEdit .tourName input').val() //|| this.targetTourPoint.context.innerText;
     $(this.editingFolderLi).find(".title").text(tourName) 
-    this.editingFolderLi.tourData.momentTour = $("#folderTourSwitch input").is(':checked') ? "black" : 'walk' 
+    //this.editingFolderLi.tourData.momentTour = $("#folderTourSwitch input").is(':checked') ? "black" : 'walk' 
+    
+    var momentTour = $("#folderTourSwitch li.chosen").attr("index"); 
+    this.editingFolderLi.tourData.momentTour = momentTour != 'default' ?  momentTour : null;
+    
+    
     this.editingFolderLi.tourItemDoms = Array.from($('#tourItemList ul li'));
      
     var done = ()=>{
@@ -1936,7 +1966,8 @@ EditGuide.prototype.completeItem = function() {//点击完成
     var tourName = $('#tourItemEdit .tourName input').val()  
     $(this.editingItemLi).find('.guide-name').text(tourName)
      
-    
+    var momentTour = $("#tourSwitch_Slice li.chosen").attr("index"); 
+    this.editingItemLi.tourData.momentTour = momentTour != 'default' ?  momentTour : null;
     
     //save导览音乐 
     var tourAudio = $('#tourItemEdit .mediaUpload input');
@@ -2899,9 +2930,7 @@ var initTransformCtl = function(THREE) {
     TransformControls.prototype.transCtlChangeMode = function(mode) {
         //if(!this.editing)return;
         if (mode && this.mode != mode) {
-            this.mode = mode;
-            $(".MenuOptions[name='transform'] li").removeClass("chosen");
-            $(".MenuOptions[name='transform'] li[index='" + mode + "']").addClass("chosen");
+            this.mode = mode; 
         }
     }
     ,
@@ -2919,8 +2948,8 @@ var initTransformCtl = function(THREE) {
 
     $(".MenuOptions[name='transform'] li").on("click", (e)=>{
         transformControls.transCtlChangeMode($(e.target).attr("index"))
-    }
-    )
+    })
+    
 
 }
 
@@ -3461,8 +3490,9 @@ var EditOverlay = {
         $(".overlayList ul").append(li);
         li.on("click", ()=>{
             player.clickOverlay(overlay)
-        }
-        )
+            player.focusPoint({aim: overlay.position})
+            
+        })
         overlay.domLi = li;
     },
     removeFromList: function(overlay) {
@@ -3491,8 +3521,11 @@ var VisiSet = {
 
     //tagVTemp //修改后还没保存的临时数据
 
-    //热点可见性
+   
     $confirmSnap: $("#camera-start"),
+    
+    changeBtn : $(".toolMid .midBottom #midBtns>button").eq(1),
+    
     colors: {
         green: "#00c8ae"
     },
@@ -3502,8 +3535,72 @@ var VisiSet = {
         player.model.add(this.meshGroup)
         $("#hotVisible").on("click", ()=>{
             VisiSet.enterSet(VisiSet.beginSetTagVisible.bind(VisiSet))
-        }
-        )
+            
+        })
+        
+        this.changeBtn.on("click",()=>{//隐藏与显示该点
+            if(this.changeBtn.attr("function") == "hide"){
+                for(let i in this.panoVLines){
+                    this.panoVLines[i].visible && this.dealPanoVisible(i);
+                } 
+            }else{
+                //显示该点时,显示周围一定距离内、到该点没有遮挡的pano
+                //????? 
+                var list = player.model.panos.sortByScore([e=>e.isAligned()], [(pano)=>{return -pano.position.distanceTo(this.panoVsetting.position)}])	
+               
+                 
+				if(list.length == 1){
+					console.log('仅有一个漫游点')
+					return;
+				} 
+                var ifBlock = function(panoA, panoB ){
+                    var A = panoA.position.clone();
+                    var B = panoB.position.clone(); 
+                    return convertTool.ifIntersectChunks(A, B, {})
+                }
+                var okList
+				var s = Math.max(-list[1].score*2,   4);	//i==1的一定显示
+                for(var i=1;i<list.length;i++){ 
+                    if(-list[i].score < s){  
+                        if(ifBlock(this.panoVsetting, list[i].pano)){
+                            list[i].block = true   //有阻挡 
+                        }
+                        list[i].good = true  
+                    }else{
+                        okList || (okList = list.filter(e=>e.good && !e.block));//绝对可以使用的
+                          
+                        if(okList.length <2 ){
+                            if(!ifBlock(this.panoVsetting, list[i].pano)){
+                                if(okList.length == 0){
+                                    okList.push(list[i])
+                                }else{//1 
+                                    var lastPos = okList[0].pano.position.clone().sub(this.panoVsetting.position).setY(0);
+                                    var thisPos = list[i].pano.position.clone().sub(this.panoVsetting.position).setY(0);
+                                    if(lastPos.angleTo(thisPos) > Math.PI / 2){
+                                        console.log('再加一个  角度'+THREE.Math.radToDeg(lastPos.angleTo(thisPos)))
+                                        break;
+                                    } 
+                                    
+                                }
+                            }
+                        }else{
+                            break;
+                        }
+                    }
+                }
+                if(okList.length==0){//如果length为0,至少加一个pano, 虽然是遮挡的
+                    okList.push(list[0].pano)
+                }
+                okList.forEach(e=>this.dealPanoVisible(e.pano.id))
+                
+                console.log(okList)
+                
+            } 
+        }) 
+        
+    
+        
+        
     },
     enterSet: function(fun) {
         var enter = function() {
@@ -3564,7 +3661,8 @@ var VisiSet = {
         this.showFootIcons(pano, true);
         this.createPanoVisiLines(pano);
         //创线
-
+        
+        this.changeBtn.removeClass('hide')
     },
 
     saveLastPanoVi: function() {
@@ -3658,7 +3756,7 @@ var VisiSet = {
         this.panoVsetting = null;
         lastPanoSetting && this.changeFIconState2(lastPanoSetting.footIcon, this.checkHasNeighbor(lastPanoSetting))
         //这句要放在this.panoVsetting = null后。 根据可见性更改透明度
-
+        this.changeBtn.addClass('hide')
     },
 
     //按理说改变了neighbourPano,tag的初始visible也要改。但是这样还要考虑已经改过的tag。。很麻烦
@@ -3686,7 +3784,10 @@ var VisiSet = {
         }        
         
     },
-
+    changeVisiBtnState: function(state){ 
+        this.changeBtn.attr("function", state ? "hide" : "show")
+        this.changeBtn.html(state ? "隐藏该点位置":"显示该点位置") 
+    },
     recoverAllState2: function() {
         //为了热点可视恢复成pano全部可见
         if(!this.footIcons)return;
@@ -3863,9 +3964,11 @@ var VisiSet = {
     setDisplay: function(state) {
         var panos = player.model.panos;
         if (state) {
-             
+            this.$confirmSnap.text('保存当前设置');
+            this.$confirmSnap.removeClass('hide');
         } else {
-            
+            this.$confirmSnap.addClass('hide');
+            this.changeBtn.addClass('hide')
         }
  
         player.path.currentPanoMarker.mesh.visible = !state;
@@ -3932,6 +4035,7 @@ var VisiSet = {
                     this.panoVLines[id].visible = !this.panoVLines[id].visible;
                     link = this.panoVLines[id].visible;
                     this.changeFIconState(panos.index[id].footIcon, this.panoVLines[id].visible ? "linked" : false)
+                 
                 } else {
                     this.createPanoSingleLine(this.panoVsetting, "new", id)
                     link = true;
@@ -3945,6 +4049,18 @@ var VisiSet = {
                     this.changeFIconState2(panos.index[id].footIcon, this.checkHasNeighbor(panos.index[id]))
                     this.changeFIconState2(panos.index[this.panoVsetting.id].footIcon, this.checkHasNeighbor(this.panoVsetting))
                 }
+                
+                
+                /* if(window.routeArray){
+                    if(this.panoVLines[id].visible)window.routeArray.push(id)
+                    else{
+                        let index = window.routeArray.indexOf(id)
+                        index > -1 && routeArray.splice(index, 1)  
+                    }
+                
+                } */
+                
+                
             }
         } else {
             //点击开始设置要设置的pano
@@ -4073,7 +4189,8 @@ var VisiSet = {
             if (this.panoVsetting) {
                 if (this.panoVsetting.id != footIcon.name) {
                     footIcon.material.uniforms.opacity.value = 1;
-                } else {//this.changeVisiBtnState(true)
+                } else {
+                    this.changeVisiBtnState(true)
                 }
             }
         } else {
@@ -4085,7 +4202,7 @@ var VisiSet = {
             } else {
                 //变为中心点时
                 footIcon.material.uniforms.opacity.value = 1;
-                //this.changeVisiBtnState(false)
+                this.changeVisiBtnState(false)
             }
         }
     },

File diff suppressed because it is too large
+ 21 - 0
js/lib/video.min.js


File diff suppressed because it is too large
+ 0 - 55920
js/main_2018.js.bak


+ 376 - 81
js/main_2020_edit.js

@@ -40,6 +40,171 @@ var sortByScore = function(list, request, rank) {
     });
 };
 
+   
+ 
+var convertTool = { 
+	getPos2d : function(point, camera, dom){//获取一个三维坐标对应屏幕中的二维坐标
+		var camera = camera || player.camera;
+		var dom = dom || player.domElement;
+		var pos = point.clone().project(camera)	//比之前hotspot的计算方式写得简单  project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
+		
+		var x,y;
+		x = (pos.x + 1) / 2 * dom.clientWidth;
+		y = (1 - (pos.y + 1) / 2) * dom.clientHeight; 
+  
+		var inSight = x <= dom.clientWidth &&  x >= 0    //是否在屏幕中   
+					&& y <= dom.clientHeight &&  y >= 0 
+	 
+	
+		return {
+			pos: new THREE.Vector2(x,y),  // 屏幕像素坐标
+			vector:  pos,   //(范围 -1 ~ 1)
+			trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点   参见Tag.update
+			inSight : inSight	//在屏幕范围内可见
+		};
+	},
+
+	ifShelter: function(pos3d, pos2d){//检测某点在视线中是否被mesh遮挡
+		if(!pos2d) pos2d = this.getPos2d(pos3d);
+		var player = player;
+		var ori = new THREE.Vector3(pos2d.x, pos2d.y, -1).unproject(player.camera);  //找到视线原点
+		var dir = pos3d.clone().sub(ori).normalize();
+		ray.set(ori, dir)//由外向里 因为模型从内侧是可见的所以从外侧
+		
+		
+		/* if(config.isEdit && publicObjectSet.editor.mainDesign.editing){
+			var o = ray.intersectObjects(publicObjectSet.editor.mainDesign.wallMeshes);
+		}else{ */
+			var o = ray.intersectObjects(player.model.colliders);
+		//} 
+		var len = pos3d.distanceTo(ori);
+		if (o && o.length) {
+			for(var i=0;i<o.length;i++){
+				if(o[i].distance < len){  return true;  }//有遮挡
+			} 
+		} 
+	},
+    
+    
+    /* 
+        拖拽时,获取鼠标在拖拽面上的位置(需要借助另一个intersectPlane面来计算,即和相机方向一样的面,可保证铺满屏幕)
+        但是不一定能获取到,比如鼠标射线不朝向拖拽面时,即使获取也会是一个意外的反方向的交点。
+	 */
+	getPosAtPlane : function(pos, info/* , mouse, camera */){ //pos:与intersectPlane的交点 见笔记
+		var A = pos; 
+        var player = player;      
+        var mouse = player.mouse;
+        var O = new THREE.Vector3(mouse.x, mouse.y, -1).unproject(player.camera);
+		
+		
+		if(info.y != void 0){//地面线的
+        
+            var y = info.y; 
+            
+            if(player.mode == "floorplan"/*  ||  Math.abs(O.x-pos.x)<0.0001 && Math.abs(O.z-pos.z)<0.0001) */){
+            //intersectPlane和地面平行,无交点
+                var x = pos.x, z = pos.z;
+            
+            }else{
+             
+                if(y<player.camera.position.y && O.y <= A.y /* || y>player.camera.position.y && O.y >= A.y  */)return null;  //鼠标射线向上。因为相机一定位于地面以上(地面不会抬高到相机上吧?),所以无交点。
+                if(O.y == A.y){console.log('一样??');return;}
+                if(A.y == y){console.log('一样2??');return;}
+                var r = (O.y-y)/(A.y-y);
+                var x = (r*A.x-O.x)/(r-1);
+                var z = (r*A.z-O.z)/(r-1); 
+			}
+		}else{//垂直的也有越过消失点以后反向变化的情况,但使用时影响不大
+			var N = info.normalVec;
+			var P = info.pullPos;
+			if(N.y != 0 ){console.log('N.y != 0');return;} //仅仅支持垂直于地面的的墙壁,目前都是
+			if(O.z==A.z){console.log('O.z==A.z?');return;}
+			if(N.z!=0 && N.x != 0){//直接用这个通用的也可以,支持斜线的墙
+				//console.log('N.z==0 && N.x == 0?');  
+				var c = ( N.x*(A.x-O.x) + N.y*(A.y-O.y) + N.z*(A.z-O.z));
+				if(c == 0){console.log("分母为0?? return;");return;} 
+				var t = -((N.x*O.x + N.y*O.y + N.z*O.z) - (P.x*N.x + P.y*N.y + P.z*N.z) ) / c
+				var x = t * (A.x - O.x) + O.x;
+				var y = t * (A.y - O.y) + O.y;
+				var z = t * (A.z - O.z) + O.z;
+				/*原理: 已知空间直线L:(x-a)/m=(x-b)/n=(z-c)/p和空间平面π:Ax+By+Cz+D=0;
+				求直线L与平面π的交点的坐标。
+				把直线方程改写成参数形式:设(x-a)/m=(x-b)/n=(z-c)/p=t;
+				则x=mt+a;y=nt+b;z=pt+c;代入平面π的方程得:
+				A(mt+a)+B(nt+b)+C(pt+c)+D=0
+				由此解得t=-(Aa+Bb+Cc+D)/(Am+Bn+Cp)
+				再代入参数方程即得交点的坐标(x,y,z). */
+			}else if(N.x ==0 ){ //z与pullPos相等
+				var z = P.z;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.z == z){console.log('一样3??');return;}
+				var r = (O.z-z)/(A.z-z);
+				var x = (r*A.x-O.x)/(r-1);
+				var y = (r*A.y-O.y)/(r-1);
+			}else if(N.z == 0){//x与pullPos相等
+				var x = P.x;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.x == x){console.log('一样3??');return;}
+				var r = (O.x-x)/(A.x-x);
+				var y = (r*A.y-O.y)/(r-1);
+				var z = (r*A.z-O.z)/(r-1);
+			}
+		}   
+		
+		return new THREE.Vector3(x,y,z);
+	},
+
+
+	
+	getMouseIntersect : function(camera, meshes, mouse){//获取鼠标和meshes交点
+		var raycaster = new THREE.Raycaster; 
+		camera.updateMatrixWorld(); 
+		var origin = new THREE.Vector3(mouse.x,mouse.y,-1).unproject(camera)
+		  , end = new THREE.Vector3(mouse.x,mouse.y,1).unproject(camera); 
+		var dir = end.sub(origin).normalize() 
+		raycaster.set(origin, dir);
+		var n = raycaster.intersectObjects(meshes);
+		if (0 === n.length)
+			return null;
+		return n[0];
+		
+	},
+	ifIntersectChunks : function(A,B,options={}){//获取某个线段/射线和meshes的交点 
+		var dir = B.clone().sub(A).normalize();
+		var len = options.InfinityLen ? Infinity :  A.distanceTo(B) + (options.extLen||0);
+		var ray = new THREE.Raycaster(A.clone(), dir, 0, len);
+          
+		var o = ray.intersectObjects(options.model || player.model.colliders);
+		if (o && o.length)return o;
+		  
+		if(options.throughWidth){ //允许最小宽度,防止穿过极小的缝隙导致撞墙感
+			var normal = math.getNormal({points:[{x:A.x, y:A.z},{x:B.x, y:B.z}]});//线段法线
+			normal.multiplyScalar(options.throughWidth)
+			var normalVec3 = new THREE.Vector3(normal.x, 0, normal.y);
+			
+			var A2 = A.clone().add(normalVec3)
+			ray.set(A2, dir);  
+			var o2 = ray.intersectObjects(options.model || player.model.colliders);
+			ray.set(A.clone().add(normalVec3.negate()), dir);
+			if (o2 && o2.length)return o2;
+			var o3 = ray.intersectObjects(options.model || player.model.colliders);
+			if (o3 && o3.length)return o3; 
+		} 
+		return null;
+	},
+	getPosAtSphere : function(pos3d, toPanoPos){
+		var dir = pos3d.clone().sub(toPanoPos); 
+		dir.normalize();//然后计算在球中
+		dir.multiplyScalar(Constants.skyRadius);   
+		dir.add(toPanoPos); 
+		return dir;
+	} 
+
+}
+
+ 
 
 
 var dom = {
@@ -3331,14 +3496,25 @@ function o(a, s, l) {
         }
         var r, o, a, s = e("three"), l = e("../settings"), c = e("./OutsideControls"), h = e("../enum/ControlActions"), u = e("../enum/MouseButton"), d = e("../util/math"), p = e("../util/browser");
         (n.prototype = Object.create(c.prototype)).zoomToContain = function(e) {
-            var t = Math.max(e.x, e.z)
-              , i = Math.min(e.x, e.z)
-              , n = Math.max(t, i * this.camera.aspect)
-              , r = Math.max(i, t * this.camera.aspect);
-            this.absoluteScale = (p.aspectRatio() < 1 ? r : n) / 2 / l.orthoBase * 1.2,
+              
+            this.absoluteScale = this.getDefaultAbsoluteScale(e);
             this.currentScale = this.absoluteScale
+             
+            
         }
         ,
+        
+        n.prototype.getDefaultAbsoluteScale = function(modelSize) {
+            var t = Math.max(modelSize.x, modelSize.z)
+              , i = Math.min(modelSize.x, modelSize.z)
+              , n = Math.max(t, i * this.camera.aspect)
+              , r = Math.max(i, t * this.camera.aspect);
+            var absoluteScale = (p.aspectRatio() < 1 ? r : n) / 2 / l.orthoBase * 1.2
+            return absoluteScale
+        },
+        
+        
+        
         n.prototype.rotateToView = function(e, t) {
             var i = 0;
             p.aspectRatio() < 1 == e.x < e.z ? 0 < t.z && (i = Math.PI) : i = 0 < t.x ? Math.PI / 2 : -Math.PI / 2,
@@ -4105,8 +4281,14 @@ function o(a, s, l) {
                 this.rotationSpeed.x = this.rotationSpeed.x * (1 - n.rotationFriction) + this.rotationAcc.x * n.rotationAccelerationInside,
                 this.rotationSpeed.y = this.rotationSpeed.y * (1 - n.rotationFriction) + this.rotationAcc.y * n.rotationAccelerationInside,
                 this.lon += this.rotationSpeed.x * e,
-                this.lat += this.rotationSpeed.y * e,
-                this.lat = Math.max(n.insideLookLimitDown, Math.min(n.insideLookLimitUp, this.lat)),
+                this.lat += this.rotationSpeed.y * e
+                
+                var insideLookLimitDown = n.insideLookLimitDown - n.insideFOV/2 + this.camera.fov / 2 
+                var insideLookLimitUp = n.insideLookLimitUp + n.insideFOV/2 - this.camera.fov / 2
+                this.lat = Math.max(insideLookLimitDown, Math.min(insideLookLimitUp, this.lat)); //通过预定义的俯仰角最大最小范围(insideLookLimitUp、insideLookLimitDown)来限制俯仰角。 注:这种数学计算很常见,因此API也很常见(clamp),等价于 this.lat = THREE.Math.clamp( this.lat, settings.insideLookLimitDown, settings.insideLookLimitUp );   
+                //this.lat = Math.max(n.insideLookLimitDown, Math.min(n.insideLookLimitUp, this.lat)),
+                
+                
                 this.phi = s.Math.degToRad(90 - this.lat),
                 this.theta = s.Math.degToRad(this.lon),
                 this.lookVector.x = Math.sin(this.phi) * Math.cos(this.theta),
@@ -4619,10 +4801,10 @@ function o(a, s, l) {
                 //音频
                 var musicInfo = this.model.heroLocations[this.destinationItem[0]].musicInfo
                 if(musicInfo && musicInfo.music){
-                    var o = musicInfo.music.includes(g_Prefix.slice(-10)) ? musicInfo.music :  g_Prefix + musicInfo.music;
+                    var o1 = musicInfo.music.includes(g_Prefix.slice(-10)) ? musicInfo.music :  g_Prefix + musicInfo.music;
                     
                     let audioSrc1 = g_tourAudio.src.split('/').pop();
-                    let audioSrc2 = o.split('/').pop();
+                    let audioSrc2 = o1.split('/').pop();
                
                     if(audioSrc1 == audioSrc2){//应该是继续播放该folder 
                         if(this.destinationItem[1] == 0){//从头开始播放 因为可能暂停后然后再点该缩略图播
@@ -4632,7 +4814,7 @@ function o(a, s, l) {
                         } 
                         
                     }else{//很可能是该folder的起始
-                        g_tourAudio.src = manage.dealURL(o);
+                        g_tourAudio.src = manage.dealURL(o1);
                         g_tourAudio.load()  
                     }
                     
@@ -4642,17 +4824,23 @@ function o(a, s, l) {
                 if (this.onTheBus = !0,
                 this.emit("update.controls"),
                 this.player.updateLastView(),
-                n || !this.atDestinationPano())
+                n || !this.atDestinationPano()){
                     if (this.player.flying || this.player.isWarping())
                         m.warn("Cannot go to new destination while player is flying or warping.");
                     else {
                         var a = this.model.getHeroDescriptorByIndex(this.destinationItem)
                           , s = null
                           , l = null;
-                        if (a.isPano()) {
-                            o = this.getMomentTour(this.destinationItem)   //window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
-                            l = this.player.warpToPanoByHeroIndex.bind(this.player, this.destinationItem, g.Show, f.Slow, o, !0, i, this.actionComplete.bind(this)),
+                        if (a.isPano()) {  
+                            o1 = this.getMomentTour(this.destinationItem)   //window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
+                            l = this.player.warpToPanoByHeroIndex.bind(this.player, this.destinationItem, g.Show, f.Slow, o1, !0, i, this.actionComplete.bind(this)),
                             s = this.arrivedAtDestination.bind(this, !0)
+                             
+                            //add
+                            if(o1=='black' && a.zoom && a.zoom != this.player.zoomLevel){
+                                this.player.smoothZoomFovTo(null, a.zoom,  r.warp.teleportTime) //瞬间过渡的时间
+                            }
+                            
                         } else{
                             l = this.player.warpToNonPanoByHeroIndex.bind(this.player, this.destinationItem, this.actionComplete.bind(this)),
                             s = this.arrivedAtDestination.bind(this, !1);
@@ -4665,8 +4853,15 @@ function o(a, s, l) {
                         .bind(this), s),
                         this.emit("update.controls")
                     }
-                else
+                }else{
+                    //add 原地旋转时, 写到_warpCameraAim里,因那有时间
+                    /* var a = this.model.getHeroDescriptorByIndex(this.destinationItem)
+                    if(a.zoom && a.zoom != this.player.zoomLevel){
+                        this.player.smoothZoomFovTo(null, a.zoom,  r.warp.teleportTime) //瞬间过渡的时间
+                    } */
+                    
                     this.arrivedAtDestination(!0)
+                }
             }
             ,
             t.prototype.tourInterlude = function() {
@@ -4928,7 +5123,7 @@ function o(a, s, l) {
                 } */
                  
                 
-                var momentTour = this.getMomentTour(this.destinationItem);
+                /* var momentTour = this.getMomentTour(this.destinationItem);
                 if ( "black" === momentTour) { // 方奕卓 瞬间过渡, 相机缩放至1 
                     var i = this.player.zoomLevel;
                     this.player.zoomEnabled = !0;
@@ -4937,24 +5132,21 @@ function o(a, s, l) {
                     }
                     .bind(this);
                     o.start(t, 1500, function() {}, 0, h.easeOutQuad, "zoom")
-                }
+                } */
                 this.goToDestination()
             }
             ,
-            t.prototype.getMomentTour = function(destinationItem) {//add
-                /* if(!item) return window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
-                var currentLocation = this.model.heroLocations[item[0]];
-                var currentChildNum = currentLocation.heroLocations ? currentLocation.heroLocations.length : 1
-                if(item[1]>=currentChildNum-1){//子目录中最后一个
-                    return window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
-                }else{
-                    return currentLocation.momentTour || "walk";
-                } */
-                if(!destinationItem || destinationItem[1] == 0) return window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
+            t.prototype.getMomentTour = function(destinationItem) {//add 
+                var wholeMomentTour = window.MP_PREFETCHED_MODELDATA.momentTour || "walk"; //最外层
+                 
+                if(!destinationItem) return wholeMomentTour
                 else{
-                    var currentLocation = this.model.heroLocations[destinationItem[0]];
-                    return currentLocation.momentTour || "walk";
-                }
+                    var currentLocation = this.model.getHeroDescriptorByIndex(destinationItem)//最内层。 如果有使用最内层
+                    if(currentLocation.momentTour)return currentLocation.momentTour;
+                    
+                    var currentLocation_ = this.model.heroLocations[destinationItem[0]];
+                    return  currentLocation_.momentTour || wholeMomentTour; //若中间层或最内层有就使用,否则使用最外层
+                } 
             }
             ,
             I.exports = t
@@ -16762,6 +16954,7 @@ function o(a, s, l) {
                             sid: n.sid 
                         }
                         var item = new p(l);
+                        item.momentTour = n.momentTour
                         container.push(item) 
                         return item
                     }
@@ -18527,11 +18720,12 @@ function o(a, s, l) {
             ,
             r.prototype.addTextSprite = function(e, t) {
                 this.removeTextSprite();
+                var ratio = 16;
                 var i = document.createElement("canvas")
                   , n = i.getContext("2d");
-                i.width = 256,
-                i.height = 256;
-                n.font = "bold 60px Arial",
+                i.width = 1024,
+                i.height = i.width / ratio;
+                n.font = " 30px Arial",
                 n.fillStyle = "white";
                 var r = n.measureText(e).width;
                 n.fillText(e, (i.width - r) / 2, (i.height + 60) / 2);
@@ -18540,10 +18734,14 @@ function o(a, s, l) {
                 var a = new s.SpriteMaterial({
                     map: o,
                     color: t || 16428055
-                });
+                }); 
                 this.text3d = new s.Sprite(a),
                 this.text3d.position.copy(this.skyboxMesh.position),
                 this.floor.add(this.text3d)
+                
+                var scale = 3
+                this.text3d.scale.y = scale/ratio
+                this.text3d.scale.x = scale
             }
             ,
             r.prototype.removeTextSprite = function() {
@@ -19113,7 +19311,7 @@ function o(a, s, l) {
             ,
             t.prototype.getHeroDescriptorByHeroIndex = function(e) {
                 var t = this.model.heroCount();
-                if (null !== this.warpDestHeroLoc && t < 2)
+                if (null !== this.warpDestHeroLoc && t < 1)
                     return H.info("ShowPath.getHeroDescriptorByHeroIndex() -> Only one hero location is available."),
                     this.model.getHeroDescriptorByIndex(0);
                 var i = this.model.getHeroDescriptorByIndex(e);
@@ -19608,6 +19806,9 @@ function o(a, s, l) {
                             var n = this.playerControls.cameras[O.PANORAMA];
                             a.setFromQuaternion(n.quaternion, D.warp.eOrder);
                             var r = i * l / o;
+                            
+                            r = Math.sign(r) * Math.max(r, 0.0001) //add  如果音频长的话,使旋转可见,否则以为停住了
+                            
                             a.y += r,
                             s.set(0, 0, -1),
                             s.applyEuler(a),
@@ -19623,18 +19824,7 @@ function o(a, s, l) {
                 V.start(n, o, c, 0, B.easeInOutQuad, "wait");
                 
                 
-                //zoom动画  方奕卓  相机缩放 
-                var currentGuide = player.model.getHeroDescriptorByIndex(player.director.currentItem)  
-                if(currentGuide.zoom && currentGuide.zoom != this.player.zoomLevel){
-                    this.player.zoomEnabled = true;
-                    var startZoom = this.player.zoomLevel
-                    var zoom = function(e, d) { 
-                        var zoomLevel = currentGuide.zoom.toFixed(2) * e + startZoom * (1-e);
-                        this.player.zoomTo( zoomLevel, true)        
-
-                    }.bind(this)
-                    V.start(zoom, 2000, null, 0, B.easeOutQuad, "zoom")
-                } 
+                 
             }
             ,
             t.prototype.warpToNonPano = function(e) {
@@ -19724,7 +19914,13 @@ function o(a, s, l) {
                     void n.lookAt(u))
                 }
                 .bind(this);
-                return a > D.warp.minRotation ? V.start(d, e, t, 0, B[D.warp.movementEasing]) : (H.info("Aim angle only is " + a.toPrecision(3) + " degrees, skipping explicit re-aim"),
+                
+                return a > D.warp.minRotation ? (V.start(d, e, t, 0, B[D.warp.movementEasing])
+                   , (this.warpDestHeroLoc.zoom != this.player.zoomLevel) && //add 原地转向最终方位时  
+                    this.player.smoothZoomFovTo(null, this.warpDestHeroLoc.zoom , e)
+                ) 
+
+                : (H.info("Aim angle only is " + a.toPrecision(3) + " degrees, skipping explicit re-aim"),
                 void (t && t()))
             }
             ,
@@ -20017,6 +20213,12 @@ function o(a, s, l) {
                             skipWarpingCheck: !1,
                             constantMoveSpeed: !0
                         };
+                        
+                        if(e == this.warpDestPano){//到达终点前,放大到终点的zoom
+                            n.zoomLevel = this.warpDestHeroLoc.zoom 
+                        } 
+                        
+                        
                         n.duration = function(e, t) {
                             var i = Math.min(this.player.position.distanceTo(e.position), D.transition.flytimeMaxDistanceThreshold) * D.transition.flytimeDistanceMultiplier + D.transition.flyTime;
                             s.copy(U.FORWARD),
@@ -21761,38 +21963,51 @@ function o(a, s, l) {
                     }
                     hots[index].mesh.visible = visible; 
                 } 
-            },
+            } 
                 
-            
+             
+
             t.prototype.flyToPano = function(e, t) {
                 
-                //e.duration = 100
-                
-                var i, n = e.pano, r = e.lookAtPoint, o = e.duration, a = e.aimDuration, s = e.maxDistanceOverride, l = e.skipWarpingCheck, c = e.constantMoveSpeed, h = null, u = null;
+                var i, n = e.pano, aim = e.lookAtPoint, aimQua = e.quaternion,//ADD
+                o = e.duration, a = e.aimDuration, s = e.maxDistanceOverride, 
+                l = e.skipWarpingCheck, c = e.constantMoveSpeed, h = null, u = null 
+                if (aim){
+                    var m = (new B.Matrix4).lookAt(n.position, aim, T.UP)
+                    aimQua = (new B.Quaternion).setFromRotationMatrix(m)  
+                }
+                else aimQua = aimQua 
+            
+                var zoomLevel = e.zoomLevel || 1  //add
                  
+                 
+                if(this.flying) return t && t(e)
                 if (window.specialScene && specialScene.special().specifySpot && specialScene.special().specifySpot(n),
                 this.isWarping() && !l && (this.path.activeTransType === R.BLACK || this.path.activeTransType === R.STD))
                     return Y.warn("Player.flyToPano() -> Cannot fly when warping"),
                     t && t(),
                     !1;
-                if (this.updateLastView(),
-                this.mode !== V.PANORAMA)
-                    return r && (i = (new B.Quaternion).setFromUnitVectors(T.FORWARD, r.sub(n.position).normalize())),
-                    void this.flyToNewMode({
+                    
+                this.updateLastView()
+                if (this.mode !== V.PANORAMA) 
+                    return void this.flyToNewMode({
                         mode: V.PANORAMA,
                         pano: n,
                         duration: o,
-                        quaternion: i,
+                        quaternion: aimQua,
                         callback: t
                     });
-                if (!n || (h = x.deepExtend(e),
-                u = function() {
+                    
+                    
+                    
+                    
+                if (!n || (h = x.deepExtend(e), u = function() {
                     j.delayOneFrame(function() {
                         this.flyToPano(h, t)
-                    }
-                    .bind(this))
-                }
-                .bind(this),
+                    }.bind(this))
+                }.bind(this),
+                
+                
                 !this.checkAndWaitForPanoLoad(n, "high", "low", this.basePanoSize, u))) {
                     var d = function(e) {
                         t && t(e)
@@ -21807,40 +22022,42 @@ function o(a, s, l) {
                         var f = s || k.transition.flytimeMaxDistanceThreshold;
                         p = Math.min(this.currentPano.position.distanceTo(n.position), f) * k.transition.flytimeDistanceMultiplier + k.transition.flyTime
                     }
+                    
+                    
                     if (.01 < k.transition.flySpeed && (p = 1e3 * this.currentPano.position.distanceTo(n.position) / k.transition.flySpeed),
-                    1 !== this.zoomLevel)
+                    zoomLevel !== this.zoomLevel)
                         switch (k.zoom.transitionStyle) {
                         case 1:
-                            this.smoothZoomToDefault(p / 2);
+                            this.smoothZoomFovTo(null, zoomLevel, zoomLevel == 1 ? p / 2 : p); //改
                             break;
                         case 2:
                             return h = x.deepExtend(e),
                             u = this.flyToPano.bind(this, h, t),
-                            void this.smoothZoomToDefault(k.zoom.restoreTime * (this.zoomLevel - 1), u)
+                            void this.smoothZoomFovTo(null, zoomLevel, k.zoom.restoreTime * (this.zoomLevel - 1), u)
                         }
-                    if (r) {
+                        
+                        
+                    if (aimQua) {
                         G.cancelById(q.LookTransition),
                         p *= k.transition.aimSlowFactor;
-                        var g = this.cameraControls.activeControl.camera.quaternion.clone()
-                          , m = (new B.Matrix4).lookAt(n.position, r, T.UP)
-                          , v = (new B.Quaternion).setFromRotationMatrix(m)
+                        var g = this.cameraControls.activeControl.camera.quaternion.clone() 
                           , y = g.clone()
                           , A = new B.Vector3;
                         if (n === this.currentPano) {
                             var C = T.FORWARD.clone().applyQuaternion(g)
-                              , I = T.FORWARD.clone().applyQuaternion(v)
+                              , I = T.FORWARD.clone().applyQuaternion(aimQua)
                               , E = C.angleTo(I);
                             return null != a || (a = 1 * Math.sqrt(E) / k.tags.navigate.rotateSpeedFactor * 1e3),
                             void G.start(function(e) {
                                 y.copy(g),
-                                H.quaternion(y, v)(e),
+                                H.quaternion(y, aimQua)(e),
                                 A.copy(T.FORWARD).applyQuaternion(y).add(this.cameraControls.activeControl.camera.position),
                                 this.cameraControls.activeControl.lookAt(A)
                             }
                             .bind(this), a, d, 0, z[k.transition.movementEasing], null, q.LookTransition)
                         }
                     }
-                    if (n === this.currentPano || this.flying)
+                    if (n === this.currentPano  )
                         return void d();
                     this.flying = !0;
                     var _ = this.position.clone()
@@ -21857,9 +22074,9 @@ function o(a, s, l) {
                     
                     
                     
-                    r && G.start(function(e) {
+                    aimQua && G.start(function(e) {
                         y.copy(g),
-                        H.quaternion(y, v)(e),
+                        H.quaternion(y, aimQua)(e),
                         A.copy(T.FORWARD).applyQuaternion(y).add(this.cameraControls.activeControl.camera.position),
                         this.cameraControls.activeControl.lookAt(A)
                     }
@@ -21948,6 +22165,48 @@ function o(a, s, l) {
             
             }
             
+            window._tranOutsideFocus = 4399 
+            t.prototype.focusPoint = function(o={}){//当在外时,聚焦相机到这一点 
+                console.log("focusPoint")
+                if(this.mode == "floorplan"){
+                    var modelSize = o.modelSize || new THREE.Vector3(8,8,8);//可视范围
+                    var control = player.cameraControls.controls.floorplan;
+                    var absoluteScale = control.getDefaultAbsoluteScale(modelSize)
+                    var currentScale = control.absoluteScale;
+                    var currentTarget = control.target.clone()
+                        
+                    G.cancelById(window._tranOutsideFocus, true);
+                    G.start(function(progress){ 
+                        control.absoluteScale = absoluteScale*progress + currentScale*(1-progress);
+                        control.target = o.aim.clone().multiplyScalar(progress).add(currentTarget.clone().multiplyScalar(1-progress))
+                        control.camera.position.copy(control.target.clone().add(control.offset)) //维持角度
+                    }.bind(this) , o.dur || 600, null/* cancelFuc */, 0, z[k.transition.movementEasing], "outsideFocus", window._tranOutsideFocus, null/* cancelFuc */);	 
+                
+                }else if(player.mode == "dollhouse"){
+                    var control = player.cameraControls.controls.dollhouse;
+                    var radius = o.radius || 8;
+                    var currentTarget = control.target.clone()
+                    var dir = control.offset.clone().normalize()
+                    var currentRadius = control.offset.length();
+                    
+                    
+                    G.cancelById(window._tranOutsideFocus, true);
+                    G.start(function(progress){  
+                        control.target = o.aim.clone().multiplyScalar(progress).add(currentTarget.clone().multiplyScalar(1-progress))
+                        let radius_ = radius*progress+currentRadius*(1-progress)
+                        control.camera.position.copy(control.target.clone().add(dir.clone().multiplyScalar(radius_)))  
+                    }.bind(this) , o.dur || 600, null/* cancelFuc */, 0, z[k.transition.movementEasing], "outsideFocus", window._tranOutsideFocus, null/* cancelFuc */);	 
+                 
+                }else if(this.mode == 'panorama'){
+                    this.flyToPano({
+                        lookAtPoint: o.aim.clone() ,
+                        pano: this.currentPano,
+                        aimDuration: o.dur || 600
+                    })
+                }
+            }
+                    
+                    
             
             t.prototype.fastForwardActivePanoFlight = function(e) {
                 e = e || k.transition.fastForwardFactor / 10 * 4 + 1,
@@ -22533,20 +22792,20 @@ function o(a, s, l) {
                 var currentLocation = this.model.heroLocations[this.director.currentItem[0]] 
                 var restChildCount = currentLocation.heroLocations ? (currentLocation.heroLocations.length-this.director.currentItem[1]-1) : 0
                 var current = g_tourAudio ? 1e3 * g_tourAudio.currentTime : 0
-                var waitTime = currentLocation && currentLocation.musicInfo.music ? currentLocation.musicInfo.time - current : 2e3;  
+                var rotTime = currentLocation && currentLocation.musicInfo.music ? currentLocation.musicInfo.time - current : 2e3;  
                 
                 if(restChildCount){//如果当前folder中还有剩下的item,平分一下时间
                     var timeEachItem = 2000;//假设每个item飞的时间
-                    var waitTime = (waitTime-timeEachItem*restChildCount) / (restChildCount+1);
+                    var rotTime = (rotTime-timeEachItem*restChildCount) / (restChildCount+1);
                      
                 } 
-                waitTime = Math.max(0, waitTime)
-                console.log("waitTime "+waitTime +" at item "+this.director.currentItem + ",musicCurrentTime:"+current) 
+                rotTime = Math.max(0, rotTime)
+                console.log("rotTime "+rotTime +" at item "+this.director.currentItem + ",musicCurrentTime:"+current) 
                  
                 this.path.waitNextStep(e, function() {//等待音乐播放一段时间再下一步,此时镜头会缓慢旋转
                     t && t()
                 }
-                .bind(this), waitTime)
+                .bind(this), rotTime)
             }
             ,
             t.prototype.stopInterlude = function() {
@@ -22670,6 +22929,24 @@ function o(a, s, l) {
                 .bind(this);
                 G.start(r, e, o, null, 0, z[k.transition.blendEasing])
             }
+            
+            ,
+            t.prototype.smoothZoomFovTo = function (fov, zoomLevel, dur, callback) {//add
+                
+                var i,
+                    n = this.zoomLevel,
+                    aimLevel = zoomLevel || this.baseFov / fov
+
+                if (n == aimLevel) return
+
+                var fun = function (e) {
+                    e > 1 && (e = 1), (i = n * (1 - e) + e * aimLevel), this.zoomTo(i, !0)
+                }.bind(this)
+
+                G.start(fun, dur, callback, null, 0, z[k.transition.easeInCubic])
+            }
+            
+            
             ,
             t.prototype.updateZoomPano = function() {
                 if (!this.panoRenderer.zoomPanoRenderingDisabled && this.mode === V.PANORAMA) {
@@ -29048,6 +29325,24 @@ function o(a, s, l) {
              
                 return visiblePanos
             } 
+            
+            ,
+            sortByScore : function(list, request, rank) {
+                var i = this.filterAll(list, request);
+                return 0 === i.length ? null : i = i.map(function(e) {
+                    return {
+                        item: e,
+                        score: rank.reduce(function(t, i) {
+                            return t + i(e);
+                        }, 0)
+                    };
+                }).sort(function(e, t) {
+                    return t.score - e.score;
+                });
+            } 
+ 
+            
+            
         },
         Math.sign = function(e) {
             return e < 0 ? -1 : 1

+ 458 - 153
js/main_2020_show.js

@@ -5,7 +5,10 @@
 window.common = null;  
 window.MathLight = null;
 window.math = null
-
+window.easing = null
+window.lerp = null
+window.transitions = null
+window.browser = null
 window.momentTourBlackNewType = 0//true
 
 g_playAudio = null
@@ -30,31 +33,8 @@ g_tourAudio.oncanplaythrough = function() {
 
 
   
-  
-  
-  
-  
-  
-  
-  
-  
-  
-  
-var sortByScore = function(list, request, rank) {
-    var i = common.filterAll(list, request);
-    return 0 === i.length ? null : i = i.map(function(e) {
-        return {
-            item: e,
-            score: rank.reduce(function(t, i) {
-                return t + i(e);
-            }, 0)
-        };
-    }).sort(function(e, t) {
-        return t.score - e.score;
-    });
-};
  
-  
+ 
   
 var dom = {//许钟文add
 	getOffset: function(type, element, parent) { 
@@ -68,6 +48,178 @@ var dom = {//许钟文add
 	}  
 };
 
+
+	
+ 
+ 
+var convertTool = { 
+	getPos2d : function(point, camera, dom){//获取一个三维坐标对应屏幕中的二维坐标
+		var camera = camera || player.camera;
+		var dom = dom || player.domElement;
+		var pos = point.clone().project(camera)	//比之前hotspot的计算方式写得简单  project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
+		
+		var x,y;
+		x = (pos.x + 1) / 2 * dom.clientWidth;
+		y = (1 - (pos.y + 1) / 2) * dom.clientHeight; 
+  
+		var inSight = x <= dom.clientWidth &&  x >= 0    //是否在屏幕中   
+					&& y <= dom.clientHeight &&  y >= 0 
+	 
+	
+		return {
+			pos: new THREE.Vector2(x,y),  // 屏幕像素坐标
+			vector:  pos,   //(范围 -1 ~ 1)
+			trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点   参见Tag.update
+			inSight : inSight	//在屏幕范围内可见
+		};
+	},
+
+	ifShelter: function(pos3d, pos2d){//检测某点在视线中是否被mesh遮挡
+		if(!pos2d) pos2d = this.getPos2d(pos3d);
+		var player = player;
+		var ori = new THREE.Vector3(pos2d.x, pos2d.y, -1).unproject(player.camera);  //找到视线原点
+		var dir = pos3d.clone().sub(ori).normalize();
+		ray.set(ori, dir)//由外向里 因为模型从内侧是可见的所以从外侧
+		
+		
+		/* if(config.isEdit && publicObjectSet.editor.mainDesign.editing){
+			var o = ray.intersectObjects(publicObjectSet.editor.mainDesign.wallMeshes);
+		}else{ */
+			var o = ray.intersectObjects(player.model.colliders);
+		//} 
+		var len = pos3d.distanceTo(ori);
+		if (o && o.length) {
+			for(var i=0;i<o.length;i++){
+				if(o[i].distance < len){  return true;  }//有遮挡
+			} 
+		} 
+	},
+    
+    
+    /* 
+        拖拽时,获取鼠标在拖拽面上的位置(需要借助另一个intersectPlane面来计算,即和相机方向一样的面,可保证铺满屏幕)
+        但是不一定能获取到,比如鼠标射线不朝向拖拽面时,即使获取也会是一个意外的反方向的交点。
+	 */
+	getPosAtPlane : function(pos, info/* , mouse, camera */){ //pos:与intersectPlane的交点 见笔记
+		var A = pos; 
+        var player = player;      
+        var mouse = player.mouse;
+        var O = new THREE.Vector3(mouse.x, mouse.y, -1).unproject(player.camera);
+		
+		
+		if(info.y != void 0){//地面线的
+        
+            var y = info.y; 
+            
+            if(player.mode == "floorplan"/*  ||  Math.abs(O.x-pos.x)<0.0001 && Math.abs(O.z-pos.z)<0.0001) */){
+            //intersectPlane和地面平行,无交点
+                var x = pos.x, z = pos.z;
+            
+            }else{
+             
+                if(y<player.camera.position.y && O.y <= A.y /* || y>player.camera.position.y && O.y >= A.y  */)return null;  //鼠标射线向上。因为相机一定位于地面以上(地面不会抬高到相机上吧?),所以无交点。
+                if(O.y == A.y){console.log('一样??');return;}
+                if(A.y == y){console.log('一样2??');return;}
+                var r = (O.y-y)/(A.y-y);
+                var x = (r*A.x-O.x)/(r-1);
+                var z = (r*A.z-O.z)/(r-1); 
+			}
+		}else{//垂直的也有越过消失点以后反向变化的情况,但使用时影响不大
+			var N = info.normalVec;
+			var P = info.pullPos;
+			if(N.y != 0 ){console.log('N.y != 0');return;} //仅仅支持垂直于地面的的墙壁,目前都是
+			if(O.z==A.z){console.log('O.z==A.z?');return;}
+			if(N.z!=0 && N.x != 0){//直接用这个通用的也可以,支持斜线的墙
+				//console.log('N.z==0 && N.x == 0?');  
+				var c = ( N.x*(A.x-O.x) + N.y*(A.y-O.y) + N.z*(A.z-O.z));
+				if(c == 0){console.log("分母为0?? return;");return;} 
+				var t = -((N.x*O.x + N.y*O.y + N.z*O.z) - (P.x*N.x + P.y*N.y + P.z*N.z) ) / c
+				var x = t * (A.x - O.x) + O.x;
+				var y = t * (A.y - O.y) + O.y;
+				var z = t * (A.z - O.z) + O.z;
+				/*原理: 已知空间直线L:(x-a)/m=(x-b)/n=(z-c)/p和空间平面π:Ax+By+Cz+D=0;
+				求直线L与平面π的交点的坐标。
+				把直线方程改写成参数形式:设(x-a)/m=(x-b)/n=(z-c)/p=t;
+				则x=mt+a;y=nt+b;z=pt+c;代入平面π的方程得:
+				A(mt+a)+B(nt+b)+C(pt+c)+D=0
+				由此解得t=-(Aa+Bb+Cc+D)/(Am+Bn+Cp)
+				再代入参数方程即得交点的坐标(x,y,z). */
+			}else if(N.x ==0 ){ //z与pullPos相等
+				var z = P.z;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.z == z){console.log('一样3??');return;}
+				var r = (O.z-z)/(A.z-z);
+				var x = (r*A.x-O.x)/(r-1);
+				var y = (r*A.y-O.y)/(r-1);
+			}else if(N.z == 0){//x与pullPos相等
+				var x = P.x;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.x == x){console.log('一样3??');return;}
+				var r = (O.x-x)/(A.x-x);
+				var y = (r*A.y-O.y)/(r-1);
+				var z = (r*A.z-O.z)/(r-1);
+			}
+		}   
+		
+		return new THREE.Vector3(x,y,z);
+	},
+
+
+	
+	getMouseIntersect : function(camera, meshes, mouse){//获取鼠标和meshes交点
+		var raycaster = new THREE.Raycaster; 
+		camera.updateMatrixWorld(); 
+		var origin = new THREE.Vector3(mouse.x,mouse.y,-1).unproject(camera)
+		  , end = new THREE.Vector3(mouse.x,mouse.y,1).unproject(camera); 
+		var dir = end.sub(origin).normalize() 
+		raycaster.set(origin, dir);
+		var n = raycaster.intersectObjects(meshes);
+		if (0 === n.length)
+			return null;
+		return n[0];
+		
+	},
+	ifIntersectChunks : function(A,B,options={}){//获取某个线段/射线和meshes的交点 
+		var dir = B.clone().sub(A).normalize();
+		var len = options.InfinityLen ? Infinity :  A.distanceTo(B) + (options.extLen||0);
+		var ray = new THREE.Raycaster(A.clone(), dir, 0, len);
+          
+		var o = ray.intersectObjects(options.model || player.model.colliders);
+		if (o && o.length)return o;
+		  
+		if(options.throughWidth){ //允许最小宽度,防止穿过极小的缝隙导致撞墙感
+			var normal = math.getNormal({points:[{x:A.x, y:A.z},{x:B.x, y:B.z}]});//线段法线
+			normal.multiplyScalar(options.throughWidth)
+			var normalVec3 = new THREE.Vector3(normal.x, 0, normal.y);
+			
+			var A2 = A.clone().add(normalVec3)
+			ray.set(A2, dir);  
+			var o2 = ray.intersectObjects(options.model || player.model.colliders);
+			ray.set(A.clone().add(normalVec3.negate()), dir);
+			if (o2 && o2.length)return o2;
+			var o3 = ray.intersectObjects(options.model || player.model.colliders);
+			if (o3 && o3.length)return o3; 
+		} 
+		return null;
+	},
+	getPosAtSphere : function(pos3d, toPanoPos){
+		var dir = pos3d.clone().sub(toPanoPos); 
+		dir.normalize();//然后计算在球中
+		dir.multiplyScalar(Constants.skyRadius);   
+		dir.add(toPanoPos); 
+		return dir;
+	} 
+}
+
+ 
+
+
+
+
+
+
 !function() {
     "use strict";
     function t(t, i) {
@@ -3442,14 +3594,20 @@ window.Modernizr = function(n, e, t) {
           , h = e("../util/browser");
         n.prototype = Object.create(a.prototype),
         n.prototype.zoomToContain = function(e) {
-            var t = Math.max(e.x, e.z)
-              , i = Math.min(e.x, e.z)
-              , n = Math.max(t, i * this.camera.aspect)
-              , r = Math.max(i, t * this.camera.aspect);
-            this.absoluteScale = (h.aspectRatio() < 1 ? r : n) / 2 / o.orthoBase * 1.2,
+            this.absoluteScale = this.getDefaultAbsoluteScale(e);
             this.currentScale = this.absoluteScale
         }
         ,
+        n.prototype.getDefaultAbsoluteScale = function(modelSize) {
+            var t = Math.max(modelSize.x, modelSize.z)
+              , i = Math.min(modelSize.x, modelSize.z)
+              , n = Math.max(t, i * this.camera.aspect)
+              , r = Math.max(i, t * this.camera.aspect);
+            var absoluteScale = (h.aspectRatio() < 1 ? r : n) / 2 / o.orthoBase * 1.2 
+            return absoluteScale
+        },
+        
+        
         n.prototype.rotateToView = function(e, t) {
             var i = 0
               , n = h.aspectRatio() < 1
@@ -4242,8 +4400,15 @@ window.Modernizr = function(n, e, t) {
                 this.rotationSpeed.x = this.rotationSpeed.x * (1 - a.rotationFriction) + this.rotationAcc.x * a.rotationAccelerationInside,
                 this.rotationSpeed.y = this.rotationSpeed.y * (1 - a.rotationFriction) + this.rotationAcc.y * a.rotationAccelerationInside,
                 this.lon += this.rotationSpeed.x * e,
-                this.lat += this.rotationSpeed.y * e,
-                this.lat = Math.max(a.insideLookLimitDown, Math.min(a.insideLookLimitUp, this.lat)),
+                this.lat += this.rotationSpeed.y * e
+                
+                
+                //this.lat = Math.max(a.insideLookLimitDown, Math.min(a.insideLookLimitUp, this.lat)),
+                var insideLookLimitDown = a.insideLookLimitDown - a.insideFOV/2 + this.camera.fov / 2 
+                var insideLookLimitUp = a.insideLookLimitUp + a.insideFOV/2 - this.camera.fov / 2
+                this.lat = Math.max(insideLookLimitDown, Math.min(insideLookLimitUp, this.lat)); //通过预定义的俯仰角最大最小范围(insideLookLimitUp、insideLookLimitDown)来限制俯仰角。 注:这种数学计算很常见,因此API也很常见(clamp),等价于 this.lat = THREE.Math.clamp( this.lat, settings.insideLookLimitDown, settings.insideLookLimitUp );   
+        
+                
                 this.phi = r.Math.degToRad(90 - this.lat),
                 this.theta = r.Math.degToRad(this.lon),
                 this.lookVector.x = Math.sin(this.phi) * Math.cos(this.theta),
@@ -4753,70 +4918,69 @@ window.Modernizr = function(n, e, t) {
             }
             ,
             n.prototype.goToDestination = function(e, t, i, n) {
-                        
-<<<<<<< HEAD
-                //音频
+              //音频 
+                //if(this.destinationItem[1] == 0){//如果是每个folder的起始
                 var musicInfo = this.model.heroLocations[this.destinationItem[0]].musicInfo
                 if(musicInfo && musicInfo.music){
-                         
                     var o = musicInfo.music.includes(g_Prefix.slice(-10)) ? musicInfo.music :  g_Prefix + musicInfo.music;
-                    g_tourAudio.src = manage.dealURL(o);
-                    g_tourAudio.load()  
-                }
-                
-=======
-                //音频 
-                //if(this.destinationItem[1] == 0){//如果是每个folder的起始
-                    var musicInfo = this.model.heroLocations[this.destinationItem[0]].musicInfo
-                    if(musicInfo && musicInfo.music){
-                        var o = musicInfo.music.includes(g_Prefix.slice(-10)) ? musicInfo.music :  g_Prefix + musicInfo.music;
-                        
-                        let audioSrc1 = g_tourAudio.src.split('/').pop();
-                        let audioSrc2 = o.split('/').pop();
-                   
-                        if(audioSrc1 == audioSrc2){//应该是继续播放该folder 
-                            if(this.destinationItem[1] == 0){//从头开始播放 因为可能暂停后然后再点该缩略图播
-                                g_tourAudio.currentTime = 0;  g_tourAudio.play();
-                            }else if(g_tourAudio.paused && g_tourAudio.currentTime < g_tourAudio.duration){//未播完
-                                g_tourAudio.play()
-                            } 
-                            
-                        }else{//很可能是该folder的起始
-                            g_tourAudio.src = manage.dealURL(o);
-                            g_tourAudio.load()  
-                        }
+                    
+                    let audioSrc1 = g_tourAudio.src.split('/').pop();
+                    let audioSrc2 = o.split('/').pop();
+               
+                    if(audioSrc1 == audioSrc2){//应该是继续播放该folder 
+                        if(this.destinationItem[1] == 0){//从头开始播放 因为可能暂停后然后再点该缩略图播
+                            g_tourAudio.currentTime = 0;  g_tourAudio.play();
+                        }else if(g_tourAudio.paused && g_tourAudio.currentTime < g_tourAudio.duration){//未播完
+                            g_tourAudio.play()
+                        } 
                         
+                    }else{//很可能是该folder的起始
+                        g_tourAudio.src = manage.dealURL(o);
+                        g_tourAudio.load()  
                     }
+                    
+                }
                 //}
->>>>>>> b82e8fc10c1f2cdf49d8cb4e20f09622457e33bb
-                
                 if (this.onTheBus = !0,
                 this.emit("update.controls"),
                 this.player.updateLastView(),
-                !n && this.atDestinationPano())
+                !n && this.atDestinationPano()){
+                    /* 
+                    // 原地旋转时, 写到_warpCameraAim里,因那有时间
+                    var r = this.model.getHeroDescriptorByIndex(this.destinationItem)
+                    if(r.zoom && r.zoom != this.player.zoomLevel){//add
+                        this.player.smoothZoomFovTo(null, r.zoom, a.warp.teleportTime) //瞬间过渡的时间
+                    } */
                     return void this.arrivedAtDestination(!0);
+                }
                 if (this.player.flying || this.player.isWarping())
                     A.warn("Cannot go to new destination while player is flying or warping.");
                 else {
                     var r = this.model.getHeroDescriptorByIndex(this.destinationItem)
                       , o = null
-                      , a = null;
+                      , a1 = null;
                     if (r.isPano()) {
                     
                         //var s = 0 === this.destinationItem || e ? u.BLACK : this.nextWarpStyle;
                         //var walk = window.MP_PREFETCHED_MODELDATA.black ? 'black' : 'walk';
                      
                         var s = this.getMomentTour(this.destinationItem)   //window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
-                        a = this.player.warpToPanoByHeroIndex.bind(this.player, this.destinationItem, v.Show, m.Slow,  s, true, i, this.actionComplete.bind(this)),
+                        a1 = this.player.warpToPanoByHeroIndex.bind(this.player, this.destinationItem, v.Show, m.Slow,  s, true, i, this.actionComplete.bind(this)),
                         o = this.arrivedAtDestination.bind(this, !0)
+                    
+                        if(s=='black' &&  r.zoom && r.zoom != this.player.zoomLevel){//add
+                            this.player.smoothZoomFovTo(null, r.zoom, a.warp.teleportTime) //瞬间过渡的时间
+                        }
+                    
+                    
                     } else{
-                        a = this.player.warpToNonPanoByHeroIndex.bind(this.player, this.destinationItem, this.actionComplete.bind(this)),
+                        a1 = this.player.warpToNonPanoByHeroIndex.bind(this.player, this.destinationItem, this.actionComplete.bind(this)),
                         o = this.arrivedAtDestination.bind(this, !1);
                     }
                     this.transitionStage = y.Moving,
                     this.model.fadePanoMarkers(0),
                     this.awaitCompletion(function() {
-                        a();          
+                        a1();          
                     }
                     .bind(this), o),
                     this.emit("update.controls") 
@@ -5055,7 +5219,7 @@ window.Modernizr = function(n, e, t) {
                 }
                   
                 
-                var momentTour = this.getMomentTour(this.destinationItem);
+               /*  var momentTour = this.getMomentTour(this.destinationItem);
                 if ( "black" === momentTour) { // 方奕卓 瞬间过渡, 相机缩放至1
                     var zoomLevel = this.player.zoomLevel;
                     this.player.zoomEnabled = true;
@@ -5066,18 +5230,22 @@ window.Modernizr = function(n, e, t) {
                     s.start(zoom, 1500, function(){
                         
                     }, 0, d.easeOutQuad, "zoom")
-                } 
+                }  */
                 
                 this.goToDestination()
             }
             ,
             n.prototype.getMomentTour = function(destinationItem) {//add
-                
-                if(!destinationItem || destinationItem[1] == 0) return window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
+                var wholeMomentTour = window.MP_PREFETCHED_MODELDATA.momentTour || "walk"; //最外层
+                 
+                if(!destinationItem) return wholeMomentTour
                 else{
-                    var currentLocation = this.model.heroLocations[destinationItem[0]];
-                    return currentLocation.momentTour || "walk";
-                }
+                    var currentLocation = this.model.getHeroDescriptorByIndex(destinationItem)//最内层。 如果有使用最内层
+                    if(currentLocation.momentTour)return currentLocation.momentTour;
+                    
+                    var currentLocation_ = this.model.heroLocations[destinationItem[0]];
+                    return  currentLocation_.momentTour || wholeMomentTour; //若中间层或最内层有就使用,否则使用最外层
+                } 
             }
              
             
@@ -17422,6 +17590,7 @@ window.Modernizr = function(n, e, t) {
                             sid: info.sid 
                         }
                         var item = new s(l);
+                        item.momentTour = info.momentTour
                         container.push(item) 
                         return item
                     }
@@ -18328,19 +18497,7 @@ window.Modernizr = function(n, e, t) {
                 })
             }
             
-            /* n.prototype.setEyeDir = function(dir,pos) {//add
-                this.skybox.material.setEyeDir(dir,pos),
-                this.chunks.forEach(function(n) {
-                    n.materialInside.setEyeDir(dir,pos)
-                })
-            }
-            ,
-            n.prototype.setBendCameraQua = function(m) {//add
-                this.skybox.material.setEyeDir(m),
-                this.chunks.forEach(function(n) {
-                    n.materialInside.setEyeDir(m)
-                })
-            } */
+     
             
             ,
             
@@ -20512,7 +20669,7 @@ window.Modernizr = function(n, e, t) {
                 this.obj3d && this.obj3d.updateMatrixWorld()
             }
             ,
-            n.prototype.calcBurnsAmount = function(e) {
+            n.prototype.calcBurnsAmount = function(e) {//计算导览点旋转角
                 var t = r.Math.degToRad(c.warp.burnsAngle);
    
                 if (this.player.mode === a.PANORAMA) {
@@ -20574,6 +20731,7 @@ window.Modernizr = function(n, e, t) {
                             var l = this.playerControls.cameras[a.PANORAMA];
                             n.setFromQuaternion(l.quaternion, c.warp.eOrder);
                             var u = r * s / i;
+                            u = Math.sign(u) * Math.max(u, 0.0001) //add  如果音频长的话,使旋转可见,否则以为停住了
                             n.y += u,
                             o.set(0, 0, -1),
                             o.applyEuler(n),
@@ -20588,18 +20746,7 @@ window.Modernizr = function(n, e, t) {
                 this.startWarpState(),
                 p.start(u, i, h, 0, d.easeInOutQuad, "wait")
 
-                //zoom动画  方奕卓  相机缩放 
-                var currentGuide = player.model.getHeroDescriptorByIndex(player.director.currentItem)  
-                if(currentGuide.zoom && currentGuide.zoom != this.player.zoomLevel){
-                    this.player.zoomEnabled = true;
-                    var startZoom = this.player.zoomLevel
-                    var zoom = function(e, d) { 
-                        var zoomLevel = currentGuide.zoom.toFixed(2) * e + startZoom * (1-e);
-                        this.player.zoomTo( zoomLevel, true)        
-
-                    }.bind(this)
-                    p.start(zoom, 2000, null, 0, d.easeOutQuad, "zoom")
-                }
+                
             }
             ,
             n.prototype.warpToNonPano = function(e) {
@@ -20672,7 +20819,7 @@ window.Modernizr = function(n, e, t) {
                 e && e()
             }
             ,
-            n.prototype._warpCameraAim = function(e, t) {
+            n.prototype._warpCameraAim = function(e, t) {//到每个片段终点时转向终点朝向。
      
                 var i = this.warpDestHeroLoc.quaternion
                   , n = this.playerControls.cameras[a.PANORAMA]
@@ -20700,8 +20847,15 @@ window.Modernizr = function(n, e, t) {
                     void n.lookAt(A))
                 }
                 .bind(this);
-                return u > c.warp.minRotation ? p.start(C, e, t, 0, d[c.warp.movementEasing]) : (y.info("Aim angle only is " + u.toPrecision(3) + " degrees, skipping explicit re-aim")
                 
+                 
+               
+                
+                return u > c.warp.minRotation ? (p.start(C, e, t, 0, d[c.warp.movementEasing])
+                    ,(this.warpDestHeroLoc.zoom != this.player.zoomLevel) &&  //add 原地转向最终方位时 
+                    this.player.smoothZoomFovTo(null, this.warpDestHeroLoc.zoom , e)
+                ): 
+                (y.info("Aim angle only is " + u.toPrecision(3) + " degrees, skipping explicit re-aim")
                 ,void (t && t())
                 )
             }
@@ -21052,7 +21206,13 @@ window.Modernizr = function(n, e, t) {
                             maxDistanceOverride: c.warp.walkMaxDist,
                             skipWarpingCheck: !1,
                             constantMoveSpeed: !0
-                        };
+                        }; 
+                        
+                        if(e == this.warpDestPano){//到达终点前,放大到终点的zoom
+                            n.zoomLevel = this.warpDestHeroLoc.zoom 
+                        } 
+                        
+                        
                         n.duration = u.call(this, e, t),
                         this.player.nonInterruptingFlyToPano(n, i)
                     } else
@@ -22055,12 +22215,12 @@ window.Modernizr = function(n, e, t) {
                     //window.DownInterface && new DownInterface().state(this,Hot);
                     window.Hotpoint && new Hotpoint().state(this,Hot);
                 }
-                if( this.overlayGroup.children.length){
-                    this.overlayGroup.children.forEach((overlay)=>{
-                        overlay.overlayType == "video" /* && overlay.inSight */&&  overlay.plane.material.map.image.play()
-                    })
-                    //this.overlayInitedPlay = true
-                }
+               
+                /* this.overlayGroup.children.forEach((overlay)=>{
+                    overlay.overlayType == "video" && overlay.visible && overlay.inSight() && overlay.videoControl(true)
+                }) */
+                 
+                
             }
             ,
 			
@@ -22401,8 +22561,16 @@ window.Modernizr = function(n, e, t) {
                         for(var i in this.model.hots){
                             this.model.hots[i].update(this.camera)
                         } 
+                        if(this.mode == 'panorama')this.overlayGroup.children.forEach(overlay=>{
+                            if(overlay.overlayType == "video"){
+                                if(overlay.visible && overlay.inSight()){
+                                    overlay.videoControl(true) 
+                                }else{
+                                    overlay.videoControl(false) 
+                                }
+                            }
+                        })
                         
-                       
                     }
                 
 
@@ -22740,8 +22908,8 @@ window.Modernizr = function(n, e, t) {
                 var plane = overlay.plane;
                 
                 if(overlay.overlayType == "video"){
-                    if(plane.material.map.image.paused)plane.material.map.image.play()
-                    else plane.material.map.image.pause();
+                    if(plane.material.map.image.paused) plane.material.map.image.play()
+                    else plane.material.map.image.pause()
                 }
                 
                /*  if(window.EditOverlay &&EditOverlay.editing){
@@ -22764,7 +22932,10 @@ window.Modernizr = function(n, e, t) {
 				for(var i in this.model.hots){
 					t.push(this.model.hots[i].mesh);
 				}
-                this.overlayGroup && (t = t.concat(this.overlayGroup.children));   
+                
+                this.overlayGroup && (t = t.concat(this.overlayGroup.children.filter(e=>e.overlayType == "video"))); 
+
+                
                 var i = new r.Vector3(e.x,e.y,-1).unproject(this.camera);
                 this.raycaster.set(i, this.getMouseDirection(e)); 
                 var n = this.raycaster.intersectObjects(t, true);//add true
@@ -22966,18 +23137,34 @@ window.Modernizr = function(n, e, t) {
                     }
                     hots[index].mesh.visible = visible; 
                 } 
-            },
+            } 
+            
+             
+            
             n.prototype.flyToPano = function(e, t) {
                 var i = e.pano
-                  , n = e.lookAtPoint
+                  , aim = e.lookAtPoint
+                  , aimQua = e.quaternion //ADD
                   , o = e.duration
                   , a = e.aimDuration
                   , s = e.maxDistanceOverride
                   , l = e.skipWarpingCheck
                   , c = e.constantMoveSpeed
                   , h = null
-                  , p = null;
-                  window.specialScene && specialScene.special().specifySpot && specialScene.special().specifySpot(i);
+                  , p = null 
+                
+                if (aim){ 
+                    var _ = (new r.Matrix4).lookAt(i.position, aim, d.UP)
+                    aimQua = (new r.Quaternion).setFromRotationMatrix(_)
+                }
+                else aimQua = aimQua 
+            
+                var zoomLevel = e.zoomLevel || 1  //add  
+                  
+                if(this.flying) return t && t(e)  
+                window.specialScene && specialScene.special().specifySpot && specialScene.special().specifySpot(i);
+                
+                
                 if (this.isWarping() && !l && (this.path.activeTransType === x.BLACK || this.path.activeTransType === x.STD))
                     return F.warn("Player.flyToPano() -> Cannot fly when warping"),
                     t && t(),
@@ -22985,12 +23172,11 @@ window.Modernizr = function(n, e, t) {
                 if (this.updateLastView(),
                 this.mode !== u.PANORAMA) {
                     var m;
-                    return n && (m = (new r.Quaternion).setFromUnitVectors(d.FORWARD, n.sub(i.position).normalize())),
                     void this.flyToNewMode({
                         mode: u.PANORAMA,
                         pano: i,
                         duration: o,
-                        quaternion: m,
+                        quaternion: aimQua ,
                         callback: t
                     })
                 }
@@ -23016,40 +23202,44 @@ window.Modernizr = function(n, e, t) {
                         var E = s || f.transition.flytimeMaxDistanceThreshold;
                         I = Math.min(this.currentPano.position.distanceTo(i.position), E) * f.transition.flytimeDistanceMultiplier + f.transition.flyTime
                     }
+                    
+                    
                     if (f.transition.flySpeed > .01 && (I = 1e3 * this.currentPano.position.distanceTo(i.position) / f.transition.flySpeed),
-                    1 !== this.zoomLevel)
+                    zoomLevel !== this.zoomLevel)
                         switch (f.zoom.transitionStyle) {
-                        case 1:
-                            this.smoothZoomToDefault(I / 2);
+                        case 1: 
+                            this.smoothZoomFovTo(null, zoomLevel, zoomLevel == 1 ? I / 2 : I); //改
                             break;
                         case 2:
                             return h = g.deepExtend(e),
                             p = this.flyToPano.bind(this, h, t),
-                            void this.smoothZoomToDefault(f.zoom.restoreTime * (this.zoomLevel - 1), p)
+                            void this.smoothZoomFovTo(null, zoomLevel, f.zoom.restoreTime * (this.zoomLevel - 1), p)
                         }
-                    if (n) {
+                        
+                        
+                        
+                    if (aimQua) {
                         y.cancelById(V.LookTransition),
                         I *= f.transition.aimSlowFactor;
                         var b = this.cameraControls.activeControl.camera.quaternion.clone()
-                          , _ = (new r.Matrix4).lookAt(i.position, n, d.UP)
-                          , T = (new r.Quaternion).setFromRotationMatrix(_)
+                          
                           , S = b.clone()
                           , M = new r.Vector3;
                         if (i === this.currentPano) {
                             var R = d.FORWARD.clone().applyQuaternion(b)
-                              , P = d.FORWARD.clone().applyQuaternion(T)
+                              , P = d.FORWARD.clone().applyQuaternion(aimQua)
                               , O = R.angleTo(P);
                             return void 0 !== a && null !== a || (a = 1 * Math.sqrt(O) / f.tags.navigate.rotateSpeedFactor * 1e3),
                             void y.start(function(e) {
                                 S.copy(b),
-                                v.quaternion(S, T)(e),
+                                v.quaternion(S, aimQua)(e),
                                 M.copy(d.FORWARD).applyQuaternion(S).add(this.cameraControls.activeControl.camera.position),
                                 this.cameraControls.activeControl.lookAt(M)
                             }
                             .bind(this), a, C, 0, A[f.transition.movementEasing], null, V.LookTransition)
                         }
                     }
-                    if (i === this.currentPano || this.flying)
+                    if (i === this.currentPano )
                         return void C();
                     this.flying = !0;
                     var L = this.position.clone()
@@ -23076,9 +23266,9 @@ window.Modernizr = function(n, e, t) {
                     //=======================================
             
                     
-                    n && y.start(function(e) {
+                    aimQua && y.start(function(e) {
                         S.copy(b),
-                        v.quaternion(S, T)(e),
+                        v.quaternion(S, aimQua)(e),
                         M.copy(d.FORWARD).applyQuaternion(S).add(this.cameraControls.activeControl.camera.position),
                         this.cameraControls.activeControl.lookAt(M)
                     }
@@ -23101,12 +23291,15 @@ window.Modernizr = function(n, e, t) {
                         C(e)
                         
                          //add:
-                        if(this.mode == "panorama" && this.model.floorLogos){
-                            this.model.floorLogos[0].position.copy(this.model.floorLogos[1].position)
-                            //this.model.adjustfloorLogoHeight()
-                            this.model.changefloorLogoOpa({index:0,opa:1,dur:0});//this.model.floorLogos[0].material.uniforms.opacity.value = 1;
-                            this.model.floorLogos[1].visible = false;
+                        if(this.mode == "panorama" ){
+                            if(this.model.floorLogos){
+                                this.model.floorLogos[0].position.copy(this.model.floorLogos[1].position)
+                                //this.model.adjustfloorLogoHeight()
+                                this.model.changefloorLogoOpa({index:0,opa:1,dur:0});//this.model.floorLogos[0].material.uniforms.opacity.value = 1;
+                                this.model.floorLogos[1].visible = false;
+                            }
                             
+                             
                             Overlay.updateVisibles([this.currentPano])//add
                         }
                     }
@@ -23168,6 +23361,53 @@ window.Modernizr = function(n, e, t) {
             }
             
             
+            window._tranOutsideFocus = 4399 
+            n.prototype.focusPoint = function(o={}){//当在外时,聚焦相机到这一点 
+                console.log("focusPoint")
+                if(this.mode == "floorplan"){
+                    var modelSize = o.modelSize || new THREE.Vector3(8,8,8);//可视范围
+                    var control = this.cameraControls.controls.floorplan;
+                    var absoluteScale = control.getDefaultAbsoluteScale(modelSize)
+                    var currentScale = control.absoluteScale;
+                    var currentTarget = control.target.clone()
+                        
+                    y.cancelById(window._tranOutsideFocus, true);
+                    y.start(function(progress){ 
+                        control.absoluteScale = absoluteScale*progress + currentScale*(1-progress);
+                        control.target = o.aim.clone().multiplyScalar(progress).add(currentTarget.clone().multiplyScalar(1-progress))
+                        control.camera.position.copy(control.target.clone().add(control.offset)) //维持角度
+                    }.bind(this) , o.dur || 600, null/* cancelFuc */, 0, A[f.transition.movementEasing], "outsideFocus", window._tranOutsideFocus, null/* cancelFuc */);	 
+                
+                }else if(player.mode == "dollhouse"){
+                    var control = player.cameraControls.controls.dollhouse;
+                    var radius = o.radius || 8;
+                    var currentTarget = control.target.clone()
+                    var dir = control.offset.clone().normalize()
+                    var currentRadius = control.offset.length();
+                    
+                    
+                    y.cancelById(window._tranOutsideFocus, true);
+                    y.start(function(progress){  
+                        control.target = o.aim.clone().multiplyScalar(progress).add(currentTarget.clone().multiplyScalar(1-progress))
+                        let radius_ = radius*progress+currentRadius*(1-progress)
+                        control.camera.position.copy(control.target.clone().add(dir.clone().multiplyScalar(radius_)))  
+                    }.bind(this) , o.dur || 600, null/* cancelFuc */, 0, A[f.transition.movementEasing], "outsideFocus", window._tranOutsideFocus, null/* cancelFuc */);	 
+                }else if(this.mode == 'panorama'){
+                    this.flyToPano({
+                        lookAtPoint: o.aim.clone() ,
+                        pano: this.currentPano,
+                        aimDuration: o.dur || 600
+                    })
+                }
+                
+            }
+                    
+                    
+                    
+                    
+            
+            
+            
             n.prototype.fastForwardActivePanoFlight = function(e) {
                 e = e || f.transition.fastForwardFactor / 10 * 4 + 1,
                 y.adjustSpeed(V.FlyToPano, e),
@@ -23764,20 +24004,20 @@ window.Modernizr = function(n, e, t) {
                 var currentLocation = this.model.heroLocations[this.director.currentItem[0]] 
                 var restChildCount = currentLocation.heroLocations ? (currentLocation.heroLocations.length-this.director.currentItem[1]-1) : 0
                 var current = g_tourAudio ? 1e3 * g_tourAudio.currentTime : 0
-                var waitTime = currentLocation && currentLocation.musicInfo.music ? currentLocation.musicInfo.time - current : 2e3;  
+                var rotTime = currentLocation && currentLocation.musicInfo.music ? currentLocation.musicInfo.time - current : 2e3;  
                 
                 if(restChildCount){//如果当前folder中还有剩下的item,平分一下时间
                     var timeEachItem = 2000;//假设每个item飞的时间
-                    var waitTime = (waitTime-timeEachItem*restChildCount) / (restChildCount+1);
+                    var rotTime = (rotTime-timeEachItem*restChildCount) / (restChildCount+1);
                      
                 } 
-                waitTime = Math.max(0, waitTime)
-                console.log("waitTime "+waitTime +" at item "+this.director.currentItem + ",musicCurrentTime:"+current) 
+                rotTime = Math.max(0, rotTime)
+                console.log("rotTime "+rotTime +" at item "+this.director.currentItem + ",musicCurrentTime:"+current) 
                   
 
                 this.path.waitNextStep(e, function() {
                     t && t()
-                }.bind(this), waitTime)
+                }.bind(this), rotTime)
             }
             ,
             n.prototype.stopInterlude = function() {
@@ -23814,12 +24054,26 @@ window.Modernizr = function(n, e, t) {
             ,
             n.prototype.getCurrentNodePanos = function(e) {
                 this.model.panos.map;
-                if (e.length = 0,
-                this.path.nodes)
-                    for (var t = 0; t < this.path.nodes.length; t++) {
-                        var i = this.path.nodes[t];
-                        e.push(this.model.panos.get(i))
+                if (e.length = 0, this.path.nodes){
+                    
+                    var momentTour = this.director.getMomentTour(this.director.destinationItem)  
+                    if(momentTour == 'black'){ //改 upcomingPanos如果是black的只需要起点和终点
+                        if(this.path.nodes.length){
+                            e.push(this.model.panos.get(this.path.nodes[0]))
+                        }
+                        if(this.path.nodes.length>1){
+                            e.push(this.model.panos.get(this.path.nodes[this.path.nodes.length-1]))
+                        }
+                    }else{ 
+                        for (var t = 0; t < this.path.nodes.length; t++) {
+                            var i = this.path.nodes[t];
+                            e.push(this.model.panos.get(i))
+                        }
                     }
+                    
+                    
+                    
+                }
             }
             ,
             n.prototype.zoomIncrementally = function(e) {
@@ -23908,6 +24162,23 @@ window.Modernizr = function(n, e, t) {
 
                 y.start(r, e, o, null, 0, A[f.transition.blendEasing])
             }
+            
+            n.prototype.smoothZoomFovTo = function (fov, zoomLevel, dur, callback) {//add
+                
+                var i,
+                    n = this.zoomLevel,
+                    aimLevel = zoomLevel || this.baseFov / fov
+
+                if (n == aimLevel) return
+
+                var fun = function (e) {
+                    e > 1 && (e = 1), (i = n * (1 - e) + e * aimLevel),
+                    this.zoomTo(i, !0)
+                }.bind(this)
+
+                y.start(fun, dur, callback, null, 0, A[f.transition.blendEasing])
+            }
+                    
             ,
             n.prototype.updateZoomPano = function() {
                 if (!this.panoRenderer.zoomPanoRenderingDisabled && this.mode === u.PANORAMA) {
@@ -24298,6 +24569,11 @@ window.Modernizr = function(n, e, t) {
             }
             u.profiling.enabled && this.overrideTextures(),
             e.appendChild(this.renderer.domElement)
+            
+            /* window.stats = new Stats();  
+            e.appendChild( stats.dom );  */
+            
+            
         }
         ,
         n.prototype.overrideTextures = function() {
@@ -24913,6 +25189,7 @@ window.Modernizr = function(n, e, t) {
             this.updateComponents(),
             this.updateTextureMemory(),
             this.render(),
+            window.stats && (window.fps = stats.update()),
             this.emit(a.AfterRender))
         };
         n.prototype.getImageData = function() {
@@ -26731,7 +27008,7 @@ window.Modernizr = function(n, e, t) {
                     const vec4 GREY  = vec4(0.5, 0.5, 0.5, 1.0);
                     vec4 colorFromPanos;
                     if (blackout == 5){
-                        colorFromPanos = textureCube( pano1Map, vWorldPosition1.xyz);
+                        colorFromPanos = textureCube( pano1Map, vWorldPosition1.xyz)                                    ;
                     }else{
                         vec4 colorFromPano0 = textureCube( pano0Map, vWorldPosition0.xyz);
                         vec4 colorFromPano1 = textureCube( pano1Map, vWorldPosition1.xyz);
@@ -29713,7 +29990,7 @@ window.Modernizr = function(n, e, t) {
                         var t = e.neighbourPanos || e.findNeighourPanos()
                           , i = [];
                         for (var n in t)
-                            i.push(this.index[n]);
+                            t[n] && i.push(this.index[n]);  //add: t[n] &&
                         return i
                     }
                     .bind(this),
@@ -30178,7 +30455,7 @@ window.Modernizr = function(n, e, t) {
             }
         }
         var r = e("../exception/DeviceMismatchException");
-        t.exports = {
+        window.browser = t.exports = {
             isFullscreen: function() {
                 return document.fullscreenElement || document.mozFullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement
             },
@@ -30350,6 +30627,9 @@ window.Modernizr = function(n, e, t) {
                 return "boolean" == typeof t ? "true" === r || "1" === r : "number" == typeof t ? parseFloat(r) : window.decodeURIComponent(r)
             }
         }
+        
+        
+        changeLog()
     }
     , {
         "../exception/DeviceMismatchException": 56
@@ -30658,7 +30938,21 @@ window.Modernizr = function(n, e, t) {
              
                 return visiblePanos
             } 
-       
+            ,
+            sortByScore : function(list, request, rank) {
+                var i = this.filterAll(list, request);
+                return 0 === i.length ? null : i = i.map(function(e) {
+                    return {
+                        item: e,
+                        score: rank.reduce(function(t, i) {
+                            return t + i(e);
+                        }, 0)
+                    };
+                }).sort(function(e, t) {
+                    return t.score - e.score;
+                });
+            } 
+ 
             
         },
         Math.sign = function(e) {
@@ -30844,6 +31138,9 @@ window.Modernizr = function(n, e, t) {
         }
         ,
         t.exports = n
+        
+        
+        window.easing = n
     }
     , {}],
     187: [function(e, t, i) {
@@ -30894,7 +31191,7 @@ window.Modernizr = function(n, e, t) {
     }],
     188: [function(e, t, i) {
         "use strict";
-        t.exports = {
+        window.lerp =  t.exports = {
             vector: function(e, t) {
                 var i = e.clone();
                 return t = t.clone(),
@@ -31453,7 +31750,7 @@ window.Modernizr = function(n, e, t) {
     195: [function(e, t, i) {
         "use strict";
         var n = e("./easing");
-        t.exports = {
+        window.transitions = t.exports = {
             globalDone: null,
             funcs: [],
             counter: 0,
@@ -58265,3 +58562,11 @@ function initTransitionPass(THREE){
 }
 
 
+/* 
+   笔记:
+   
+    导览缩放的几处: 1 搜索smoothZoomFovTo  2 flightStepWalk里
+   
+   
+
+ */

+ 68 - 26
js/overlay.js

@@ -1,4 +1,6 @@
-
+var MathLight = {};
+MathLight.RADIANS_PER_DEGREE = Math.PI / 180;
+MathLight.DEGREES_PER_RADIAN = 180 / Math.PI;
 
  
  
@@ -56,8 +58,10 @@ var initOverlay = function(THREE) {
         overlayGroup.add(this);
 
         if (info.media) {
-            if (info.media.includes('video')) {
-                var video = $('<video controls="controls" loop autoplay x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload"></video>')[0]
+            if (info.media.includes('video')) { 
+                var id = "video"+ this.sid  
+                var video = $(`<video id="${ id }" style='display:none' controls="controls" loop autoplay x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload"></video>`)[0]
+                 
                 video.setAttribute("crossOrigin", 'Anonymous')
                 //要在src设置好前解决跨域
                 $(video).on('contextmenu', function() {
@@ -69,10 +73,9 @@ var initOverlay = function(THREE) {
                 info.media = video;
                 info.type = "video"
 
-                video.addEventListener('loadeddata', ()=>{
+                /* video.addEventListener('loadeddata', ()=>{
                     console.log(this.sid + " loaded!!!")
-                }
-                )
+                }) */
                 video.volume = 0
                 video.muted = true
                 plane.material.opacity = 1;
@@ -231,7 +234,7 @@ var initOverlay = function(THREE) {
     Overlay.prototype.updateVisibles = function(panos) {
         this.visible = !!panos.find(pano=>this.visiblePanos.includes(pano))
         if (!this.visible && this.overlayType == 'video')
-            this.plane.material.map.image.pause()
+            this.videoControl('stop')
     }
     
     
@@ -242,21 +245,48 @@ var initOverlay = function(THREE) {
             player.overlayGroup.children.forEach(e=>e.updateVisibles(panos))
         }
     }
-    
-    /* Overlay.prototype.inSight = function(){
-        var maxAngle = THREE.Math.degToRad( cameraLight.getHFOVFromVFOV(70, player.domElement.clientWidth, app.player.domElement.clientHeight) / 2);
-        //角度为可见范围 
-        var v1 = cameraDir.clone().setY(0);
-        var v2 = overlays[i].plane.getWorldPosition().sub(player.position).setY(0)
-        if(v1.angleTo(v2) <= maxAngle){
-            Overlay.loadQueue.push(overlays[i])
-            if(Overlay.loadQueue.length>=10) break;
-        } 
-        
-    } */
+
+    Overlay.prototype.videoControl = function(state){
+        if(this.overlayType != "video")return
+        if(!state || state == 'stop'){
+            this.plane.material.map.image.paused || this.plane.material.map.image.pause()
+            if(state == 'stop'){
+                this.plane.material.map.image.currentTime = 0;
+               
+            }
+            //console.log("pause")
+        }else if(state){ 
+            this.plane.material.map.image.paused && this.plane.material.map.image.play()
+            //console.log("play")
+        }
+    }     
+    Overlay.prototype.inSight = function(){
+        if(player.mode == 'panorama'){
+            var position = this.plane.getWorldPosition()
+            var pos2d = math.getPos2d(position, player.camera, $("#player")[0])
+            if(pos2d.trueSide && pos2d.inSight){
+                return true
+            }else{ 
+                var cornerPoint = [
+                    new THREE.Vector3(-settings.overlay.width/2, settings.overlay.height/2, 0),
+                    new THREE.Vector3(settings.overlay.width/2, settings.overlay.height/2, 0),
+                    new THREE.Vector3(settings.overlay.width/2, -settings.overlay.height/2, 0),
+                    new THREE.Vector3(-settings.overlay.width/2, -settings.overlay.height/2, 0),
+                ];            
+                for(var i=0;i<4;i++){
+                    cornerPoint[i].applyMatrix4(this.plane.matrixWorld);
+                    var pos2d = math.getPos2d(cornerPoint[i], player.camera, $("#player")[0])
+                    if(pos2d.trueSide && pos2d.inSight){
+                        return true
+                    }
+                }
+            }
+        }else{
+            return true
+        }
+    }
     
     
-
     Overlay.prototype.addToLoadQueue = function() {
         if (this.overlayType == 'photo') {
             Overlay.loadQueue.includes(this) || Overlay.loadQueue.push(this)
@@ -299,9 +329,6 @@ var initOverlay = function(THREE) {
         Overlay.loadQueue.slice(0, Overlay.maxLoadingCount - loadings.length).forEach(e=>e.requestDownload())
         Overlay.loadQueue.splice(0, Overlay.maxLoadingCount - loadings.length)
     }
-    
-    
-    
 
     Overlay.getNeedLoad = function() {//计算获取loadQueue,每次都重新计算,覆盖旧的
         if (!player || !player.domElement || !player.mode)
@@ -319,11 +346,26 @@ var initOverlay = function(THREE) {
         }
         Overlay.loadWhenOutside = true
         var overlays = player.overlayGroup.children.filter(e=>!e.hasRequestLoad && e.visiblePanos.includes(player.currentPano))
+        //var maxAngle = THREE.Math.degToRad( cameraLight.getHFOVFromVFOV(70, player.domElement.clientWidth, app.player.domElement.clientHeight) / 2);
         var cameraDir = player.getDirection()
 
-         
+        /* var maxCount = 5; 
+        if(overlays.length>maxCount){
+            for(var i=0;i<overlays.length;i++){ 
+                //角度为可见范围 
+                var v1 = cameraDir.clone().setY(0);
+                var v2 = overlays[i].plane.getWorldPosition().sub(player.position).setY(0)
+                if(v1.angleTo(v2) <= maxAngle){
+                    Overlay.loadQueue.push(overlays[i])
+                    if(Overlay.loadQueue.length>=10) break;
+                }  
+            } 
+            if(Overlay.loadQueue.length<Overlay.maxLoadingCount){
+                Overlay.loadQueue.push()
+            }
+        }else{ */
         Overlay.loadQueue = overlays
-        
+        //} 
 
         var request = [(overlay)=>{
             return true
@@ -339,7 +381,7 @@ var initOverlay = function(THREE) {
             return -angle * 20
         }
         ]
-        var result = sortByScore(Overlay.loadQueue, request, rank);
+        var result = common.sortByScore(Overlay.loadQueue, request, rank);
         Overlay.loadQueue = result ? result.slice(0, 5).map(e=>e.item) : player.overlayGroup.children.filter(e=>!e.hasRequestLoad).slice(0, 2);
 
     }

+ 120 - 0
js/stats.min.js

@@ -0,0 +1,120 @@
+// stats.js - http://github.com/mrdoob/stats.js
+var Stats = function() {
+    function h(a) {
+        c.appendChild(a.dom);
+        return a
+    }
+    function k(a) {
+        for (var d = 0; d < c.children.length; d++)
+            c.children[d].style.display = d === a ? "block" : "none";
+        l = a
+    }
+    var l = 0
+      , c = document.createElement("div");
+    c.style.cssText = "position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";
+    c.addEventListener("click", function(a) {
+        a.preventDefault();
+        k(++l % c.children.length)
+    }, !1);
+    var g = (performance || Date).now()
+      , e = g
+      , a = 0
+      , r = h(new Stats.Panel("FPS","#0ff","#002"))
+      , f = h(new Stats.Panel("MS","#0f0","#020"));
+    if (self.performance && self.performance.memory)
+        var t = h(new Stats.Panel("MB","#f08","#201"));
+    k(0);
+    return {
+        REVISION: 16,
+        dom: c,
+        addPanel: h,
+        showPanel: k,
+        begin: function() {
+            g = (performance || Date).now()
+        },
+        end: function() {
+            /* a++;
+            var c = (performance || Date).now();
+            if(f.dom.clientWidth) f.update(c - g, 200);
+            
+            
+            if (c > e + 1E3 && (r.dom.clientWidth && r.update(1E3 * a / (c - e), 100),
+            e = c,
+            a = 0,
+            t && t.dom.clientWidth)) {
+                var d = performance.memory;
+                t.update(d.usedJSHeapSize / 1048576, d.jsHeapSizeLimit / 1048576)
+            } 
+            return 1E3 * a / (c - e)//c */
+            
+            a++; 
+            var c = (performance || Date).now();
+      
+            if(c > e + 1E3){
+                var v = 1E3 * a / (c - e)
+                var {min,max} = r.update(v, 100)
+                e = c
+                a = 0
+                return {min, max, fps:v}
+            }  
+            
+            
+        },
+        update: function() {
+            g = this.end()
+            return g
+        },
+        domElement: c,
+        setMode: k
+    }
+};
+Stats.Panel = function(h, k, l) {
+    var c = Infinity
+      , g = 0
+      , e = Math.round
+      , a = e(window.devicePixelRatio || 1)
+      , r = 80 * a
+      , f = 48 * a
+      , t = 3 * a
+      , u = 2 * a
+      , d = 3 * a
+      , m = 15 * a
+      , n = 74 * a
+      , p = 30 * a
+      , q = document.createElement("canvas");
+    q.width = r;
+    q.height = f;
+    q.style.cssText = "width:80px;height:48px";
+    var b = q.getContext("2d");
+    b.font = "bold " + 9 * a + "px Helvetica,Arial,sans-serif";
+    b.textBaseline = "top";
+    b.fillStyle = l;
+    b.fillRect(0, 0, r, f);
+    b.fillStyle = k;
+    b.fillText(h, t, u);
+    b.fillRect(d, m, n, p);
+    b.fillStyle = l;
+    b.globalAlpha = .9;
+    b.fillRect(d, m, n, p);
+    return {
+        dom: q,
+        update: function(f, v) {
+            c = Math.min(c, f);
+            g = Math.max(g, f);
+            b.fillStyle = l;
+            b.globalAlpha = 1;
+            b.fillRect(0, 0, r, m);
+            b.fillStyle = k;
+            b.fillText(e(f) + " " + h + " (" + e(c) + "-" + e(g) + ")", t, u);
+            b.drawImage(q, d + a, m, n - a, p, d, m, n - a, p);
+            b.fillRect(d + n - a, m, a, p);
+            b.fillStyle = l;
+            b.globalAlpha = .9;
+            b.fillRect(d + n - a, m, a, e((1 - f / v) * p))
+            
+            return {min:c, max:g}
+        }
+    }
+}
+;
+"object" === typeof module && (module.exports = Stats);