【问题标题】:C matrix libraries, suited for opengl on Android (NDK)C 矩阵库,适用于 Android 上的 opengl (NDK)
【发布时间】:2011-03-05 04:36:53
【问题描述】:

我正在使用带有 NDK 的 opengl es 2.0 用 C 语言编写渲染例程。我对矩阵图形转换的(速度超过精度)库以及您可以推荐的任何最佳实践感兴趣。

编写自己的函数并非不可能,但我想在重新发明轮子之前先在这里问一下。谢谢。

【问题讨论】:

标签: android-ndk opengl-es-2.0


【解决方案1】:

OpenGL Mathematics (GLM) 看起来不错。

【讨论】:

  • 谢谢,效果很好。虽然我要了一个C库,但是cpp方向还是值得的。仅供参考:要使用此库,请务必使用 stlport,请参阅 CPLUSPLUS-SUPPORT 文档了解如何使用。
  • 我无法用 NDK 编译它。我收到func_common.hpp:240: error: expected unqualified-id before 'sizeof'func_common.inl:1217: error: expected ')' before 'sizeof' 之类的错误有什么建议吗?
【解决方案2】:

here 获取 android.opengl.matrix java 代码的副本。 然后将语法从 Java 更改为 C,一切顺利。这是我用于自己项目的代码。不过,它并不是一套完整的 Opengl 矩阵函数。

#include <stdlib.h>
#include <math.h>

#define PI 3.1415926f
#define normalize(x, y, z)                  \
{                                               \
        float norm = 1.0f / sqrt(x*x+y*y+z*z);  \
        x *= norm; y *= norm; z *= norm;        \
}
#define I(_i, _j) ((_j)+4*(_i))

void matrixSetIdentityM(float *m)
{
        memset((void*)m, 0, 16*sizeof(float));
        m[0] = m[5] = m[10] = m[15] = 1.0f;
}

void matrixSetRotateM(float *m, float a, float x, float y, float z)
{
        float s, c;

        memset((void*)m, 0, 15*sizeof(float));
        m[15] = 1.0f;

        a *= PI/180.0f;
        s = sin(a);
        c = cos(a);

        if (1.0f == x && 0.0f == y && 0.0f == z) {
                m[5] = c; m[10] = c;
                m[6] = s; m[9]  = -s;
                m[0] = 1;
        } else if (0.0f == x && 1.0f == y && 0.0f == z) {
                m[0] = c; m[10] = c;
                m[8] = s; m[2]  = -s;
                m[5] = 1;
        } else if (0.0f == x && 0.0f == y && 1.0f == z) {
                m[0] = c; m[5] = c;
                m[1] = s; m[4] = -s;
                m[10] = 1;
        } else {
                normalize(x, y, z);
                float nc = 1.0f - c;
                float xy = x * y;
                float yz = y * z;
                float zx = z * x;
                float xs = x * s;
                float ys = y * s;
                float zs = z * s;
                m[ 0] = x*x*nc +  c;
                m[ 4] =  xy*nc - zs;
                m[ 8] =  zx*nc + ys;
                m[ 1] =  xy*nc + zs;
                m[ 5] = y*y*nc +  c;
                m[ 9] =  yz*nc - xs;
                m[ 2] =  zx*nc - ys;
                m[ 6] =  yz*nc + xs;
                m[10] = z*z*nc +  c;
        }
}

void matrixMultiplyMM(float *m, float *lhs, float *rhs)
{
        float t[16];
        for (int i = 0; i < 4; i++) {
                register const float rhs_i0 = rhs[I(i, 0)];
                register float ri0 = lhs[ I(0,0) ] * rhs_i0;
                register float ri1 = lhs[ I(0,1) ] * rhs_i0;
                register float ri2 = lhs[ I(0,2) ] * rhs_i0;
                register float ri3 = lhs[ I(0,3) ] * rhs_i0;
                for (int j = 1; j < 4; j++) {
                        register const float rhs_ij = rhs[ I(i,j) ];
                        ri0 += lhs[ I(j,0) ] * rhs_ij;
                        ri1 += lhs[ I(j,1) ] * rhs_ij;
                        ri2 += lhs[ I(j,2) ] * rhs_ij;
                        ri3 += lhs[ I(j,3) ] * rhs_ij;
                }
                t[ I(i,0) ] = ri0;
                t[ I(i,1) ] = ri1;
                t[ I(i,2) ] = ri2;
                t[ I(i,3) ] = ri3;
        }
        memcpy(m, t, sizeof(t));
}

void matrixScaleM(float *m, float x, float y, float z)
{
        for (int i = 0; i < 4; i++)
        {
                m[i] *= x; m[4+i] *=y; m[8+i] *= z;
        }
}

void matrixTranslateM(float *m, float x, float y, float z)
{
        for (int i = 0; i < 4; i++)
        {
                m[12+i] += m[i]*x + m[4+i]*y + m[8+i]*z;
        }
}

void matrixRotateM(float *m, float a, float x, float y, float z)
{
        float rot[16], res[16];
        matrixSetRotateM(rot, a, x, y, z);
        matrixMultiplyMM(res, m, rot);
        memcpy(m, res, 16*sizeof(float));
}

void matrixLookAtM(float *m,
                float eyeX, float eyeY, float eyeZ,
                float cenX, float cenY, float cenZ,
                float  upX, float  upY, float  upZ)
{
        float fx = cenX - eyeX;
        float fy = cenY - eyeY;
        float fz = cenZ - eyeZ;
        normalize(fx, fy, fz);
        float sx = fy * upZ - fz * upY;
        float sy = fz * upX - fx * upZ;
        float sz = fx * upY - fy * upX;
        normalize(sx, sy, sz);
        float ux = sy * fz - sz * fy;
        float uy = sz * fx - sx * fz;
        float uz = sx * fy - sy * fx;

        m[ 0] = sx;
        m[ 1] = ux;
        m[ 2] = -fx;
        m[ 3] = 0.0f;
        m[ 4] = sy;
        m[ 5] = uy;
        m[ 6] = -fy;
        m[ 7] = 0.0f;
        m[ 8] = sz;
        m[ 9] = uz;
        m[10] = -fz;
        m[11] = 0.0f;
        m[12] = 0.0f;
        m[13] = 0.0f;
        m[14] = 0.0f;
        m[15] = 1.0f;
        matrixTranslateM(m, -eyeX, -eyeY, -eyeZ);
}

void matrixFrustumM(float *m, float left, float right, float bottom, float top, float near, float far)
{
        float r_width  = 1.0f / (right - left);
        float r_height = 1.0f / (top - bottom);
        float r_depth  = 1.0f / (near - far);
        float x = 2.0f * (near * r_width);
        float y = 2.0f * (near * r_height);
        float A = 2.0f * ((right+left) * r_width);
        float B = (top + bottom) * r_height;
        float C = (far + near) * r_depth;
        float D = 2.0f * (far * near * r_depth);

        memset((void*)m, 0, 16*sizeof(float));
        m[ 0] = x;
        m[ 5] = y;
        m[ 8] = A;
        m[ 9] = B;
        m[10] = C;
        m[14] = D;
        m[11] = -1.0f;
}

【讨论】:

    【解决方案3】:

    GLM 数学库不仅仅是变换和其他矩阵运算。例如,它具有 GLSL 风格的 mix() api,可用于在将值发送到着色器之前对其进行插值。

    【讨论】:

      【解决方案4】:

      有点晚,但可能与选择使用 C 的人有关:

      我发现了一个单文件标头,它具有很好的写出所需的所有线性功能。

      https://github.com/datenwolf/linmath.h/blob/master/linmath.h

      它包含所有必需的矩阵/向量类型,并且可以与 Android NDK/GL2 完美配合。例如:

      mat4x4 projection;
      mat4x4 modelview;
      
      // other stuff such as initialization etc
      
      mat4x4_frustum(projection, -1, 1, -1, 1, 0.5, 100);
      mat4x4_translate(modelview, 0, 0, -1);
      
      // ...
      
      // Render Operation: mvMatrixHandle and pMatrixHandle are defined previously
      glUniformMatrix4fv(mvMatrixHandle, 1, GL_FALSE, modelview);
      glUniformMatrix4fv(pMatrixHandle, 1, GL_FALSE, projection);
      

      【讨论】:

      • 请添加一些解释。否则,您的答案可能会被标记为“低质量”并最终被删除。 Stackoverflow 对仅链接的答案不太友好,因为链接可能会断开,然后答案变得毫无价值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-14
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多