3

行列を使用してベクトルを回転させようとしていますが、混乱しました。

回転行列を作成し、それをベクトルに乗算して回転ベクトルを取得するだけでよいと思いました。

ここでは、 Processingを使用して行った簡単なテストを見ることができます。

テキストの処理

回転をインクリメントするにはaを使用し、軸を変更するには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を使用していませんか?使用する必要がありますか、それともバグですか?ヒントはありますか?

4

2 に答える 2

4

これが原因です:

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;

問題を解決します。

于 2010-10-08T01:01:16.020 に答える
3

PVectorの代わりに、toxiclibsジオメトリクラスを使用することもできます。これは、構文全体をかなり単純化するのに役立ちます。

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;
}

後者は、単純な軸の回転では少し遅くなりますが、同時に他の変換(たとえば、移動など)も行う場合はより理にかなっています。また、どちらの場合も、angleはラジアンであると想定されます。

お役に立てば幸いです。

于 2010-10-08T19:34:35.910 に答える