I need to be pointed in the right direction. 3 Dimensional Geometry question from a 3D artist.

50 Views Asked by At

So I have a geometry question and I'm not really sure what to search for.

Im working on a python script, and a part of it I need to identify, what I've been calling 'parallel faces'... for example:

This is my test geometry

I need a calculation that gives me the '3D slope' (tangent might be the right word) or something that will have the same value for all faces that are 'parallel to each other,' like the yellow-colored faces in this image.

My script gives me the (x,y,z) coordinates of the for each of the faces in the geometry geometry with coordinates, is there a way I can use the coordinates to determine the '3D slope' of the triangulated faces?

Also, what is the correct terminology for 'parallel (3D) faces' and '3D slope'?

2

There are 2 best solutions below

7
On BEST ANSWER

You want the direction of the normal (the vector perpendicular to the plane), but even here, there are two normals, pointing in opposite directions. For example, the normal to the $xy$-plane could be in the direction of the positive $z$-axis or the negative $z$-axis.

You have the coordinates of each point, so you can get the vectors from one point to another by subtraction. If you take two vectors in the same plane, and compute their cross-product, that will give you a vector normal to the plane. In order to conveniently compare normals, divide the normal by its length. That gives you a normal of length $1$. Two planes are parallel if they have the same unit normals, or one is the negative of the other. To avoid choosing two parallel vectors, take three consecutive vertices, say $A,B,C$, and compute the cross product of $\vec{v_1}=\vec{AB}$ and $\vec{v_2}=\vec{BC}$

One final point. You are doing floating point calculations, so you can't expect the normals to be identical, just equal up to some small tolerance.

0
On

This is not an answer, just an example of how to implement saulspatz's answer in a computer program.

The unit normal $\hat{n}$ to a triangle with vertices $\vec{v}_1$, $\vec{v}_2$, and $\vec{v}_3$ is calculated as $$\begin{aligned} \vec{n} &= \left( \vec{v}_2 - \vec{v}_1 \right) \times \left( \vec{v}_3 - \vec{v}_1 \right) \\ \hat{n} &= \frac{\vec{n}}{\left\lVert\vec{n}\right\rVert} = \frac{\vec{n}}{\sqrt{\vec{n}\cdot\vec{n}}} \\ \end{aligned}$$ where $\times$ is the cross product and $\cdot$ is the dot product of two three-dimensional vectors. This uses the convention that when you look at the triangle from directly above it, with the vertices in counterclockwise orientation, in a right-handed 3D coordinate system the normal vector is towards you.

Let's say you have two unit normal vectors, $\hat{n}_A$ and $\hat{n}_B$. The angle between the two is $\theta$, $$\cos \theta = \hat{n}_A \cdot \hat{n}_B \quad \iff \quad \theta = \operatorname{arccos}\left( \hat{n}_A \cdot \hat{n}_B \right)$$ In the general case, the dot product would need to be divided by the product of the lengths of the two vectors, but because we use unit vectors here, the divisor would be 1 anyway.

In practice, you can use cosine similarity to compare the "similarity" of the two vectors, simply by looking at $\cos\theta$. If $\cos\theta = 1$, the two vectors are parallel, and the two triangles face the same direction. If $\cos\theta = 0$, the two triangle faces are perpendicular. If $\cos\theta = -1$, the two triangles face the opposite direction.

In many computer graphics systems, triangles are one-sided, in that they are only rendered when their vertices appear counterclockwise on the projection plane (display). This is called back-face culling. In the display coordinates, the projection plane is the $x y$ plane, and only faces with a normal vector with a positive $z$ coordinate are drawn. Note that this normal vector does not even need to be an unit vector, and boils down to multiplications, additions and subtractions, all of which are "fast" operations for computers. (Division is "slower", and square root and trigonometric functions are "slow", in comparison. Also note that although we talk about $\cos\theta$ here, you do not actually need either $\cos$ or $\operatorname{arccos}$ functions at all; the value you use is $\cos\theta$, or $\hat{n}_A\cdot\hat{n}_B$.)

If, however, you have two-sided triangles, and your normal vectors don't really indicate which way the triangle faces, you can use the magnitude of the cosine angle of the two unit normal vectors, $\left\lvert\cos\theta\right\rvert$ (or "absolute value", abs(x_n1*x_n2 + y_n1*y_n2 + z_n1*z_n2)), as the similarity.


For coloring the faces according to the direction they are facing, there is a trivial yet visually extremely powerful trick you can use: the color cube.

Essentially, you pick six (pastel colors or low-saturation colors, like $(1.0,0.6,0.6)$, $(0.3,0.9,0.3)$, $(0.3,0.6,0.6)$, for example, using floating-point RGB color components), one each for positive $x$ axis, negative $x$ axis, positive $y$ axis, negative $y$ axis, positive $z$ axis, and negative $z$ axis. If your planar faces are bidirectional (and not just one-sided), use the same color for positive and negative ends of each axis. Let's say these colors are $c_{x+}$, $c_{x-}$, $c_{y+}$, $c_{y-}$, $c_{z+}$, and $c_{z-}$.

The trick is that the $x$, $y$, and $z$ components of $\hat{n}$ define the color directly, as coefficients to the colors!

Let's say $\hat{n} = (x_n, y_n, z_n)$, with $x_n \ge 0$, $y_n \ge 0$, and $z_n \ge 0$ (ie. the unit normal vector $\hat{n}$ is in the "positive octant"), and the three colors are defined in floating-point RGB as $c_{x+} = (r_{x+}, g_{x+}, b_{x+})$, $c_{y+} = (r_{y+}, g_{y+}, b_{y+})$, and $c_{z+} = (r_{z+}, g_{z+}, b_{z+})$. Note that if one of the unit normal vector $\hat{n}$ components was negative, you'd choose the other color instead. Then, the face color is $$\begin{cases} r = r_{x+} x_n^2 + r_{y+} y_n^2 + r_{z+} z_n^2 \\ g = g_{x+} x_n^2 + g_{y+} y_n^2 + g_{z+} z_n^2 \\ b = b_{x+} x_n^2 + b_{y+} y_n^2 + b_{z+} z_n^2 \\ \end{cases}$$ Because $\lvert\hat{n}\rvert = 1 = \sqrt{x_n^2 + y_n^2 + z_n^2}$, $x_n^2 + y_n^2 + z_n^2 = 1$, and the unit normal vector $\hat{n}$ interpolates between the three colors, and no scaling (division by the sum of the weight coefficients) is needed. Also, because of squaring the coefficients, the coefficients are always nonnegative (zero or positive), so this works as-is for two-sided faces. (For one-sided faces, where the direction of the normal vector matters, you need to choose the color for each axis based on the sign of the corresponding unit normal coordinate component.)

The RGB colors space is not the best one for interpolating colors, though. The YCbCr color space is much better visually. (There, the color components are Y, Cb, and Cr. This is used in JPEG images and video compression, exactly because the color components Cb and Cr are more linear wrt. human perception, and the luma component Y corresponds pretty well to perceived "brightness". Conversion between RGB and YCbCr is shown in the Wikipedia YCbCr article.)