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 );
}
}
路径漫游部分模型导入+动画系统验证代码(非demo_pathroam)
最新推荐文章于 2022-12-23 16:22:20 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)