高德地图 JS API—3D立体图形网格Mesh

高德地图 JS API—3D立体图形网格Mesh

Mesh指的是所有用三角形面组合成的三维物体,JS API 目前提供的 Mesh 类型有:Mesh、MeshAcceptLights、Prism、MeshLine 四种,MeshLine表现为带状线条,放在下一篇介绍

Mesh 和 MeshAcceptLights

Mesh 和 MeshAcceptLights 为 JS API 提供的比较底层的两个网格类型,默认的图元绘制类型为gl.TRIANGLES。以绘制一个垂直于地面的矩形为例,首先我们创建一个Mesh实例:

创建Mesh实例

JavaScript
var rectangle = new AMap.Object3D.Mesh()
var geometry = rectangle.geometry;//创建之后获取geometry

设置attribute属性

接着需要给实例的geometry的各个attribute属性填入数值。任何一个 Object3D 的形体都具有顶点坐标、顶点颜色两个基本属性;如果有大量重复顶点的时候可以使用顶点索引;如果用到贴图的话,就需要顶点纹理坐标,多纹理的时候还会用到纹理索引;需要光照的时候还会有顶点法向量。

Gometry的属性类型说明
verticesArray<Number>存放顶点位置的一维数组,三个元素代表一个顶点的位置
vertexColorsArray<Number>存放顶点颜色的一维数组,四个元素代表一个顶点的颜色
facesArray<Integer>存放三角形顶点索引的一维数组,三个元素代表一个三角形面。当faces长度不为0时,按照faces顶点索引来绘制;否则当faces长度为0时,按照vertices来以此绘制三角形面。
vertexUVsArray<Number>存放顶点纹理坐标的一维数组,两个元素代表一个顶点的纹理坐标
textureIndicesArray<Integer>存放顶点纹理索引的一维数组,一个元素元素代表一个顶点的纹理索引。当Mesh的textures属性的长度大于1时,代表一个mesh使用多个纹理,textureIndices表示每个顶点使用哪个纹理。只使用一个纹理时,这个属性可以不设置
vertexNormalsArray<Number>存放顶点法向量的一维数组,三个元素元素代表一个顶点的法向量。MeshAcceptLights专用。

以我们所要绘制垂直于地面的矩形为例,它拥有四个顶点V0、V1、V2、V3,首先我们要取得四个顶点的三维坐标,V0和V1的坐标的xy分量值我们通过 Map 实例对象的lngLatToGeodeticCoord方法可以算出,V2、V3在V0、V1的基础上增加 z 分量就可以了:

JavaScript
var lnglat1 = new AMap.LngLat(116.39, 39.9)
var lnglat2 = new AMap.LngLat(116.40, 39.9)
var v0xy = map.lngLatToGeodeticCoord(lnglat1);
var v1xy = map.lngLatToGeodeticCoord(lnglat2);
var z = -1000;//3D地图Z方向朝下,所以负值
geometry.vertices.push(v0xy.x, v0xy.y, 0);//V0
geometry.vertices.push(v1xy.x, v1xy.y, 0);//V1
geometry.vertices.push(v0xy.x, v0xy.y, z);//V3
geometry.vertices.push(v1xy.x, v1xy.y, z);//V2

矩形有两个三角形面F1(V0V1V3)、F2(V1V2V3)组成,我们这里使用了两个共享的顶点V1和V3所以可以启用faces顶点索引,顶点索引的内容为构成三角形面的顶点在vertices中的索引:

JavaScript
geometry.faces.push(0, 1, 3)
geometry.faces.push(1, 2, 3)

接着我们可以给四个顶点赋予相应的颜色值,默认情况下不开启颜色混合,如果使用了透明颜色或者透明贴图需要设置 Mesh实例的transparent属性为true方能看到透明混合的效果:

JavaScript
geometry.vertexColors.push(1, 0, 0, 1); //V0
geometry.vertexColors.push(0, 1, 0, 1); //V1
geometry.vertexColors.push(0, 0, 1, 1); //V2
geometry.vertexColors.push(0, 1, 1, 1); //V3

rectangle.transparent = false;

也可以使用纹理给进行填色,设定纹理坐标的同时需要给meshtexturs中添加一张纹理图片

JavaScript
rectangle.textures.push("https://a.amap.com/jsapi_demos/static/tourist/crate.gif");

使用纹理时需要给所有顶点添加纹理坐标,纹理坐标以图片的左上角为原点,

x轴朝右,y轴朝下:

geometry.vertexUVs.push(0, 1); //V0
geometry.vertexUVs.push(1, 1); //V1
geometry.vertexUVs.push(1, 0); //V2
geometry.vertexUVs.push(0, 0); //V3

vertexNormalsMeshAcceptLights专有的属性,用作记录顶点法向量,来实现光照,这里不细说明。

添加到 Object3DLayer

做好上面的工作之后将 Mesh实例添加到Object3DLayer中即可,Mesh类型默认以顺时针为正面,默认显示反面,可以通过MeshbackOrFront属性来控制显示正反面,这里我们开启两面。

JavaScript
rectangle.backOrFront = 'both';//'back'、'front'、'both'
object3DLayer.add(rectangle)

棱柱 Prism

为了简化使用,我们在 MeshAcceptLights 之上封装了Prism类型,Prism 可以基于经纬度、高度、颜色来构建不规则棱柱体,使用方法如下:

JavaScript
var bounds = [
    new AMap.LngLat(116.5,39.25),
    new AMap.LngLat(116.75,39.5),
    new AMap.LngLat(116.5,39.75),
    new AMap.LngLat(116.25,39.5)
]
var height = 500000;
var color = [0,0,1,0.6];
var prism2 = new AMap.Object3D.Prism({
    path:island,
    height:height,
    color:color
});

垂面 Wall

垂面为垂直于地面的一个折面,用法同Prism,通过经纬度path、高度height、颜色color来定义,可接收全局光照。与Prism的区别是 Wall没有顶面,只有侧面。

0 0 投票数
文章评分
订阅评论
提醒
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x