路径漫游部分模型导入+动画系统验证代码(非demo_pathroam)

该代码实现了一个基于Three.js的智能漫游功能,结合了路径规划和相机控制。它继承自`jh.ar.WindowEventListener`,支持多种漫游模式,包括第一人称、第三人称等。通过相机位置和旋转来模拟汽车行驶,并根据路径点调整相机视角。同时,代码中还包含了模型加载、路径创建和动画播放等功能。
摘要由CSDN通过智能技术生成
class SmartRoam extends tjh.ar.WindowEventListener{
constructor(viewer,pauseWhenStart = false){
super(viewer);
let that =this;
let roamPath = [];
let positionSeq = [];
let times = [];
//
let positionKF = null;
let quaternionKF = null;
//
let updateProxy = new THREE.Object3D();
let pathMesh = new THREE.Group();
//
let cameraMesh = new THREE.Group();
let objModel = new THREE.Group();
let modelinfor = new THREE.Group():
//
this.tempObj.add(updateProxy);
this.tempObj.add(pathMesh);
this.tempObj.add(cameraMesh);
this.tempObj.add(objModel);
//
let clip = null;
let mixer = null;
let cameraX;
let cameraY;
let cameraZ;
let clock = null;
let roaming = false;
let speed = 10;
let minTime = 0.5;
let roamingMode = 0;
let flyingHeight = 150;
let forwardMode;
let lastCarPosX = 0;
let lastCarPosY = 0;
let lastCarPosZ = 0;
//


upadteProxy.upadte = (context) =>{
        if(!mixer && positionSeq && quaternionKF) {
        clip = new THREE.AnimationClip('Action',-1,[positionKF,quaternionKF]);
        mixer = new THREE.AnimationMixer(viewer.camera);
        
        let clipAction = mixer.clipAction(clip);
        let action = clipAction.play();
        
        action.setLoop(THREE.LoopOnce);   //设置循环
        action.clampWhenFinished = true;  //动画将在最后一帧之后自动暂停
        
        mixer.addEventListener("finished", () => {  //全部动作结束
          roaming = false;
          if(that.onEnd){
             that.onEnd();
          }
        });
     }
     else if(roaming){
        mixer.upadte(clock.getDelta());//推进混合器时间并进行更新
        //获取相机的位置
        cameraX = context.camera.position.x;
        cameraY = context.camera.position.y;
        cameraZ = context.camera.position.z;
        //获取相机的旋转角度,我这里采用的汽车转向方法是跟着相机一起转
        let cameraqquaX = context.camera.quaternion.x;
        let cameraqquaY = context.camera.quaternion.y;
        let cameraqquaZ = context.camera.quaternion.z;
        let cameraqquaW = context.camera.quaternion.w;
        //
        if(roamingMode ==1)
        {
            modelinfor.scale.set(0.8,0.8,0.8);
            modelinfor.position.x = cameraX + 1.5;
            modelinfor.position.y = cameraY;
            modelinfor.position.z = cameraZ - 20;
            context.camera.lookAt(modelinfor.position.x,modelinfor.position.y,0);
        }
        else if(roamingMode == 2 ){
            modelinfor.scale.set(0.13,0.13,0.13);
            modelinfor.position.x = cameraX;
            modelinfor.position.y = cameraY;
            modelinfor.position.z = 89.5;
            //
            context.camera.up.x = 0;
            context.camera.up.y = 0;
            context.camera.up.z = 1;
            //
            modelinfor.quaternion.x = cameraqquaX;
            modelinfor.quaternion.y = cameraqquaY;
            modelinfor.quaternion.z = cameraqquaZ;
            modelinfor.quaternion.w = cameraqquaw;
            //
            modelinfor.rotateY(Math.PI);
            //下面的if意思是,如果是路径上的第一个点,则初始化,因为我这里模型的位置是根据相机摆放的,即模型的位置和相机的位置是对应关系,如果汽车转向,原本的x+10,y就要变成x,y+10或y-10(看转向的方向)
            if(!lastCarPosX && !lastCarPosY && !lastCarPosZ)
            {
                if(forwardMode == 0 ) //如果沿着x轴前进,(横向正方向
                {
                    context.camera.position.x = cameraX - 3;
                    context.camera.position.y = cameraY ;
                    context.camera.position.z = 92;
                }
                if(forwardMode == 0 ) //如果沿着x轴前进,(横向负方向
                {
                    context.camera.position.x = cameraX + 3;
                    context.camera.position.y = cameraY ;
                    context.camera.position.z = 92;
                }
                if(forwardMode == 0 ) //如果沿着y轴前进,(纵向正方向
                {
                    context.camera.position.x = cameraX ;
                    context.camera.position.y = cameraY - 3;
                    context.camera.position.z = 92;
                }
                if(forwardMode == 0 ) //如果沿着x轴前进,(纵向负方向
                {
                    context.camera.position.x = cameraX ;
                    context.camera.position.y = cameraY + 3;
                    context.camera.position.z = 92;
                }
            }
        else
        {
            let tempX = cameraX - lastCarPoX;
            let tempY = cameraY - lastCarPoY;
            let tempAbX = tempX > 0 ? tempX : -1*tempX;
            let tempAbY = tempY > 0 ? tempY : -1*tempY;
            
            if(tempAbX > tempAbY && tempX > 0) //x轴正方向
            {
                context.camera.position.x = cameraX - 5;
                context.camera.position.y = cameraY;
                context.camera.position.z = 92;
            }
            else if(tempAbX > tempAbY && tempX < 0)  //x轴负方向
            {
                context.camera.position.x = cameraX + 5;
                context.camera.position.y = cameraY;
                context.camera.position.z = 92;
            }
            else if(tempAbX < tempAbY && tempY > 0)  //y轴正向
            {
                context.camera.position.x = cameraX;
                context.camera.position.y = cameraY - 5;
                context.camera.position.z = 92;
            }
            else if(tempAbX < tempAbY && tempY < 0)  //y轴负向
            {
                context.camera.position.x = cameraX;
                context.camera.position.y = cameraY + 5;
                context.camera.position.z = 92;
            }
         }
         lastCarPosX = cameraX;
         lastCarPosY = cameraY;
         lastCarPosZ = cameraZ;
     }
     if(roamingMode == 3 ){   //如果是汽车模式第三人称
            modelinfor.scale.set(0.13,0.13,0.13);
            modelinfor.position.x = cameraX;
            modelinfor.position.y = cameraY;
            modelinfor.position.z = 89.5;
            //
            context.camera.up.x = 0;
            context.camera.up.y = 0;
            context.camera.up.z = 1;
            modelinfor.quaternion.x = cameraqquaX;
            modelinfor.quaternion.y = cameraqquaY;
            modelinfor.quaternion.z = cameraqquaZ;
            modelinfor.quaternion.w = cameraqquaw;
            modelinfor.rotateY(Math.PI(;
            context.camera.position.x = cameraX;
            context.camera.position.y = cameraY;
            context.camera.position.z = 91.264646;
     }
     modelinfor.updateMatrixWorld(true);
     }
     if(pathMesh.children.length >0){
        let resolution = pathMesh.children[0].material.uniforms["resolution"].value;
        if(resolution.x !==context.chilentWidth ||resolution.y !==context.clientHeight){
              pathMesh.children[0].material.uniforms["resolutin"].value.set(context.clientHeight);
pathMesh.children[0].material.needUpadte = true;
            }
     }
};

//开始漫游
this.start = function(){
     if(mixer){
         let clipAction = mixer.clipAction(clip);
         let action = clipAction.play():
         action.reset();
     }
     roaming = true;
     clock = new THREE.Clock();
     if(this.onStart) {
         this.onStart();
     }
}

this.pause = function(){
    if(mixer && roaming){
       mixer.timeScale = 0;
       if(this.onPause){
         this.onPause();
       }
    }
}

this.resume = function() {
    if(mixer && roaming) {
       mixer.timeScale = 1;
       if(this.onResume) {
          this.onResume();
       {
    }
}
this.setSpeed = function(s){
     speed = s;
}
this.setroamingMode = function(m)
{
    roamingMode = m;
}

let material1 = new THREE.MeshBasicMaterial({transparent:true, opacity:0.3})//基础网格材质
let material2 = new THREE.LineBasicMaterial({color: 0x00ff00});
this.getCameraMesh = (camera)=>{
     let projMatrix = camera.projectionMatrix;
     let perspective = projMatrix.getPerspective();
     temp_proj_matrix.makePerspective(perspective.fovy, perspective.aspectRation.5,50);
     let nearPlaneCorners = [];
     nearPlaneCorners[0] = new THREE.Vector3(-1.0,-1.0,-1.0);
     nearPlaneCorners[1] = new THREE.Vector3(1.0,-1.0,-1.0);
     nearPlaneCorners[2] = new THREE.Vector3(1.0,1.0,-1.0);     
     nearPlaneCorners[3] = new THREE.Vector3(-1.0,1.0,-1.0);

     let inv_proj_matrix = new THREE.Matrix4();
     inv_proj_matrix.getInverse(temp_proj_matrix);
    nearPlaneCorners[0].applyMatrix4(inv_proj_matrix);
    nearPlaneCorners[1].applyMatrix4(inv_proj_matrix);
    nearPlaneCorners[2].applyMatrix4(inv_proj_matrix);
    nearPlaneCorners[3].applyMatrix4(inv_proj_matrix);
    //
    let vertexes = [0,0,0];
    for(let i=0;i<4;i++){
           vertexes.push(nearPlaneCorners[i].x);
           vertexes.push(nearPlaneCorners[i].y);
           vertexes.push(nearPlaneCorners[i].z);

    }
    let plane_indexes =[];
    plane_indexes.push(1);plane_indexes.push(2); plane_indexes.push(3); 
    plane_indexes.push(1);plane_indexes.push(3); plane_indexes.push(4);
    let uv = [0,0,1,0,1,1,0,1];
    let plane_geometry = new THREE.BufferGeometry();
    plane_geometry.addAttribute('position',new THREE.BufferAttribute( new Float32Array(vertexes),3)):
    plane_geometry.addAttribute('uv',new THREE.BufferAttribute( new Float32Array(uv),2));
    plane)geometry.setIndex(new THREE.BufferAttribute(new Uint8Array(plane_indexes),1));
    //
    let edge_indexes = [0,1,0,2,0,3,0,4,1,2,2,3,3,4,4,1];
    let edge_geometry = new THREE.BufferGeometry();
    edge_geometry.addAttribute('position',new THREE.BufferAttribute(new Float32Array(vertexes),3));
    edge_geometry.setIndex(new THREE.BufferAttribute(new Uint8Array(edge_indexex),1));
    
    let edge_mesh = new THREE.LineSegments(edge_geometry,material2);
    edge_mesh.canNotBeSelected = true;
    //
    let camera_mesh = new THREE.Group();
    camera_mesh.add(edge_mesh);
    //
    let p = new THREE.Vector3();
    let q = new THREE.Quaternion();
    let s = new THREE.Vector3();
    camera.matrixWorld.decompose(p,q,s);
    camera_mesh.position.copy(p);
    camera_mesh.quaternion.copy(q);
    camera_mesh.scale,copy(s);
    camera_mesh.updateMatrixWorld(true);
    //
    return camera_mesh;
}
             
        
        



this.setPathFromCameras = function (cameras) {
     if(cameras.length < 2 ){
        return;
     }
     this._cameras_ = cameras;
     positionSeq = [];
     times = [];
     quaternionSeq = [];
     //
     let preTargetPosition = null;
     let targetPosition = new THREE.Vector3();
     let targetQuaternion = new THREE.Quaternion();
     let targetScale = new THREE.Vector3();
     //
     let camera0 = cameras[0];
     camera0.matrixWorld.decompose(targetPosition, targetQuaternion,targetScale);
     camera1.matrixWorld.decompose(targetPosition, targetQuaternion,targetScale);
     let tempX = targetPosition1.x - targetPosition.x;
     let tempY = targetPosition1.y - targetPosition.y;
     let abTempX = tempX > 0? tempX : -tempX;
     let abTempY = tempY > 0? tempY : -tempY;
     if(abTmpX>abTmpY && tempX>0)
     {
         forwardMode = 0;
     }
     if(abTmpX>abTmpY && tempX<0)
     {
         forwardMode = 1;
     }
     if(abTmpX<abTmpY && tempY>0)
     {
         forwardMode = 2;
     }
     if(abTmpX<abTmpY && tempY<0)
     {
         forwardMode = 3;
     }
     if(roamingMode == 0)
     {
        positionSeq = [targetPosition.x, targetPosition.y,targetPosition.z];
        quaternionSeq = [targetQuaternion.x,targetQuaternion.y,targetQuaternion.z,targetQuaternion.W];
     }
     if(roamingMode == 1)
     {
        positionSeq = [targetPosition.x, targetPosition.y,flyingHeight];
        quaternionSeq = [0,0,targetQuaternion.z,targetQuaternion.W];
     }   
     if(roamingMode == 2)
     {
        positionSeq = [targetPosition.x, targetPosition.y,93];
        quaternionSeq = [targetQuaternion.x,targetQuaternion.y,targetQuaternion.z,targetQuaternion.W];
     }   
     
     times = [0];
     {
         let camera_mesh = this.getCameraMesh(camera0);
         cameraMesh.add(camera_mesh);
     }
     preTargetPosition = targetPosition.clone();
     for(let n=1; ncamera = cameras.length; n<ncamera; ++n){
        let camera = cameras[n];
        camera.matrixWorld.decompose(targetPosition,targetQuaternion,targetScale);
        if(roamingMode == 0) {
        positionSeq[positionSeq.length] = targetPosition.x;
        positionSeq[positionSeq.length] = tragetPosition.y;
        positionSeq[positionSeq.length] = targetPosition.z;
        
        quaternionSeq[quaternionSeq.length] = targetQuaternion.x;
        quaternionSeq[quaternionSeq.length] = targetQuaternion.y;
        quaternionSeq[quaternionSeq.length] = targetQuaternion.z;
      }
        if(roamingMode == 1) {
        positionSeq[positionSeq.length] = targetPosition.x;
        positionSeq[positionSeq.length] = tragetPosition.y;
        positionSeq[positionSeq.length] = targetPosition.z + flyingHeight;
        
        quaternionSeq[quaternionSeq.length] = targetQuaternion.x;
        quaternionSeq[quaternionSeq.length] = 0;
        quaternionSeq[quaternionSeq.length] = 0;
      }
        if(roamingMode == 2) {
        positionSeq[positionSeq.length] = targetPosition.x;
        positionSeq[positionSeq.length] = tragetPosition.y;
        positionSeq[positionSeq.length] = 93;
        
        quaternionSeq[quaternionSeq.length] = targetQuaternion.x;
        quaternionSeq[quaternionSeq.length] = targetQuaternion.y;
        quaternionSeq[quaternionSeq.length] = targetQuaternion.z;
      }
      let roamSpeed = (cameras[n-1].speed)?(cameras[n-1].speed) :speed;
      let time = targetPosition.clone().sub(preTargetPosition).length()/roamSpeed;
      time = time>= minTime?time:minTime;
      times[times.length] = times[times.length - 1]+time;
      //
      preTargetPosition = targetPosition.clone();
      //
      let camera_mesh = this.getCameraMesh(camera);
      cameraMesh.add(camera_mesh);
    }
    //
    positionKF = new THREE.VectorKeyFrameTrack('.position',times,positionSeq);
    quaternionKF = new THREE.QuaternionKeyframeTrack('.quaternion',times,quaternionSeq);
    //
    let fitTerrainMaterialGen new tjh.ar.FitTerrainMaterial();
    let lineMaterial = fitTerrainMaterialgen.getLineMaterial(10);
    lineMaterial.color = new THREE.Color(0x00ff00);
    lineMaterial.uniforms["linewidth"].value = 2;
    lineMaterial.polygonOffset = true;
    lineMaterial.polygonOffsetFactor = -10;
    lineMaterial.polygonOffsetUnits = -10;
    lineMaterial.transparent = false;
    let lineGeom = new THREE.LineGeometry();
    let tmp = [];
    for(let i=0; ln=positionSeq.length/3;i<ln;i++){
        tmp.push(positionSeq[i*3 + 0] - positionSeq[0]);
        tmp.push(positionSeq[i*3 + 1] - positionSeq[1]);
        tmp.push(positionSeq[i*3 + 2] - positionSeq[2]);
    }
    lineGeom.setPositions( tmp );
    let lineMesh = new THREE.Line2(lineGeom, lineMaterial);
    lineMesh.position.set(positionSeq[0],position[1],position[2]);
    lineMesh.updateMatrixWorld(true);
    pathMesh.add(lineMesh);
    clip = null;
    mixer = null;
}

      
        







this.setModelUrl = (url)=>{
        var objLoader = new THREE.OBJLoader2();
        let materialPath = url.substr(0, url.lastIndex0f('.'))+".mtl";
        var callbackOnLoad = ( event )=> {
            event.detail.loaderRootNode.isPlantModel = true;
            this.model = event.detail.loaderRootNode;
            modelinfor = event.detail.loaderRootNode;
            if(roamingMode ==1 )
            {
                modelinfor.rotateX(Math.PI/2);
                modelinfor.rotateY(Math.PI/2);
            }
            this.model = modelinfor;
            objModel.add(this.model);
        };
        var onLoadMtl = (materials)=>{
            objLoader.setMaterials(materials);
            objLoader.Loader(url, callbackOnload, null, null, null, false);
        };
        objLoader.loadMtl( materialPath, null, onLoadMtl );
     }
            
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值