1

Qtは、透視変換とアフィン変換の両方に 3x3 変換行列を使用します。行列の最後の行が [0 0 1] に等しい場合、行列はアフィンと見なされます。このため、x 軸と y 軸の回転行列は「非アフィン」であり、遠近歪みが生じます。しかし、さらなる影響があります。ユーザーがペイントするすべてのピクセルには、座標 (x、y、1) があります。z 座標を 0 に設定し、回転させてから z を別の値に設定する方法はありません。どういうわけか、任意の点を中心に回転できるようにすることはまだ可能ですか? おそらく、 z をゼロに「近い」値に設定してから回転させることでしょうか?

編集:

やりたいこと、まさに。「通常の」透視投影行列の 3 行目と 3 列目を消すと、 で使用できる行列が得られQtます。また、ウィンドウ マトリックスを使用して に変換しますQGraphicsItem。それは今のところ2つの行列になります:

window * projection

いくつかのコード:

float const w(rect.width());
float const h(rect.height());

// aspect ratio
auto const ar(h / w);

// symmetrical infinite frustum
f_[4] = 1.f;
f_[1] = ::std::tan(.5f * hFov_) * f_[4];
f_[0] = -f_[1];
f_[3] = ar * f_[1];
f_[2] = -f_[3];

// perspective projection matrix
auto const rml(f_[1] - f_[0]);
auto const tmb(f_[3] - f_[2]);

::etl::matrix<float, 3, 3> const pMatrix{
  2.f * f_[4] / rml, 0.f              , (f_[1] + f_[0]) / rml,
  0.f              , 2.f * f_[4] / tmb, (f_[3] + f_[2]) / tmb,
  0.f              , 0.f              , -1.f};

auto const halfW(.5f * w);
auto const halfH(.5f * h);

// window matrix
::etl::matrix<float, 3, 3> const wMatrix{
  halfW, 0.f   , halfW,
  0.f  , -halfH, halfH,
  0.f  , 0.f   , 1.f};

wpvMatrix_ = wMatrix * pMatrix;

QPixmap次に、aを投影する世界に変換します。これは、たとえば次のマトリックスで行われます。

zMatrix =
  worldPixmapWidth / pixmap.width(), 0, p(0),
  0, -worldPixmapHeight / pixmap.height(), p(1),
  0, 0, p(2);

したがってwMatrix * pMatrix * zMatrix、ピックスマップを変換するために使用できます。

pを翻訳したいポイントですQPixmap。これでピックスマップは になりましたp = (p(0), p(1), p(2))。を通り、y 軸に平行な軸を中心に回転させたいと思いpます。どうやってするの?通常は を行いますが、座標T(p) * Ry(phi) * T(-p)を設定できる変換行列がないため、できません。z直接当てるRyと原点を中心に回転します。変換をまったく行わなくても、 は、 にzなりたい1ので、 ではありません。0Ry

4

1 に答える 1