1

Code: https://plnkr.co/edit/QNA31hMYnIJwotwbaDhT?p=preview

Question: How can I interpolate all properties of fromRotationTranslationScaleOrigin from gl-matrixin draw function of this cube?

Let's interpolate over 3 seconds: from:

q = quat.create(),
translate =[-3, 0, -10],
scale = [1,1,1],
pivot = [0,0,0]

to:

q = quat.create(),
translate =[0, 0, -8],
scale = [3,3,3],
pivot = [1,1,1]

Program:

var gl,
    shaderProgram,
    vertices,
    matrix = mat4.create(),
    vertexCount,
    indexCount,
    q = quat.create(),
    translate =[-3, 0, -10],
    scale = [1,1,1],
    pivot = [0,0,0];


initGL();
createShaders();
createVertices();
createIndices();
draw();

function initGL() {
  var canvas = document.getElementById("canvas");
  gl = canvas.getContext("webgl");
  gl.enable(gl.DEPTH_TEST);
  gl.viewport(0, 0, canvas.width, canvas.height);
  gl.clearColor(1, 1, 1, 1);
}

function createShaders() {
  var vertexShader = getShader(gl, "shader-vs");
  var fragmentShader = getShader(gl, "shader-fs");

  shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  gl.useProgram(shaderProgram);
}

function createVertices() {
  vertices = [
    -1, -1, -1,     1, 0, 0, 1,     // 0
     1, -1, -1,     1, 1, 0, 1,     // 1
    -1,  1, -1,     0, 1, 1, 1,     // 2
     1,  1, -1,     0, 0, 1, 1,     // 3
    -1,  1,  1,     1, 0.5, 0, 1,   // 4
     1,  1,  1,     0.5, 1, 1, 1,   // 5
    -1, -1,  1,     1, 0, 0.5, 1,   // 6
     1, -1,  1,     0.5, 0, 1, 1,   // 7
  ];

  vertexCount = vertices.length / 7;

  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

  var coords = gl.getAttribLocation(shaderProgram, "coords");
  gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, 0);
  gl.enableVertexAttribArray(coords);  

  var colorsLocation = gl.getAttribLocation(shaderProgram, "colors");
  gl.vertexAttribPointer(colorsLocation, 4, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, Float32Array.BYTES_PER_ELEMENT * 3);

  gl.enableVertexAttribArray(colorsLocation);
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  var pointSize = gl.getAttribLocation(shaderProgram, "pointSize");
  gl.vertexAttrib1f(pointSize, 20);

//   var color = gl.getUniformLocation(shaderProgram, "color");
//   gl.uniform4f(color, 0, 0, 0, 1);

  var perspectiveMatrix = mat4.create();
  mat4.perspective(perspectiveMatrix, 1, canvas.width / canvas.height, 0.1, 11);
  var perspectiveLoc = gl.getUniformLocation(shaderProgram, "perspectiveMatrix");
  gl.uniformMatrix4fv(perspectiveLoc, false, perspectiveMatrix);

}

function createIndices() {
  var indices = [
    0, 1, 2,   1, 2, 3,
    2, 3, 4,   3, 4, 5,
    4, 5, 6,   5, 6, 7,
    6, 7, 0,   7, 0, 1,
    0, 2, 6,   2, 6, 4,
    1, 3, 7,   3, 7, 5
  ];
  indexCount = indices.length;

  var indexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices), gl.STATIC_DRAW);


}

function draw() {

  mat4.fromRotationTranslationScaleOrigin(
    matrix,
    q,
    translate,
    scale,
    pivot
  );

  var transformMatrix = gl.getUniformLocation(shaderProgram, "transformMatrix");
  gl.uniformMatrix4fv(transformMatrix, false, matrix);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_BYTE, 0);
  requestAnimationFrame(draw);
}


  /*
   * https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context
   */
  function getShader(gl, id) {
    var shaderScript, theSource, currentChild, shader;

    shaderScript = document.getElementById(id);

    if (!shaderScript) {
      return null;
    }

    theSource = "";
    currentChild = shaderScript.firstChild;

    while (currentChild) {
      if (currentChild.nodeType == currentChild.TEXT_NODE) {
        theSource += currentChild.textContent;
      }

      currentChild = currentChild.nextSibling;
    }
    if (shaderScript.type == "x-shader/x-fragment") {
      shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
      shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
      // Unknown shader type
      return null;
    }
    gl.shaderSource(shader, theSource);

// Compile the shader program
    gl.compileShader(shader);

// See if it compiled successfully
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
      return null;
    }

    return shader;
  }
<canvas id="canvas" width="600" height="600"></canvas>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>

  <script id="shader-vs" type="x-shader/x-vertex">
  attribute vec4 coords;
  attribute float pointSize;
  uniform mat4 transformMatrix;
  attribute vec4 colors;
  varying vec4 varyingColors;
  uniform mat4 perspectiveMatrix;
  void main(void) {
    gl_Position = perspectiveMatrix * transformMatrix  * coords;
    gl_PointSize = pointSize;
    varyingColors = colors;
  }
  </script>

  <script id="shader-fs" type="x-shader/x-fragment">
  precision mediump float;
  uniform vec4 color;
  varying vec4 varyingColors;
  void main(void) {
    gl_FragColor = varyingColors;
  }
  </script>

1 Answer 1

0

To the call back function of requestAnimationFrame is passe one single argument, which is a time value.
This time can be used to calculate a matrix by a function of time.

function draw(timeMs) {
    requestAnimationFrame(draw);

    let interval = timeMs / 3000; // 3000 ms are 3 seconds
    let t = interval - Math.floor(interval);  

    // [...]
}

Use vec3.lerp to interpolate the translation, pivot and scale, dependent on the time interval t:

function draw(timeMs) {

    // [...]

    let trans_t = vec3.lerp([], translate, translate2, t);
    let scale_t = vec3.lerp([], scale, scale2, t);
    let pivot_t = vec3.lerp([], pivot, pivot2, t);

    mat4.fromRotationTranslationScaleOrigin(matrix, q, trans_t, scale_t, pivot_t);

    // [...]

}

See the example, where I applied the suggestions to the code of the question:

var gl,
    shaderProgram,
    vertices,
    matrix = mat4.create(),
    vertexCount,
    indexCount,
    q = quat.create(),
    translate =[-3, 0, -10],
    scale = [1,1,1],
    pivot = [0,0,0];
    
    translate2 = [0, 0, -8],
    scale2 = [3,3,3],
    pivot2 = [1,1,1]


initGL();
createShaders();
createVertices();
createIndices();
draw();

function initGL() {
  var canvas = document.getElementById("canvas");
  gl = canvas.getContext("webgl");
  gl.enable(gl.DEPTH_TEST);
  gl.viewport(0, 0, canvas.width, canvas.height);
  gl.clearColor(1, 1, 1, 1);
}

function createShaders() {
  var vertexShader = getShader(gl, "shader-vs");
  var fragmentShader = getShader(gl, "shader-fs");

  shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  gl.useProgram(shaderProgram);
}

function createVertices() {
  vertices = [
    -1, -1, -1,     1, 0, 0, 1,     // 0
     1, -1, -1,     1, 1, 0, 1,     // 1
    -1,  1, -1,     0, 1, 1, 1,     // 2
     1,  1, -1,     0, 0, 1, 1,     // 3
    -1,  1,  1,     1, 0.5, 0, 1,   // 4
     1,  1,  1,     0.5, 1, 1, 1,   // 5
    -1, -1,  1,     1, 0, 0.5, 1,   // 6
     1, -1,  1,     0.5, 0, 1, 1,   // 7
  ];

  vertexCount = vertices.length / 7;

  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

  var coords = gl.getAttribLocation(shaderProgram, "coords");
  gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, 0);
  gl.enableVertexAttribArray(coords);  

  var colorsLocation = gl.getAttribLocation(shaderProgram, "colors");
  gl.vertexAttribPointer(colorsLocation, 4, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, Float32Array.BYTES_PER_ELEMENT * 3);

  gl.enableVertexAttribArray(colorsLocation);
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  var pointSize = gl.getAttribLocation(shaderProgram, "pointSize");
  gl.vertexAttrib1f(pointSize, 20);

//   var color = gl.getUniformLocation(shaderProgram, "color");
//   gl.uniform4f(color, 0, 0, 0, 1);

  var perspectiveMatrix = mat4.create();
  mat4.perspective(perspectiveMatrix, 1, canvas.width / canvas.height, 0.1, 11);
  var perspectiveLoc = gl.getUniformLocation(shaderProgram, "perspectiveMatrix");
  gl.uniformMatrix4fv(perspectiveLoc, false, perspectiveMatrix);

}

function createIndices() {
  var indices = [
    0, 1, 2,   1, 2, 3,
    2, 3, 4,   3, 4, 5,
    4, 5, 6,   5, 6, 7,
    6, 7, 0,   7, 0, 1,
    0, 2, 6,   2, 6, 4,
    1, 3, 7,   3, 7, 5
  ];
  indexCount = indices.length;

  var indexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices), gl.STATIC_DRAW);


}

function draw(timeMs) {
  requestAnimationFrame(draw);

  let interval = timeMs / 3000
  let t = interval - Math.floor(interval); 

  let trans_t = vec3.lerp([], translate, translate2, t);
  let scale_t = vec3.lerp([], scale, scale2, t);
  let pivot_t = vec3.lerp([], pivot, pivot2, t);

  mat4.fromRotationTranslationScaleOrigin(matrix, q, trans_t, scale_t, pivot_t);

  var transformMatrix = gl.getUniformLocation(shaderProgram, "transformMatrix");
  gl.uniformMatrix4fv(transformMatrix, false, matrix);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_BYTE, 0);
}


  /*
   * https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context
   */
  function getShader(gl, id) {
    var shaderScript, theSource, currentChild, shader;

    shaderScript = document.getElementById(id);

    if (!shaderScript) {
      return null;
    }

    theSource = "";
    currentChild = shaderScript.firstChild;

    while (currentChild) {
      if (currentChild.nodeType == currentChild.TEXT_NODE) {
        theSource += currentChild.textContent;
      }

      currentChild = currentChild.nextSibling;
    }
    if (shaderScript.type == "x-shader/x-fragment") {
      shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
      shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
      // Unknown shader type
      return null;
    }
    gl.shaderSource(shader, theSource);

// Compile the shader program
    gl.compileShader(shader);

// See if it compiled successfully
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
      return null;
    }

    return shader;
  }
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 coords;
attribute float pointSize;
uniform mat4 transformMatrix;
attribute vec4 colors;
varying vec4 varyingColors;
uniform mat4 perspectiveMatrix;
void main(void) {
  gl_Position = perspectiveMatrix * transformMatrix  * coords;
  gl_PointSize = pointSize;
  varyingColors = colors;
}
</script>

<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 color;
varying vec4 varyingColors;
void main(void) {
  gl_FragColor = varyingColors;
}
</script>

<canvas id="canvas" width="600" height="600"></canvas>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.