This article, followed by the previous one, focuses on the details of how to build the earth grid in a highly-detailed way.
At this point, the globe creates a corresponding Tileterrain class for each slice (globesurfacetile), which is used to maintain the relevant logic of the terrain slice; and then, in Requesttilegeometry, The Tileterrain requests the terrain data that should be sliced. If the reader has questions about this part, you can read the cesium principle: 1 The longest frame of the rendering schedule; Finally, if you are using a terrain service with a height map, the terrain data corresponds to the Heightmapterraindata class, and finally, The Terraindata forms a terrainmesh mesh. Below, we will give you a detailed description of the last step of the relevant content.
Height chart
First of all, how to understand the height map? Usually a tile will correspond to a 256*256 image slice, representing the corresponding image content of the tile corresponding to the XYZ range, the height map is the same idea, but at this time, the former each pixel represents the current position corresponding to the color, and the latter represents the current position corresponding to the height
In general, the height map is a thumbnail, such as in the Cesium, in the absence of real terrain data, height map width is 16*16 size, each point corresponding to the value is 0, in the real terrain data, the height map is the size of 65*65. It can be seen that the height of the map is diluted, not one by one correspondence, one does not need, or is a point cloud, and secondly, the computational capacity of the network is very large, but also the effect and efficiency of a compromise.
Workers threads
Cesium scheduling is based on state change, seemingly simple, but personally think very essence of. Compared to the event-driven strategy, state-based processing of big data in real-time, logic is simple and clear, of course, this is a digression, we continue to return to the terrain itself.
With the data, the state of Tileterrain is changed from receiving to received, Nature has entered the next step. Transform: The process of converting raw terrain data (heightmapterraindata) to Grid (Terrainmesh).
This process involves a small amount of computation, so cesium uses promise + workers technology to put the computational amount into the thread, which ensures smooth interface operation. Interested in workers can refer to the "Cesium Principle: 4Web workers analysis".
The HeightmapTerrainData.prototype.createMesh method provides a way to build a grid, in which the workers thread is used, and below we go to the topic, detailing the details of the high-level network.
Heightmaptessellator
As above is a process, horizontal line above is the main thread, call Createmesh, create thread, put buffer (height value array), Width high (width&height), The tile's range (rectangle) and center point (centers) are used as parameters for the Createverticesfromheightmap function, so that each tile creates a worker thread and implements the mesh build in the thread.
Paremeters
The algorithm of grid construction is encapsulated in the Heightmaptessellator.computevertices function, we first understand the parameters in detail:
- Heightmap
Height map point string used to build the grid
- Width&height
Pixel width height of altitude graphs
- Skirtheight
Commonly known as skirts, each tile will be surrounded by a fence, specifying the height of the fence, to ensure that there is no gap with the adjacent tile splicing
- Nativerectangle
The extent of the tile, if it is the WGS coordinate system, the unit is the degree, if it is Mercator, the unit is the meter
- Exaggeration
Terrain height scaling factor, usually 1, real-world terrain height
- Rectangle
The tile corresponds to the geographic range, in radians, rectangle and nativerectangle at least one, and if two parameters are available, they are matched to each other.
- Isgeographic
True is the WGS coordinate, false is Mercator
- Relativetocenter
The center point of the tile, in which the unit is a Cartesian coordinate based on the centre of the globe, in meters
- Ellipsoid
Ellipsoid class, providing some calculation and conversion methods
- Structure
Height graph data structure, follow up again, feel a little chicken
These are the parameters that must be passed in (there are some inaccuracies, if these parameters are not set, the default values are used), and of course there are optional parameters. And then formally began to construct the net. The process of constructing a network is divided into four parts:
- Building grids
- Calculate Boundingsphere
- Calculate horizonculling
- Encode
Grid nodes
The code to build the grid is very long, but it is not difficult to read it carefully, combined with the following picture, let us explain the idea.
Here we first think of this grid as a square (like a globe tiled into a map), which is a grid of tiles. Through the previously passed parameters, we know the length of the tile (rectangle), the number of columns (width&height), it is not difficult to calculate the location of each node (latitude and longitude), plainly, is two for loop, pseudo-code as follows:
Of course, this is a pseudo-code, if it is really short, but cesium that the computational capacity of the construction grid is large and frequent, so the optimization here is a simplified version of the Cartographictocartesian function, which is complex and complex, You need to understand the ellipsoid, say simple, because even if you do not understand, you can set the formula directly. The approximate diagram and formula are as follows:
where b is the Latitude, L is the longitude, n is the long half axis, here is the earth radius of 6378137 meters, and N (1-e^2) is the short half axis of the ellipse, here the value is 6356752.3142451793 meters. In addition, the width and height of the nodes in the grid are consistent, so that each node corresponds to a height heightsample in the height graph, so that the above formula, corresponding implementation code and comments are as follows:
In this way, each node in the corresponding grid, we can calculate the positions and heights the two arrays, the same, once again the tile mesh to imagine a plane, each tile also corresponds to an image slice, assuming the two translucent paper stacked together, the following is a grid, The picture above is the image, which is the following effect:
Usually the image slice is 256*256 pixel size, we map [0,256] pixel range to [0,1] scale, so we can also calculate the ratio of each node corresponding to [0,1], that is, the usual UV (OpenGL inside the texture coordinates, the need to use this parameter to render the texture). The code for implementing Uvs in Cesium is as follows:
In addition, when the grid node is computed, the distance of each node relativetocenter from the Tile Center point is calculated, which is required when calculating boundingsphere below. This requires mastering some mathematical foundations of graphics and matrices:
As above, with two traversal, we get three arrays corresponding to the grid node one by one: Positions,heights,uvs and the maximum maximum and minimum values minimum the distance from the center point.
Cull cropping
If just a simple grid construction, the work has been completed, but the actual is not enough, the most direct problem is that you do not know whether you need to display this tile.
If the person who has done the rendering optimization has such a resonance, the fastest way to render an object is not to render it. It looks right, but it's really a serious question. Translating this sentence into a programmer's language is to determine whether the object's scope is within the current visual range. In conjunction with the Cesium terrain we are discussing, considering the large-scale, frequent rendering environment, under the camera's view cone, it is a serious question how to quickly and simply determine whether the current topographic grid is visible. and cesium on this issue, to achieve the ultimate, let me deeply amazed.
First, cesium mainly uses two kinds of cutting methods:
- Frustum Cull
- Horizon Cull
Because it involves a lot of algorithms, frankly, every single detail, unfolds are very knowledgeable, so the following are mainly ideas and personal understanding, I also try to clear some of the clarity, so that we can a complete understanding. Due to the length of space, this article mainly introduces the cone cutting part, the water level is cut in the tin terrain when involved.
Frustum Cull
First, when an object is not within the range of the cone, it is naturally not necessary to display it. The size of the cones is clear, so the rest is how to calculate the bounds of the object. At the same time, from the perspective of the century, this judgment process must not exceed the time to render the object, otherwise it is meaningless. Therefore, the key to building this bounds lies in the balance between fast and effective. That is to be able to build a relatively fast approximate accurate bounds, and this bounds can also be efficient and more accurate to determine whether the visibility.
Boundingsphere
Cesium is the first to provide a boundingsphere, such as a model of the boundingsphere, that is, the circumscribed circle of an object.
Now that we understand the concept of boundingsphere, then we have a bunch of dots, how do we implement the Boundingsphere.frompoints function? Before reading the following, I hope you can also ponder this problem.
Boundingsphere is a ball, so the question is to get the ball's sphere and radius. Before I encountered a similar problem, there was a heap of dots, known as the center point of the case, to calculate its radius. My idea is to traverse all points, calculate the distance between each point and the center point, and take the maximum value as the radius.
Now, this center point is unknown, so we need to traverse all points first, find Max and Min in xyz three direction, X (Min,max), Y (Min,max), Z (Min,max), and then calculate the mean of Min and Max, as the center point, that is: P = (min+ MAX)/2. This has the center point, the front also gives the idea of calculating the radius, we realized the boundingsphere.frompoints.
This algorithm is not difficult to understand, but also the simplest and quickest way, in cesium, called this algorithm for Na?ve method, see Na?ve, do not know how many people will blurt out "pattern Tucson broken"? But this algorithm also has a disadvantage, the ball is usually not optimal, like you wear a large one-size clothes, slightly less elegant.
Next, Cesium compared the Jack Ritter algorithm. This algorithm and na?ve algorithm similar, also need to traverse two times, after the first traversal, estimate an initial ball, and then traverse again, if the point in this ball does not do anything, if the point is outside the ball, then adjust the center point and radius, to ensure that the point within the ball. The tuning algorithm is as follows:
Na?ve and Jack Ritter, the first traversal process is basically the same, but the second traversal, na?ve only modifies the radius, the latter will adjust the center point and radius. Jack Ritter himself to the test, which is equivalent in calculation, but the latter is 5% more accurate. But cesium own test found that 19% of the case, the effect will be worse than the former, and 11% of the case, the effect will be better than the former, indicating that the first estimate of the ball and the order of adding points will also affect the results of the Jack Ritter algorithm.
As above is a test data comparison (reference), at the end of the cesium will be executed at the same time Na?ve and Ritter algorithm, with the radius of the largest value as the final result, this idea is desirable, two times the calculation of the traversal of 99% are the same, like carpool, a lift, a lot of benefit. With Boundingsphere, how to determine whether in the scope of the cone, in the "Cesium principle: 2 The longest frame of the grid" in the detailed explanation, here do not repeat.
Orientedboundingbox
It's been so peaceful for a long time, people's pursuit of performance has not stopped. Before the Boundingsphere discovery is still not accurate enough, you see, the ball has a lot of white space, resulting in excessive rendering, there is no more accurate bound, this is orientedboundingbox.
BoundingBox refers to the bounding box, plus oriented, as the name implies is a bounding box facing. In the previous comparison, you can see that this is actually a bounding box in the local coordinate system, as shown below is a orientedboundingbox and contrast chart, it is obvious that the scope is much smaller.
Again, we have to consider two issues, get the cost of this bounds, and determine whether the cost of bounds is visible.
First, there will always be a center point for a tile, which is the parameter relativetocenter, which corresponds to the tangent plane + normal of the sphere, which forms the XYZ axis of the Local Coordination (Neu:north East up). Such a relative neu coordinate orthogonal geometry, relative to the sphere of the Cartesian coordinate system is a diagonal geometry, which is not as good as boundingsphere symmetry, can be very straightforward to use the parameterized way to construct. Orientedboundingbox default is a 2*2*2 cube, center is the central point of the bounding box, and there is a matrix halfaxes used to record the bounding box according to the center point of rotation and scaling information.
Here's a quick introduction to how to get a orientedboundingbox for a tile, which is the Cesium.OrientedBoundingBox.fromRectangle function.
First, we know the tile corresponding to the relativetocenter, and then constructs the Ellipsoidtangentplane object, namely the point corresponding ellipsoid plane, this process is actually from Cartesian coordinates to neu coordinate process, And then get the normal direction of the point corresponding to the ellipsoid, point + normal = tangent plane. For example, the red line is a two-dimensional elliptical tangent, and the corresponding three-dimensional ellipsoid is a tangent:
At this point, we just get the three orientations of XYZ in Orientedboundingbox and extend infinitely in XYZ three directions, but we cannot determine the specific extent. How do you calculate this range?
Let me give you a simple example, in a dark room where you are holding the football against a wall and putting a light on the ball. Suppose that the black part is translucent, and the white light is opaque, so that the shadow of the black plane will be on the wall. We kept the ball close to the wall, until it was just right on the surface, and the shadow of each slice was the smallest.
Obviously, this aspect is an arc, and the wall is a plane, just the process of projecting XYZ's three-dimensional body to the XY plane. Cesium is also using the same idea, The EllipsoidTangentPlane.prototype.projectPointsToNearestOnPlane method calculates the extent of each tile terrain on the XY (not all points at this time, but similar to the nine Gongge, which calculates the tile corresponding to the upper and lower left nine points ), and Z's range can be simply understood as the current topographic data corresponding to the highest and lowest point, resulting in the tile corresponding to the Minx, MaxX, Miny, Maxy, MinZ, MaxZ (the value is relativetocenter as the origin, meter units).
Finally, the halfaxes matrix is constructed by combining the Neu matrix with the accurate center point of the bounding box as well as the relative offset and scaling ratio.
In this way, we found the terrain tile corresponding to the orientedboundingbox, frankly, the understanding is much more complex than boundingsphere, but in the computational amount, because only for the feature points to calculate, in fact, the performance is better, of course, the individual did not test, just speculation.
How to determine the position of the bounding box and the cone of view, this is very similar to the boundingsphere algorithm. Whether the effect of this way is improved, but also to see the curative effect, the following is cesium to provide their own comparative effect (reference):
Can be seen, improve the effect is very good, and judge whether the performance of the intersection is not very different:
In fact, both bounds are used in the cesium, and there are some repetitive computations in the grid positions and two bounds (Boundingsphere,orientedboundingbox). So there is a certain amount of optimization space. But this is mainly in the comparison of programming skills, from the logic and algorithms, cesium has been very professional, I personally feel that in the study of source code, in all aspects, have benefited.
As above, we calculated the Positions,heights,uvs and bounds, We basically completed the Heightmapterraindata.createmesh process, but also the most critical aspect of the terrain, the next step is to start loading into the graphics card, through the shader rendering, we will introduce in the follow-up. At the same time, due to the length of the issue, the provisional decision to cut the level and encode part of the cancellation, the following to find a suitable opportunity to introduce.
Cesium principle: 3 The longest frame of the terrain (2: Height map)