webGL : Rotation of a rectangle about a point alon

2019-07-30 18:31发布

Assume I have a rectangle having 4 vertices (x1,y1), (x2,y2) (x3,y3) and (x4,y4). These vertices are in clockwise order.The rectangle is oriented like (x1,y1) is the top most left side corner and (x3,y3) is the bottom most Right Corner.

Now i want to rotate the rectangle around one of the edge i,e along the edge that includes (x2,y2) and (x3,y3).I want to achieve this effect in Shaders by rotating two Vertices (x1,y1) and (x4,y4).

My question is What is the formula for Rotating a point (x1,y1) with an angle Theta around a certain point.

I have searched the older forums and found some relevant information https://stackoverflow.com/a/3162657/1804924

My question is can i use the equation as it is.. because it is like rotation about Y-axis.

标签: webgl
2条回答
走好不送
2楼-- · 2019-07-30 19:06

There's a series of articles that goes over the math for 2D rotations here

https://webglfundamentals.org/webgl/lessons/webgl-2d-rotation.html

It's starts simple and builds up to 2D matrix math which is the most common way to do this stuff

Once you have the matrices working you'd generate a matrix that translates the rectangle so that the point between X2,y2 and x3,y3 is at 0,0. Then generate a matrix that rotates. Then another to translate back. Multiply them all together and you'll get one matrix that does the entire thing.

// Compute the matrices
var rotatePointX = (x2 + x3) / 2;
var rotatePointY = (y2 + y3) / 2;

var moveToRotationPointMatrix = makeTranslation(-rotatePointX, -rotatePointY);
var rotationMatrix = makeRotation(angleInRadians);
var moveBackMatrix = makeTranslation(rotatePointX, rotatePointY);

// Multiply the matrices.
var matrix = matrixMultiply(moveToRotationPointMatrix, rotationMatrix);
matrix = matrixMultiply(matrix, moveBackMatrix);
...

Now use that matrix

Here's an example. It's rotating halfway between around the center of the right edge.

function main() {
  // Get A WebGL context
  var canvas = document.getElementById("canvas");
  var gl = canvas.getContext("webgl");
  if (!gl) {
    return;
  }

  // setup GLSL program
  program = twgl.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
  gl.useProgram(program);

  // look up where the vertex data needs to go.
  var positionLocation = gl.getAttribLocation(program, "a_position");

  // lookup uniforms
  var colorLocation = gl.getUniformLocation(program, "u_color");
  var matrixLocation = gl.getUniformLocation(program, "u_matrix");

  // Create a buffer.
  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.enableVertexAttribArray(positionLocation);
  gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

  // Set Geometry.
  setGeometry(gl);

  // Set a random color.
  gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1);

  var translation = [100, 150];
  var angleInRadians = 0;
  var scale = [1, 1];
    
  // Draw the scene.
  function drawScene() {
    angleInRadians += 0.01;
    // Clear the canvas.
    gl.clear(gl.COLOR_BUFFER_BIT);

    // Compute the matrices
    var projectionMatrix = make2DProjection(canvas.width, canvas.height);

    var x2 = 130;
    var x3 = 130;
    var y2 =  30;
    var y3 = 150;
      
    var rotatePointX = (x2 + x3) / 2;
    var rotatePointY = (y2 + y3) / 2;
      
    var moveToRotationPointMatrix = makeTranslation(-rotatePointX, -rotatePointY);
    var rotationMatrix = makeRotation(angleInRadians);
    var moveBackMatrix = makeTranslation(rotatePointX, rotatePointY);

    // Multiply the matrices.
    var matrix = matrixMultiply(moveToRotationPointMatrix, rotationMatrix);
    matrix = matrixMultiply(matrix, moveBackMatrix);
    matrix = matrixMultiply(matrix, projectionMatrix);
    
    // Set the matrix.
    gl.uniformMatrix3fv(matrixLocation, false, matrix);

    // Draw the geometry.
    gl.drawArrays(gl.TRIANGLES, 0, 6);
      
    requestAnimationFrame(drawScene);
  }
  drawScene();
}

function make2DProjection(width, height) {
  // Note: This matrix flips the Y axis so 0 is at the top.
  return [
    2 / width, 0, 0,
    0, -2 / height, 0,
    -1, 1, 1
  ];
}

function makeTranslation(tx, ty) {
  return [
    1, 0, 0,
    0, 1, 0,
    tx, ty, 1
  ];
}

function makeRotation(angleInRadians) {
  var c = Math.cos(angleInRadians);
  var s = Math.sin(angleInRadians);
  return [
    c,-s, 0,
    s, c, 0,
    0, 0, 1
  ];
}

function makeScale(sx, sy) {
  return [
    sx, 0, 0,
    0, sy, 0,
    0, 0, 1
  ];
}

function matrixMultiply(a, b) {
  var a00 = a[0*3+0];
  var a01 = a[0*3+1];
  var a02 = a[0*3+2];
  var a10 = a[1*3+0];
  var a11 = a[1*3+1];
  var a12 = a[1*3+2];
  var a20 = a[2*3+0];
  var a21 = a[2*3+1];
  var a22 = a[2*3+2];
  var b00 = b[0*3+0];
  var b01 = b[0*3+1];
  var b02 = b[0*3+2];
  var b10 = b[1*3+0];
  var b11 = b[1*3+1];
  var b12 = b[1*3+2];
  var b20 = b[2*3+0];
  var b21 = b[2*3+1];
  var b22 = b[2*3+2];
  return [a00 * b00 + a01 * b10 + a02 * b20,
          a00 * b01 + a01 * b11 + a02 * b21,
          a00 * b02 + a01 * b12 + a02 * b22,
          a10 * b00 + a11 * b10 + a12 * b20,
          a10 * b01 + a11 * b11 + a12 * b21,
          a10 * b02 + a11 * b12 + a12 * b22,
          a20 * b00 + a21 * b10 + a22 * b20,
          a20 * b01 + a21 * b11 + a22 * b21,
          a20 * b02 + a21 * b12 + a22 * b22];
}

// Fill the buffer with the values that make a rect.
function setGeometry(gl) {
  gl.bufferData(
      gl.ARRAY_BUFFER,
      new Float32Array([
           10,  30,
          130,  30,
           10, 150,
           10, 150,
          130,  30,
          130, 150]),
      gl.STATIC_DRAW);
}
main();
canvas {
    border: 1px solid black;
}
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;

uniform mat3 u_matrix;

void main() {
  // Multiply the position by the matrix.
  gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;

uniform vec4 u_color;

void main() {
   gl_FragColor = u_color;
}
</script>
<canvas id="canvas" width="400" height="300"></canvas>

查看更多
我只想做你的唯一
3楼-- · 2019-07-30 19:09

basically to rotate an object around the vector you need to translate(and rotate if needed) it in such way that this vector will appear in middle so your object will be positioned in vectors local coordinate system. then you apply rotation and after it put object back where it was. Here is good helper library.

查看更多
登录 后发表回答