3D Math BasisThe math classes provide basic operations in 3-space useful for graphics:
This is a basic discussion of the mathematics behind these classes. Vectors and PointsThere are two important building blocks in 3D: the vector and the point in cartesian 3-space. Both are comprised by 3 values in R, the real numbers. So programatically in Qt both vectors and points are stored in a QVector3D instance, since that class can store 3 qreal values. But there are important differences between points and vectors:
In 3D math points and vectors are represented by column vectors: In normal text where the over-arrow symbol is not available the vector is just a bolded lower-case letter. A point is a capital letter, non-bolded. The fourth element in the column vectors above, w = 1 for points and w = 0 for vectors means that vectors are not altered by certain affine transformations such as translate(). This affine transform T comprises a rotation and a translation. Remember that applying the transform is done by the matrix multiplication P * T = P'. Notice how the 1 in the column for the translation multiplies out to zero against the vectors last 0 value, so the vector is "immune" to the translation. In the case of the point the w = 1 "triggers" the translation values in the matrix. So the take away principle is that points and vectors, while represented by the same data structure are different and behave differently in 3D math. Vector Magnitude and Normal VectorsAnother important difference between points and vectors is that a vector has a magnitude, whereas a point does not. Consider the vector v = (v0, v1, v2) to be rooted at the origin O = (0, 0, 0) and pointing to the point P = (v0, v1, v2), then its magnitude is the length of the line O to P. Magnitude is represented by vertical bars and is found by this formula: Unit vectors are those with a magnitude of exactly 1. The math notation is a "hat" (or circumflex) over the bolded vector symbol. A unit vector parallel to one of the axes is easy to form without any division: More typically such a vector is found by dividing by its own length: Vectors used for 3D normals are usually normalized to unit length. Confusingly enough, since that is two different uses of the word "normal". A normal is simply a vector perpendicular to something. For example a plane normal is perpendicular to the plane. Typically a normal vector is unit length, for convenience in 3D applications (but there is nothing mathematically to say a normal vector has to be unit length). A vertex normal is perpendicular to the surface modelled by the vertex, and is used in lighting calculations. Reviewing Operations on VectorsThe QVector3D class provides two very useful functions - the vector dot-product and the vector cross-product. Here's a quick review of their uses:
A vector has the following operations defined on it in 3-space
Multiplying and dividing by vectors is not defined - these operations make no sense in 3-D space. Although you cannot add a vector to a point as such, you can consider the vector from the origin to the point, and add the vector to that. Thus rather than out-lawing adding a vector to a point it is simply defined as such. This allows the convenient notation for lines and planes introduced in the next section. Representing Lines and PlanesThe QLine3D is represented by a point and a vector: the point anchors the line in cartesian 3-space; and the vector is the direction the line is oriented in through that point. The line is infinite. The QPlane3D is represented also by a point and a vector. Again the point anchors the line in cartesian 3-space; but the vector this time is a normal to the plane. The plane is infinite. This representation turns out to make many types of calculations required for 3D graphics very straight forward. For example to find if a point P lies on a plane take the vector p from the point to the planes origin, and find the dot-product with the planes normal n. If p . n is zero, then p is perpendicular to n, and P is on the plane. Vector and Point ArithmeticSlightly more complex arithmetic with the components of QLine3D and QPlane3D is possible, with some care about what operations can be performed. As an example look at the implementation for QLine3D::intersection(const QLine3D &) : the two lines are defined as: If the two lines intersect then P(t) == Q(s) and for some ordered pair s, t is a solution to the equations for both lines. The aim is to solve for s and t. The equations can be rearranged algebraically as shown in the last line above. But since dividing by a vector is not defined, tempting options such as dividing by v to solve for t are not possible. In the implementation the next step is breaking the points and vectors down into their x, y and z components giving 3 simultaneous equations: This can be readily solved using gaussian elimination to get a solution for s, and substituting back gives t. |