c++ - 如何在openGL中围绕全局轴旋转模型?
问题描述
在 OpenGL 中,我想围绕全局轴旋转模型。
我要旋转的对象如下所示:
class Object {
public:
inline Object()
: vao(0),
positionBuffer(0),
colorBuffer(0),
indexBuffer(0),
elements(0)
{}
inline ~Object() { // GL context must exist on destruction
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &indexBuffer);
glDeleteBuffers(1, &colorBuffer);
glDeleteBuffers(1, &positionBuffer);
}
GLuint vao; // vertex-array-object ID
GLuint positionBuffer; // ID of vertex-buffer: position
GLuint colorBuffer; // ID of vertex-buffer: color
GLuint indexBuffer; // ID of index-buffer
GLuint elements; // Number of Elements
glm::mat4x4 model; // model matrix
};
启动对象的函数如下所示:
void initObject(Object &obj, vector<glm::vec3> &vertices, vector<glm::vec3> &colors, vector<GLushort> &indices, glm::vec3 offset)
{
GLuint programId = program.getHandle();
GLuint pos;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Step 0: Create vertex array object.
glGenVertexArrays(1, &obj.vao);
glBindVertexArray(obj.vao);
// Step 1: Create vertex buffer object for position attribute and bind it to the associated "shader attribute".
glGenBuffers(1, &obj.positionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, obj.positionBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW);
// Bind it to position.
pos = glGetAttribLocation(programId, "position");
glEnableVertexAttribArray(pos);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Step 2: Create vertex buffer object for color attribute and bind it to...
glGenBuffers(1, &obj.colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, obj.colorBuffer);
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_STATIC_DRAW);
// Bind it to color.
pos = glGetAttribLocation(programId, "color");
glEnableVertexAttribArray(pos);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Step 3: Create vertex buffer object for indices. No binding needed here.
glGenBuffers(1, &obj.indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, obj.indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), indices.data(), GL_STATIC_DRAW);
// Unbind vertex array object (back to default).
glBindVertexArray(0);
// Modify model matrix.
obj.model = glm::translate(glm::mat4(1.0f), offset);
}
现在我得到了一个实例,它是作为球体的镶嵌八面体,我想围绕全局轴旋转,特别是 X 轴。该对象的中心位于 (3, 1, 0) 处,因此如果原点位于 (3, 0, 1) 处,则围绕 90 度旋转。
我试图用glm::rotate
方法做到这一点:
glm::vec3 axis;
axis = { 1.0, 0.0f, 0.0f };
sphere.model = glm::rotate(sphere.model, glm::radians(90.0f), axis);
但这只会围绕它的本地轴旋转对象。
我尝试的另一个解决方案是这个:
glm::vec3 axis;
axis = glm::inverse(sphere.model) * glm::vec4(1.0, 0.0, 0.0, 0.0f);
sphere.model = glm::rotate(sphere.model, (2.0f*3.1415f)/48.0f, axis);
另一只手的行为就像全局轴位于模型的中心。因此,如果对象的中心等于全局坐标系的原点,则旋转是正确的。
解决方案
retMat = glm::rotate(curMat, ...)
计算旋转矩阵并将其与给定curMat
矩阵相乘。
返回的矩阵retMat
可以与在同一坐标系(又称“空间”)中定义的任何点一起使用,curMat
以计算新坐标,再次在同一空间中:newXYZ = retMat * oldXYZ
.
给定的旋转轴glm::rotate
总是穿过空间的原点。
如果您需要另一条旋转线(不包含原点),那么您必须执行“平移到线上的某个点 ==> 旋转 ==> 向后平移”的顺序
对于你的情况,我猜你的球体是这样定义的,它的中心是 origin 0,0,0
。这意味着“模型空间”与“全局空间”相同。因此,您无需在旋转之前平移球体。
旋转对象后,将其平移到您希望的位置。
推荐阅读
- python - 如何从已知参数构造相机矩阵
- swift - 从单独的类调用函数不起作用
- android - Firebase Crashlytics - 获取堆栈跟踪信息以在 CrashlyticsListener.crashlyticsDidDetectCrashDuringPreviousExecution() 期间显示
- jquery - 如何将完整的日历日期添加到动态文本框
- .htaccess - 我想使用 url 重写来缩短我的 url,但它不起作用
- javascript - 调用函数时如何解决函数范围问题
- javascript - 客户端从C#压缩字符串解压回字符串
- node.js - 端口转发不适用于 Nodejs 应用程序
- python - 关闭图像中的开放边界
- progressive-web-apps - 如何从 PWA 拨打移动电话