天天看點

A Crash Course in 3D Graphics Math(令人吐血的3D圖形學裡的數學)

周一到周五,每天一篇,中原標準時間早上7點準時更新~

First, we do not pretend here that we will cover everything that is important for you to know(首先,我們不會在這裡去涵蓋所有對你來說很重要的東西). In fact, we will not even try to cover everything you should know(實際上,我們甚至都不會涵蓋你應該知道的東西). In this chapter, we are just going to cover what you really need to know(在本章節,我們隻是介紹一下那些你必須知道的東西). If you’re already a math whiz, you should skip immediately to the section ahead on the standard 3D transformations(如果你數學已經學的很好了,那麼你應該跳過本段). Not only do you already know what we are about to cover, but most math fans will be somewhat offended that we did not give sufficient space to their favorite feature of homogeneous coordinate spaces(不僅僅是因為你已經知道了我們要介紹的東西,并且對于很多數學狂魔來說,他們會覺得本段根本連個屁都沒說). Imagine one of those reality TV shows where you must escape a virtual swamp filled with crocodiles(想象一下綜藝頻道裡那些從虛拟的充滿了鳄魚的沼澤裡逃亡的遊戲(這或許是作者自己看過的什麼綜藝節目,法克,誰能想象出來啊)). How much 3D math do you really need to know to survive(為了生存,你需要多少3D數學呢?)? That’s what the next two sections are going to be about—3D math survival skills(接下來的2個小段就是關于如何生存下來的3D數學). The crocodiles do not care if you really know what a homogeneous coordinate space is(如果你真的懂得齊次坐标的話,鳄魚根本不在話下,分分鐘可以吊打,當着它女朋友的面吃它的肉肉)

Vectors, or Which Way Is Which?(向量或者啥是啥?)

The main input to OpenGL is the vertex, which has a number of attributes that normally include a position(OpenGL的輸入資料是vertex,它通常情況下都會包含位置這個屬性). Basically, this is a position in xyz coordinate space, and a given position in space is defined by exactly one and only one unique xyz triplet(基本上這個位置在給定的某個空間裡是唯一存在的). An xyz triplet, however, can be represented by a vector (in fact, for the mathematically pure of heart, a position is actually a vector too—there, we threw you a bone)(一個xyz的位置可以使用一個向量去表示). A vector is perhaps the single most important foundational concept to understand when it comes to manipulating 3D geometry(當俺們開始聊3D幾何的時候,或許向量就是一個最重要的玩意了). Those three values (x, y, and z) combined represent two important values: a direction and a magnitude(向量的那三個值能表達兩個非常重要的東西:方向和長度)

Figure 4.1 shows a point in space (picked arbitrarily) and an arrow drawn from the origin of the coordinate system to that point in space(圖4.1展示了一個空間中的點以及一個從坐标系原點發出來,指向該點的一個箭頭). The point can be thought of as a vertex when you are stitching together triangles, but the arrow can be thought of as a vector(這個點可以被當成是你去拼湊三角形的那些資料,然而這個箭頭可以被看成是一個向量). A vector is first, and most simply, a direction from the origin toward a point in space(向量首先最簡單的表達的是從原點指向一個點的方向). We use vectors all the time in OpenGL to represent directional quantities(我們總是在OpenGL裡面使用向量去描述方向資料). For example, the x axis is the vector (1, 0, 0)(比如x軸的向量是(1,0,0)). This says to go positive one unit in the x direction, and zero in the y and z directions(意思是說,指向x軸正方向一個機關的距離以及y,z方向0個機關距離的地方). A vector is also how we point to where we are going—for example, which way is the camera pointing, or in which direction do we want to move to get away from that crocodile?(一個向量同樣也被用來指向我們将要去哪裡,比如錄影機指向哪裡,還比如我們向哪個方向走來避開鳄魚先生)

A Crash Course in 3D Graphics Math(令人吐血的3D圖形學裡的數學)

The vector is so fundamental to the operation of OpenGL that vectors of various sizes are first-class types in GLSL and are given names such as vec3 and vec4 (representing three- and four-element vectors, respectively)(向量是OpenGL中很多操作的基礎,根據向量中資料個數的不同又分為N維向量,比如vec4、vec3這樣子). The second quantity a vector can represent is the magnitude(向量能表達的第二個東西就是長度). The magnitude of a vector is the length of the vector(向量的magnitude就是指向量的長度,是以之前我們就直譯成長度了,在國外混過的都知道這個基本概念). For our x-axis vector (1, 0, 0), the length of the vector is 1(對于我們x軸的向量來說,它的長度是1). A vector with a length of 1 we call a unit vector(長度隻有1的向量叫做機關向量). If a vector is not a unit vector and we want to scale it to make it one, we call that normalization(如果一個向量的長度不是1,而我們想把它的長度變成1的話,這個過程叫做機關化). Normalizing a vector scales it such that its length becomes 1 and the vector is then said to be normalized(機關化一個向量會讓它的長度變成1,變化完後,這個向量就可以被看成是已經被機關化鳥). Unit vectors are important when we want to represent only a direction and not a magnitude(當我們僅想表達一個方向,而不關心長度的時候,機關向量是很重要的). Also, if vector lengths appear in the equations we’ll be using, they get a whole lot simpler when those lengths are 1!(并且,當向量的長度是1的時候,我們在做向量運算的時候,總體來說會讓情況變得更簡單) A magnitude can be important as well; for example, it can tell us how far we need to move in a given direction—how far away we need to get from that crocodile(當然,向量的長度也很重要,比如,它可以告訴我們,沿着給定的方向,我們需要移動多少距離,才能避開我們的鳄魚lady gaga們)

Vectors (and matrices) are such important concepts in 3D graphics that they are firstclass citizens in GLSL—the language in which you write your shaders(向量和矩陣是如此的重要,以至于當你在寫shader的時候,他們是被GLSL原生的支援的). However, this is not so in languages like C++(然而,C++并不支援這貨). To allow you to use them in your C++ programs, the vmath library, which is provided with this book’s source code, contains classes that can represent vectors and matrices that are named similarly to their GLSL counterparts(為了讓你在C++程式裡也能使用,俺寫的vmath庫将會提供這部分能力,它的命名和使用方式就是抄襲了GLSL裡的). For instance, vmath::vec3 can represent a three-component floating-point vector (x, y, z), vmath::vec4 can represent a four-component floating-point vector (x, y, z, w), and so on(例如,vmath::vec3就可以表達3個浮點數組成的向量,vmath::vec4能表達四個浮點數組成的向量等等). The w coordinate is added to make the vector homogeneous but is typically set to 1.0(w分量使得向量變成了奇次向量,基本上這家夥的值就是1.0). The x, y, and z values might later be divided by w, which, when it is 1.0, essentially leaves the xyz values alone(x、y、z的值可能在後面會被w除,當它是1的時候,會保持xyz的值不變). The classes in vmath are actually templated classes with type definitions to represent common types such as single- and doubleprecision floating-point values, and signed- and unsigned-integer variables. (vmath是模闆類,随便用就可以了,如果不清楚模闆原理的可以觀看東漢書院C++ Tricks課程,隻要9塊8,趕上書院正在舉行老漢下鄉,支援社會主義新農村建設,我們鄭重承諾,買一送一! 買課程送壯妹一名,9塊8買不到吃虧,9塊8買不到上當,9塊8你什麼都買不到,哈哈哈哈。 不過說句正經的,尤其是需要寫引擎核心的同學,讓你站在深層次去看C++代碼到底在幹嘛,看完後對于如何使用别人的C++模闆庫是非常有幫助的。) vmath::vec3 and vmath::vec4 are defined simply as follows(vmath::vec3和vmath::vec4的定義如下)

typedef Tvec3 vec3;
typedef Tvec4 vec4;           

Declaring a three-component vector is as simple as(申明一個三維向量如下的例子如下)

vmath::vec3 vVector;           

If you include using namespace vmath; in your source code, you can even write(如果你直接把vmath的命名空間全部導入到你的項目中,你甚至可以像下面這樣使用vmath)

vec3 vVector;           

However, in these examples, we’ll always qualify our use of the vmath library by explicitly using the vmath:: namespace(然而,在這些例子中,我們依然會顯示的去使用vmath這個命名空間). All of the vmath classes define a number of constructors and copy operators, which means you can declare and initialize vectors as follows:(所有的vmath的類都定義了很多構造函數和拷貝的運算符,也就是說,你可以像下面如此這般來使用這個庫)

vec3 vmath::vVertex1(0.0f, 0.0f, 1.0f);
vec4 vmath::vVertex2 = vec4(1.0f, 0.0f, 1.0f, 1.0f);
vec4 vmath::vVertex3(vVertex1, 1.0f);           

Now, an array of three-component vertices, such as for a triangle, can be declared as(一個三維的點可以被如下類似的代碼定義:)

vec3 vmath::vVerts[] = { vmath::vec3(-0.5f, 0.0f, 0.0f),
    vmath::vec3(0.5f, 0.0f, 0.0f),
    vmath::vec3(0.0f, 0.5f, 0.0f) } ;           

This should look similar to the code that we introduced in the “Drawing Our First Triangle” section in Chapter 2(這個應該跟我們在第2章裡畫三角形時的那些代碼長的很像,反正我是已經忘了第二章那個代碼長啥樣了). The vmath library also includes lots of math-related functions and overrides most operators on its class to allow vectors and matrices to be added, subtracted, multiplied, transposed, and so on(vmath庫也包含了很多跟數學相關的函數并且重載了很多運算符,這樣一來,那些個向量和矩陣就可以進行一些基本的運算操作了)

We need to be careful here not to gloss over that fourth w component too much(我們需要注意的是,别被w向量所吸引鳥). Most of the time when you specify geometry with vertex positions, a three-component vertex is all you want to store and send to OpenGL(大部分情況下,你需要表達一個幾何形體的某個點的時候,三維向量就夠了). For many directional vectors, such as a surface normal (a vector pointing perpendicular to a surface that is used for lighting calculations), a three-component vector suffices(對于很多方向向量,比如法線,三維向量就很夠用了). However, we will soon delve into the world of matrices, and to transform a 3D vertex, you must multiply it by a 4 × 4 transformation matrix(當然,我們将很快進入矩陣的世界,并且,我們需要使用4x4的矩陣來對3D的點來進行操作). The rules are you must multiply a four-component vector by a 4 × 4 matrix(這裡需要注意的是,你必須要用一個四維向量去與一個4x4的矩陣進行乘法操作); if you try and use a three-component vector with a 4 × 4 matrix, the crocodiles will eat you!(如果你用一個三維向量與一個4x4的矩陣進行配對,那些鳄魚就會來吃你的大腿上的肉,就是我們在公衆号裡,那個人妖大腿内側畫了紋身的那一塊肉) More on what all this means soon. Essentially, if you are going to do your own matrix operations on vectors, then you will probably want four-component vectors in many cases(更多的内容我們将會很快進行介紹。基本上,如果你希望使用矩陣對向量進行操作的時候,你将更多的會使用四維向量)

繼續閱讀