How to convert vertices without changing the format?

If I want to change the size or position of an object in WebGL, I take the initial data of the vertices {x, y, z} of this object and pass it to the vertex shader, where it is multiplied by a matrix that contains information about the transformations, as a result of which a new set is created coordinates, which is known only to my GPU, but invisible to me.

This works great because the only thing that matters is the image on the screen, but I want to be able to save the converted vertices without additional information about matrix multiplications, just like x, y, z-values, like the original data.

The idea was to take the last step in multiplying the transformation matrix by the original vertex data in my own language in JavaScript, but I just don't get it working!

I wrote the following function to multiply a 4x4 matrix with an array of x, y, z values, adding a fourth value {1.0} to change the vec3 data into vec4 data ...

function matrixVectorProduct (mat4, data) { var result = new Array( ); for (var i = 0; i < data.length / 3; i++) { var n = i * 3; var vec4 = [data[n], data[n + 1], data[n + 2], 1.0]; var x = mat4[0] * vec4[0] + mat4[1] * vec4[1] + mat4[2] * vec4[2] + mat4[3] * vec4[3]; var y = mat4[4] * vec4[0] + mat4[5] * vec4[1] + mat4[6] * vec4[2] + mat4[7] * vec4[3]; var z = mat4[8] * vec4[0] + mat4[9] * vec4[1] + mat4[10] * vec4[2] + mat4[11] * vec4[3]; var w = mat4[12] * vec4[0] + mat4[13] * vec4[1] + mat4[14] * vec4[2] + mat4[15] * vec4[3]; result.push(x, y, z, w); } return result; } 

... but besides the fact that I have no idea how to convert vec4 values ​​back to vec3 values, there should be something wrong with the concept as a whole:

Suppose we have vertices for a simple triangle of type

 var vertices = [0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0]; 

and we create a 4x4 matrix with

 function createMat4 ( ) { var mat4 = new Float32Array(16); mat4[0] = 1; mat4[1] = 0; mat4[2] = 0; mat4[3] = 0; mat4[4] = 0; mat4[5] = 1; mat4[6] = 0; mat4[7] = 0; mat4[8] = 0; mat4[9] = 0; mat4[10] = 1; mat4[11] = 0; mat4[12] = 0; mat4[13] = 0; mat4[14] = 0; mat4[15] = 1; return mat4; } 

translate it into - let's say [0, 0, -5] - using this function

 function translateMat4 (mat4, vec3) { var x = vec3[0], y = vec3[1], z = vec3[2]; var a = mat4; mat4[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; mat4[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; mat4[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; mat4[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; return mat4; } 

and finally, multiply the created and translated matrix by the vertex data stored in vertices using the matrixVectorProduct function noted above, the result should be

 translatedVertices = [0.0, 1.0, -5.0, -1.0, -1.0, -5.0, 1.0, -1.0, -5.0]; 

but it is just [x, y, z, 1] because -5 x 0.0 (z-value) is 0, so it cannot work that way.

What am I doing wrong?

+5
source share
1 answer

You are very close. I will implement it from the very beginning, just for the case.

Allows you to have a simple triangle model with vertices:

 var triangleVertices = [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]; 

Now we create mat4, which represents all the transformations made on this model. No transformation is represented by an identity matrix, each of which is 0, and 1 is diagonal.

 var identityMatrix = [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ]; var modelMatrix = identityMatrix.slice(0); // slice = clone the array 

We are ready to carry out translations, rotation or scaling. The best way to apply it to a model is to create another mat4 that will represent our desired transformation, and then multiply the model matrix by the transformation matrix. Thus, we can make several transformations in the desired order with just a few operations with matrices, and now we do not need to worry about vertices.

So, let's create a translation matrix that will be the easiest. You start with the identity matrix, and you should only change the mat [12, 13, 14], which is x, y, z.

translate it into - let's say [0, 0, -5] - using this function

 var translate = [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,-5.0, 1.0 ]; 

The transformation matrix is ​​done, and we want to multiply it by our model matrix. Animation matrices are a transformation, any transformation. The function for matrix multiplication that I have done right now. It should work, I hope :) A mathematical source from the wiki.

 var mat4Multiply = (function () { function ABProduct(i, j, a, b) { var k, sum = 0; for (k = 0; k < 4; k++) { sum += a[i * 4 + k] * b[j + k * 4]; } return sum; } function mat4Multiply(a, b) { var i, j, product = []; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { product[i * 4 + j] = ABProduct(i, j, a, b); } } return product; } return mat4Multiply; })(); // a = model matrix, b = transformation 

Just to demonstrate how to do multiplication, short code:

 modelMatrix = mat4Multiply(modelMatrix, translate); // but now I change my mind and I want to move model again by another 3 in Z translate = [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 3.0, 1.0 ]; modelMatrix = mat4Multiply(modelMatrix, translate); // after this content of the modelMatrix is: // [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -2, 1] 

Now we need to do only the final vertex transformation. As I said, translation is the simplest conversion, so I will only perform the translation function, this is a related wiki article .

Note

Do not confuse this picture: enter image description here

This was the view used in OpenGL, but later we decided to use a transposed version of the matrix, which is a simple operation in the following figure:

http://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Matrix_transpose.gif/200px-Matrix_transpose.gif

END NOTE

Translation Function:

 function vec3TranslateMat4(vec, mat4) { vec[0] += mat4[12]; vec[1] += mat4[13]; vec[2] += mat4[14]; return vec; } 

To translate the vertices of a triangle, you should only do:

 var i, vertex; for(i=0;i<triangleVertices.length;i+=3) { vertex = triangleVertices.slice(i, i+3); vertex = vec3TranslateMat4(vertex, modelMatrix) triangleVertices[i] = vertex[0]; triangleVertices[i+1] = vertex[1]; triangleVertices[i+2] = vertex[2]; } 

Once we have applied the transformation matrix, we must again set the model matrix to unity. After that, we can do new transformations, but on modified vertices.

And we are done. Personaly I use gl matrix library , which already contains all the operations for matrices and vectors that I need.

Transformations with and without matrices

All transformations could be done without matrices. But the matrix allows us to store the current location in one variable without the need to immediately convert the vertices. The vertex transformations are long and long.

Another good reason is that you can use only a few basic functions, mat4Multiply and vec3TransformMat4 (I did not show you this one). See how rotation and scale are integrated into the matrix (the left side of the image, the right side is the camera).

enter image description here

+1
source

All Articles