zhouenguang 3 lat temu
rodzic
commit
77c5d10b5c

Plik diff jest za duży
+ 2082 - 0
dist/assets/config - 副本.json


+ 1 - 1
dist/assets/config.json

@@ -389,7 +389,7 @@
 					"className": "粗模",
 					"assetId": "",
 					"name": "Ground_LV01_xverse.glb",
-					"url": "https://app-mgt-resource-1258211750.file.myqcloud.com/model/407033cdaf0d4159bfd9c783b72f90ab/Ground_LV01_xverse.glb",
+					"url": "./assets/house.glb",
 					"thumbnailUrl": ""
 				}, {
 					"typeName": "CONFIG",

BIN
dist/assets/house.glb


BIN
dist/assets/house0.glb


+ 225 - 0
dist/assets/points.json

@@ -0,0 +1,225 @@
+[{
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [1, 12, 13, 11, 14],
+	"id": 0,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": -1.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [0, 2, 14, 13, 15],
+	"id": 1,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [1, 4, 15, 14, 3],
+	"id": 2,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": 1.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [5, 15, 4, 2, 6],
+	"id": 3,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": 2.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [2, 3, 15],
+	"id": 4,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": 2.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [3, 7, 6],
+	"id": 5,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": 3.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [5, 3],
+	"id": 6,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": 3.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [5],
+	"id": 7,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": 4.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [],
+	"id": 8,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": 4.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [11, 10, 12],
+	"id": 9,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": -3.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [9, 12, 11],
+	"id": 10,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": -3.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [9, 13, 12, 0, 10],
+	"id": 11,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": -2.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [0, 10, 11, 9, 13],
+	"id": 12,
+	"position": {
+		"x": 0.0,
+		"y": 0.0,
+		"z": -2.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [0, 11, 14, 1, 12],
+	"id": 13,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": -1.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [1, 13, 15, 0, 2],
+	"id": 14,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": 0.0
+	}
+}, {
+	"rotation": {
+		"w": 1.0,
+		"x": 0.0,
+		"y": 0.0,
+		"z": 0.0
+	},
+	"contact": [2, 3, 14, 1, 4],
+	"id": 15,
+	"position": {
+		"x": -1.0,
+		"y": 0.0,
+		"z": 1.0
+	}
+}]

+ 178 - 11
src/ActionsHandler.js

@@ -8,6 +8,12 @@ import Logger from "./Logger.js"
 import Response from "./Response.js"
 import { VDecoder } from "./h264Decoder/VDecoder.js";
 
+import { SrsRTC } from "./srsRtc.js";
+import { Connection } from "./connection.js";
+
+
+const ossVideoDir = "https://laser-data.oss-cn-shenzhen.aliyuncs.com/test-video/optest/"
+
 window.currentFrame = null
 const logger = new Logger('actions-handler')
 const QueueActions = [Actions.Transfer, Actions.ChangeSkin, Actions.GetOnVehicle, Actions.GetOffVehicle];
@@ -30,6 +36,71 @@ export default class ActionsHandler {
             console.log("ready");
             window.workerReady = true
         })
+
+        this.initSocket()
+    }
+    
+    initSocket() {
+
+        const sdk = new SrsRTC();
+        const testConfig = {
+          sceneCode: "testApp",
+          userId: "testUser",
+          roomId: "8888",
+        };
+        const connection = new Connection(testConfig);
+        
+        console.log("sdk", sdk);
+        console.log("sdk", connection);
+        const url = "webrtc://demo-kms.4dage.com/live/test1";
+        sdk.start(url);
+
+        window.connection = connection
+
+
+        
+        window.connection.socket.on("getRoute", (pathArr) => {
+            console.error("getRoute", pathArr);
+            
+            let {anglePlus, dircNum} = window.room.sceneManager.correctCameraDirec()
+            
+            pathArr.forEach(point => {
+                // todo 矫正
+                let ue4Pos = util.xversePosition2Ue4({x: point.location.x-0.8, y: point.location.y, z: point.location.z+0.8})
+                point.location = new BABYLON.Vector3(ue4Pos.x, ue4Pos.y, ue4Pos.z)
+            })
+
+            let walkPoints = []
+            let videoArr = []
+            for(let i = 0; i < pathArr.length - 1; i++) {
+
+                videoArr.push( ossVideoDir + pathArr[i].id + "/" + pathArr[i].id + "_" + pathArr[i+1].id + "_" + dircNum)
+
+                let point0 = new BABYLON.Vector3(pathArr[i].location.x, pathArr[i].location.y, pathArr[i].location.z)
+                let point1 = new BABYLON.Vector3(pathArr[i+1].location.x, pathArr[i+1].location.y, pathArr[i+1].location.z)
+                let distanceVec = point1.clone().subtract(point0)
+                let distancePerFrame = distanceVec.length() / 30
+                let dir = distanceVec.normalize()
+                for(let currentFrame = 1; currentFrame <= 30; currentFrame++) {
+                    walkPoints.push(point0.add(dir.scale(distancePerFrame * currentFrame)))
+                }
+            }
+
+            console.error(walkPoints)
+
+            window.walkSettings = {
+                "frameNum": 30 * (pathArr.length - 1),
+                "walkPoints": walkPoints,
+            }
+
+            window.walking = true
+
+
+            this.mutiFetchData({
+                type: 'move',
+                videoPathArr: videoArr
+            })
+        });
     }
 
     async avatarComponentsSync(e){
@@ -111,6 +182,18 @@ export default class ActionsHandler {
             }
     }
     async moveTo(e) {
+
+        // 镜头矫正
+        let {anglePlus, dircNum} = window.room.sceneManager.correctCameraDirec()
+        if(Math.abs(anglePlus) > 0.0001) {
+            window.moveBackCall = {
+                func: this.moveTo.bind(this),
+                args: [e]
+            }
+            this.rotate({type: 'rotate', angle: anglePlus})
+            return
+        }
+
         const {point: t, extra: r="", motionType: n} = e
           , o = {
             action_type: Actions.Clicking,
@@ -122,9 +205,62 @@ export default class ActionsHandler {
             },
             clicking_state: this.room._currentClickingState
         };
-        return this.sendData({
-            data: o
-        })
+
+        let player = window.room.sceneManager.avatarComponent._mainUser
+
+        let closestPoint = window.room.sceneManager.getClosestPointData(t)
+        let closestPointSelf = window.room.sceneManager.getClosestPointData(player.position)
+
+        window.connection.socket.emit("getRoute", {
+            sceneCode: "testApp",
+            userId: "testUser",
+            roomId: "8888",
+            s_location: {
+                x: closestPointSelf.position0.x,
+                y: closestPointSelf.position0.y,
+                z: closestPointSelf.position0.z,
+            },
+            e_location: {
+                x: closestPoint.position0.x,
+                y: closestPoint.position0.y,
+                z: closestPoint.position0.z,
+            },
+        });
+
+
+        // if(this.walkHandle) clearInterval(this.walkHandle)
+
+        // // window.room.moveTo(t)
+        // let currentFrame = 0
+        // this.walkHandle = setInterval(() => {
+        //     currentFrame++
+        //     let targetPos = {
+        //         "x": player.position.x + distanceVec.x / frameNum,
+        //         "y": player.position.y + distanceVec.y / frameNum,
+        //         "z": player.position.z + distanceVec.z / frameNum
+        //     }
+        //     if(currentFrame < frameNum) {
+        //         window.room.moveTo({
+        //             position: targetPos, 
+        //             isEnd: false
+        //         })
+        //     } else {
+        //         window.room.moveTo({
+        //             position: targetPos, 
+        //             isEnd: true
+        //         })
+        //         clearInterval(this.walkHandle)
+        //     }
+        // }, 1000 / fps)
+
+        // let date = new Date()
+        // console.error(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds())
+        
+        // console.error(closestPointSelf.id)
+
+        // return this.sendData({
+        //     data: o
+        // })
     }
     transfer(e) {
         const {renderType: t, player: r, camera: n, areaName: o, attitude: a, pathName: s, person: l, noMedia: u, timeout: c, tag: h, special: f} = e
@@ -384,11 +520,12 @@ export default class ActionsHandler {
         let endRotation = util.xverseRotation2Ue4(window.room.sceneManager.cameraComponent.mainCamera.rotation).yaw
         endRotation = (endRotation % 360 + 360) % 360
         
-        let sfns = Math.round(endRotation/6)
+        // todo 矫正
+        let sfns = Math.round((endRotation + 180)/6)        // 仅视频贴图偏移矫正180度
         endRotation += angle/Math.PI*180
         endRotation = (endRotation % 360 + 360) % 360
 
-        let efns = Math.round(endRotation/6)
+        let efns = Math.round((endRotation + 180)/6)
         
         if(window.currentFrame == null){
             window.currentFrame = efns
@@ -410,12 +547,17 @@ export default class ActionsHandler {
         window.rotateFrame = efns - sfns   // 旋转帧数
         window.camera_endRotation = endRotation
         window.star_angle = angle
+        
+
+        let player = window.room.sceneManager.avatarComponent._mainUser
+        let closestPointSelf = window.room.sceneManager.getClosestPointData(player.position)
 
         console.log('取帧:'+sfns+','+efns);
         this.fetchData({
-            type:type,
-            sFrame:sfns,
-            eFrame:efns
+            type: type,
+            path: ossVideoDir + closestPointSelf.id + "/" + closestPointSelf.id,
+            sFrame: sfns,
+            eFrame: efns
         })
         
         if(typeof(window.star_angle) == 'undefined'){
@@ -477,13 +619,38 @@ export default class ActionsHandler {
     }
     */
 
-    fetchData({type:type, sFrame: sfns, eFrame: efns}){
+    fetchData({type, path, sFrame: sfns, eFrame: efns}){
         if(window.workerReady){
             this.vDecoder.fetch({
-                path: "https://laser-data.oss-cn-shenzhen.aliyuncs.com/test-video/2",
+                // path: "https://laser-data.oss-cn-shenzhen.aliyuncs.com/test-video/res/720p",
+                path: path,
                 // range: [sfns, efns],
                 range: sfns == efns ? [efns] : [sfns, efns],
-              });
+            });
+        }
+        else{
+            console.error('还没准备好')
+        }
+    }
+
+    mutiFetchData({type, videoPathArr}){
+        console.error(videoPathArr)
+        if(window.workerReady){
+            // https://laser-data.oss-cn-shenzhen.aliyuncs.com/test-video/optest/0/0_1_0/
+            let sendData = []
+            // let videoPathArr = [
+            //     "https://laser-data.oss-cn-shenzhen.aliyuncs.com/test-video/1011",
+            //     "https://laser-data.oss-cn-shenzhen.aliyuncs.com/test-video/1",
+            // ]
+            videoPathArr.forEach(path => {
+                for(let i = 0; i < 30; i++) {
+                    sendData.push({
+                        path: path,
+                        frame: i,
+                    })
+                }
+            })
+            this.vDecoder.mutiFetch(sendData);
         }
         else{
             console.error('还没准备好')

+ 1 - 1
src/XAvatar.js

@@ -295,7 +295,7 @@ export default class XAvatar {
               , c = new BABYLON.Ray(u,o,s)
               , h = (d = this.avatarManager.sceneManager) == null ? void 0 : d.getGround(e);
             if (!h || h.length <= 0)
-                return logger.warn(`\u89D2\u8272 id= ${this.id} \u627E\u4E0D\u5230\u5730\u9762\uFF0C\u5F53\u524D\u9AD8\u5EA6\u4E3A\u4E0B\u53D1\u9AD8\u5EA6`),
+                return console.warn(`\u89D2\u8272 id= ${this.id} \u627E\u4E0D\u5230\u5730\u9762\uFF0C\u5F53\u524D\u9AD8\u5EA6\u4E3A\u4E0B\u53D1\u9AD8\u5EA6`),
                 t(0);
             let f = c.intersectsMeshes(h);
             if (f.length > 0)

+ 21 - 8
src/XAvatarManager.js

@@ -3,6 +3,7 @@ import BillboardStatus from "./enum/BillboardStatus.js"
 import {avatarLoader} from "./XAvatarLoader.js"
 import XAvatar from "./XAvatar.js"
 import Logger from "./Logger.js"
+import util from "./util"
 
 const logger = new Logger('AvatarManager')
 export default class XAvatarManager {
@@ -177,7 +178,7 @@ export default class XAvatarManager {
                 avatarManager: n,
                 assets: o,
                 status: a
-            });            
+            });
             this.registerAvatar(u);
             if (r == 0)
                 this.setMainAvatar(u.id),
@@ -554,12 +555,6 @@ export default class XAvatarManager {
                 console.log("body_man缩放", s.rootNodes[0]._children[0]._scaling)
                 window.initFinished = true
 
-                // 开始旋转
-                window.room.actionsHandler.rotate({
-                    type: 'rotate',
-                    angle: 0
-                });
-
                 a.xReferenceCount++;
                 const l = {
                     isRender: !1,
@@ -644,7 +639,25 @@ export default class XAvatarManager {
         const r = Date.now();
         return new Promise((n,o)=>{
             this.loadBody(e.avatarType, e.avatarType, t).then(a=>{
-                // console.error(a.root._children[0]._scaling)
+                // console.error(a.root._children[0])
+                // zeg 赋人物初始坐标
+                setTimeout(() => {
+                    let pos0 = window.points[0].position
+                    window.room.moveTo({
+                        position: pos0,
+                        needTurnAround: false,
+                        isEnd: true
+                    })
+                    // todo 初始角度
+                    // window.camera_endRotation = 180
+                    // window.room.doRotate(Math.PI)
+                    // 开始旋转
+                    window.room.actionsHandler.rotate({
+                        type: 'rotate',
+                        angle: 0
+                    });
+                }, 300)
+
                 var s;
                 if (!a)
                     return e.isInLoadingList = !1,

+ 37 - 5
src/XMaterialComponent.js

@@ -269,16 +269,49 @@ export default class XMaterialComponent {
             this.initReceve = true
             window.vDecoder.on("decodeData",this.receveFrames.bind(this))
         }
-        
     }
+
     //xst
     receveFrames(data){
         // console.error("decodeData", data.clipId, data.renderStateId)
-        if(!window.rotating) return
-        if(window.rotateFrame <= data.renderStateId) window.rotating = false
+        if(!window.rotating && !window.walking) return
+
+        if(window.rotating) {
+            if(window.rotateFrame <= data.renderStateId) window.rotating = false
+            window.room.doRotate(window.star_angle)
+            // window.room.doRotate(Math.PI/30 * Math.sign(window.star_angle))
+        } 
+        else if(window.walking) {
+
+            let targetPos = window.walkSettings.walkPoints[data.renderStateId]
+
+            // if(window.walkSettings.currentFrame < frameNum) {
+            if(data.renderStateId < window.walkSettings.frameNum - 1) {
+                window.room.moveTo({
+                    position: targetPos,
+                    needTurnAround: true, 
+                    isEnd: false
+                })
+            } else {
+                window.room.moveTo({
+                    position: targetPos,
+                    needTurnAround: true, 
+                    isEnd: true
+                })
+                window.walking = false
+            }
+        }
 
-        window.room.doRotate(window.star_angle)
+        this.updateHouseTexture(data)
 
+        if(window.moveBackCall) {
+            window.moveBackCall.func(...window.moveBackCall.args)
+            window.moveBackCall = null
+        }
+    }
+
+    updateHouseTexture(data) {
+        
         const { width, height, data: buffer } = data;
         let stream = new Uint8Array(buffer)
         var o, a;
@@ -333,7 +366,6 @@ export default class XMaterialComponent {
             }
             */
         }
-
     }
 
     //调试

+ 60 - 4
src/XSceneManager.js

@@ -11,6 +11,8 @@ import XEngineRunTimeStats from "./XEngineRunTimeStats.js"
 import EShaderMode from "./enum/EShaderMode.js"
 import defaultLog from "./defaultLog.js"
 import Logger from "./Logger.js"
+import { http1 } from "./Http1.js"
+import util from "./util.js"
 
 const logger = new Logger('XSceneManager')
 
@@ -77,7 +79,10 @@ export default class XSceneManager {
         );
         E(this, "addNewLowPolyMesh", async(e,t)=>(this._currentShader == null && await this.initSceneManager(),
         this._lowpolyManager.addNewLowPolyMesh(e, t, this._currentShader)));
-        E(this, "initSceneManager", async()=>(await this._materialManager.initMaterial(),this.applyShader()));
+        E(this, "initSceneManager", async()=>(
+            await this._materialManager.initMaterial(),
+            this.applyShader()
+        ));
         E(this, "registerAfterRender", ()=>{
             var e;
             if (this._forceKeepVertical) {
@@ -121,9 +126,9 @@ export default class XSceneManager {
         this.scene.clearCachedVertexData(),
         this.scene.cleanCachedTextureBuffer(),
         // 周恩光加 调试用工具栏
-        // this.scene.debugLayer.show({
-        //     embedMode: true,
-        // })
+        this.scene.debugLayer.show({
+            embedMode: true,
+        })
         this.urlTransformer = t.urlTransformer || (s=>Promise.resolve(s)),
         t.logger && defaultLog.setLogger(t.logger),
         this.gl = e.getContext("webgl2", {
@@ -164,6 +169,7 @@ export default class XSceneManager {
         this._billboardManager = new XBillboardManager(this),
         this.billboardComponent.loadBackGroundTexToIDB(),
         this._lightManager = new XLightManager(this),
+        this.readPointData(),
         this.postprocessing(),
         this.initSceneManager(),
         this.engineRunTimeStats = new XEngineRunTimeStats,
@@ -452,4 +458,54 @@ export default class XSceneManager {
         ),
         r
     }
+
+    // zeg
+    readPointData() {
+        
+        return fetch("./assets/points.json", {
+            headers: {
+                'content-type': 'application/json'
+            },
+            method: 'GET',
+        })
+        .then(response => response.json())
+        .then(response => {
+            response.forEach(data => {
+                // 当前json数据坐标处理有问题,x需取负,转BABYLON默认坐标
+                // 又根据xversePosition2Ue4方法猜测,xverse坐标和BABYLON默认坐标xy方向相反,xz再次取负
+                // todo 矫正
+                let ue4Pos = util.xversePosition2Ue4({x: data.position.x-0.8, y: data.position.y, z: data.position.z+0.8})
+                // console.error(data.position, ue4Pos)
+                data.position0 = data.position
+                data.position = new BABYLON.Vector3(ue4Pos.x, ue4Pos.y, ue4Pos.z)
+            })
+            window.points = response
+        })
+
+    }
+
+    getClosestPointData(vec) {
+        vec = new BABYLON.Vector3(vec.x, vec.y, vec.z)
+        let closestPoint = { data: null, length: 99999 }
+        window.points.forEach( data => {
+            let length = vec.clone().subtract(data.position).length()
+            if(length < closestPoint.length) {
+                closestPoint.data = data
+                closestPoint.length = length
+            }
+        })
+        return closestPoint.data
+    }
+
+    correctCameraDirec() {
+        // 视频逆时针旋转
+        let num = Math.round((this._cameraManager.mainCamera.rotation.y + Math.PI) / (Math.PI/4))       // 矫正
+        let angle = num * (Math.PI/4) - (this._cameraManager.mainCamera.rotation.y + Math.PI)
+
+        return {
+            anglePlus: angle,
+            dircNum: num <= 0 ? -num : 8-num
+        }
+    }
+
 }

+ 79 - 0
src/Xverse_Room.js

@@ -148,6 +148,7 @@ export default class Xverse_Room extends EventEmitter {
     doRotate(angle){
         //this.sceneManager.materialComponent.initreceveFrames()
 
+        // 获得相机旋转后的位置
         let cameraPostion0 = util.xversePosition2Ue4(this.sceneManager.cameraComponent.mainCamera.position.clone())
         let playerPosition = this.sceneManager.avatarComponent._mainUser.position
 
@@ -158,6 +159,27 @@ export default class Xverse_Room extends EventEmitter {
 
         cameraPos.rotateByQuaternionAroundPointToRef(rotationQuaternion, cameraCenter, cameraPos)
 
+        
+        // 相机碰撞检测
+        let cameraPosXverse = util.ue4Position2Xverse(cameraPos)
+        let cameraCenterXverse = util.ue4Position2Xverse(playerPosition)
+        cameraCenterXverse.y = cameraPosXverse.y
+
+        if(!this.ray) this.ray = new BABYLON.Ray(new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,1), 50);
+        this.ray.origin = cameraCenterXverse
+        this.ray.direction = BABYLON.Vector3.Normalize( cameraPosXverse.clone().subtract(cameraCenterXverse) )
+        let info = this.ray.intersectsMeshes(this.sceneManager.getGround())[0];
+
+        // todo 矫正
+        const offset = 0.09
+        if(info) {
+            info.distance = Math.min(info.distance, 4.5 + offset)
+            cameraPosXverse = cameraCenterXverse.add(this.ray.direction.clone().scale(Math.max( info.distance - offset, 0.1 )))
+            cameraPos = util.xversePosition2Ue4(cameraPosXverse)
+        }
+
+
+
         let cameraState = {
             "position": {
                 "x": cameraPos.x,
@@ -203,6 +225,63 @@ export default class Xverse_Room extends EventEmitter {
     
     }
 
+    
+    moveTo({ position, needTurnAround, isEnd }) {
+
+        // console.error(position)
+        
+        let player = this.sceneManager.avatarComponent._mainUser
+
+        let playerPos = new BABYLON.Vector3( player.position.x, player.position.y, player.position.z )
+        let playerPosNew = new BABYLON.Vector3(position.x, position.y, position.z)
+
+        let walkDistanceVec = playerPosNew.clone().subtract(playerPos)
+
+        let angle = BABYLON.Vector3.GetAngleBetweenVectors(new BABYLON.Vector3(0, -1, 0), walkDistanceVec, new BABYLON.Vector3(0, 0, 1))
+        let rotationQuaternion = BABYLON.Quaternion.RotationAxis( new BABYLON.Vector3(0, 0, 1), angle )
+        let playerRotaTemp = rotationQuaternion.toEulerAngles()
+        playerRotaTemp = new BABYLON.Vector3(playerRotaTemp.x, playerRotaTemp.z, playerRotaTemp.y)  // 因为是用ue4pos算的,需要矫正一下
+        let playerRotaNew = util.xverseRotation2Ue4(playerRotaTemp)
+
+        let cameraPosTemp = util.xversePosition2Ue4(this.sceneManager.cameraComponent.mainCamera.position)
+        let cameraPos = new BABYLON.Vector3( cameraPosTemp.x, cameraPosTemp.y, cameraPosTemp.z )
+        let cameraPosNew = cameraPos.add(walkDistanceVec)
+
+        let cameraRota = util.xverseRotation2Ue4(this.sceneManager.cameraComponent.mainCamera.rotation)
+        
+        if(player.position){
+            let response = JSON.parse(JSON.stringify(Response))
+
+            response.signal.newUserStates[0].userId = player.id
+    
+            response.signal.newUserStates[0].playerState.player.position.x = playerPosNew.x
+            response.signal.newUserStates[0].playerState.player.position.y = playerPosNew.y
+            response.signal.newUserStates[0].playerState.player.position.z = playerPosNew.z
+    
+            response.signal.newUserStates[0].playerState.player.angle.pitch = player.rotation.pitch
+            response.signal.newUserStates[0].playerState.player.angle.yaw = needTurnAround ? playerRotaNew.yaw : player.rotation.yaw
+            response.signal.newUserStates[0].playerState.player.angle.roll = player.rotation.roll
+    
+            response.signal.newUserStates[0].playerState.camera.position.x = cameraPosNew.x
+            response.signal.newUserStates[0].playerState.camera.position.y = cameraPosNew.y
+            response.signal.newUserStates[0].playerState.camera.position.z = cameraPosNew.z
+            
+            response.signal.newUserStates[0].playerState.camera.angle.pitch = cameraRota.pitch
+            response.signal.newUserStates[0].playerState.camera.angle.yaw = cameraRota.yaw
+            response.signal.newUserStates[0].playerState.camera.angle.roll = cameraRota.roll
+    
+            response.signal.newUserStates[0].playerState.cameraCenter.x = playerPosNew.x
+            response.signal.newUserStates[0].playerState.cameraCenter.y = playerPosNew.y
+            response.signal.newUserStates[0].playerState.cameraCenter.z = playerPosNew.z
+
+            // 用于人物动画更新
+            response.signal.newUserStates[0].renderInfo.isMoving = !isEnd
+            
+            console.log('角色行走')
+            this.signal.handleSignal(response)
+        }
+    }
+
     get currentNetworkOptions() {
         return this._currentNetworkOptions
     }

+ 41 - 0
src/connection.js

@@ -0,0 +1,41 @@
+// import { io } from "https://cdn.socket.io/4.4.1/socket.io.esm.min.js";
+
+export class Connection {
+  constructor(config) {
+    socket: null;
+    client: null;
+    userSig: null;
+    this.init(config);
+  }
+
+  startSocket(config) {
+    //192.168.0.52:9099/?userId=123
+    console.log("init-startSocket");
+    const {  sceneCode, userId } = config;
+    const socketUrl ='wss://demo-kms.4dage.com'
+    // const socketUrl ='ws://192.168.0.152:9099'
+    this.socket = io(socketUrl, {
+      reconnectionDelayMax: 10000,
+      transports: ["websocket"],
+      query: {
+        userId: userId,
+        sceneCode: sceneCode,
+      },
+    });
+    this.socket.on("connect", (data) => {
+      console.log("111", data);
+    });
+    this.socket.on("connect_error", (error) => {
+      console.log("error", error);
+    });
+
+    // setTimeout(() => {
+    //   console.log("this.socket", this.socket);
+    // }, 3000);
+  }
+
+   init(config) {
+    console.log("init-trtc",config);
+    this.startSocket(config);
+  }
+}

+ 193 - 0
src/srsRtc.js

@@ -0,0 +1,193 @@
+export class SrsRTC {
+  constructor(url) {
+    this.stream = new MediaStream();
+    this.url = url;
+    this.offer = null;
+
+    const supportsInsertableStreams =
+      !!RTCRtpSender.prototype.createEncodedStreams;
+    console.log("supportsInsertableStreams", supportsInsertableStreams);
+    // this.pc.ontrack =  (event) => {
+    //         // https://webrtc.org/getting-started/remote-streams
+    //     console.warn('event',event.track)
+    //     if(this.stream){
+    //         this.stream.addTrack(event.track);
+    //     }
+    // };
+
+    this.pc = new RTCPeerConnection({
+      encodedInsertableStreams: true,
+    });
+    this.pc.addEventListener("icecandidate", (e) =>
+      this.onIceCandidate(this.pc, e)
+    );
+    this.pc.addEventListener("datachannel", this.ondatachannel);
+    // var dc = this.pc.createDataChannel("datachannel");
+    // dc.onmessage = function (event) {
+    //   console.log("received: " + event.data);
+    // };
+
+    // dc.onopen = function () {
+    //   console.log("datachannel open");
+    // };
+
+    // dc.onclose = function () {
+    //   console.log("datachannel close");
+    // };
+    // this.pc.ondatachannel = (event) => {
+    //   console.log("ondatachannel", event);
+    //   //   this.inputChannel.onopen = () => {
+    //   //     console.log("连接");
+    //   //   };
+    //   //   this.inputChannel.onmessage = (event) => {
+    //   //     // mark00 rtcp接收
+    //   //     console.log("连接", event);
+    //   //   };
+    //   //   this.inputChannel.close = (event) => {
+    //   //     // mark00 rtcp接收
+    //   //     console.log("close", event);
+    //   //   };
+    // };
+  }
+  onIceCandidate(event) {
+    // console.warn("icecandidate", event);
+  }
+  ondatachannel(event) {
+    console.warn("ondatachannel", ondatachannel);
+  }
+
+  close() {
+    var remoteVideo = document.querySelector("#testVideoFeed");
+    if (remoteVideo.srcObject) {
+      remoteVideo.srcObject.getTracks().forEach((track) => track.stop());
+    }
+    this.pc && this.pc.close();
+    this.pc = null;
+  }
+
+  async start(clipUrl) {
+    this.pc.addTransceiver("video", { direction: "recvonly" });
+    const serverApi = "https://demo-kms.4dage.com:443/rtc/v1/play/";
+    const tid = Number(parseInt(new Date().getTime() * Math.random() * 100))
+      .toString(16)
+      .slice(0, 7);
+    var offer = await this.pc.createOffer();
+    await this.pc.setLocalDescription(offer);
+    const session = await new Promise(function (resolve, reject) {
+      // @see https://github.com/rtcdn/rtcdn-draft
+      var data = {
+        api: serverApi,
+        tid: tid,
+        streamurl: clipUrl,
+        clientip: null,
+        sdp: offer.sdp,
+      };
+      console.log("Generated offer: ", data);
+      $.ajax({
+        type: "POST",
+        url: serverApi,
+        data: JSON.stringify(data),
+        contentType: "application/json",
+        dataType: "json",
+      })
+        .done(function (data) {
+          console.log("Got answer: ", data);
+          if (data.code) {
+            reject(data);
+            return;
+          }
+
+          resolve(data);
+        })
+        .fail(function (reason) {
+          reject(reason);
+        });
+    });
+    await this.pc.setRemoteDescription(
+      new RTCSessionDescription({ type: "answer", sdp: session.sdp })
+    );
+  }
+
+  async getVideo(clipUrl) {
+    if (!this.pc) {
+      this.pc = new RTCPeerConnection(null);
+      this.pc.ontrack = (event) => {
+        // https://webrtc.org/getting-started/remote-streams
+        console.log("event", event);
+        if (this.stream) {
+          // this.stream.removeTrack(event.track));
+          const videoTrack = this.stream
+            .getVideoTracks()
+            .find((i) => i.kind === "video");
+          console.log("旧videoTrack", videoTrack);
+          if (videoTrack) {
+            this.stream.removeTrack(videoTrack);
+          }
+          // if(this.stream.removeTrack())
+          this.stream.addTrack(event.track);
+        }
+        //    mediaRecorder.
+      };
+
+      this.pc.ondatachannel = (event) => {
+        console.log("ondatachannel", ondatachannel);
+        this.inputChannel.onopen = () => {
+          console.log("连接");
+        };
+        this.inputChannel.onmessage = (event) => {
+          // mark00 rtcp接收
+          console.log("连接", event);
+        };
+        this.inputChannel.close = (event) => {
+          // mark00 rtcp接收
+          console.log("close", event);
+        };
+      };
+    }
+
+    this.pc.addTransceiver("video", { direction: "recvonly" });
+
+    const serverApi = "https://demo-kms.4dage.com:443/rtc/v1/play/";
+    const tid = Number(parseInt(new Date().getTime() * Math.random() * 100))
+      .toString(16)
+      .slice(0, 7);
+    var offer = await this.pc.createOffer();
+    this.offer = offer;
+    await this.pc.setLocalDescription(offer);
+    const session = await new Promise(function (resolve, reject) {
+      // @see https://github.com/rtcdn/rtcdn-draft
+      var data = {
+        api: serverApi,
+        tid: tid,
+        streamurl: clipUrl,
+        clientip: null,
+        sdp: offer.sdp,
+      };
+      console.log("Generated offer: ", data);
+      $.ajax({
+        type: "POST",
+        url: serverApi,
+        data: JSON.stringify(data),
+        contentType: "application/json",
+        dataType: "json",
+      })
+        .done(function (data) {
+          console.log("Got answer: ", data);
+          if (data.code) {
+            reject(data);
+            return;
+          }
+
+          resolve(data);
+        })
+        .fail(function (reason) {
+          reject(reason);
+        });
+    });
+    await this.pc.setRemoteDescription(
+      new RTCSessionDescription({ type: "answer", sdp: session.sdp })
+    );
+
+    return session;
+  }
+}