Javascript matrix multiplication by scalar - javascript

I have an object called Cube. It is set up like this
//Cube object
function Cube(vertices, color, scale)
{
//this.vertices = vertices;
this.setColor(color);
this.setScale(vertices, 1);
}
I commented out //this.vertices = vertices; because im not sure if I have to set vertices here or set them within setScale() function.
I want to set a scale on a matrix. The matrix is:
var verts = [
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
The function i use to set the scale is like this:
Cube.prototype.setScale = function(vertices, scale)
{
var length = vertices.length;
for( var i = 0; i < length; i++)
{
//alert("before "+ vertices[i]+ " i "+ i);
vertices[i] *= scale;
//alert("after "+ vertices[i]);
}
I think that by doing this the for loop should take the matrix length and start a for loop.
Within this for loop I will get the vertice at i and multiply it by the scale.
When I do it like this though the for loop will reiterate. I.e. when i hits 72 the loop does not stop.

I commented out //this.vertices = vertices; because im not sure if I have to set vertices here
You either need to set it there or at the end of the constructor. Your setScale function is nicely decoupled from where the vertices array is stored and I'd keep it that way. But you might consider renaming it scaleVertices() instead.
When I do it like this though the for loop will reiterate. I.e. when i hits 72 the loop does not stop.
Really? That's odd. I must be missing something; the code looks correct.
Don't use alert(), by the way, it will make your life hell to debug anything. You're much better using console.log().

Related

Draw quad (interleaved) in three.js

I'm trying to draw a quad in three.js, but three.js keeps complaining that 'tex' is not a 'WebGLTexture' and refuse to run, what's going on here? thank you.
// z= depth, tex is texture
function drawQuad(z, tex)
{
var verts = [
-1.0, 1.0, z, 0.0, 1.0,
-1.0, -1.0, z, 0.0, 0.0,
1.0, 1.0, z, 1.0, 1.0,
1.0, -1.0, z, 1.0, 0.0,
];
const gl = renderer.getContext();
gl.disable(gl.DEPTH_TEST);
gl.useProgram(quadShader);
var vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 20, 0);
gl.enableVertexAttribArray(1);
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 20, 12);
gl.uniform1i(gl.getUniformLocation(quadShader, 'su_tex'), 0)
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
gl.enable(gl.DEPTH_TEST);
}
tex is loaded like this
wallTex = loader.load("https://r105.threejsfundamentals.org/threejs/resources/images/wall.jpg");
drawQuad(1.0, wallTex);
Ok, i've figured it out.
Anyway, this may help those who are still confused (c++ opengl pragrammers):
WebGlTexture is the id you created with glGenTextures(1, &texturId), it is for rendering.
THREE.js.Texture is a texture container, it contains texture descriptions and image data downloaded from web or whatever, it has a hidden property __webglTexture which is null if this THREE.js.Texture never been used for rendering. then what if it has been used for rendering? it will create a WebGLTexture (via glGenTextures(1, &textureId) internally i guess) and assign this WebGlTexture id to its __webglTexture, and now you can use it for rendering.
It might be more appropriate to call THREE.js.Texture as THREE.js.TextrureRes IMO, less mis-leading.

WebGL transformation matrices in shader or in the application

I'm studying WebGl transformations and I understood the it is possible to build transformation matrices in the application (Javascript file) or in the shader programs (html).
For example I can write all the code about a rotation matrix on the x axis directly in the GLSL program :
uniform mat 4 rx;
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, s.x, 0.0,
0.0, -s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0 );
Or i can write it into the Javascript file and use the :
rx = context.getUniformLocation(program, "rx");
To specify the value of my uniform.
I would like to understand which is the best choice and why.
Thanks for the help.

Initializing a javascript object containing an array

I have the following C++ struct which I want to create as faithfully as possible in Javascript:
struct Vertex
{
float coords[4];
float colors[4];
};
So I did the following:
function Vertex(coords, colors)
{
this.coords = [];
this.colors = [];
}
Now, the following works to create a Vertex instance:
var oneVertex = new Vertex();
oneVertex.coords = [20.0, 20.0, 0.0, 1.0];
oneVertex.colors = [0.0, 0.0, 0.0, 1.0];
but the following (slicker?) doesn't:
var oneVertex = new Vertex([20.0, 20.0, 0.0, 1.0],
[0.0, 0.0, 0.0, 1.0]);
Why? I am new to Javascript and what little I have read suggests it should be ok. Obviously not. It would be helpful to understand what I am missing. Thanks.
you need to use the arguments passed in to the function for it to work, as:
function Vertex(coords, colors)
{
this.coords = coords || [];
this.colors = colors || [];
}
You're constructor should initialize the properties:
function Vertex(coords, colors)
{
this.coords = coords;
this.colors = colors;
}
var oneVertex = new Vertex([20.0, 20.0, 0.0, 1.0],
[0.0, 0.0, 0.0, 1.0]);

How to create a geometry out of an array in JavaScript with Three.js?

Which one is the best (fastest) method to create a geometry out of this data-array? I create the Array on-the-fly and can also create a object instead of an array. Everything that I can do to improve this would be perfect.
Data (x,y,z):
var data = [
[-500,0,-500],
[-496,0,-500],
[-492,0,-500],
//..
[488,0,496],
[492,0,496],
[496,0,496]
];
//data.length: 62500
My way:
var geo = new THREE.Geometry();
for(i = 0; i < data.length; i++)
geo.vertices.push(data[i][0],data[i][1],data[i][2]);
And then I loop trough all vertices and create the faces to get a terrain (like the following picture, but not flat)
If you are looking for speed, I suggest using BufferGeometry.
It uses a flat Float23Array to reduce the cost of sending data to the GPU.
e.g.
var geometry = new THREE.BufferGeometry();
// create a simple square shape. We duplicate the top left and bottom right
// vertices because each vertex needs to appear once per triangle.
var vertices = new Float32Array([
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0
]);
// itemSize = 3 because there are 3 values (components) per vertex
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var mesh = new THREE.Mesh( geometry, material );
Source https://threejs.org/docs/#api/en/core/BufferGeometry

glmatrix.js anomaly - changing order of transforms does not change outcome

In creating a webgl "hello world" for demonstration to a high school class, I am experiencing an anomalous result.
Using gl-matrix.js version 2.2.0, reversing the order of two transforms does not produce a difference in output.
This code produces the desired result:
function DrawScene(gl) {
var time_now = new Date();
var elapsed_time = new Date();
elapsed_time.setDate(time_program_started - time_now);
var projection_matrix = mat4.create();
var modelview_matrix = mat4.create();
var mvp = mat4.create();
gl.viewport(0, 0, gl.size[0], gl.size[1]);
gl.clearColor(0.2, 0.2, 0.2, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
mat4.perspective(projection_matrix, D2R(50.0), gl.size[0] / gl.size[1], 1.0, 10.0);
mat4.translate(modelview_matrix, modelview_matrix, [0.0, 0.0, -3.5]);
mat4.rotate(modelview_matrix, modelview_matrix, D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0]);
mat4.multiply(mvp, projection_matrix, modelview_matrix);
triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}
namely a triangle that spins in place about its Y axis.
Reversing the order of the translate and rotate should spin the triangle around the camera (part of my intended lesson), but instead continues to spin the triangle in place. I sanity checked this in an equivalent legacy OpenGL "hello world" producing exactly the expected results.
The vertex shader simply multiples the vertex position attribute with the mvp uniform. Is there a problem in gl-matrix.js or in this code?
For completeness, here is the render function.
Triangle.prototype.Render = function (gl, shader_index, color, mvp) {
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertex_buffer_object);
gl.vertexAttribPointer(shaders[shader_index].VP, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaders[shader_index].VP);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.element_buffer_object);
shaders[shader_index].Use(gl);
gl.uniformMatrix4fv(shaders[shader_index].MVP, false, mvp);
if (shader_index == 0)
gl.uniform4fv(shaders[shader_index].COLOR, color);
else {
gl.bindBuffer(gl.ARRAY_BUFFER, this.color_buffer_object);
gl.vertexAttribPointer(shaders[shader_index].COLOR, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaders[shader_index].COLOR);
}
gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
shaders[shader_index].StopUsing(gl);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
Thank you.
I believe there is an error in my use of gl-matrix or gl-matrix itself. Replacing gl-matrix with mjs.js works as expacted.
function DrawScene(gl) {
var time_now = new Date();
var elapsed_time = new Date();
elapsed_time.setDate(time_program_started - time_now);
var projection_matrix = M4x4.I;
var modelview_matrix = M4x4.I;
var mvp = M4x4.I;
gl.viewport(0, 0, gl.size[0], gl.size[1]);
gl.clearColor(0.2, 0.2, 0.2, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
projection_matrix = M4x4.makePerspective(50.0, gl.size[0] / gl.size[1], 1.0, 10.0);
modelview_matrix = M4x4.rotate(D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0], modelview_matrix);
modelview_matrix = M4x4.translate([0.0, 0.0, -5.5], modelview_matrix);
mvp = M4x4.mul(projection_matrix, modelview_matrix);
triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}
Does indeed rotate about the camera. Reversing to translate then rotate spins about the Y axis of the triangle.
I would be very pleased to have my code for gl-matrix corrected. If it cannot, gl-matrix is very broken.

Categories

Resources