123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- import * as THREE from 'three';
- import {GLTFLoader} from "three/addons/loaders/GLTFLoader.js";
- import List from '../../config/routeList.json'
- import texture1 from "../../assets/arrow2.png";
- export const FlyGLTFClass = {
- constructor(options){
- this.webgl = options.webgl;
- this.view = options.view;
- this.mixer = options.mixer;
- this.airCraftMixer = options.airCraftMixer;
- this.clock = options.clock;
- this.airCraftClock = options.airCraftClock;
- this.path = options.path; //路径点
- this.pathProgress = options.pathProgress; //路径速度
- this.pathCurve = options.pathCurve; //路径曲线
- this.targetObject = options.targetObject; //路径飞行的目标对象
- this._camera = options._camera;
- this.raycaster = options.raycaster; // 射线投射器
- this.mouse = options.mouse; // 鼠标位置
- this.callBackFunction = options.callBackFunction; // 回调函数
- this.mouseClickEvent = null;
- this.uavid = options.uavid;
- },
- initialize(){
- this.mixer = new THREE.AnimationMixer();
- this.airCraftMixer = new THREE.AnimationMixer();
- this.clock = new THREE.Clock();
- this.airCraftClock = new THREE.Clock();
- this.renderer = new THREE.WebGLRenderer({
- context:this.gl,
- premultipliedAlpha: false
- });
- this.renderer.setPixelRatio(window.devicePixelRatio);
- this.renderer.setViewport(0,0,this.view.width,this.view.height);
- this.renderer.autoClear = false;
- this.renderer.autoClearDepth = false;
- this.renderer.autoClearColor = false;
- let originalSetRenderTarget = this.renderer.setRenderTarget.bind(this.renderer);
- this.renderer.setRenderTarget = function(target){
- originalSetRenderTarget(target);
- if(target){
- this.bindRenderTarget()
- }
- }
- this.scene = new THREE.Scene();
- let cam = this.camera;
- this._camera = new THREE.PerspectiveCamera(cam.fovY,cam.aspect,cam.near,cam.far);
- //添加坐标轴辅助工具
- const axesHelper = new THREE.AxesHelper(1);
- axesHelper.position.set(1000000,1000000,1000000);
- this.scene.add(axesHelper);
- const grid = new THREE.GridHelper(30,10,0xf0f0f0,0xffffff);
- this.scene.add(grid);
- this.ambient = new THREE.AmbientLight(0xffffff,5);
- this.scene.add(this.ambient);
- this.loadGLTF();
- //初始化路径曲线
- //this.initPathCurve();
- this.resetWebGLState();
- this.mouseClickEvent = this.view.on("click", this.onMouseClick.bind(this));
- },
- loadGLTF(){
- const loader = new GLTFLoader();
- let that = this;
- loader.load('public/gltf/mtwrj.glb', function (gltf) {
- gltf.scene.scale.set(6, 6, 6);
- that.scene.add(gltf.scene);
- that.targetObject = gltf.scene;
- // 添加动画
- that.mixer = new THREE.AnimationMixer(gltf.scene);
- const AnimationAction = that.mixer.clipAction(gltf.animations[0]);
- AnimationAction.play();
- // 创建信息面板
- // const panelGeometry = new THREE.PlaneGeometry(3.5, 3.5); // 面板大小
- // const canvas = document.createElement('canvas');
- // const context = canvas.getContext('2d');
- // // 加载背景图片
- // const backgroundImage = new Image();
- // backgroundImage.src = 'public/imgs/serviceBackground.png'; // 替换为你的图片路径
- // backgroundImage.onload = () => {
- // // 确保背景透明
- // context.clearRect(0, 0, canvas.width, canvas.height); // 清除所有内容,包含黑色
- // context.fillStyle = 'rgba(0, 0, 0, 0)'; // 设置透明背景
- // context.fillRect(0, 0, canvas.width, canvas.height); // 填充透明背景
- //
- // context.save();
- // context.scale(-1, 1);
- // context.translate(-canvas.width, 0);
- // // 绘制背景图片,填满整个 canvas
- // context.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
- //
- // // // 绘制文字信息
- // // context.fillStyle = '#fff';
- // // context.font = 'normal 15px Arial';
- // // context.fillText('无人机信息:',40, 25);
- // // context.fillText('无人机名称: 无人机1号', 40, 50);
- // // context.fillText('所属企业: 美团', 40, 70);
- // // context.fillText('速度: 100km/h', 40, 90);
- // // context.fillText('高度: 200m', 40, 110);
- // // context.fillText('状态: 正常',40, 130);
- //
- //
- // const textInfo = [
- // { text: '无人机信息: ', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 25 },
- // { text: '无人机名称:'+this.panelInfo.data.name, color: '#fff', font: '15px Arial', offsetX:40, offsetY: 50 },
- // { text: '所属企业: 美团: ', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 70 },
- // { text: '速度: '+Math.floor(this.panelInfo.data.speed * 3.6)+'km/h',color: '#fff', font: '15px Arial', offsetX:40, offsetY: 90 },
- // { text: '高度: '+ this.panelInfo.data.altitude+'m', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 110 },
- // { text: '状态: 正常',color: '#fff',font: '15px Arial', offsetX:40, offsetY: 130 }
- // ];
- // // 绘制文字
- // textInfo.forEach((line) => {
- // context.fillStyle = line.color;
- // context.font = line.font;
- // context.fillText(line.text, line.offsetX, line.offsetY);
- // });
- //
- //
- // // 标记纹理需要更新
- // texture.needsUpdate = true;
- // };
- //
- // const texture = new THREE.CanvasTexture(canvas);
- // const panelMaterial = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide, transparent: true });
- // panelGeometry.scale(-1,1,1);
- // const panelMesh = new THREE.Mesh(panelGeometry, panelMaterial);
- // // 将面板附加到无人机模型
- // panelMesh.position.set(0, 2.5, 0); // 调整面板位置到无人机上方
- // gltf.scene.add(panelMesh);
- //
- // // 保存信息面板,以便更新
- // that.infoPanel = { canvas, context, texture, mesh: panelMesh };
- });
- },
- // 点击事件处理函数
- onMouseClick(event) {
- // 获取点击位置的屏幕坐标
- let mouse = []
- this.webgl.toRenderCoordinates(
- this.view,
- [event.mapPoint.x, event.mapPoint.y, event.mapPoint.z],
- 0,
- this.view.spatialReference,
- mouse,
- 0,
- 1
- );
- const mousePoint = new THREE.Vector3(mouse[0], mouse[1], mouse[2]);
- // 获取摄像机位置
- const cameraPosition = new THREE.Vector3().setFromMatrixPosition(this._camera.matrixWorld);
- // 计算射线方向
- const rayDirection = new THREE.Vector3().subVectors(mousePoint, cameraPosition).normalize();
- // 设置射线起点和方向
- this.raycaster.set(cameraPosition, rayDirection);
- //this.visualizeRay()
- // 检测射线与网格的相交
- const intersects = this.raycaster.intersectObject(this.targetObject);
- if (intersects.length > 0) {
- this.callBackFunction(this.uavid);
- } else {
- console.log("未选中任何无人机");
- }
- },
- // 设置面板类似
- setPanelInfo(uavInfo) {
- this.panelInfo = uavInfo;
- },
- // 更新面板信息
- updateInfoPanel() {
- if (this.infoPanel) {
- const { canvas, context, texture ,mesh } = this.infoPanel;
- // 加载背景图片
- const backgroundImage = new Image();
- const topImage = new Image();
- const bottomImage = new Image();
- let typeInfo = "";
- switch (this.panelInfo.type){
- case "conflict":
- backgroundImage.src = 'public/imgs/基本信息框-红.png'; // 替换为你的图片路径
- topImage.src = 'public/imgs/warningBackground_time.png'; // 替换为你的图片路径
- bottomImage.src = 'public/imgs/warningBackground_conflict.png'; // 替换为你的图片路径
- typeInfo = "异常"
- break;
- case "electricityWarning":
- backgroundImage.src = 'public/imgs/基本信息框-红.png'; // 替换为你的图片路径
- typeInfo = "电池电量低"
- break;
- case "routeDeviate":
- backgroundImage.src = 'public/imgs/基本信息框-红.png'; // 替换为你的图片路径
- typeInfo = "异常"
- break;
- case "noFlyZone":
- backgroundImage.src = 'public/imgs/基本信息框-红.png'; // 替换为你的图片路径
- typeInfo = "异常"
- break;
- case "collision":
- backgroundImage.src = 'public/imgs/基本信息框-红.png'; // 替换为你的图片路径
- typeInfo = "建筑物过近"
- break;
- case "clearZone":
- backgroundImage.src = 'public/imgs/基本信息框-红.png'; // 替换为你的图片路径
- typeInfo = "净空区"
- break;
- default:
- backgroundImage.src = 'public/imgs/基本信息框.png'; // 替换为你的图片路径
- typeInfo = "正常"
- break;
- }
- // backgroundImage.src = 'public/imgs/serviceBackground.png'; // 替换为你的图片路径
- if(this.panelInfo.type == "conflict" && this.panelInfo.action == "wait"){
- topImage.onload = () => {
- bottomImage.onload = () => {
- // 确保背景透明
- context.clearRect(0, 0, canvas.width, canvas.height); // 清除所有内容,包含黑色
- context.fillStyle = 'rgba(0, 0, 0, 0)'; // 设置透明背景
- context.fillRect(0, 0, canvas.width, canvas.height); // 填充透明背景
- // 绘制顶部图片
- const topImageHeight = canvas.height * 0.2; // 设定顶部图片高度为 canvas 高度的 20%
- context.drawImage(topImage, 0, 0, canvas.width, topImageHeight);
- // 绘制底部图片
- const bottomImageHeight = canvas.height * 0.7; // 设定底部图片高度为 canvas 高度的 20%
- context.drawImage(bottomImage, 0, canvas.height - bottomImageHeight, canvas.width, bottomImageHeight);
- const textInfo = [
- { text: '暂停飞行原地等待:' + this.panelInfo.data.waitTime +'秒', color: '#fff', font: 'bold 16px Arial', offsetX:50, offsetY: 20 },
- { text: '距预测撞点前方: ', color: '#fff', font: '20px Verdana', offsetX:70, offsetY: 90 },
- { text: Math.floor(this.panelInfo.data.danger_path_distance * 1) + '米', color: '#ff0000', font: 'bold 22px Courier New', offsetX:120, offsetY: 120 }
- ];
- // 绘制文字
- textInfo.forEach((line) => {
- context.fillStyle = line.color;
- context.font = line.font;
- context.fillText(line.text, line.offsetX, line.offsetY);
- });
- // 标记纹理需要更新
- texture.needsUpdate = true;
- }
- }
- }else if(this?.panelInfo?.type == "routeDeviate"){
- //获取当前下标index
- let index = this.panelInfo.index * 1 +Math.floor(this.panelInfo.data.distance * 1 / 10) * 1 + 1;
- let targetPoint = [];
- this.webgl.toRenderCoordinates(
- this.view,
- [List.originList[index].mapX, List.originList[index].mapY, List.originList[index].mapZ],
- 0,
- this.view.spatialReference,
- targetPoint,
- 0,
- 1
- );
- this.targetPosition = new THREE.Vector3(targetPoint[0], targetPoint[1], targetPoint[2]);
- backgroundImage.onload = () => {
- // 确保背景透明
- context.clearRect(0, 0, canvas.width, canvas.height); // 清除所有内容,包含黑色
- context.fillStyle = 'rgba(0, 0, 0, 0)'; // 设置透明背景
- context.fillRect(0, 0, canvas.width, canvas.height); // 填充透明背景
- // 绘制背景图片,填满整个 canvas
- context.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
- const textInfo = [
- { text: '计划偏离: ', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 25 },
- { text: '偏离距离: '+Math.floor(this.panelInfo.data.distance* 1) +'米', color: '#ff0000', font: 'bold 22px Courier New', offsetX:70, offsetY: 60 },
- { text: '无人机正在偏离计划航线飞行', color: '#fff', font: '18px Arial', offsetX:40, offsetY: 90 },
- { text: '请及时调整飞行路线', color: '#fff', font: '18px Arial', offsetX:40, offsetY: 120 }
- ];
- // 绘制文字
- textInfo.forEach((line) => {
- context.fillStyle = line.color;
- context.font = line.font;
- context.fillText(line.text, line.offsetX, line.offsetY);
- });
- // 标记纹理需要更新
- texture.needsUpdate = true;
- };
- }else{
- backgroundImage.onload = () => {
- // 确保背景透明
- context.clearRect(0, 0, canvas.width, canvas.height); // 清除所有内容,包含黑色
- context.fillStyle = 'rgba(0, 0, 0, 0)'; // 设置透明背景
- context.fillRect(0, 0, canvas.width, canvas.height); // 填充透明背景
- // 绘制背景图片,填满整个 canvas
- context.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
- const textInfo = [
- { text: '无人机信息: ', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 25 },
- { text: '无人机名称:'+this.panelInfo.data.name, color: '#fff', font: '15px Arial', offsetX:40, offsetY: 50 },
- { text: '所属企业: 美团: ', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 70 },
- { text: '速度: '+Math.floor(this.panelInfo.data.speed * 3.6)+'km/h', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 90 },
- { text: '高度: '+ this.panelInfo.data.altitude+'m', color: '#fff', font: '15px Arial', offsetX:40, offsetY: 110 },
- { text: `状态: ${typeInfo}`, color: '#fff', font: '15px Arial', offsetX:40, offsetY: 130 }
- ];
- // 绘制文字
- textInfo.forEach((line) => {
- context.fillStyle = line.color;
- context.font = line.font;
- context.fillText(line.text, line.offsetX, line.offsetY);
- });
- // 标记纹理需要更新
- texture.needsUpdate = true;
- };
- }
- mesh.up.set(1, 0, 0); // 保持面板的 "上" 方向为 Y 轴正方向
- mesh.lookAt(this._camera.position);
- }
- },
- getClosestPointOnCurve(position, curve) {
- let closestPoint = null;
- let minDistance = Infinity;
- const points = curve.getPoints(100);
- points.forEach(point => {
- const distance = position.distanceTo(point);
- if (distance < minDistance) {
- minDistance = distance;
- closestPoint = point;
- }
- });
- return closestPoint;
- },
- setPathCurve(path,duration){
- this.path = path;
- this.pathProgress = 0; // 重置路径进度
- this.startTime = Date.now(); // 路径开始时间
- this.duration = duration || 2500;
- if(this.path.length > 1){
- //用于存储路径的点
- const points = this.path.map(point => {
- const renderPoint = [0,0,0];
- this.webgl.toRenderCoordinates(
- this.view,
- point,
- 0,
- this.view.spatialReference,
- renderPoint,
- 0,
- 1
- );
- return new THREE.Vector3(renderPoint[0],renderPoint[1],renderPoint[2]);
- });
- //创建一个CurvePath来容纳多条直线路径
- this.pathCurve = new THREE.CurvePath();
- //将路径点的相邻俩点组成一条直线添加到pathCurve中
- for(let i=0;i<points.length-1;i++){
- const line = new THREE.LineCurve3(points[i],points[i+1]);
- this.pathCurve.add(line);
- }
- //创建几何体以便在场景中可视化路径
- const geometry = new THREE.BufferGeometry().setFromPoints(this.pathCurve.getPoints(100));
- const material = new THREE.LineBasicMaterial({color:0xff0000,lineWidth:2});
- this.pathLine = new THREE.Line(geometry,material);
- this.scene.add(this.pathLine);
- if (this.recommandPathLineGroup) {
- this.scene.remove(this.recommandPathLineGroup);
- }
- if(this?.panelInfo?.type == "routeDeviate"){
- this.updateRecommandPath();
- }
- }
- },
- // 获取当前位置和方向信息
- getCurrentPositionAndDirection() {
- if (this.pathCurve && this.targetObject) {
- // 获取当前位置
- const position = this.pathCurve.getPointAt(this.pathProgress);
- // 获取切线方向
- const tangent = this.pathCurve.getTangentAt(this.pathProgress);
- // 计算目标朝向(四元数)
- this.targetObject.quaternion.setFromUnitVectors(new THREE.Vector3(0, 0, 1), tangent);
- // 获取路径进度对应的点
- const pathProgress = this.pathProgress;
- // 计算路径的总长度和每条线段的长度
- let totalLength = 0;
- const segmentLengths = [];
- const segments = [];
- for (let i = 0; i < this.path.length - 1; i++) {
- const startPoint = this.path[i];
- const endPoint = this.path[i + 1];
- const segmentLength = Math.sqrt(
- Math.pow(endPoint[0] - startPoint[0], 2) +
- Math.pow(endPoint[1] - startPoint[1], 2) +
- Math.pow(endPoint[2] - startPoint[2], 2)
- );
- segmentLengths.push(segmentLength);
- totalLength += segmentLength;
- // 存储当前线段的起点和终点
- segments.push({ start: startPoint, end: endPoint });
- }
- // 计算当前位置对应的进度在整个路径的比例
- let progress = pathProgress * totalLength;
- let currentSegmentIndex = 0;
- let accumulatedLength = 0;
- // 判断当前进度所在的线段
- for (let i = 0; i < segmentLengths.length; i++) {
- accumulatedLength += segmentLengths[i];
- if (progress <= accumulatedLength) {
- currentSegmentIndex = i;
- break;
- }
- }
- // 获取当前所在的线段
- const currentSegment = segments[currentSegmentIndex];
- const segmentStart = currentSegment.start;
- const segmentEnd = currentSegment.end;
- return {
- position: position, // 当前坐标
- tangent: tangent, // 当前切线方向
- rotation: this.targetObject.rotation, // 当前旋转信息(朝向)
- pathProgress: this.pathProgress, // 当前路径进度
- currentSegment: { start: segmentStart, end: segmentEnd } // 当前所在的线段
- };
- }
- return null;
- },
- // 设置悬停状态
- setHovering(isHovering) {
- this.isHovering = isHovering;
- },
- updatePosition(){
- const currentTime = Date.now();
- const elapsedTime = currentTime - this.startTime; // 已经过的时间
- // 计算路径进度
- this.pathProgress = elapsedTime / this.duration;
- if (this.pathCurve && this.targetObject) {
- // 如果到达终点,重置路径并请求新路径
- if (this.pathProgress >= 1) {
- this.pathProgress = 1; // 确保进度不超过 1
- }
- try{
- const position = this.pathCurve.getPointAt(this.pathProgress);
- const tangent = this.pathCurve.getTangentAt(this.pathProgress);
- this.targetObject.position.copy(position);
- this.targetObject.quaternion.setFromUnitVectors(
- new THREE.Vector3(0, 0, 1), tangent
- );
- }catch(e){
- console.log("this.pathProgress",this.pathProgress)
- }
- }
- //this.targetObject.rotation.x = -Math.PI/2;
- this.targetObject.rotation.y = 0;
- this.targetObject.rotation.z = -Math.PI/2;
- if (this.recommandPathLineGroup) {
- this.map.offset.y -= 0.1;
- }
- },
- updateRecommandPath() {
- // 如果已存在曲线或管道,将其从场景中移除
- if (this.recommandPathLineGroup) {
- this.scene.remove(this.recommandPathLineGroup);
- }
- let startPoint = this.pathCurve.getPointAt(this.pathProgress);
- let endPoint = this.targetPosition;
- // 创建两个点之间的中间控制点
- const midPoint1 = new THREE.Vector3(
- (2 * startPoint.x + endPoint.x) / 3,
- (2 * startPoint.y + endPoint.y) / 3 + 5, // 可调整中间点的高度
- (2 * startPoint.z + endPoint.z) / 3
- );
- const midPoint2 = new THREE.Vector3(
- (startPoint.x + 2 * endPoint.x) / 3,
- (startPoint.y + 2 * endPoint.y) / 3 + 5, // 可调整中间点的高度
- (startPoint.z + 2 * endPoint.z) / 3
- );
- // 使用 CatmullRomCurve3 创建一条平滑曲线
- const curve = new THREE.CatmullRomCurve3([
- startPoint,
- midPoint1,
- midPoint2,
- endPoint
- ]);
- // 设置传送带的宽度
- const width = 5;
- // 创建纹理
- let textureLoader = new THREE.TextureLoader();
- this.map = textureLoader.load(texture1);
- // 贴图颜色空间校正
- this.map.encoding = THREE.sRGBEncoding;
- this.map.wrapS = THREE.RepeatWrapping;
- this.map.wrapT = THREE.RepeatWrapping;
- this.map.repeat.set(1, 1);
- // 材质使用 MeshBasicMaterial(无需光源)
- const material = new THREE.MeshBasicMaterial({
- map: this.map,
- transparent: true,
- opacity: 1,
- side: THREE.DoubleSide,
- });
- // 创建一个组来存放所有的分段
- this.recommandPathLineGroup = new THREE.Group();
- // 动态分段数计算
- const pathLength = curve.getLength(); // 获取路径总长度
- const segmentLength = 5; // 每段的目标长度
- const segments = Math.max(2, Math.ceil(pathLength / segmentLength)); // 确保至少分成2段
- const step = 1 / segments;
- for (let i = 0; i < segments; i++) {
- const t1 = i * step;
- const t2 = (i + 1) * step;
- // 获取当前段的起点和终点
- const point1 = curve.getPointAt(t1);
- const point2 = curve.getPointAt(t2);
- // 创建平面
- const planeGeometry = new THREE.PlaneGeometry(width, segmentLength);
- const plane = new THREE.Mesh(planeGeometry, material);
- // 设置平面的位置和旋转
- plane.position.copy(point1.clone().add(point2).multiplyScalar(0.5)); // 平面中心
- plane.lookAt(point2); // 让平面朝向下一个点
- plane.rotateX(Math.PI / 2); // 使平面与路径对齐
- plane.rotateY(Math.PI / 2); // 使平面与路径对齐
- // 将平面添加到组中
- this.recommandPathLineGroup.add(plane);
- }
- // 将组添加到场景
- this.scene.add(this.recommandPathLineGroup);
- return curve; // 返回生成的曲线对象
- },
- render(){
- let cam = this.camera;
- //需要调整相机的视角
- this._camera.position.set(cam.eye[0], cam.eye[1], cam.eye[2]);
- this._camera.up.set(cam.up[0], cam.up[1], cam.up[2]);
- this._camera.lookAt(new THREE.Vector3(cam.center[0], cam.center[1], cam.center[2]));
- // Projection matrix can be copied directly
- this._camera.projectionMatrix.fromArray(cam.projectionMatrix);
- this.updateInfoPanel(); // 更新面板信息
- if (this.mixer) {
- this.mixer.update(this.clock.getDelta());
- }
- if (this.airCraftMixer) {
- this.airCraftMixer.update(this.airCraftClock.getDelta());
- }
- this.updatePosition();
- this.renderer.state.reset();
- this.bindRenderTarget();
- this.renderer.render(this.scene, this._camera);
- // as we want to smoothly animate the ISS movement, immediately request a re-render
- this.requestRender();
- // cleanup
- this.resetWebGLState();
- }
- }
|