我正在用C使用opengl es 2.0和NDK编写渲染例程。我对基于矩阵的图形转换(速度超过精度)库以及任何可推荐的最佳实践感兴趣。C矩阵库,适合在Android上使用opengl(NDK)
写我自己的功能并不是不可能的,但我想我会在重新发明车轮之前问这里。谢谢。
我正在用C使用opengl es 2.0和NDK编写渲染例程。我对基于矩阵的图形转换(速度超过精度)库以及任何可推荐的最佳实践感兴趣。C矩阵库,适合在Android上使用opengl(NDK)
写我自己的功能并不是不可能的,但我想我会在重新发明车轮之前问这里。谢谢。
OpenGL Mathematics (GLM)似乎是一个不错的选择。
谢谢,这个结果很好。虽然我要求一个C库,但是cpp的方向值得采纳。仅供参考:要使用此库,请务必使用stlport,请参阅CPLUSPLUS-SUPPORT文档了解操作方法。 – LazyBitStream 2011-03-07 01:46:08
我无法使用NDK进行编译。我在'sizeof'之前得到错误,比如'func_common.hpp:240:错误:在'sizeof'或'func_common.inl:1217:error:expected')之前预期的不合格id。 – j00hi 2011-09-15 16:57:22
你不能只使用内建的Java矩阵类(例如http://developer.android.com/reference/android/opengl/Matrix.html)来进行转换吗?
你特别想做什么(即什么类型的变换)?已经建立了许多常见的转换:(例如参见this)
感谢您的回复,但不幸的是您的示例涵盖了opengl es 1.0(固定功能流水线)。这些内置函数在opengl es 2.0中不存在。 – LazyBitStream 2011-03-05 05:16:12
对于矩阵库,这是非常有用的,但看看它的来源,它是一些本地调用的Java混合。我想尽可能避免从C中调用java。 – LazyBitStream 2011-03-05 05:20:40
GLM数学库不仅仅是变换和其他矩阵运算。例如,它具有GLSL样式mix()api,可以在将值发送到着色器之前对其进行插值。
从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;
}
有点晚,但可能对那些谁选择用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不会太热情地链接回答。 – 2016-03-05 21:22:28
要回答我自己的问题,我可能会写我自己的例程,使用这个写得很好的代码作为参考。 https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/google/resources/moz/matrix4x4.js – LazyBitStream 2011-03-05 05:17:21