点击这里:Win32 OpenGL编程(8) 3D模型变换及其组合应用

  提要

  在前文(系列文章(7)以下简称XO7系列其他文章类似)中照相机比喻中提到了4种3D变换如下:

  1.确定照相机位置过程对应于“视图变换”(Viewing Transformations)

  2.确定物体位置过程对应于“模型变换”(Modeling Transformations)

  3.确定照相机放大倍数过程对应于“投影变换”(Projection Transformations)

  4.确定照片大小过程对应于“视口变换”(Viewport Transformations)

  XO7中我们讲是第种变换视图变换即改变观察者本身位置视角等变换效果本文开始继续按顺序讲解下个3D变换过程模型变换

  模型变换

  模型变换指是以设置模型(即我们观察物体)位置方向为目变换过程还在2D时XO4内容就已经涉及模型变换知识了(我还提供了个2D中使用glTranslate*和glRotate*较复杂例子Win32 OpenGL编程系列 2D例子 -- 7巧板图形绘制)只不过那时候我们纯粹是在2D空间中研究这个问题并且描述如移动旋转等变换时提及对象是图元其实那就是3D模型变换在2D世界个简化版而已我们可以将以前知识在3D空间扩展开来各种变换效果和意义还是类似glTranslate*,glRotate*使用方式和2D是类似仅仅是多考虑个Z轴值而已比如glTranslate*就可能将模型移出原来x-y平面(即Z=0平面)而glRotate*旋转也可能使模型不再在原x-y平面上对变换角度计算时不要漏了就可以了

  其实当时讲2D时还有个模型变换没有讲到那就是改变模型大小glScale*

  OpenGL Programming Guide:

    glScale — multiply the current matrix by a general scaling matrix
    C Specication
    void glScaled(    GLdouble      x,
         GLdouble      y,
         GLdouble      z);
    void glScalef(    GLfloat      x,
         GLfloat      y,
         GLfloat      z);
    Parameters
    x, y, z
                            Specy scale factors along the x, y, and z axes, respectively.


  此使用起来很简单我用个动画效果来演示此此例是从XO7中glPolygonFace例子改过来已经处理好了正面背面和视角我仅仅添加了几句glScale*

//这里进行所有绘图工作
void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
     GLfloat fScaleY = 1.0;
     GLboolean bScaleWay = true;
    (bScaleWay)
    {
        (fScaleY <= 1.5)
        {
            fScaleY  0.01;
        }
        
        {
            bScaleWay = false;
        }
    }
    
    {
        (fScaleY >= 0.5)
        {
            fScaleY -= 0.01;
        }
        
        {
            bScaleWay = true;
        }
    }
    glPushMatrix;
    glScalef(1.0, fScaleY, 1.0);
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;
    glLoadIdentity;
    gluLookAt(gViewPosX, gViewPosY, gViewPosZ, gViewDirX, gViewDirY, gViewDirZ, gViewUpDirX, gViewUpDirY, gViewUpDirZ);
    glFlush;
}  


  此时模型高度在0.5和1.5倍的间来回变换加上以前框架你可以变换各种角度来查看glScale*使用在此例中就很明显了x,y,z值分别对应原模型变换倍数1.0即不变1.5即增长以此类推

  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2009-10-26\glScaleSample 目录获取方式见文章最后有关获取博客完整源代码介绍说明

  模型变换组合

  以上3个模型变换可以起组合使用实现复杂效果 7巧板例中就是完全靠glTranslate*河glRotate*来为各块图形定位和控制旋转

  原 7巧板中CShape绘制图形时使用代码如下:

void Draw
{
    glLoadIdentity;
    glColor4fv(mfvColor);
    glPushMatrix;
    glTranslatef(mfPosX, mfPosY, 0.0);
    glRotatef(mfDegree, 0.0, 0.0, 1.0);
    DrawImp;
    glPopMatrix;
}


  现在看起来很简单无非就是先将块 7巧板通过glTranslatef移动到某个确定X,Y位置然后通过glRotatef旋转那么我们能不能先旋转好了角度然后再移动到确定位置去呢?从理论上来说这条路和以前应该样嘛比如下列代码仅仅更改了glTranslatef和 glRotatef先后顺序效果会样吗?

void Draw
{
    glLoadIdentity;
    glColor4fv(mfvColor);
    glPushMatrix;
    glRotatef(mfDegree, 0.0, 0.0, 1.0);
    glTranslatef(mfPosX, mfPosY, 0.0);
    DrawImp;
    glPopMatrix;
}


  但是最后效果和我们所想并不

  

  原因嘛需要好好解释正如我提及模型变换常常说是坐标系变换我喜欢从这个角度来看模型变换模型变换改变不是模型本身改变是模型所处坐标系此时移动改变仅仅是坐标系原点转动坐标系方向都变了缩放坐标系单位长度变化了这样考虑话就知道为什么上述例子中两个顺序改变会导致结果改变了先转动时坐标系已经转动了而我们移动时候数据还是相对于原来OpenGL默认坐标系自然就不对了为了更形象看到结果这里我给出个同时显示 3个区别处理 3角锥例子:

//这里进行所有绘图工作
void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    // 原 3角锥
    DrawSmoothColorPyramid(0.5);
    // 先转动后移动 3角锥
    glPushMatrix;
    glRotatef(90, 0.0, 0.0, 1.0);
    glTranslatef(0.0, 0.5, 0.0);
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;
    // 先移动后转动 3角锥
    glPushMatrix;
    glTranslatef(0.0, -0.5, 0.0);
    glRotatef(90, 0.0, 0.0, 1.0);
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;

    glLoadIdentity;
    gluLookAt(gViewPosX, gViewPosY, gViewPosZ, gViewDirX, gViewDirY, gViewDirZ, gViewUpDirX, gViewUpDirY, gViewUpDirZ);
    glFlush;
} 


  运行效果如下图所示:

  

  图片看不清楚?请点击这里查看原图(大图)

  例子还是在以前 3角锥绘制代码上改动而来运行效果如下图中间 3角锥即是没有经过任何变换原始 3角锥左边那个 3角锥是先转动后移动产生 3角锥理解下是如何通过上述操作得出来首先逆时针转动90度此时此 3角锥局部坐标Y正轴已经是指向屏幕正左边了所以此时通过glTranslate*将其向Y正方向移动0.5导致其移动到了屏幕左边下边那个 3角锥即是先移动后转动产生由于移动操作仅影响坐标轴原点位置不改变方向和单位长度所以很好理解主要注意那个先旋转后移动 3角锥移动方向已经不是屏幕全局坐标系了

  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2009-10-26\glComposModelTrans 目录获取方式见文章最后有关获取博客完整源代码介绍说明

  glScale*和glRotate*类似话也会对坐标系产生影响导致以后操作都会按照影响结果而改变比如先将坐标系放大1倍那么以前移动0.5操作将会变成移动1点由于和glRotate*组合使用效果见下面例子:

//这里进行所有绘图工作
void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    // 原 3角锥
    DrawSmoothColorPyramid(0.5);
    // 先缩放后移动
    glPushMatrix;
    glScalef(1.5, 1.5, 1.5);
    glTranslatef(0.0, 0.3, 0.0);
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;
    // 先移动后缩放
    glPushMatrix;
    glTranslatef(0.0, 0.3, 0.0);
    glScalef(1.5, 1.5, 1.5);
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;

    glLoadIdentity;
    gluLookAt(gViewPosX, gViewPosY, gViewPosZ, gViewDirX, gViewDirY, gViewDirZ, gViewUpDirX, gViewUpDirY, gViewUpDirZ);
    glFlush;
}  


  运行效果如图:

  

  图片看不清楚?请点击这里查看原图(大图)

  作为比较对象留下来原 3角锥在最下面(原中间位置)中间那个大 3角锥是按照默认大小坐标系上移了0.3距离而上面大 3角锥在中也是上移0.3距离但是此距离首先经过了glScale*放大所以可以看出实际效果上移动要比默认0.3要远所以导致图像无法重合

  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2009-10-26\glComposModelTrans2 目录获取方式见文章最后有关获取博客完整源代码介绍说明

  最后作为额外例子展示几个相关有趣图以及代码不牵涉到新知识不做过多解释

  有趣组合效果个放大了1倍 3角锥和个移动到上面 3角锥组合而成

void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    glPushMatrix;
    glScalef(2.0, 2.0, 2.0);
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;
    glPushMatrix;
    glTranslatef(0.0, 0.5, 0.0);
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;

    glLoadIdentity;
    gluLookAt(gViewPosX, gViewPosY, gViewPosZ, gViewDirX, gViewDirY, gViewDirZ, gViewUpDirX, gViewUpDirY, gViewUpDirZ);
    glFlush;
}  




  

  图片看不清楚?请点击这里查看原图(大图)



Tags:  免费3d模型 点击这里

延伸阅读

最新评论

发表评论