Homogeneous(同次)座標系を使ったClipping
OpenGLライブラリの中には、glClipPlane(https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClipPlane.xml)という関数がある。この関数は平面を表すベクトル(というより、数の組)を受け取り、受け取った平面でクリッピングを行う。クリッピングの方法として、
If the dot product of ... a vertex with the stored plane equation components is positive or zero, the vertex is in with respect to that clipping plane. Otherwise, it is out.
と書かれているが、これで本当にクリッピングができるのか考えてみた。
前提
plane equation components
三次元空間内の二次元平面は、と表せる。すなわち、(A, B, C, D)の4つの数字の組で平面を指定できる。これがplane equation componentsだ(と思う)。そして、両辺に0でない数をかけても表す平面は変わらない。たとえば、もと同じ平面を表している。homogeneous座標系
cartesian座標系で(x, y, z)と表される点は、homogeneous座標系においては0でない任意数wを新たに導入して(wx, wy, wz, w)と表される。とくに、w=1のとき(普通はそうする)は(x, y, z, 1)となる。wは遠近法を考えるときに使えたりするのだけれど、省略。homogeneous座標系についての詳細はhttps://en.wikipedia.org/wiki/Homogeneous_coordinatesとかで読んでね。以降の説明では、homogeneous座標系の点(x, y, z, 1)とcartesian座標系の点(x, y, z)を同一視する。考えてみる
the dot product of a vertex with the stored plane equation componentsは、vertexの座標を、平面の方程式をとすると、となる。ここで、dotはdot product(ie. 内積)を表している。以降、vertexと点を同一視する。Dが0でないとき
plane equation components (A, B, C, D)で構成される平面(以降、とする)上の、あるvertexの座標がだったとする。すると、より、cartesian座標がであるようなvertexとの内積は、
となる。これは、平面上の任意のvertexについて成り立つので、平面に平行な各平面上のvertexたちの内積は一定であることがわかる。さらに、三次元空間内の任意の点は平面に平行な平面の内どれか一つの上にあるので、これまでの議論で空間内のすべてのvertexについての内積を考えられる。下図ではこのことを模式的に表している。
dotが正であるところがクリッピングされるのだったから、Dが正だとすると、この場合は平面に対して左側がクリッピングされることになる。
一方、plane equation components (-A, -B, -C, -D)で構成される平面もまた平面である。この場合についても先ほどと同じように考えてみる。平面上のあるvertexの座標がだったとする。すると、
より、cartesian座標がであるようなvertexとの内積は、
となり、先ほどの場合のdotの値(1-s)Dとは符号が反転している。この場合の模式図は、
となるので、Dが正だとすると、平面に対して右側がクリッピングされることになる。先ほどは左側がクリッピングされていたので、クリッピングの範囲が入れ替わっている。
Dが0でないときのまとめ
Dが0でないときには、Dの符号によってクリッピングされる範囲を瞬時に判断することができる。plane equation componentsが(A, B, C, D)であるとき、D>0ならば平面によって分けられた二つの空間のうち、原点を含む方がクリッピングされ、D<0ならば、原点を含まない方がクリッピングされる。このような仕組みで、単純に内積を取るだけでクリッピングができる。だが、D=0の場合には上の議論は破綻してしまう。模式図を見ても、D=0の時には全ての平面が一つになってしまうので、空間内の全てのvertexの内積について言及していないことが明らかにわかる。そこで、D=0のときは別に考えてみる。
Dが0のとき
plane equation componentsが(A, B, C, 0)であり、それが構成する平面をとするとき、ベクトルv(A, B, C)と平面は直行する。軽く説明しておくと、平面上の任意の点P(s, t, u)について、平面上にあるためにだが、これはまさしくベクトルvとPの位置ベクトルが直交することを意味している。そして、Pは任意点なので、ベクトルvと平面は直行していることがわかるといった具合。まあ、直交していることはのちの議論では使わず、ただ単に、位置ベクトル(A, B, C)が表す点がが平面に含まれることはないということが言いたかっただけ。plane equation componentsが(A, B, C, 0)であり、それが構成する平面をとする。座標がのvertexの内積は、ベクトル(A, B, C)とベクトルの内積に等しい。これより下図のように、ベクトルが平面に対してベクトル(A, B, C)と同じ方向にあるときはdotが正、逆方向にあるときはdotが負になる。
よってこの場合、平面の上側がクリッピングされる。
一方、plane equation componentsが(-A, -B, -C, 0)であるときも、それが構成する平面はと同じである。先ほどと同じように考えると、ベクトルが平面に対してベクトル(-A, -B, -C)と同じ方向にあるときはdotが正、逆方向にあるときはdotが負になる。
よってこの場合には、平面の下側がクリッピングされる。