1

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

现在我想围绕其中一个边缘旋转矩形,即沿着包括(x2,y2)和(x3,y3)的边缘。我想通过旋转两个顶点(x1,y1)和(x4,y4)。

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

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

我的问题是我可以按原样使用方程式吗?因为它就像围绕 Y 轴旋转。

4

2 回答 2

8

这里有一系列文章介绍了 2D 旋转的数学运算

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

它开始很简单,并建立了二维矩阵数学,这是最常见的方法

一旦你的矩阵工作了,你就会生成一个矩阵来平移矩形,这样 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>

于 2012-11-08T07:56:52.277 回答
1

基本上要围绕您需要平移(并在需要时旋转)它的向量旋转对象,以使该向量将出现在中间,因此您的对象将定位在向量局部坐标系中。然后你应用旋转,然后将对象放回原来的位置。是好帮手库。

于 2012-11-08T05:45:11.933 回答