使用 GLM(旋转)为 OpenGL 创建变换矩阵
Creating a transformation matrix for OpenGL with GLM (Rotations)
原问题:
问题
我有一个 unit cube,我想将其转换为连接两点。我是 OpenGL 的新手,只知道线性代数的最基本部分。在我努力连接点的过程中,我试图模仿类似于极坐标的东西。当 Z 和另一个轴发生变化时,我当前的实现不起作用。我也试过mat = glm::lookAt(center, terminal, y_axis);
,但是没有成功。
代码
这来自位于 schedule_edge_update()
的 for 循环体。
auto const initial = p1;
auto const terminal = p2;
auto const distance = glm::distance(initial, terminal);
auto const length = distance * 0.5f;
auto const center = (initial + terminal) / 2.f;
auto const rejection = terminal - initial;
auto const delta = glm::normalize(rejection);
auto mat = glm::mat4(1);
// translate
mat = glm::translate(mat, center);
// rotate
auto const phi_hyp = glm::length(glm::vec2(delta.x, delta.z));
if (phi_hyp != 0.0f) {
auto phi = acosf(delta.x / phi_hyp);
mat = glm::rotate(mat, phi, y_axis);
}
auto const theta_hyp = glm::length(glm::vec2(delta.x, delta.y));
if (theta_hyp != 0.0f) {
auto theta = acosf(delta.x / theta_hyp);
theta *= delta.x > 0 ? -1.0f : 1.0f;
mat = glm::rotate(mat, theta, z_axis);
}
// scale
edges->add_matrix(glm::scale(mat, glm::vec3(length, 0.05f, 0.01f)));
将矩阵添加到 edges
后,它会排队等待缓冲以进行实例化渲染。
远方
这是我的测试点和我制作的一个大立方体。
特写
这是一个它不起作用的例子。起点标记为 p1,终点标记为 p2。不连接任何点的线应该连接 p1 和 p2。
不同的特写
这是另一个例子,但是这个例子标出了 p1 和 p2 的坐标。 p1 和 p2 的区别在于 Y 和 Z 的变化。但是,我的代码将立方体(在平移之后)围绕 y 轴旋转 90 度。然后是缩放它。您可以看出它已旋转,因为它在其中一个轴(旋转前的 y 轴)上更宽。
完整坐标列表
// Test points
auto const A = glm::vec3(-10.0f, -10.0f, -20.0f);
auto const B = glm::vec3(+10.0f, -10.0f, -20.0f);
auto const C = glm::vec3(+10.0f, +10.0f, -20.0f);
auto const D = glm::vec3(+00.0f, +10.0f, -20.0f);
auto const E = glm::vec3(+05.0f, +05.0f, -20.0f);
auto const F = glm::vec3(+00.0f, +00.0f, -30.0f);
auto const G = glm::vec3(-10.0f, -10.0f, -30.0f);
auto const H = glm::vec3(+55.0f, -15.0f, -60.0f);
auto const I = glm::vec3(+55.0f, -05.0f, -70.0f);
get_nodes().emplace_back(A);
get_nodes().emplace_back(B);
get_nodes().emplace_back(C);
get_nodes().emplace_back(D);
get_nodes().emplace_back(E);
get_nodes().emplace_back(F);
get_nodes().emplace_back(G);
get_nodes().emplace_back(H);
get_nodes().emplace_back(I);
get_edges().emplace_back(A, B);
get_edges().emplace_back(B, C);
get_edges().emplace_back(C, D);
get_edges().emplace_back(D, E);
get_edges().emplace_back(E, F);
get_edges().emplace_back(F, G);
get_edges().emplace_back(G, H);
get_edges().emplace_back(H, I);
// Big cube
auto const C0 = glm::vec3(-5.0f, -5.0f, -5.0f);
auto const C1 = glm::vec3(-5.0f, -5.0f, +5.0f);
auto const C2 = glm::vec3(-5.0f, +5.0f, -5.0f);
auto const C3 = glm::vec3(-5.0f, +5.0f, +5.0f);
auto const C4 = glm::vec3(+5.0f, -5.0f, -5.0f);
auto const C5 = glm::vec3(+5.0f, -5.0f, +5.0f);
auto const C6 = glm::vec3(+5.0f, +5.0f, -5.0f);
auto const C7 = glm::vec3(+5.0f, +5.0f, +5.0f);
get_nodes().emplace_back(C0);
get_nodes().emplace_back(C1);
get_nodes().emplace_back(C2);
get_nodes().emplace_back(C3);
get_nodes().emplace_back(C4);
get_nodes().emplace_back(C5);
get_nodes().emplace_back(C6);
get_nodes().emplace_back(C7);
get_edges().emplace_back(C0, C1);
get_edges().emplace_back(C0, C2);
get_edges().emplace_back(C0, C4);
get_edges().emplace_back(C1, C3);
get_edges().emplace_back(C1, C5);
get_edges().emplace_back(C2, C3);
get_edges().emplace_back(C2, C6);
get_edges().emplace_back(C3, C7);
get_edges().emplace_back(C4, C5);
get_edges().emplace_back(C4, C6);
get_edges().emplace_back(C5, C7);
get_edges().emplace_back(C6, C7);
schedule_node_update();
schedule_edge_update();
Spektre 使用 GLM 的解决方案
代码
auto constexpr A = vec3(-0.5f, 0.0f, 0.0f);
auto constexpr B = vec3(+0.5f, 0.0f, 0.0f);
auto const C = p1;
auto const D = p2;
auto M = mat4(1.0f);
// Translate
auto const center = 0.5 * (C + D);
M = translate(M, center);
// Rotate
auto constexpr p = B - A;
auto const q = D - C;
auto const n = cross(p, q);
if (n != vec3()) {
auto const a = angle(normalize(p), normalize(q));
M = rotate(M, a, n);
}
// Scale
auto constexpr thickness = 0.05f;
M = scale(M, vec3(0.5f * distance(C, D), thickness, thickness));
edges->add_matrix(M);
成功的结果
所以问题归结为:
我知道 4 个点 A,B,C,D
,我想计算将 A,B
转换为 C,D
的变换矩阵。
可以这样做。假设我们像这样转换点:
M * A = C
M * B = D
其中 M
是我们要计算的变换矩阵。有无数种可能的解决方案(因为直线 AB
可以在其自身的轴上任意旋转)
如果你 只是知道位置、方向和比例的问题。
比例最简单
就是变换前后线长的比值
scale = |CD|/|AB|
方向
它由单位基向量表示。我们可以利用 AB 和 CD 只有一次旋转(所有其他只产生无限数量的解决方案)这一事实,所以我们可以将 AB
旋转 AB
、CD
之间的角度围绕垂直于 AB
、CD
的轴。我们可以通过平行于AB
,CD
的单位向量之间的点积acos得到的角度。唯一的问题是不会给我们旋转方向,所以我们需要测试两种可能性 (CW,CCW)。
所以:
axis = cross(B-A,D-C)
angle = +/- acos(dot(B-A,D-C) / |B-A|*|D-C|)
翻译
这个很简单,我们只需将 A
转换为 M
,无需翻译,我们称之为 A'
,然后只需更正结果位置,使其变为 C
。
M_origin += C-A'
注意翻译应该直接设置,而不是应用翻译矩阵。那些通常在本地坐标系 [LCS]
中转换,这涉及首先将差异转换为它。在这种情况下使用
translate(Inverse(M)*(C-A'))
或
translate(M*(C-A'))
取决于使用的符号。
这里小C++/VCL/oldGL例子:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include "gl_simple.h"
#include "OpenGLrep4d_double.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
double arot=0.0; // just animation angle
//---------------------------------------------------------------------------
const int pnts=8;
double pnt[pnts*3]= // Vertexes for 10x10x10 cube centered at (0,0,0)
{
-5.0,-5.0,-5.0,
-5.0,+5.0,-5.0,
+5.0,+5.0,-5.0,
+5.0,-5.0,-5.0,
-5.0,-5.0,+5.0,
-5.0,+5.0,+5.0,
+5.0,+5.0,+5.0,
+5.0,-5.0,+5.0,
};
const int lins=12;
int lin[lins*2]= // lines (index of point used) no winding rule
{
0,1,1,2,2,3,3,0,
4,5,5,6,6,7,7,4,
0,4,1,5,2,6,3,7,
};
double A[3]={-5.0,-5.0,-5.0}; // cube diagonal
double B[3]={+5.0,+5.0,+5.0};
double C[3]={-4.5, 2.0, 0.0}; // wanted cube diagonal
double D[3]={+4.5, 5.0, 0.0};
double M[16]; // our transform matrix
//---------------------------------------------------------------------------
void compute_M()
{
double scale,p[3],q[3],n[3],a;
const double deg=180.0/M_PI;
const double rad=M_PI/180.0;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// scale
vector_sub(p,B,A); // p=B-A
vector_sub(q,D,C); // q=D-C
scale=vector_len(q)/vector_len(p); // =|q|/|p|
// rotation between AB and CD
vector_mul(n,p,q); // n = (p x q) ... cross product
vector_one(p,p); // p = p/|p|
vector_one(q,q); // q = q/|q|
a=acos(vector_mul(p,q)); // angle between AB and CD in [rad]
glLoadIdentity(); // unit matrix
glRotated(+a*deg,n[0],n[1],n[2]); // rotate by angle around normal to AB,CD
glScaled(scale,scale,scale); // apply scale
glGetDoublev(GL_MODELVIEW_MATRIX,M); // get the M from OpenGL
// translation
matrix_mul_vector(p,M,A); // p = M*A
vector_sub(p,C,p); // p = C-p
M[12]=p[0];
M[13]=p[1];
M[14]=p[2];
M[15]=1.0;
// verify
matrix_mul_vector(p,M,B); // p = M*B
vector_sub(p,p,D); // p = p-C
if (vector_len(p)>1e-3) // if |p| too big use other direction to rotate
{
glLoadIdentity(); // unit matrix
glRotated(-a*deg,n[0],n[1],n[2]); // rotate by angle around normal to AB,CD
glScaled(scale,scale,scale); // apply scale
glGetDoublev(GL_MODELVIEW_MATRIX,M); // get the M from OpenGL
}
glPopMatrix();
}
//---------------------------------------------------------------------------
void gl_draw() // main rendering code
{
int i;
double m0[16],m1[16],m[16],x[3],y[3],z[3],t2[3][3];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0.0,0.0,-50.0);
glRotated(15.0,1.0,0.0,0.0);
glRotated(arot,0.0,1.0,0.0);
glBegin(GL_LINES);
glColor3f(1.0,0.0,0.0); for (i=0;i<lins*2;i++) glVertex3dv(pnt+(lin[i]*3)); // render original cube
glColor3f(0.0,1.0,0.0); glVertex3dv(A); glVertex3dv(B); // render original diagonal AB
glColor3f(1.0,1.0,0.0); glVertex3dv(C); glVertex3dv(D); // render wanted diagonal CD
glEnd();
// render transformed cube
glMatrixMode(GL_MODELVIEW);
glMultMatrixd(M);
glBegin(GL_LINES);
glColor3f(0.0,0.0,1.0); for (i=0;i<lins*2;i++) glVertex3dv(pnt+(lin[i]*3)); // render transformed cube
glEnd();
glFlush();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
// application init
gl_init(Handle);
compute_M();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
// application exit
gl_exit();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
// window resize
gl_resize(ClientWidth,ClientHeight);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
// window repaint
gl_draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
arot+=1.5; if (arot>=360.0) arot-=360.0;
gl_draw();
}
//---------------------------------------------------------------------------
忽略 VCL 相关的东西。您可以在这里找到 GL 支持函数:
这里唯一重要的东西是 compute_M()
和全局变量。
矢量数学函数已被注释(因此您可以将其转换为 GLM)如果您需要实现,您可以在上面链接的 QA 中找到它们。基本上需要。为简单起见,我使用了 GL 原生旋转(注意它们是度数而不是弧度)。
此处预览:
red
是原始立方体
green
是原来的对角线AB
blue
是由 M
变换的立方体
yellow
要对角CD
如您所见,它是匹配的。
如果您需要对齐的不仅仅是一条线,您需要添加更多对齐信息(例如 2 条线(3 点))等。有关更多信息,请参阅:
- Problem superimposing and aligning 3D triangles
原问题:
问题
我有一个 unit cube,我想将其转换为连接两点。我是 OpenGL 的新手,只知道线性代数的最基本部分。在我努力连接点的过程中,我试图模仿类似于极坐标的东西。当 Z 和另一个轴发生变化时,我当前的实现不起作用。我也试过mat = glm::lookAt(center, terminal, y_axis);
,但是没有成功。
代码
这来自位于 schedule_edge_update()
的 for 循环体。
auto const initial = p1;
auto const terminal = p2;
auto const distance = glm::distance(initial, terminal);
auto const length = distance * 0.5f;
auto const center = (initial + terminal) / 2.f;
auto const rejection = terminal - initial;
auto const delta = glm::normalize(rejection);
auto mat = glm::mat4(1);
// translate
mat = glm::translate(mat, center);
// rotate
auto const phi_hyp = glm::length(glm::vec2(delta.x, delta.z));
if (phi_hyp != 0.0f) {
auto phi = acosf(delta.x / phi_hyp);
mat = glm::rotate(mat, phi, y_axis);
}
auto const theta_hyp = glm::length(glm::vec2(delta.x, delta.y));
if (theta_hyp != 0.0f) {
auto theta = acosf(delta.x / theta_hyp);
theta *= delta.x > 0 ? -1.0f : 1.0f;
mat = glm::rotate(mat, theta, z_axis);
}
// scale
edges->add_matrix(glm::scale(mat, glm::vec3(length, 0.05f, 0.01f)));
将矩阵添加到 edges
后,它会排队等待缓冲以进行实例化渲染。
远方
这是我的测试点和我制作的一个大立方体。
特写
这是一个它不起作用的例子。起点标记为 p1,终点标记为 p2。不连接任何点的线应该连接 p1 和 p2。
不同的特写
这是另一个例子,但是这个例子标出了 p1 和 p2 的坐标。 p1 和 p2 的区别在于 Y 和 Z 的变化。但是,我的代码将立方体(在平移之后)围绕 y 轴旋转 90 度。然后是缩放它。您可以看出它已旋转,因为它在其中一个轴(旋转前的 y 轴)上更宽。
完整坐标列表
// Test points
auto const A = glm::vec3(-10.0f, -10.0f, -20.0f);
auto const B = glm::vec3(+10.0f, -10.0f, -20.0f);
auto const C = glm::vec3(+10.0f, +10.0f, -20.0f);
auto const D = glm::vec3(+00.0f, +10.0f, -20.0f);
auto const E = glm::vec3(+05.0f, +05.0f, -20.0f);
auto const F = glm::vec3(+00.0f, +00.0f, -30.0f);
auto const G = glm::vec3(-10.0f, -10.0f, -30.0f);
auto const H = glm::vec3(+55.0f, -15.0f, -60.0f);
auto const I = glm::vec3(+55.0f, -05.0f, -70.0f);
get_nodes().emplace_back(A);
get_nodes().emplace_back(B);
get_nodes().emplace_back(C);
get_nodes().emplace_back(D);
get_nodes().emplace_back(E);
get_nodes().emplace_back(F);
get_nodes().emplace_back(G);
get_nodes().emplace_back(H);
get_nodes().emplace_back(I);
get_edges().emplace_back(A, B);
get_edges().emplace_back(B, C);
get_edges().emplace_back(C, D);
get_edges().emplace_back(D, E);
get_edges().emplace_back(E, F);
get_edges().emplace_back(F, G);
get_edges().emplace_back(G, H);
get_edges().emplace_back(H, I);
// Big cube
auto const C0 = glm::vec3(-5.0f, -5.0f, -5.0f);
auto const C1 = glm::vec3(-5.0f, -5.0f, +5.0f);
auto const C2 = glm::vec3(-5.0f, +5.0f, -5.0f);
auto const C3 = glm::vec3(-5.0f, +5.0f, +5.0f);
auto const C4 = glm::vec3(+5.0f, -5.0f, -5.0f);
auto const C5 = glm::vec3(+5.0f, -5.0f, +5.0f);
auto const C6 = glm::vec3(+5.0f, +5.0f, -5.0f);
auto const C7 = glm::vec3(+5.0f, +5.0f, +5.0f);
get_nodes().emplace_back(C0);
get_nodes().emplace_back(C1);
get_nodes().emplace_back(C2);
get_nodes().emplace_back(C3);
get_nodes().emplace_back(C4);
get_nodes().emplace_back(C5);
get_nodes().emplace_back(C6);
get_nodes().emplace_back(C7);
get_edges().emplace_back(C0, C1);
get_edges().emplace_back(C0, C2);
get_edges().emplace_back(C0, C4);
get_edges().emplace_back(C1, C3);
get_edges().emplace_back(C1, C5);
get_edges().emplace_back(C2, C3);
get_edges().emplace_back(C2, C6);
get_edges().emplace_back(C3, C7);
get_edges().emplace_back(C4, C5);
get_edges().emplace_back(C4, C6);
get_edges().emplace_back(C5, C7);
get_edges().emplace_back(C6, C7);
schedule_node_update();
schedule_edge_update();
Spektre 使用 GLM 的解决方案
代码
auto constexpr A = vec3(-0.5f, 0.0f, 0.0f);
auto constexpr B = vec3(+0.5f, 0.0f, 0.0f);
auto const C = p1;
auto const D = p2;
auto M = mat4(1.0f);
// Translate
auto const center = 0.5 * (C + D);
M = translate(M, center);
// Rotate
auto constexpr p = B - A;
auto const q = D - C;
auto const n = cross(p, q);
if (n != vec3()) {
auto const a = angle(normalize(p), normalize(q));
M = rotate(M, a, n);
}
// Scale
auto constexpr thickness = 0.05f;
M = scale(M, vec3(0.5f * distance(C, D), thickness, thickness));
edges->add_matrix(M);
成功的结果
所以问题归结为:
我知道 4 个点 A,B,C,D
,我想计算将 A,B
转换为 C,D
的变换矩阵。
可以这样做。假设我们像这样转换点:
M * A = C
M * B = D
其中 M
是我们要计算的变换矩阵。有无数种可能的解决方案(因为直线 AB
可以在其自身的轴上任意旋转)
如果你
比例最简单
就是变换前后线长的比值
scale = |CD|/|AB|
方向
它由单位基向量表示。我们可以利用 AB 和 CD 只有一次旋转(所有其他只产生无限数量的解决方案)这一事实,所以我们可以将
AB
旋转AB
、CD
之间的角度围绕垂直于AB
、CD
的轴。我们可以通过平行于AB
,CD
的单位向量之间的点积acos得到的角度。唯一的问题是不会给我们旋转方向,所以我们需要测试两种可能性 (CW,CCW)。所以:
axis = cross(B-A,D-C) angle = +/- acos(dot(B-A,D-C) / |B-A|*|D-C|)
翻译
这个很简单,我们只需将
A
转换为M
,无需翻译,我们称之为A'
,然后只需更正结果位置,使其变为C
。M_origin += C-A'
注意翻译应该直接设置,而不是应用翻译矩阵。那些通常在本地坐标系
[LCS]
中转换,这涉及首先将差异转换为它。在这种情况下使用translate(Inverse(M)*(C-A'))
或
translate(M*(C-A'))
取决于使用的符号。
这里小C++/VCL/oldGL例子:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include "gl_simple.h"
#include "OpenGLrep4d_double.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
double arot=0.0; // just animation angle
//---------------------------------------------------------------------------
const int pnts=8;
double pnt[pnts*3]= // Vertexes for 10x10x10 cube centered at (0,0,0)
{
-5.0,-5.0,-5.0,
-5.0,+5.0,-5.0,
+5.0,+5.0,-5.0,
+5.0,-5.0,-5.0,
-5.0,-5.0,+5.0,
-5.0,+5.0,+5.0,
+5.0,+5.0,+5.0,
+5.0,-5.0,+5.0,
};
const int lins=12;
int lin[lins*2]= // lines (index of point used) no winding rule
{
0,1,1,2,2,3,3,0,
4,5,5,6,6,7,7,4,
0,4,1,5,2,6,3,7,
};
double A[3]={-5.0,-5.0,-5.0}; // cube diagonal
double B[3]={+5.0,+5.0,+5.0};
double C[3]={-4.5, 2.0, 0.0}; // wanted cube diagonal
double D[3]={+4.5, 5.0, 0.0};
double M[16]; // our transform matrix
//---------------------------------------------------------------------------
void compute_M()
{
double scale,p[3],q[3],n[3],a;
const double deg=180.0/M_PI;
const double rad=M_PI/180.0;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// scale
vector_sub(p,B,A); // p=B-A
vector_sub(q,D,C); // q=D-C
scale=vector_len(q)/vector_len(p); // =|q|/|p|
// rotation between AB and CD
vector_mul(n,p,q); // n = (p x q) ... cross product
vector_one(p,p); // p = p/|p|
vector_one(q,q); // q = q/|q|
a=acos(vector_mul(p,q)); // angle between AB and CD in [rad]
glLoadIdentity(); // unit matrix
glRotated(+a*deg,n[0],n[1],n[2]); // rotate by angle around normal to AB,CD
glScaled(scale,scale,scale); // apply scale
glGetDoublev(GL_MODELVIEW_MATRIX,M); // get the M from OpenGL
// translation
matrix_mul_vector(p,M,A); // p = M*A
vector_sub(p,C,p); // p = C-p
M[12]=p[0];
M[13]=p[1];
M[14]=p[2];
M[15]=1.0;
// verify
matrix_mul_vector(p,M,B); // p = M*B
vector_sub(p,p,D); // p = p-C
if (vector_len(p)>1e-3) // if |p| too big use other direction to rotate
{
glLoadIdentity(); // unit matrix
glRotated(-a*deg,n[0],n[1],n[2]); // rotate by angle around normal to AB,CD
glScaled(scale,scale,scale); // apply scale
glGetDoublev(GL_MODELVIEW_MATRIX,M); // get the M from OpenGL
}
glPopMatrix();
}
//---------------------------------------------------------------------------
void gl_draw() // main rendering code
{
int i;
double m0[16],m1[16],m[16],x[3],y[3],z[3],t2[3][3];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0.0,0.0,-50.0);
glRotated(15.0,1.0,0.0,0.0);
glRotated(arot,0.0,1.0,0.0);
glBegin(GL_LINES);
glColor3f(1.0,0.0,0.0); for (i=0;i<lins*2;i++) glVertex3dv(pnt+(lin[i]*3)); // render original cube
glColor3f(0.0,1.0,0.0); glVertex3dv(A); glVertex3dv(B); // render original diagonal AB
glColor3f(1.0,1.0,0.0); glVertex3dv(C); glVertex3dv(D); // render wanted diagonal CD
glEnd();
// render transformed cube
glMatrixMode(GL_MODELVIEW);
glMultMatrixd(M);
glBegin(GL_LINES);
glColor3f(0.0,0.0,1.0); for (i=0;i<lins*2;i++) glVertex3dv(pnt+(lin[i]*3)); // render transformed cube
glEnd();
glFlush();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
// application init
gl_init(Handle);
compute_M();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
// application exit
gl_exit();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
// window resize
gl_resize(ClientWidth,ClientHeight);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
// window repaint
gl_draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
arot+=1.5; if (arot>=360.0) arot-=360.0;
gl_draw();
}
//---------------------------------------------------------------------------
忽略 VCL 相关的东西。您可以在这里找到 GL 支持函数:
这里唯一重要的东西是 compute_M()
和全局变量。
矢量数学函数已被注释(因此您可以将其转换为 GLM)如果您需要实现,您可以在上面链接的 QA 中找到它们。基本上需要。为简单起见,我使用了 GL 原生旋转(注意它们是度数而不是弧度)。
此处预览:
red
是原始立方体green
是原来的对角线AB
blue
是由M
变换的立方体
yellow
要对角CD
如您所见,它是匹配的。
如果您需要对齐的不仅仅是一条线,您需要添加更多对齐信息(例如 2 条线(3 点))等。有关更多信息,请参阅:
- Problem superimposing and aligning 3D triangles