webGL:围绕Y轴的点旋转矩形

时间:2012-11-07 04:53:30

标签: webgl

假设我有一个有4个顶点(x1,y1), (x2,y2) (x3,y3) and (x4,y4)的矩形。这些顶点按顺时针顺序排列。矩形的方向类似于(x1,y1)是最左侧的角落,(x3,y3)是最右下角。

现在我想沿着包含(x2,y2)和(x3,y3)的边缘围绕其中一个边缘旋转矩形。我希望通过旋转两个顶点(x1,在着色器中实现此效果) y1)和(x4,y4)。

我的问题是旋转点(x1,y1)的公式是什么,角度Theta围绕某一点。

我搜索了较旧的论坛并找到了一些相关信息 https://stackoverflow.com/a/3162657/1804924

我的问题是我可以使用方程式,因为它就像绕Y轴旋转一样。

2 个答案:

答案 0 :(得分:7)

这里有一系列关于2D旋转数学的文章

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

它开始很简单并且构建到2D矩阵数学,这是最常用的方法

一旦矩阵工作,你就会生成一个矩阵来转换矩形,使得X2,y2和x3,y3之间的点为0,0。然后生成一个旋转的矩阵。然后另一个翻译回来。将它们相乘,您将获得一个完成整个过程的矩阵。

// 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);
...

现在使用那个矩阵

这是一个例子。它在右边缘中心周围旋转。

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>

答案 1 :(得分:1)

基本上围绕你需要平移的矢量旋转一个物体(并在需要时旋转),使得这个矢量将出现在中间,这样你的物体就会被定位在矢量局部坐标系中。然后你应用旋转,然后将物体放回原处。 Here是好帮手库。