绝对比例 - 旋转比例矢量
Absolute scale - Rotating scale vector
需要获取 object 的全局绝对比例才能用 OpenGL 显示它。
当我只乘以 parents 和 children 的比例向量时,我得到了世界轴 space 的绝对比例。当我旋转 object 时,它沿全局轴缩放,而不是局部轴。
我决定我也需要旋转比例矢量。但是:
当我试图用方向向量旋转它时 - 它的值有时会变成 0
,并且也会缩放。
{ scale.x * forward.x , scale.y * forward.y , scale.z * forward.z }
当我试图用 glm::rotate
旋转它时,它会产生意想不到的结果,例如无限 rotating/scaling、扳手和其他网格效果。
auto globalScale = glm::vec3(scale.x, scale.y, scale.z);
globalScale = glm::rotate(globalScale, rotation.x, {1,0,0});
globalScale = glm::rotate(globalScale, rotation.y, {0,1,0});
globalScale = glm::rotate(globalScale, rotation.z, {0,0,1});
我的渲染代码:
void Render(Material *mat, Transform* tr){
glEnable(GL_COLOR_MATERIAL);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
// Get object transformations
Vector3 pos = tr->globalPosition();
Vector3 rot = tr->globalRotation();
Vector3 scale = (tr->globalScale());
auto globalScale = glm::vec3(scale.x, scale.y, scale.z);
// First, scaling, then rotating, then translating in world space
// ( Initially all objects rendering starts at (0,0,0) )
glScaled(globalScale.x, globalScale.y, globalScale.z);
glRotatef(rot.x, 1.0, 0.0, 0.0);
glRotatef(rot.y, 0.0, 1.0, 0.0);
glRotatef(rot.z, 0.0, 0.0, 1.0);
glTranslated(pos.x, pos.y, pos.z);
// Rendering
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3,GL_FLOAT,0,vertexArray);
glNormalPointer(GL_FLOAT,0,normalArray);
glClientActiveTexture(GL_TEXTURE0_ARB);
glTexCoordPointer(2,GL_FLOAT,0,uvArray);
glDrawArrays(GL_TRIANGLES,0,numVerts);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// Rolling transformations back
glTranslated(-pos.x, -pos.y, -pos.z);
glRotated(-rot.z, 0.0, 0.0, 1.0);
glRotated(-rot.y, 0.0, 1.0, 0.0);
glRotated(-rot.x, 1.0, 0.0, 0.0);
glScaled(1/globalScale.x, 1/globalScale.y, 1/globalScale.z);
}
渲染调用:
void RenderObject(GameObject* go){
for(auto goc : go->children)
goc->Update<MeshRenderer>();//RenderObject(goc);
}
void RenderScene(){
auto scene = EditorInstance::GetSingleton()->currentScene;
for(auto go : scene->hierarchy){
RenderObject(go);
if(auto mr = (go->GetComponent<Camera>())){
mr->Update();
}
}
}
... render->setOnRender(RenderScene); ...
主要渲染方式:
int render()
{
#ifdef EDITOR
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // Bind our frame buffer for rendering
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states
DrawGrid(100);
#else
if(NukeOGL::getSingleton() != this){
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // Bind our frame buffer for rendering
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states
}
#endif
//glClearColor(0, 0, 0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
gluLookAt(transform->position.x,
transform->position.y,
transform->position.z,
transform->position.x + transform->direction().x,
transform->position.y + transform->direction().y,
transform->position.z + transform->direction().z,
0.0,
1.0,
0.0);
if(_onRender.size() > 0)
for(auto _rn : _onRender){
_rn();
}
#ifdef EDITOR
glPopAttrib(); // Restore our glEnable and glViewport states
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture
#else
if(NukeOGL::getSingleton() != this){
glPopAttrib(); // Restore our glEnable and glViewport states
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture
}
#endif
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(_onGUI.size() > 0)
for(auto _rn : _onGUI){
_rn();
}
glutSwapBuffers();
//glutPostRedisplay();
return 0;
}
我做错了什么?我应该怎么做才能使其从本地扩展到世界 space?
缩放和旋转是线性变换,它们的作用是相对于到坐标系原点的距离。您必须以正确的顺序和正确的来源应用它们。
我用二维的方式解释,这样更容易理解。
假设您有一个大小为 axb 的矩形,其中心位于 {cx,cy}
并且您想要缩放和旋转(按此顺序)。然后你先翻译成 {0,0}
然后缩放,然后旋转,然后再翻译回 {cx,cy}
。由于每个变换都由一个矩阵定义,并且通常 OpenGL 矩阵是按列主顺序定义的,因此该对象的组合矩阵可能是:
MObj_i = MObj_i_trans(cx,cy) * MObj_i_rot(cangle, caxis) * MObj_i_sca(cfactor) * MObj_i_trans(-cx,-cy)
在对每个对象(每个对象都有自己的 center/scale/rotation)进行这些转换后,您需要 "global" 缩放和旋转。同样,您需要 scale/rotation:
的中心
MGlobal = MGlo_trans(gx,gy) * MGlo_rot(gangle, gaxis) * MGlo_sca(gfactor) * MGlo_trans(-gx,-gy)
通常世界中心是 `{0,0}' 这样您就可以避免平移:
MGlobal = MGlo_rot(gangle, gaxis) * MGlo_sca(gfactor)
好消息是变换可以组合成唯一矩阵。因此,对于每个对象,您应用矩阵:
MObjec_i = MGlobal * MObj_i
如果您使用 glm 进行这些数学计算,请不要忘记初始化一个 恒等矩阵:
glm::mat4 objScale(1.0);
objScale(objScale, vec3(fx, fy, fz));
glm::mat4 objRotate(1.0);
objRotate(objRotate, angle, vec3(axis.x, axis.y, axis.z));
etc.
需要获取 object 的全局绝对比例才能用 OpenGL 显示它。 当我只乘以 parents 和 children 的比例向量时,我得到了世界轴 space 的绝对比例。当我旋转 object 时,它沿全局轴缩放,而不是局部轴。
我决定我也需要旋转比例矢量。但是:
当我试图用方向向量旋转它时 - 它的值有时会变成
0
,并且也会缩放。{ scale.x * forward.x , scale.y * forward.y , scale.z * forward.z }
当我试图用
glm::rotate
旋转它时,它会产生意想不到的结果,例如无限 rotating/scaling、扳手和其他网格效果。auto globalScale = glm::vec3(scale.x, scale.y, scale.z); globalScale = glm::rotate(globalScale, rotation.x, {1,0,0}); globalScale = glm::rotate(globalScale, rotation.y, {0,1,0}); globalScale = glm::rotate(globalScale, rotation.z, {0,0,1});
我的渲染代码:
void Render(Material *mat, Transform* tr){
glEnable(GL_COLOR_MATERIAL);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
// Get object transformations
Vector3 pos = tr->globalPosition();
Vector3 rot = tr->globalRotation();
Vector3 scale = (tr->globalScale());
auto globalScale = glm::vec3(scale.x, scale.y, scale.z);
// First, scaling, then rotating, then translating in world space
// ( Initially all objects rendering starts at (0,0,0) )
glScaled(globalScale.x, globalScale.y, globalScale.z);
glRotatef(rot.x, 1.0, 0.0, 0.0);
glRotatef(rot.y, 0.0, 1.0, 0.0);
glRotatef(rot.z, 0.0, 0.0, 1.0);
glTranslated(pos.x, pos.y, pos.z);
// Rendering
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3,GL_FLOAT,0,vertexArray);
glNormalPointer(GL_FLOAT,0,normalArray);
glClientActiveTexture(GL_TEXTURE0_ARB);
glTexCoordPointer(2,GL_FLOAT,0,uvArray);
glDrawArrays(GL_TRIANGLES,0,numVerts);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// Rolling transformations back
glTranslated(-pos.x, -pos.y, -pos.z);
glRotated(-rot.z, 0.0, 0.0, 1.0);
glRotated(-rot.y, 0.0, 1.0, 0.0);
glRotated(-rot.x, 1.0, 0.0, 0.0);
glScaled(1/globalScale.x, 1/globalScale.y, 1/globalScale.z);
}
渲染调用:
void RenderObject(GameObject* go){
for(auto goc : go->children)
goc->Update<MeshRenderer>();//RenderObject(goc);
}
void RenderScene(){
auto scene = EditorInstance::GetSingleton()->currentScene;
for(auto go : scene->hierarchy){
RenderObject(go);
if(auto mr = (go->GetComponent<Camera>())){
mr->Update();
}
}
}
... render->setOnRender(RenderScene); ...
主要渲染方式:
int render()
{
#ifdef EDITOR
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // Bind our frame buffer for rendering
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states
DrawGrid(100);
#else
if(NukeOGL::getSingleton() != this){
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // Bind our frame buffer for rendering
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states
}
#endif
//glClearColor(0, 0, 0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
gluLookAt(transform->position.x,
transform->position.y,
transform->position.z,
transform->position.x + transform->direction().x,
transform->position.y + transform->direction().y,
transform->position.z + transform->direction().z,
0.0,
1.0,
0.0);
if(_onRender.size() > 0)
for(auto _rn : _onRender){
_rn();
}
#ifdef EDITOR
glPopAttrib(); // Restore our glEnable and glViewport states
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture
#else
if(NukeOGL::getSingleton() != this){
glPopAttrib(); // Restore our glEnable and glViewport states
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture
}
#endif
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(_onGUI.size() > 0)
for(auto _rn : _onGUI){
_rn();
}
glutSwapBuffers();
//glutPostRedisplay();
return 0;
}
我做错了什么?我应该怎么做才能使其从本地扩展到世界 space?
缩放和旋转是线性变换,它们的作用是相对于到坐标系原点的距离。您必须以正确的顺序和正确的来源应用它们。
我用二维的方式解释,这样更容易理解。
假设您有一个大小为 axb 的矩形,其中心位于 {cx,cy}
并且您想要缩放和旋转(按此顺序)。然后你先翻译成 {0,0}
然后缩放,然后旋转,然后再翻译回 {cx,cy}
。由于每个变换都由一个矩阵定义,并且通常 OpenGL 矩阵是按列主顺序定义的,因此该对象的组合矩阵可能是:
MObj_i = MObj_i_trans(cx,cy) * MObj_i_rot(cangle, caxis) * MObj_i_sca(cfactor) * MObj_i_trans(-cx,-cy)
在对每个对象(每个对象都有自己的 center/scale/rotation)进行这些转换后,您需要 "global" 缩放和旋转。同样,您需要 scale/rotation:
的中心MGlobal = MGlo_trans(gx,gy) * MGlo_rot(gangle, gaxis) * MGlo_sca(gfactor) * MGlo_trans(-gx,-gy)
通常世界中心是 `{0,0}' 这样您就可以避免平移:
MGlobal = MGlo_rot(gangle, gaxis) * MGlo_sca(gfactor)
好消息是变换可以组合成唯一矩阵。因此,对于每个对象,您应用矩阵:
MObjec_i = MGlobal * MObj_i
如果您使用 glm 进行这些数学计算,请不要忘记初始化一个 恒等矩阵:
glm::mat4 objScale(1.0);
objScale(objScale, vec3(fx, fy, fz));
glm::mat4 objRotate(1.0);
objRotate(objRotate, angle, vec3(axis.x, axis.y, axis.z));
etc.