DrawPolygon3D関数を使って画像を傾けさせる関数を作っているのですが、座標の計算がどうしても出来ません。
仕様は、
・画像の角度を0度にすると今までどおりに表示。
・角度を0度以上にすると画像の右側を奥側にする。
・角度を0度以下にすると画像の左側を奥側にする。
・また、別角度を入力し、上下にも適用させる。
という風ににしたのですが、角度に元ずく計算がどうしてもわかりません。
どうすればよいでしょうか?
DrawPolygon3D関数について
Re:DrawPolygon3D関数について
>角度に元ずく計算がどうしてもわかりません
画像(ポリゴン)の初期状態がカメラの方を向いている、と仮定した状態で
右や左を奥に(Y軸回転)するには CreateRotationYMatrix()を使って
指定した角度だけY軸で回転させた行列を作り、SetTransformToWorld()に
ワールド行列として設定し DrawPolygon3D()で描画、でいいと思います。
X軸回転も同様に CreateRotationXMatrix()で指定できますが、
これと CreateRotationYMatrix()を併用する場合は
2つの行列を CreateMultiplyMatrix()で掛け合わせてワールド行列と
して下さい。
テストはしていませんが、だいたいこんな感じです。
[color=#d0d0ff" face="monospace]
MATRIX matResult, m;
// 移動
CreateTranslationMatrix(&matResult, pos.x, pos.y, pos.z);
// 回転Y
CreateRotationYMatrix(&m, rotateY);
CreateMultiplyMatrix(&matResult, &m, &matResult);
// 回転X
CreateRotationXMatrix(&m, rotateX);
CreateMultiplyMatrix(&matResult, &m, &matResult);
// 描画
SetTransformToWorld(&matResult);
DrawPolygon3DBase(vertex, 4, DX_PRIMTYPE_TRIANGLESTRIP, mg, FALSE);
[/color]
Re:DrawPolygon3D関数について
角度に元ずく計算は行列を使えばよいというのはわかりましたが、その行列を座標(VERTEX_3D)に変換するにはどうすればよいのでしょう?
Re:DrawPolygon3D関数について
>その行列を座標(VERTEX_3D)に変換するにはどうすればよいのでしょう?
なるほど。
つまり、角度を指定して表示はしたいけど、SetTransformToWorld()を使わないで
あえて VERTEX_3Dの方を変更して表示したいのですね。
だとするとオリジナルの頂点情報は別途保持しておかないといけなくなりますが、
先で求めた行列を使って
[color=#d0d0ff" face="monospace]
VERTEX_3D orgVer[4] = { }; // 元の頂点情報
VERTEX_3D destVer[4]; // 表示の時に使う頂点情報
for(int n=0; n<4; ++n)
VectorTransform(&destVer[n].pos, &orgVer[n].pos, &matResult);
[/color]のように VectorTransform()を使って変換できます。
Re:DrawPolygon3D関数について
さくっとサンプルを作ってみました。
(表示には適当なテクスチャ "test.png"が必要です)
左(DrawTransRotatePolygon1)に表示されているのは一般的な SetTransformToWorld()を
使って表示したもので、右(DrawTransRotatePolygon2)に表示されているものは VERTEX_3Dを
直接変更して表示したものです。
キーボード上下左右で回転します。
[color=#d0d0ff" face="monospace]
#include "DxLib.h"
#include <cstdlib>
// 行列計算
void CalcRotateMatrix(MATRIX *pMatResult, const VECTOR& pos, const VECTOR &rot)
{
// 移動
MATRIX m;
CreateTranslationMatrix(pMatResult, pos.x, pos.y, pos.z);
// 回転Z
CreateRotationZMatrix(&m, rot.z);
CreateMultiplyMatrix(pMatResult, &m, pMatResult);
// 回転Y
CreateRotationYMatrix(&m, rot.y);
CreateMultiplyMatrix(pMatResult, &m, pMatResult);
// 回転X
CreateRotationXMatrix(&m, rot.x);
CreateMultiplyMatrix(pMatResult, &m, pMatResult);
}
// ワールド行列を変更して表示
void DrawTransRotatePolygon1(int img, VERTEX_3D *vertex, int vertexNum, const VECTOR& pos, const VECTOR &rot)
{
// 行列計算
MATRIX matResult, matOrgWorld;
CalcRotateMatrix(&matResult, pos, rot);
GetTransformToWorldMatrix(&matOrgWorld);
// 描画
SetTransformToWorld(&matResult);
DrawPolygon3DBase(vertex, vertexNum, DX_PRIMTYPE_TRIANGLESTRIP, img, FALSE);
SetTransformToWorld(&matOrgWorld);
}
// 頂点を変更して表示
void DrawTransRotatePolygon2(int img, VERTEX_3D *vertex, int vertexNum, const VECTOR& pos, const VECTOR &rot)
{
// 行列計算
MATRIX matResult;
CalcRotateMatrix(&matResult, pos, rot);
// 座標計算
VERTEX_3D *v = (VERTEX_3D*)std::malloc(sizeof(VERTEX_3D) * vertexNum);
if(v == NULL) return;
for(int n=0; n<vertexNum; ++n)
{
v[n] = vertex[n];
VectorTransform(&v[n].pos, &v[n].pos, &matResult);
}
// 描画
DrawPolygon3DBase(v, vertexNum, DX_PRIMTYPE_TRIANGLESTRIP, img, FALSE);
std::free(v);
}
// カメラ設定
void SetDefaultCamera()
{
MATRIX cam;
VECTOR vCamPos = { 0, 0, 100 }, vCamAt = { 0, 0, 0 }, vCamUp = { 0, 1, 0 };
CreateLookAtMatrix(&cam, &vCamPos, &vCamAt, &vCamUp);
SetTransformToView(&cam);
}
// 頂点情報
const float basePosX = 0.f, basePosY = 0.f, basePosZ = 0.f, baseLengh = 20.f;
VERTEX_3D vertex[/url] =
{
{ basePosX - baseLengh, basePosY + baseLengh, basePosZ, 255, 255, 255, 255, 0.f, 0.f },
{ basePosX - baseLengh, basePosY - baseLengh, basePosZ, 255, 255, 255, 255, 0.f, 1.f },
{ basePosX + baseLengh, basePosY + baseLengh, basePosZ, 255, 255, 255, 255, 1.f, 0.f },
{ basePosX + baseLengh, basePosY - baseLengh, basePosZ, 255, 255, 255, 255, 1.f, 1.f },
};
[/color]
長いので、次に続きます。
(表示には適当なテクスチャ "test.png"が必要です)
左(DrawTransRotatePolygon1)に表示されているのは一般的な SetTransformToWorld()を
使って表示したもので、右(DrawTransRotatePolygon2)に表示されているものは VERTEX_3Dを
直接変更して表示したものです。
キーボード上下左右で回転します。
[color=#d0d0ff" face="monospace]
#include "DxLib.h"
#include <cstdlib>
// 行列計算
void CalcRotateMatrix(MATRIX *pMatResult, const VECTOR& pos, const VECTOR &rot)
{
// 移動
MATRIX m;
CreateTranslationMatrix(pMatResult, pos.x, pos.y, pos.z);
// 回転Z
CreateRotationZMatrix(&m, rot.z);
CreateMultiplyMatrix(pMatResult, &m, pMatResult);
// 回転Y
CreateRotationYMatrix(&m, rot.y);
CreateMultiplyMatrix(pMatResult, &m, pMatResult);
// 回転X
CreateRotationXMatrix(&m, rot.x);
CreateMultiplyMatrix(pMatResult, &m, pMatResult);
}
// ワールド行列を変更して表示
void DrawTransRotatePolygon1(int img, VERTEX_3D *vertex, int vertexNum, const VECTOR& pos, const VECTOR &rot)
{
// 行列計算
MATRIX matResult, matOrgWorld;
CalcRotateMatrix(&matResult, pos, rot);
GetTransformToWorldMatrix(&matOrgWorld);
// 描画
SetTransformToWorld(&matResult);
DrawPolygon3DBase(vertex, vertexNum, DX_PRIMTYPE_TRIANGLESTRIP, img, FALSE);
SetTransformToWorld(&matOrgWorld);
}
// 頂点を変更して表示
void DrawTransRotatePolygon2(int img, VERTEX_3D *vertex, int vertexNum, const VECTOR& pos, const VECTOR &rot)
{
// 行列計算
MATRIX matResult;
CalcRotateMatrix(&matResult, pos, rot);
// 座標計算
VERTEX_3D *v = (VERTEX_3D*)std::malloc(sizeof(VERTEX_3D) * vertexNum);
if(v == NULL) return;
for(int n=0; n<vertexNum; ++n)
{
v[n] = vertex[n];
VectorTransform(&v[n].pos, &v[n].pos, &matResult);
}
// 描画
DrawPolygon3DBase(v, vertexNum, DX_PRIMTYPE_TRIANGLESTRIP, img, FALSE);
std::free(v);
}
// カメラ設定
void SetDefaultCamera()
{
MATRIX cam;
VECTOR vCamPos = { 0, 0, 100 }, vCamAt = { 0, 0, 0 }, vCamUp = { 0, 1, 0 };
CreateLookAtMatrix(&cam, &vCamPos, &vCamAt, &vCamUp);
SetTransformToView(&cam);
}
// 頂点情報
const float basePosX = 0.f, basePosY = 0.f, basePosZ = 0.f, baseLengh = 20.f;
VERTEX_3D vertex[/url] =
{
{ basePosX - baseLengh, basePosY + baseLengh, basePosZ, 255, 255, 255, 255, 0.f, 0.f },
{ basePosX - baseLengh, basePosY - baseLengh, basePosZ, 255, 255, 255, 255, 0.f, 1.f },
{ basePosX + baseLengh, basePosY + baseLengh, basePosZ, 255, 255, 255, 255, 1.f, 0.f },
{ basePosX + baseLengh, basePosY - baseLengh, basePosZ, 255, 255, 255, 255, 1.f, 1.f },
};
[/color]
長いので、次に続きます。
Re:DrawPolygon3D関数について
[color=#d0d0ff" face="monospace]
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hP, LPSTR lpC, int nC)
{
// 初期化
ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return(-1);
SetDrawScreen(DX_SCREEN_BACK);
int img = LoadGraph("test.png");
const float pi = 3.1415926535f, offsetRotate = 1.f * pi / 180.f;
VECTOR p1 = { 20, 0, 0 }, p2 = { -20, 0, 0 }, rot = { 0 };
// カメラ設定
SetDefaultCamera();
//メインループ
while(ProcessMessage() == 0)
{
char key[256];
GetHitKeyStateAll(key);
if(key[KEY_INPUT_ESCAPE]) break;
if(key[KEY_INPUT_DOWN]) rot.x += offsetRotate;
if(key[KEY_INPUT_UP]) rot.x -= offsetRotate;
if(key[KEY_INPUT_LEFT]) rot.y += offsetRotate;
if(key[KEY_INPUT_RIGHT]) rot.y -= offsetRotate;
ClearDrawScreen();
DrawTransRotatePolygon1(img, vertex, 4, p1, rot);
DrawTransRotatePolygon2(img, vertex, 4, p2, rot);
ScreenFlip();
}
DxLib_End();
return 0;
}
[/color]
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hP, LPSTR lpC, int nC)
{
// 初期化
ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return(-1);
SetDrawScreen(DX_SCREEN_BACK);
int img = LoadGraph("test.png");
const float pi = 3.1415926535f, offsetRotate = 1.f * pi / 180.f;
VECTOR p1 = { 20, 0, 0 }, p2 = { -20, 0, 0 }, rot = { 0 };
// カメラ設定
SetDefaultCamera();
//メインループ
while(ProcessMessage() == 0)
{
char key[256];
GetHitKeyStateAll(key);
if(key[KEY_INPUT_ESCAPE]) break;
if(key[KEY_INPUT_DOWN]) rot.x += offsetRotate;
if(key[KEY_INPUT_UP]) rot.x -= offsetRotate;
if(key[KEY_INPUT_LEFT]) rot.y += offsetRotate;
if(key[KEY_INPUT_RIGHT]) rot.y -= offsetRotate;
ClearDrawScreen();
DrawTransRotatePolygon1(img, vertex, 4, p1, rot);
DrawTransRotatePolygon2(img, vertex, 4, p2, rot);
ScreenFlip();
}
DxLib_End();
return 0;
}
[/color]
Re:DrawPolygon3D関数について
すごいです!
ちょうどこのような機能を持たせたかったのですが、自分ではうまくいきませんでした。
行列にはこのような使い方もあるんですね。
ありがとうございました。
ちょうどこのような機能を持たせたかったのですが、自分ではうまくいきませんでした。
行列にはこのような使い方もあるんですね。
ありがとうございました。