bambooflow Note

Transform

最終更新:

bambooflow

- view
メンバー限定 登録/ログイン


行列変換の説明

Scale


汎用のスケール行列を生成

  • パラメータ
x,y,z x,y,z軸各々のスケール係数

  • 変換行列
\begin{pmatrix}x&0&0&0\cr 0&y&0&0\cr 0&0&z&0\cr 0&0&0&1\cr \end{pmatrix}


Translate

変換行列を生成

  • パラメータ
x,y,z 変換ベクトルのx,y,z座標

  • 変換行列
\begin{pmatrix}1&0&0&x\cr 0&1&0&y\cr 0&0&1&z\cr 0&0&0&1\cr \end{pmatrix}


Rotate

回転行列を生成

  • パラメータ
angle 回転する角度
x,y,z ベクトルのx,y,z座標


  • 変換行列
\begin{pmatrix}\left(1-c\right)\,x^2+c&\left(1-c\right)\,x\,y-s\,z&\left( 1-c\right)\,x\,z+s\,y&0\cr \left(1-c\right)\,x\,y-s\,z&\left(1-c \right)\,y^2+c&\left(1-c\right)\,y\,z-s\,x&0\cr \left(1-c\right)\,x \,z-s\,y&\left(1-c\right)\,y\,z+s\,x&\left(1-c\right)\,z^2+c&0\cr 0& 0&0&1\cr \end{pmatrix}
c=\cos \left(angle \right)
s=\sin \left(angle \right)


Frustum


射影行列を生成

  • パラメータ
left, right クリップ面の左右の垂直座標
bottom,top クリップ面の上下の水平座標
zNear,zFar クリップ面の奥行であるnearとfar座標

  • 変換行列
\begin{pmatrix}{{2\,{\it zNear}}\over{{\it right}-{\it left}}}&0&A&0\cr 0 &{{2\,{\it zNear}}\over{{\it top}-{\it bottom}}}&B&0\cr 0&0&C&D\cr 0 &0&-1&0\cr \end{pmatrix}
A={{{\it right}+{\it left}}\over{{\it right}-{\it left}}}
B={{{\it top}+{\it bottom}}\over{{\it top}-{\it bottom}}}
C=-{{{\it zNear}+{\it zFar}}\over{{\it zFar}-{\it zNear}}}
D=-{{2\,{\it zFar}\,{\it zNear}}\over{{\it zFar}-{\it zNear}}}


Perspective

透視射影行列の生成

  • パラメータ
fovy y方向の視野を度数で指定
aspect x方向の視野を決定する縦横比(aspect ratio)を指定。
    縦横比は、y(高さ)に対するx(幅)の割合。
zNear ビューアから近くのクリップ面までの距離
zFar ビューアから遠くのクリップ面までの距離


  • 変換行列
f={{1}\over{\tan \left( \frac{fovy} {2} \right)}}
\begin{pmatrix}{{f}\over{{\it aspect}}}&0&0&0\cr 0&f&0&0\cr 0&0&{{ {\it zNear}+{\it zFar}}\over{{\it zNear}-{\it zFar}}}&{{2\, {\it zFar}\,{\it zNear}}\over{{\it zNear}-{\it zFar}}}\cr 0&0&-1&0 \cr \end{pmatrix}


Ortho


  • パラメータ
left, right 左右の垂直のクリップ面の座標
bottom,top 上下の水平のクリップ面の座標
zNear,zFar 遠近デプスのクリップまでの距離。
      面がビューアの後にある場合は,これらの値は負の数となる。


  • 変換行列
\begin{pmatrix}{{2}\over{{\it right}-{\it left}}}&0&0&t_{x}\cr 0&{{2 }\over{{\it top}-{\it bottom}}}&0&t_{y}\cr 0&0&-{{2}\over{{\it zFar} -{\it zNear}}}&t_{z}\cr 0&0&0&1\cr \end{pmatrix}
t_{x}=-{{{\it right}-{\it left}}\over{{\it right}-{\it left}}}
t_{y}=-{{{\it top}-{\it bottom}}\over{{\it top}-{\it bottom}}}
t_{z}=-{{{\it zNear}-{\it zFar}}\over{{\it zFar}-{\it zNear}}}


LookAt


  • パラメータ
eyeX, eyeY, eyeZ 眼点の位置
centerX, centerY, centerZ 参照点の位置
upX, upY, upZ 上向きベクトルの方向



  • 変換行列
F=\begin{pmatrix}{{\it centerX}-{\it eyeX}\cr {\it centerY}-{\it eyeY}\cr  {\it centerZ}-{\it eyeZ}\cr \end{pmatrix}
f={{F}\over{\sqrt{F_{z}^2+F_{y}^2+F_{x}^2}}}
{\it UP}=\begin{pmatrix}{\it upX}&{\it upY}&{\it upZ}\cr \end{pmatrix}
UP'={{{\it UP}}\over{\sqrt{{\it UP}_{z}^2+{\it UP}_{y}^2+{\it UP}_{x} ^2}}}

s=f \times UP'
s=s \times f

M=\begin{pmatrix}s_{0}&s_{1}&s_{2}&0\cr u_{0}&u_{1}&u_{2}&0\cr -f_{0}&-f _{1}&-f_{2}&0\cr 0&0&0&1\cr \end{pmatrix}

MultMatrixf(M);
Translate(-eyeX, -eyeY, -eyeZ);


Transformソースコード


  • Transform.h
#ifndef __TRANSFORM_H_
#define __TRANSFORM_H_
 
#include <GL/gl.h>
 
// vector
 
GLfloat sl_Amountf(const GLfloat *v);
void sl_Normalizef(GLfloat *v);
GLfloat sl_Dotf(const GLfloat v0[3], const GLfloat v1[3]);
void sl_Crossf(GLfloat result[3], const GLfloat v0[3], const GLfloat v1[3]);
 
 
// Matrix
 
void sl_Scalef( GLfloat *result, GLfloat sx, GLfloat sy, GLfloat sz);
void sl_Translatef( GLfloat *result, GLfloat tx, GLfloat ty, GLfloat tz);
void sl_Rotatef( GLfloat *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
void sl_MultMatrixf( GLfloat *result, GLfloat *srcA, GLfloat *srcB); 
void sl_LoadIdentityf(GLfloat *result);
 
// ModelView
 
void sl_Frustumf(
    GLfloat *result,
    float left, float right,
    float bottom, float top,
    float nearZ, float farZ);
 
void sl_Perspectivef(
    GLfloat *result,
    float fovy, float aspect,
    float nearZ, float farZ);
 
void sl_Orthof(
    GLfloat *result,
    float left, float right,
    float bottom, float top,
    float nearZ, float farZ);
 
void sl_LookAtf(
    GLfloat *result,
    float ex, float ey, float ez,
    float tx, float ty, float tz,
    float ux, float uy, float uz);
 
#endif /* __TRANSFORM_H_ */
 

  • Transform.cpp
#include <math.h>
#include "Transform.h"
 
///////////////////////////////////////////////////////////////////////////////
// vector
//
GLfloat sl_Amountf(const GLfloat v[3])
{
    return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
 
void sl_Normalizef(GLfloat *v)
{
    GLfloat a = sl_Amountf(v);
 
    if (a == 0.0f) {
        return;
    }
    for (int i=0; i<3; ++i) {
        v[i] /= a;
    }
}
 
GLfloat sl_Dotf(const GLfloat v0[3], const GLfloat v1[3])
{
    return v0[0]*v1[0] + v0[1]*v1[1] + v0[2]*v1[2];
}
 
void sl_Crossf(GLfloat result[3], const GLfloat v0[3], const GLfloat v1[3])
{
    GLfloat temp[3];
 
    temp[0] = v0[1]*v1[2] - v0[2]*v1[1];
    temp[1] = v0[2]*v1[0] - v0[0]*v1[2];
    temp[2] = v0[0]*v1[1] - v0[1]*v1[0];
 
    for (int i=0; i<3; ++i) {
        result[i] = temp[i];
    }
}
 
 
///////////////////////////////////////////////////////////////////////////////
// Matrix
//
 
void sl_Scalef(
    GLfloat *result,
    GLfloat sx,
    GLfloat sy,
    GLfloat sz)
{
    result[ 0] *= sx;
    result[ 1] *= sx;
    result[ 2] *= sx;
    result[ 3] *= sx;
 
    result[ 4] *= sy;
    result[ 5] *= sy;
    result[ 6] *= sy;
    result[ 7] *= sy;
 
    result[ 8] *= sz;
    result[ 9] *= sz;
    result[10] *= sz;
    result[11] *= sz;
}
 
void sl_Translatef(
    GLfloat *result,
    GLfloat tx,
    GLfloat ty,
    GLfloat tz)
{
    result[12] += (result[ 0] * tx + result[ 4] * ty + result[ 8] * tz);
    result[13] += (result[ 1] * tx + result[ 5] * ty + result[ 9] * tz);
    result[14] += (result[ 2] * tx + result[ 6] * ty + result[10] * tz);
    result[15] += (result[ 3] * tx + result[ 7] * ty + result[11] * tz);
}
 
void sl_Rotatef(
    GLfloat *result,
    GLfloat angle,
    GLfloat x,
    GLfloat y,
    GLfloat z)
{
    GLfloat sinAngle, cosAngle;
    GLfloat mag = sqrtf(x * x + y * y + z * z);
 
    if (mag > 0.0f) {
        GLfloat xx, yy, zz;
        GLfloat xy, yz, xz;
        GLfloat xs, ys, zs;
        GLfloat oneMinusCos;
        GLfloat rotMat[16];
 
        x /= mag;
        y /= mag;
        z /= mag;
 
        sinAngle = sinf(angle * M_PI / 180.0f);
        cosAngle = cosf(angle * M_PI / 180.0f);
 
        xx = x * x;
        yy = y * y;
        zz = z * z;
        xy = x * y;
        yz = y * z;
        xz = x * z;
        xs = x * sinAngle;
        ys = y * sinAngle;
        zs = z * sinAngle;
        oneMinusCos = 1.0f - cosAngle;
 
        rotMat[ 0] = (xx * oneMinusCos) + cosAngle;
        rotMat[ 1] = (xy * oneMinusCos) + zs;
        rotMat[ 2] = (xz * oneMinusCos) - ys;
        rotMat[ 3] = 0.0f;
 
        rotMat[ 4] = (xy * oneMinusCos) - zs;
        rotMat[ 5] = (yy * oneMinusCos) + cosAngle;
        rotMat[ 6] = (yz * oneMinusCos) + xs;
        rotMat[ 7] = 0.0f;
 
        rotMat[ 8] = (xz * oneMinusCos) + ys;
        rotMat[ 9] = (yz * oneMinusCos) - xs;
        rotMat[10] = (zz * oneMinusCos) + cosAngle;
        rotMat[11] = 0.0f;
 
        rotMat[12] = 0.0f;
        rotMat[13] = 0.0f;
        rotMat[14] = 0.0f;
        rotMat[15] = 1.0f;
 
        sl_MultMatrixf(result, result, rotMat);
    }
}
 
 
void sl_MultMatrixf(
    GLfloat *result,
    GLfloat *srcA,
    GLfloat *srcB)
{
    GLfloat tmp[16];
 
    for (int i=0; i<4; ++i) {
        tmp[i*4+0] = 
              srcA[i*4+0] * srcB[ 0]
            + srcA[i*4+1] * srcB[ 4]
            + srcA[i*4+2] * srcB[ 8]
            + srcA[i*4+3] * srcB[12];
 
        tmp[i*4+1] = 
              srcA[i*4+0] * srcB[ 1]
            + srcA[i*4+1] * srcB[ 5]
            + srcA[i*4+2] * srcB[ 9]
            + srcA[i*4+3] * srcB[13];
 
        tmp[i*4+2] = 
              srcA[i*4+0] * srcB[ 2]
            + srcA[i*4+1] * srcB[ 6]
            + srcA[i*4+2] * srcB[10]
            + srcA[i*4+3] * srcB[14];
 
        tmp[i*4+3] = 
              srcA[i*4+0] * srcB[ 3]
            + srcA[i*4+1] * srcB[ 7]
            + srcA[i*4+2] * srcB[11]
            + srcA[i*4+3] * srcB[15];
    }
    for (int i=0; i<16; ++i) {
        result[i] = tmp[i];
    }
}
 
 
void sl_LoadIdentityf(GLfloat *result)
{
    for (int i=0; i<16; ++i) {
        result[i] = 0.0f;
    }
    result[ 0] = 1.0f;
    result[ 5] = 1.0f;
    result[10] = 1.0f;
    result[15] = 1.0f;
}
 
 
 
///////////////////////////////////////////////////////////////////////////////
// ModelView
//
 
void sl_Frustumf(
    GLfloat *result,
    float left, float right,
    float bottom, float top,
    float nearZ, float farZ)
{
    float deltaX = right - left;
    float deltaY = top - bottom;
    float deltaZ = farZ - nearZ;
    GLfloat frust[16];
 
    if ( (nearZ <= 0.0f) || (farZ <= 0.0f) ||
         (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f))
        return;
 
    frust[ 0] = 2.0f * nearZ / deltaX;
    frust[ 1] = frust[ 2] = frust[ 3] = 0.0f;
 
    frust[ 5] = 2.0f * nearZ / deltaY;
    frust[ 4] = frust[ 6] = frust[ 7] = 0.0f;
 
    frust[ 8] = (right + left) / deltaX;
    frust[ 9] = (top + bottom) / deltaY;
    frust[10] = -(nearZ + farZ) / deltaZ;
    frust[11] = -1.0f;
 
    frust[14] = -2.0f * nearZ * farZ / deltaZ;
    frust[12] = frust[13] = frust[15] = 0.0f;
 
    //sl_MultMatrixf(result, frust, result);
    sl_MultMatrixf(result, result, frust);
}
 
void sl_Perspectivef(
    GLfloat *result,
    float fovy, float aspect,
    float nearZ, float farZ)
{
    GLfloat frustumW, frustumH;
 
    frustumH = tanf(fovy / 360.0f * M_PI) * nearZ;
    frustumW = frustumH * aspect;
 
    sl_Frustumf(result, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ);
}
 
void sl_Orthof(
    GLfloat *result,
    float left, float right,
    float bottom, float top,
    float nearZ, float farZ)
{
    float deltaX = right - left;
    float deltaY = top - bottom;
    float deltaZ = farZ - nearZ;
    GLfloat ortho[16];
 
    if ((deltaX == 0.0f) || (deltaY = 0.0f) || (deltaZ == 0.0f))
        return;
 
    sl_LoadIdentityf(ortho);
    ortho[ 0] = 2.0f / deltaX;
    ortho[12] = -(right + left) / deltaX;
    ortho[ 5] = 2.0f / deltaY;
    ortho[13] = -(top + bottom) / deltaY;
    ortho[10] = -2.0f / deltaZ;
    ortho[14] = -(nearZ + farZ) / deltaZ;
 
    //sl_MultMatrixf(result, ortho, result);
    sl_MultMatrixf(result, result, ortho);
}
 
 
void sl_LookAtf(
    GLfloat *result,
    float ex, float ey, float ez,
    float tx, float ty, float tz,
    float ux, float uy, float uz)
{
    GLfloat lookAt[16];
 
    float l;
    tx = ex - tx;
    ty = ey - ty;
    tz = ez - tz;
    l = sqrtf(tx * tx + ty * ty + tz * tz);
    lookAt[ 2] = tx / l;
    lookAt[ 6] = ty / l;
    lookAt[10] = tz / l;
 
    tx = uy * lookAt[10] - uz * lookAt[ 6];
    ty = uz * lookAt[ 2] - ux * lookAt[10];
    tz = ux * lookAt[ 6] - uy * lookAt[ 2];
    l = sqrtf(tx * tx + ty * ty + tz * tz);
    lookAt[ 0] = tx / l;
    lookAt[ 4] = ty / l;
    lookAt[ 8] = tz / l;
 
    lookAt[ 1] = lookAt[ 6] * lookAt[ 8] - lookAt[10] * lookAt[ 4];
    lookAt[ 5] = lookAt[10] * lookAt[ 0] - lookAt[ 2] * lookAt[ 8];
    lookAt[ 9] = lookAt[ 2] * lookAt[ 4] - lookAt[ 6] * lookAt[ 0];
 
    lookAt[12] = -(ex * lookAt[ 0] + ey * lookAt[ 4] + ez * lookAt[ 8]);
    lookAt[13] = -(ex * lookAt[ 1] + ey * lookAt[ 5] + ez * lookAt[ 9]);
    lookAt[14] = -(ex * lookAt[ 2] + ey * lookAt[ 6] + ez * lookAt[10]);
 
    lookAt[ 3] = lookAt[ 7] = lookAt[11] = 0.0f;
    lookAt[15] = 1.0f;
 
    sl_MultMatrixf(result, result, lookAt);
}
 
 


参考

タグ:

OpenGL GLSL
記事メニュー
ウィキ募集バナー