当前位置: 首页 > Web前端 > vue.js

three.js入门制作3D地球有图

时间:2023-03-31 19:17:00 vue.js

(第五部分:VectorEarthwithpointsPointsintoaplanevectorearth)本文效果图:注:我画的很差哈哈哈哈哈哈哈。..1.geojson基本概念本文中我们要画一个矢量地球,那么首先要知道这个矢量地球是由什么组成的,比如要画'中国',那么我们只需要知道坐标把中国边界上的所有点,然后把这些点一个一个连接起来,就形成了一个中国的轮廓,因为每个点之间的距离都很近,所以虽然我们用直线连接,但是还是可以形成一个平滑的球形效果。简单理解geojson就是这样一组数据,里面包含了绘制各个国家轮廓所需要的所有点信息。如果你深入了解,你会发现geojson中有各种各样的分组信息,但我们这篇文章主要讲的是画出最基本的国家轮廓,就不展开讨论了。我们先画一张平面图。这是我之前写的一篇文章,详细介绍了geojson。有兴趣的同学可以去了解一下,有助于大家更好地理解地图:记得有一次前端“揭开地图之谜”的分享会。本章设计的数学知识是初级的,后面会涉及到矩阵等知识。到时候用最通俗的方式给大家讲解一下。不局限于概念而是最通俗的理解方式,本文后面会有经纬度转xyz的详细解释和图表。2.经纬度这里的概念很基础也很重要,不熟悉的请仔细阅读。经度‖‖‖经度是地球上某点从称为本初子午线的南北线向东或向西的度数。本初子午线的经度为0°,地球上其他地方的经度为东经180°或西经180°,作为本初子午线的线是人们选择的,每时区都有一个时区15°我之前分享的bug:timezonerelatedbug)。如图所示,电脑中用正数和负数来区分东经和西经。东经为正数,西经为负数。度数的范围是[-180,180]。纬度通过椭球面上某一点画法线,该点的法线与赤道面的夹角在0度到90度之间。赤道以北一点的纬度称为北纬,记作N;赤道以南某点的纬度称为南纬,记为S。如图所示,在计算机中用正负数来区分北纬和南纬。北纬为正数,南纬为负数。度数的范围是[-90,90]。知识延伸:测量经纬度地球上任何地方,只要有一块手表、一根竹竿、一把卷尺,就可以知道当地的经纬度。但该表必须对照国家的标准时间进行核对。具体方法有兴趣可以上百度百科测试。3.你还记得三角函数吗大浪,别怕我们毕业了不用背,只要会用,我们一起温习一下:名字公式sin(∠A)a/ccos(∠A)b/ctan(∠A)A)a/b因为geojson中存储的数据是经纬度,所以我们后面会用到它来将经纬度转换成坐标。当然geojson也可以直接存储坐标。4.弧度即从圆心向圆周射出两条射线,形成一个夹角和与该夹角正对的圆弧。当这条弧的长度恰好等于圆的半径时,两条射线的夹角为1弧度。5.前端代码中的实现如果你想当然的认为在前端代码中直接写Math.sin(30)就会输出0.5,那你就错了。因为在我们的Math运算中,需要输入的是弧度,这就是为什么我会重复上面弧度的概念,所以如果我们要求sin(30),我们需要写Math.sin(30*Math.PI/180)。为了让大家更容易理解,我就简单的把推导过程写下来。1弧度是以弧长为半径对应的角度。已知圆周长为2πr。可以得出一个圆一共有2πr÷r弧度,即2π弧度是一个圆。圆的角是360°,1°角对应的弧是2π÷360,即π/180。所以上面说的sin(30°)就是Math.sin(30*Math.PI/180)6.画一个平面世界等高线之间没有接壤,我们需要把它们处理成一个数组,也就是这句话country.geometry.type===“多边形”。/cc_map_3d_pro/src/components/cc_map.vueimportworldGeofrom"../assets/geojson/world.geo";.../initEarth(){constR=envConifg.r;worldGeo.features.forEach((country)=>{if(country.geometry.type==="Polygon"){country.geometry.coordinates=[country.geometry.coordinates];}varline=countryLine(R,国家.geometry.coordinates);this.scene.add(line);});},world的geojson可以在我项目的github上找到。上面我们将radius和point传给countryLine方法进行处理,添加到环境中。稍后,我们将讨论将图形对象分成不同的组。在这里,我们就不展开知识点了。七。使用虚线/cc_map_3d_pro/src/utils/countryLine.js这个方法,我们专门画出国家的轮廓。从“三”导入*作为三;函数countryLine(R,polygonArr){letgroup=newTHREE.Group();polygonArr.forEach(polygon=>{letpointArr=[];polygon[0].forEach(elem=>{pointArr.push(elem[0],elem[1],0)});group.add(line(pointArr));});returngroup;}newTHREE.Group()inthree.js中文网沿袭原话,和Object3D差不多,其目的是为了让group中对象的语法结构更加清晰。假设我现在生成两个立方体几何体,分别命名为a和b,那么我可以创建一个组而不是下面这样写:this.scene.add(a);这个.scene.add(b);newTHREE.Group();group.add(a)group.add(b)this.scene.add(group);我们将在后续章节中详细讨论。上面我们依赖了一个叫line的方法,这是本次的一个重要知识点。八。画线段并不简单(line方法)functionline(pointArr){letgeometry=newTHREE.BufferGeometry();让顶点=newFloat32Array(pointArr);letattribute=newTHREE.BufferAttribute(vertices,3);几何学。attributes.position=属性;letmaterial=newTHREE.LineBasicMaterial({color:0x00aaaa//线条颜色});letline=newTHREE.LineLoop(geometry,material);返回线;}1。传入参数pointArr;从countryLine方法可以看出这里是[x1,y1,z1,x2,y2,z2,x3,y3,z3]等一系列坐标,大家可能觉得这种形式不符合思路js,但是符合webgl或者是svg的思想。关于webgl的知识,让你在讲解shader的时候就明白了。现在你不需要学得太深,因为这里的知识很深。2.新三.BufferGeometry();使用BufferGeometry可以有效减少将上述数据传输到GPU所需的开销。一个国家平均有几百组点,用普通的Geometry会变得很卡。别着急,我们会继续优化我会在相关篇幅统一讲,这里可以暂时理解为three.js转换的数据流。3.新的Float32Array();js原生知识:Float32Array类型数组表示一个平台字节序的32位浮点数数组(对应C浮点数据类型),数据量大的时候Float32Array更好一些,更符合webgl的参数标准,TypedArray这个类型是个大话题,我会在shader章节详细讲。4.新三.BufferAttribute();该类用于存储与BufferGeometry关联的属性(例如顶点位置向量、面片索引、法线向量、颜色值、UV坐标和任何自定义属性),使用BufferAttribute可以更高效地向GPU传递数据。第一个参数:是数据源,就是上面处理的坐标数组。第二个参数:数据存储为任意长度的向量,这里是3,可以理解为一组三个数据,即一组x1,y1,z1,一组x2,y2,z2,等等。5.新三.LineBasicMaterial();基础线材,即专业线描,可以调整颜色和粗细,还有线头的外观。6.geometry.attributes.position=attribute这个写法看起来很粗鲁,意思是用我们处理过的数组替换图形的位置信息,也就是给图形设置每个点的位置。7.新三.LineLoop();循环线就是首尾相接的线,就像我们每次创建一个矩形一样,这个方法创建了一条循环线。由于我们将z轴的值设为0,就会出现下图所示的平面图。9.将经纬度转换为直角坐标系(理论)直接制作这种平面地球的库也有很多,但是我们的系列文章是学习圆地球的,所以需要将经纬度进行转换坐标转换为球坐标。让我们从xyz一一开始。最简单的y轴y轴其实只和纬度有关。最简单的求法如下图所示:球面上的一点,这个点到圆心的距离就是圆的半径r。现在我们要求这个点远离zy平面距离。该点的x和z不一定为0,所以垂线不一定落在x轴上,但无论垂线怎么画,线段与xz平面的夹角都不会改变,而这个角度就是纬度,所以可以看出我们知道斜边的长度是r,三角函数sin(纬度)=对边/斜边,对边就是y轴的值,我们左右两边分别乘以r,最后得到:sin(Latitude)乘以r=y,计算出x轴x轴需要点来计算。一步步来吧,每一步都有图:上面的演示是我们可以把这个点看成一个立方体,一个已知的对角线长度为r的立方体,那么我们就可以把这个立方体拿出来研究一下,我们可以脱离这个坐标系。现在已知立方体的对角线长度为r,高为y轴坐标。接下来,使用纬度找到底部的对角线。我们用类似y轴的方法求x1的长度:cos(纬度)乘以r=x1从图中我们可以看出经度是下面沿yz平面延伸的对角线的角度,我们可以用罪的对面比较斜边求长度。sin(经度)*x1=x带入x1的公式:x=sin(经度)乘以cos(纬度)x对应的z轴与x的原理相同,只是这里我们用的是相邻的边cos来比较斜边。z=cos(longitude)乘以cos(latitude)十。实战中不要忘记将经纬度转换为笛卡尔坐标系(代码),先将经纬度转换为弧度。//经纬度转换函数lon2xyz(R,longitude,latitude){constlon=longitude*Math.PI/180;constlat=纬度*Math.PI/180;constx=R*Math.cos(lat)*Math.sin(lon);consty=R*Math.sin(lat);constz=R*Math.cos(lon)*Math.cos(lat);return{x,y,z};}exportdefaultlon2xyz;其他一些教程其他一些教程会要求把经度倒过来,同时把x和z倒过来,这种写法不推荐,我们只是遵循正常的思维方式。11.圆球经过不懈努力,我们终于拯救了圆球。让我们看看他还缺少什么:从上图可以看出还有很多问题,比如线条相互覆盖,我们应该让这个地球看不透,暂时这个地球不能点击,度数现实还不够,真的任重而道远。end????????????????????????????????????????????????????????????????????????????????????????????如何在地图上打点,给地球添加光环等效果。至此,本系列文章还不到一半。射线拾取国家、三角投掷点的知识也将陆续发布。精彩有趣的知识还在后头,希望与大家一起进步。