如何在处理中使用矩阵旋转向量?

发布于 2024-09-26 23:28:22 字数 2466 浏览 7 评论 0原文

我试图使用矩阵旋转向量,但感到困惑。

我认为我需要做的就是创建一个旋转矩阵并将其乘以一个向量以获得旋转向量。

在这里您可以看到我使用 处理

处理文本

使用a< /strong> 增加旋转,x/y/z 更改轴。

这是来源:

PVector[] clone,face = {new PVector(50,0,50),new PVector(-50,0,50),new PVector(-50, 0, -50),new PVector(50, 0, -50)};
color faceC = color(255,0,0),cloneC = color(0,255,0);
float angle = 90;
PVector x = new PVector(1,0,0),y = new PVector(0,1,0),z = new PVector(0,0,1), axis = x;
PFont ocr;

void setup(){
  size(400,400,P3D);
  strokeWeight(1.1610855);smooth();
  clone = rotateVerts(face,angle,axis);
  ocr = loadFont("ocr.vlw");
}
void draw(){
  background(255);
  fill(0);textFont(ocr,10);text("a = increment rotation\nx/y/z = change axis\nrotation: " + angle + "\naxis: " + axis,10,10,200,200);fill(255);
  translate(width*.5,height*.5);
  rotateX(map(mouseY,height*.5,-height*.5,0,TWO_PI));
  rotateY(map(mouseX,0,width,0,TWO_PI));
    drawQuad(face,faceC);
    drawQuad(clone,cloneC);
  stroke(128,0,0);line(0,0,0,100,0,0);stroke(0,128,0);line(0,0,0,0,-100,0);stroke(0,0,128);line(0,0,0,0,0,100);
}
void keyPressed(){
  if(key == 'a') angle += 15;
  if(angle > 360) angle -= 360;
  if(key == 'x') axis = x;
  if(key == 'y') axis = y;
  if(key == 'z') axis = z;
  clone = rotateVerts(face,angle,axis);
}
PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){
  int vl = verts.length;
  PVector[] clone = new PVector[vl];
  for(int i = 0; i<vl;i++) clone[i] = PVector.add(verts[i],new PVector());
  //rotate using a matrix
  PMatrix3D rMat = new PMatrix3D();
  rMat.rotate(radians(angle),axis.x,axis.y,axis.z);
  for(int i = 0; i<vl;i++) rMat.mult(clone[i],clone[i]);
  return clone;
}
void drawQuad(PVector[] verts,color c){
  stroke(c);
  beginShape(QUADS);
    for(int i = 0 ; i < 4; i++) vertex(verts[i].x,verts[i].y,verts[i].z);
  endShape();
}

处理带有 PVectorPMatrix3D

我是否没有使用 PMatrix 他们应该使用它还是这是一个错误? 有什么提示吗?

I am trying to rotate vectors using matrices, but got confused.

I thought all I needed to do is create a rotation matrix and multiply it to a vector to get the rotated vector.

Here you can see a simple test I've done using Processing:

processing text

Use a to increment rotation, and x/y/z to changes the axis.

And here is source:

PVector[] clone,face = {new PVector(50,0,50),new PVector(-50,0,50),new PVector(-50, 0, -50),new PVector(50, 0, -50)};
color faceC = color(255,0,0),cloneC = color(0,255,0);
float angle = 90;
PVector x = new PVector(1,0,0),y = new PVector(0,1,0),z = new PVector(0,0,1), axis = x;
PFont ocr;

void setup(){
  size(400,400,P3D);
  strokeWeight(1.1610855);smooth();
  clone = rotateVerts(face,angle,axis);
  ocr = loadFont("ocr.vlw");
}
void draw(){
  background(255);
  fill(0);textFont(ocr,10);text("a = increment rotation\nx/y/z = change axis\nrotation: " + angle + "\naxis: " + axis,10,10,200,200);fill(255);
  translate(width*.5,height*.5);
  rotateX(map(mouseY,height*.5,-height*.5,0,TWO_PI));
  rotateY(map(mouseX,0,width,0,TWO_PI));
    drawQuad(face,faceC);
    drawQuad(clone,cloneC);
  stroke(128,0,0);line(0,0,0,100,0,0);stroke(0,128,0);line(0,0,0,0,-100,0);stroke(0,0,128);line(0,0,0,0,0,100);
}
void keyPressed(){
  if(key == 'a') angle += 15;
  if(angle > 360) angle -= 360;
  if(key == 'x') axis = x;
  if(key == 'y') axis = y;
  if(key == 'z') axis = z;
  clone = rotateVerts(face,angle,axis);
}
PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){
  int vl = verts.length;
  PVector[] clone = new PVector[vl];
  for(int i = 0; i<vl;i++) clone[i] = PVector.add(verts[i],new PVector());
  //rotate using a matrix
  PMatrix3D rMat = new PMatrix3D();
  rMat.rotate(radians(angle),axis.x,axis.y,axis.z);
  for(int i = 0; i<vl;i++) rMat.mult(clone[i],clone[i]);
  return clone;
}
void drawQuad(PVector[] verts,color c){
  stroke(c);
  beginShape(QUADS);
    for(int i = 0 ; i < 4; i++) vertex(verts[i].x,verts[i].y,verts[i].z);
  endShape();
}

Processing comes with a PVector and PMatrix3D which I've used.

Am I not using PMatrix they it should be used or is this a bug ?
Any hints ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

擦肩而过的背影 2024-10-03 23:28:22

这就是罪魁祸首:

rMat.mult(clone[i],clone[i]);

这样做并不安全,因为与 C 或 JAVA 不同,源随着操作的进行而变化。

将函数末尾更改为:

PVector[] dst = new PVector[vl];
for(int i = 0; i<vl;i++) dst[i] = new PVector();
for(int i = 0; i<vl;i++) rMat.mult(clone[i],dst[i]);
return dst;

将解决该问题。

This is the culprit:

rMat.mult(clone[i],clone[i]);

this is not safe to do, because unlike in C or JAVA, the source is changing as the operation proceeds.

changing the end of the function to:

PVector[] dst = new PVector[vl];
for(int i = 0; i<vl;i++) dst[i] = new PVector();
for(int i = 0; i<vl;i++) rMat.mult(clone[i],dst[i]);
return dst;

will resolve the issue.

荒岛晴空 2024-10-03 23:28:22

除了PVector,您还可以使用有毒库几何类,这将有助于大大简化整个语法:

import toxi.geom.*;

Vec3D[] rotateVerts(Vec3D[] verts, float angle, Vec3D axis){
  Vec3D[] clone = new Vec3D[verts.length];
  for(int i = 0; i<verts.length;i++)
    clone[i] = verts[i].getRotatedAroundAxis(axis,angle);
  return clone;
}

或者使用矩阵进行变换:

Vec3D[] rotateVerts(Vec3D[] verts, float angle, Vec3D axis){
  Matrix4x4 mat=new Matrix4x4();
  mat.rotateAroundAxis(axis,angle);
  Vec3D[] clone = new Vec3D[verts.length];
  for(int i = 0; i<verts.length;i++) clone[i] = mat.applyTo(verts[i]);
  return clone;
}

后者对于简单的轴旋转来说会稍微慢一些,但会产生更多的效果如果您同时进行其他转换(例如翻译等),请注意。另外,在这两种情况下,角度都被假定为弧度......

希望有帮助!

Instead of PVector, you could also use the toxiclibs geometry classes, which would help to simplify the whole syntax quite a bit:

import toxi.geom.*;

Vec3D[] rotateVerts(Vec3D[] verts, float angle, Vec3D axis){
  Vec3D[] clone = new Vec3D[verts.length];
  for(int i = 0; i<verts.length;i++)
    clone[i] = verts[i].getRotatedAroundAxis(axis,angle);
  return clone;
}

Or using a matrix to do the transform:

Vec3D[] rotateVerts(Vec3D[] verts, float angle, Vec3D axis){
  Matrix4x4 mat=new Matrix4x4();
  mat.rotateAroundAxis(axis,angle);
  Vec3D[] clone = new Vec3D[verts.length];
  for(int i = 0; i<verts.length;i++) clone[i] = mat.applyTo(verts[i]);
  return clone;
}

The latter will be slightly slower for just a simple axis rotation, but makes more sense if you also do other transformations at the same time (e.g. translate etc.). Also, in both cases, the angle is assumed to be in radians...

Hope that helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文