矩阵向量乘法
Matrix-vector Multiplication
例如我有一个名为 Matrix4x4 的 class 并且 class 具有以下功能:
public float[] MultiplyVec(float[] vec){
float[] newV = new float[4];
for(int i = 0; i < 4; i++){
int value = 0;
for(int j = 0; j < 4; j++){
value += matrix[i][j] * vec[j];
}
newV[i] = value;
}
return newV;
}
在另一个 class 中,我有一个对象名称 modelMatrix,它是 Matrix4x4 的一个实例,它是这样初始化的:
public Matrix4x4 modelMatrix = Matrix4x4.IdentityM();
其中IdentityM()函数包含:
public static Matrix4x4 IdentityM(){
return new Matrix4x4(new float[][]{
{1f, 0f, 0f, 0f},
{0f, 1f, 0f, 0f},
{0f, 0f, 1f, 0f},
{0f, 0f, 0f, 1f}
});
}
现在有个小问题想不通。
例如,假设我有一个包含 x、y、宽度和高度的矩形。
例如,现在我这样做:
modelMatrix.translate(0.002f, 0.002f, 0);
其中翻译函数包含:
public void translate(float x, float y, float z){
matrix[0][3] += x;
matrix[1][3] += y;
matrix[2][3] += z;
}
当我将模型矩阵发送到着色器时使用 OpenGL ES,对象正确移动,但是当我使用模型矩阵计算顶点时,它们保持不变并且没有改变,计算顶点的函数是:
public float[] getVertices(){
// Vertices in object space:
float[] vector1 = {x, y, 0f, 1f};
float[] vector2 = {x + width, y, 0f, 1f};
float[] vector3 = {x + width, y + height, 0f, 1f};
float[] vector4 = {x, y, 0f, 1f};
// Calculate the vertices in world space:
float[] vector1r = modelMatrix.MultiplyVec(vector1);
float[] vector2r = modelMatrix.MultiplyVec(vector2);
float[] vector3r = modelMatrix.MultiplyVec(vector3);
float[] vector4r = modelMatrix.MultiplyVec(vector4);
if(LoggerConfig.ON) Log.d("Middle Vertex", vector1r[2] + ", "
+ vector1r[3]);
return new float[] {
vector1r[0], vector1r[1],
vector2r[0], vector2r[1],
vector3r[0], vector3r[1],
vector4r[0], vector4r[1]
};
}
即使我移动对象并且对象在 OpenGL 中移动,日志中的结果也保持不变,这是我正在进行的计算的问题吗?我该如何更正它?
在您的 MultiplyVec()
方法中,您将所有中间值四舍五入为整数:
for(int i = 0; i < 4; i++){
int value = 0;
for(int j = 0; j < 4; j++){
value += matrix[i][j] * vec[j];
}
newV[i] = value;
}
由于value
是int
类型的变量,所有部分和将四舍五入为整数。您需要为中间值使用 float
变量:
for(int i = 0; i < 4; i++){
float value = 0f;
...
例如我有一个名为 Matrix4x4 的 class 并且 class 具有以下功能:
public float[] MultiplyVec(float[] vec){
float[] newV = new float[4];
for(int i = 0; i < 4; i++){
int value = 0;
for(int j = 0; j < 4; j++){
value += matrix[i][j] * vec[j];
}
newV[i] = value;
}
return newV;
}
在另一个 class 中,我有一个对象名称 modelMatrix,它是 Matrix4x4 的一个实例,它是这样初始化的:
public Matrix4x4 modelMatrix = Matrix4x4.IdentityM();
其中IdentityM()函数包含:
public static Matrix4x4 IdentityM(){
return new Matrix4x4(new float[][]{
{1f, 0f, 0f, 0f},
{0f, 1f, 0f, 0f},
{0f, 0f, 1f, 0f},
{0f, 0f, 0f, 1f}
});
}
现在有个小问题想不通。 例如,假设我有一个包含 x、y、宽度和高度的矩形。 例如,现在我这样做:
modelMatrix.translate(0.002f, 0.002f, 0);
其中翻译函数包含:
public void translate(float x, float y, float z){
matrix[0][3] += x;
matrix[1][3] += y;
matrix[2][3] += z;
}
当我将模型矩阵发送到着色器时使用 OpenGL ES,对象正确移动,但是当我使用模型矩阵计算顶点时,它们保持不变并且没有改变,计算顶点的函数是:
public float[] getVertices(){
// Vertices in object space:
float[] vector1 = {x, y, 0f, 1f};
float[] vector2 = {x + width, y, 0f, 1f};
float[] vector3 = {x + width, y + height, 0f, 1f};
float[] vector4 = {x, y, 0f, 1f};
// Calculate the vertices in world space:
float[] vector1r = modelMatrix.MultiplyVec(vector1);
float[] vector2r = modelMatrix.MultiplyVec(vector2);
float[] vector3r = modelMatrix.MultiplyVec(vector3);
float[] vector4r = modelMatrix.MultiplyVec(vector4);
if(LoggerConfig.ON) Log.d("Middle Vertex", vector1r[2] + ", "
+ vector1r[3]);
return new float[] {
vector1r[0], vector1r[1],
vector2r[0], vector2r[1],
vector3r[0], vector3r[1],
vector4r[0], vector4r[1]
};
}
即使我移动对象并且对象在 OpenGL 中移动,日志中的结果也保持不变,这是我正在进行的计算的问题吗?我该如何更正它?
在您的 MultiplyVec()
方法中,您将所有中间值四舍五入为整数:
for(int i = 0; i < 4; i++){
int value = 0;
for(int j = 0; j < 4; j++){
value += matrix[i][j] * vec[j];
}
newV[i] = value;
}
由于value
是int
类型的变量,所有部分和将四舍五入为整数。您需要为中间值使用 float
变量:
for(int i = 0; i < 4; i++){
float value = 0f;
...