OpenGL中存在6种坐标系,
1. Object or model coordinates
2. World coordinates
3. Eye (or Camera) coordinates
4. Clip coordinates
5. Normalized device coordinates
6. Window (or screen) coordinates
经常用到的 世界坐标 物体坐标, 屏幕坐标 ,眼坐标
物体坐标是以物体某一点为原点而建立的“世界坐标”,该坐标系仅对该物体适用,用来简化对物体各部分坐标的描述。物体放到场景中时,各部分经历的坐标变换相同,相对位置不变,所以可视为一个整体,与人类的思维习惯一致。
眼坐标是以视点为原点,以视线的方向为Z+轴正方向的坐标系中的方向。OpenGL管道会将世界坐标先变换到眼坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算。
同样的,有投影变换矩阵栈(Projection),栈顶矩阵就是当前投影变换矩阵,负责将场景各坐标变换到眼坐标,由所得到的结果是裁剪后的场景部分,称为裁剪坐标。前面提到过的视见体设定其实就是在建立该矩阵。
设备坐标:OpenGL 的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。值得一提的是,OpenGL可以只使用设备的一部分进行绘制,这个部分称为视区或视口(viewport)。投影得到的是视区内的坐标(投影坐标),从投影坐标到设备坐标的计算过程就是设备变换了。
坐标其实跟现实世界中差不多,我们可以把自己当成当前的 相机(眼), 看向某 一个物体, 而所处的空间就是世界。
举个例子, opengl 中的旋转 可以采用 gl.glRotatef(30, 1, y, z) 物体绕着自身 X轴 旋转, 此时是以 世界为参照物
而当我们的 眼睛 绕着物体旋转时,如果以我们的眼睛为参照物 , 可以认为 是 物体自身在旋转,
其它方法跟上篇一样
一 物体本身旋转
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
//每次rota 增加原有的0.5 因为我们这边每次绘制的时候 会
//gl.glLoadIdentity(); 重置原来的位置, 旋转的轴 感觉应该是 如果是绕X轴旋转 感觉是将X轴平移到 中垂线的交点,然后//绕着该轴旋转 ,没验证过
rota+=0.5;//清楚颜色,深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//开启模型试图矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);//加载一个基本矩阵 可以理解为重置矩阵,因为每次draw后 会保留原来的矩阵,如果不重置矩阵 ,在translate时 物体就会越离越远gl.glLoadIdentity();//眼睛设的视野距离为 -1,-20的坐标,则只有在该范围内 的物体才能看到 将物体移动到 z =-3处
gl.glTranslatef(0, 0, -3f);//定义坐标点 数组 Specifies the number of coordinates per vertex. Must be 2, 3, or 4. The initial value is 4.gl.glRotatef(rota, 1, 0,0);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0,getFloatBuffer(lines));//启用定点数组 跟下面disable 相互对应 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//设置画笔颜色
gl.glColor4f(1.0F, 0F,0F,1.0F);//绘制三角形
gl.glDrawArrays(GL10.GL_TRIANGLES, 0,3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);}
gl.glLoadIdentity();是加载一个单位矩阵, opengl 还提供了gl.glPushMatrix(),gl.glPopMatrix() 将当前矩阵放入入栈 和出栈,
开销比 gl.glLoadIdentity()小
gl.glPushMatrix();
gl.glTranslatef(0, 0, -3f);
//定义坐标点 数组 Specifies the number of coordinates per vertex. Must be 2, 3, or 4. The initial value is 4.
gl.glRotatef(rota, 1, 0,0);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0,getFloatBuffer(lines));
//启用定点数组 跟下面disable 相互对应
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//设置画笔颜色
gl.glColor4f(1.0F, 0F,0F,1.0F);
//绘制三角形
gl.glDrawArrays(GL10.GL_TRIANGLES, 0,3);
gl.glPopMatrix();
二 通过改变 眼睛 所在位置 从而达到物体旋转
GLU.gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ, float upX, float upY,
float upZ)
eye 为眼睛所处的距离 center 为眼睛看向的点 比如 看向 (0,0 ,-3 )这个点 up为 眼睛所处的 角度 (0,1,0)就可以理解为站着 (0,-1,0)倒立
下面是通过 改变 我们眼睛 (相机)的位置 来实现 物体旋转
float rota=0.5f;
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
//清楚颜色,深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//开启模型试图矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
//改变眼睛所处的位置,眼睛看向的点 是物体所处坐标的中心点 此处 为,0,0,-3 ( 移动到了-3处, 绕着中心点旋转,到圆心的坐标 就可以通过 //cos^2X +sin^2Y=R^2 这个公式来推导了
gl.glLoadIdentity();
GLU.gluLookAt(gl,0,(float)Math.cos(Math.toRadians(rota))*3,(float)Math.sin(Math.toRadians(rota))*3-3,0,0,-3,0, 1, 0);
rota+=0.5;
//加载一个基本矩阵 可以理解为重置矩阵,因为每次draw后 会保留原来的矩阵,如果不重置矩阵 ,在translate时 物体就会越离越远
//眼睛设的视野距离为 -1,-20的坐标,则只有在该范围内 的物体才能看到 将物体移动到 z =-3处
gl.glTranslatef(0, 0, -3f);
//定义坐标点 数组 Specifies the number of coordinates per vertex. Must be 2, 3, or 4. The initial value is 4.
//gl.glRotatef(rota, 1, 0,0);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0,getFloatBuffer(lines));
//启用定点数组 跟下面disable 相互对应
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//设置画笔颜色
gl.glColor4f(1.0F, 0F,0F,1.0F);
//绘制三角形
gl.glDrawArrays(GL10.GL_TRIANGLES, 0,3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}