地形表面

Download: GR_Cubic.Zip (138kb)


1. Introduction

Welcome to another extended DirectXGraphics article. This isn't going to be a tutorial as such, more of a covering-note for the downloadable source code.

I have a considerable interest in terrain modeling, and often read articles/white-papers on the subject. One area that crops up every so often is the use of quadratic/cubic/quartic/quintic patches to approximate an area of terrain. There are many advantages to this - the mathematical nature of the terrain makes it easy to implement LOD (Level Of Detail) algorithms, and it also provides nice results :-)

我经常研究一些地形方面的著作,发现它也能在VB中能够实现,也许你会对此感兴趣。So, just for fun I decided to re-read several articles that I found and see if I could get it working in VB, and the fact that you're now reading this text shows that I managed to do it - and maybe you'd be interested in seeing how it all works!

下面6幅图展示了结果,LOG越高,地形表面越光滑,但多边形越多。The following 6 pictures show (in wireframe and solid forms) what the results are, the LOD is scalar, so the higher it is the smoother the terrain (but the more triangles / slower it gets).


Above and below: The lowest (0) possible setting


Above and Below: A low setting, but starting to look better!


Above and Below: A high resolution render, note very smooth :)


2. The Cubic Equations

这个方程用来生成简单的"patches"The equations used to generate these "patches" are quite simple if you're good at math's, but if you're not familiar with parametric equations you'll need to do some research before continuing (I don't have the time to teach/explain them properly!)

我们先做一个简单的线性方程,从AB一直线,只能完成一些简单的工作。First we take the simple linear equation: 
(A+B)=1
where A is the distance from the start (0.0 to 1.0) and B is the distance from the end (0.0 to 1.0). This basically expands to:
A + t(B-A)
with a little work.

我们现在扩展它的次方-2次方-3次方-4次方。We can then extend this to be "to the power n" - 2 (Quadratic), 3 (Cubic), 4 (Quartic), 5 (Quintic). When we raise it to one of these powers we need to multiply out the brackets, which gives us the polynomial to power n. For example:

(A+B)2 = A2 + 2AB + B2
(A+B)3 = A3 + 3A2B + 3AB2 + B3
(A+B)4 = A4 + 4A3B + 6A2B2 + 4AB3 + B4
(A+B)5 = A5 + 5A4B + 10A2B3 + 5AB4 + B5

我现在只说3次方的情况,你可扩展其他的。I'm going to focus on the cubic equation, but you can easily work out the other versions if you really want them...

if we take A and B to be the distances along the line, we need to express them as one parameter (so we can get an f(t) formatted function). using the linear equation above:为了表达在AB之间的线段我们要用一个参数表达它,按上面方程求解
(A+B)3 = 1     'cube-root both sides 两边立方
(A+B) = 1       'cube root of 1 is still 1 开方还是1
B = 1-A          'rearrange for B
  移动B

换一种方法,先将其展开并把B = 1-A 代入if we now substitute this into the main cubic equation:

A3 + 3A2(1-A) + 3A(1-A)2 + (1-A)3

不要简化,我们无须证明1=10=1don't simplify it yet, as all you'll do is prove that 1=1 or 0=0 :-)

在每一项分别乘系数abcd,注意不要把系数同大写的AB混淆。to control our curve we're going to add a coefficient to each term of the equation and consider them to be "control points" - these are additional 3D points that will "guide" the curve accordingly. I will use lower case letters a, b, c, d (don't muddle these with A and B).

aA3 + b3A2(1-A) + c3A(1-A)2 + d(1-A)3

0<=A<=1上曲线总是落在AB点上。as it stands, with parameter A being in the range 0<=A<=1, control point 'a' is the start of the line (A=0.0), 'd' is the end of the line (A=1.0) and points 'b' and 'c' are just used to guide the curve (the curve wont actually pass through these points).

方程如下We can now expand these into the final parametric equations:

X(A) = axA3 + bx3A2(1-A) + cx3A(1-A)2 + dx(1-A)3
Y(A) = ayA3 + by3A2(1-A) + cy3A(1-A)2 + dy(1-A)3
Z(A) = azA3 + bz3A2(1-A) + cz3A(1-A)2 + dz(1-A)3

方程绘制出的曲线落在AB点还会受到c、d点的影响。These equations will work perfectly for drawing a line between 'a' and 'd' influenced by 'c' and 'd'


An example of a cubic spline

现在扩展 2D Okay, we now need to expand this to cover a 2D patch, where we pass in an x and y value, and we get the "height" at the given point (this is the equation used to generate the meshes shown above).

(A+B)3•(C+D)3=1

将两条线结合就得到了结果!basically, we just multiply the two curves, and we'll get the desired result!

(A3 + 3A2B + 3AB2 + B3)•(A3 + 3A2B + 3AB2 + B3)

我放出完整的参数方程。I'll just jump to the full parametric equations, feel free to do the working-through if you want!

X(a,c) = Axa³c³ + Bx3a³c²(1-c) + Cx3a³c(1-c)² + Dxa³(1-c)³ + Ex3a²(1-a)c³ +
            Fx9a²(1-a)c²(1-c) + Gx9a²(1-a)c(1-c)² + Hx3a²(1-a)(1-c)³ + Ix3a(1-a)²c³ + 
            Jx9a(1-a)²c²(1-c) + Kx9a(1-a)²c(1-c)² + Lx3a(1-a)²(1-c)³ +
            Mx(1-a)³c³ + Nx3(1-a)³c²(1-c) + Ox3(1-a)³c(1-c)² + Px(1-a)³(1-c)³       

Y(a,c) = Aya³c³ + By3a³c²(1-c) + Cy3a³c(1-c)² + Dya³(1-c)³ + Ey3a²(1-a)c³ +
            Fy9a²(1-a)c²(1-c) + Gy9a²(1-a)c(1-c)² + Hy3a²(1-a)(1-c)³ + Iy3a(1-a)²c³ + 
            Jy9a(1-a)²c²(1-c) + Ky9a(1-a)²c(1-c)² + Ly3a(1-a)²(1-c)³ +
            My(1-a)³c³ + Ny3(1-a)³c²(1-c) + Oy3(1-a)³c(1-c)² + Py(1-a)³(1-c)³  

Z(a,c) = Aza³c³ + Bz3a³c²(1-c) + Cz3a³c(1-c)² + Dza³(1-c)³ + Ez3a²(1-a)c³ +
            Fz9a²(1-a)c²(1-c) + Gz9a²(1-a)c(1-c)² + Hz3a²(1-a)(1-c)³ + Iz3a(1-a)²c³ + 
            Jz9a(1-a)²c²(1-c) + Kz9a(1-a)²c(1-c)² + Lz3a(1-a)²(1-c)³ +
            Mz(1-a)³c³ + Nz3(1-a)³c²(1-c) + Oz3(1-a)³c(1-c)² + Pz(1-a)³(1-c)³ 

看一下带码就知道了That's the math's behind the cubic-patch, you'll have to read through the source code in order to understand it fully.