实现生成星星,让星星自转和绕原点公转的简单demo。

物体旋转都用到了gl.glRotatef,然而我们知道旋转函数是绕此时经过绘图原点的轴旋转的,即

             gl.glLoadIdentity();
//右移 1.5 单位,并移入屏幕 4.0
gl.glTranslatef(0f, 0f, -4f);
//旋转矩阵
gl.glRotatef(rotateTri, 0.0f, 3.0f,0f);
绕过点(0,0,-4)的向量(0,3,0)旋转的。星星的公转是绕屏幕中心原点旋转,而绘图和自转都是绕星星本身的中心旋转,因此为了让两个旋转不相互干扰,必须在设置绘图原点和自转之前就进行公转的设定:
       gl.glLoadIdentity();
gl.glTranslatef(0f, 0.0f, -deep);//先将屏幕移到深层
gl.glRotatef(start.angle, 0f , 0f, 1f);//函数本身的意思是将图形绕z轴旋转到angle角度,通过修改angle的值来实现公转,此时绘图原点还在屏幕中心
gl.glTranslatef(start.dist*(float)Math.cos(start.angle),start.dist*(float)Math.sin(start.angle), 0);//由于星星初始角度不同,离原点距离不同就会导致其中心位置,即绘图原点的不同,通过角度和离屏幕中心点的距离计算出
gl.glRotatef(rotateY , 1f , 0f, 0f);//绕y轴自转,此时绘图原点已经移到星星自身的中心
 
下面是实现了多个星星在屏幕内旋转和自转的demo:
start类:
public class Start {
float dist;
int r , g , b;
float angle;
boolean IsBigging = true;//是否正在背离原点旋转
float rotateSelf; //自转的角速度
float rotateElse; //公转的角速度
 
public Start (float dist , int r , int g , int b , float angle,float rotateSelf,float rotateElse)
{
this.dist = dist;
this.r = r;
this.g = g;
this.b = b;
this.angle = angle;
this.rotateSelf = rotateSelf;
this.rotateElse =rotateElse;
}
}
Render类:
package com.example.zp.rotatestartdemo;
 
import android.opengl.GLSurfaceView;
 
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
 
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
 
/**
* Created by lenovo on 2016/9/6.
*/
public class GLRender implements GLSurfaceView.Renderer{
 
private int numberStarts =50;
private Start [] starts = new Start[numberStarts];
private float deep = 6f;
private float maxDist = 4f;//屏幕在deep层能显示的最大横坐标,这里表示的是离原点的最大值

 
private void init()
{
//初始化星星
for(int i = 0 ; i < numberStarts ; i++)
{
float dis = 0.2f*i;
int r = (int)(Math.random()*256);
int g = (int)(Math.random()*256);
int b = (int)(Math.random()*256);
float angle =(float)(Math.random())*2f*(float)Math.PI;
float rotateSelf = (float)(Math.random())*2f*(float)Math.PI/8f;
float rotateElse = (float)(Math.random())*2f*(float)Math.PI/16f;
starts[i] = new Start(dis , r , g , b , angle,rotateSelf,rotateElse);
}
}
 
//三角形
FloatBuffer vertices = BufferUtil.floatToBuffer(new float[]{
-0.025f,0.05f,0f,
-0.1f,0.05f,0f,
-0.05f,-0.025f,0f,
-0.1f,-0.1f,0f,
0f,-0.05f,0f,
0.1f,-0.1f,0f,
0.05f,-0.025f,0f,
0.1f,0.05f,0f,
0.025f,0.05f,0f,
0f,0.1f,0f,
-0.025f,0.05f,0f
 
});
//五边形
FloatBuffer vertices2 = BufferUtil.floatToBuffer(new float[]{
-0.025f,0.05f,0f,
-0.05f,-0.025f,0f,
0f,-0.05f,0f,
 
-0.025f,0.05f,0f,
0f,-0.05f,0f,
0.025f,0.05f,0f,
 
0f,-0.05f,0f,
0.05f,-0.025f,0f,
0.025f,0.05f,0f
});
 
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glShadeModel(GL10.GL_SMOOTH);
// 黑色背景
gl.glClearColor(0, 0, 0, 0);
// 设置深度缓存
gl.glClearDepthf(1.0f);
// gl.glEnable(GL10.GL_CULL_FACE);//启用这个后,当目前图片转到背面时候就看不到了,意思就是画一个面,只能从正面看到这个面,从背面就看不到,因此不能随便加
// 启用阴影平滑
 
// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
// 告诉系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
init();
}
 
 
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
float ratio = (float) width / height;
//设置OpenGL场景的大小
gl.glViewport(0, 0, width, height);
//设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩阵
gl.glLoadIdentity();
// 设置视口的大小
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
// 选择模型观察矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置模型观察矩阵
gl.glLoadIdentity();
}
 
@Override
public void onDrawFrame(GL10 gl) {
// 清除屏幕和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
for(int i = 0 ; i < numberStarts ; i++) {
drawStart(gl, starts[i]);
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
 
}
 
// float rotateSpeed = 0.3f ;
float rotateY = 0;
public void drawStart(GL10 gl , Start start)
{
gl.glLoadIdentity();
gl.glTranslatef(0f, 0.0f, -deep);
gl.glRotatef(start.angle, 0f , 0f, 1f);//rotateZ
gl.glTranslatef(start.dist*(float)Math.cos(start.angle),start.dist*(float)Math.sin(start.angle), 0);
gl.glRotatef(rotateY , 1f , 0f, 0f);
 
float r = (float)(start.r)/255f;
float g = (float)start.g/255f;
float b = (float)start.b/255f;
gl.glColor4f(r,g,b,1f);
 
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices);
 
for(int i = 0 ; i <5 ; i ++)
{
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,i*2,3);
}
gl.glFinish();
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices2);
for(int i = 0 ; i <3 ; i ++)
{
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,i*3,3);
}
gl.glFinish();
 
 
if(start.dist>=maxDist)
start.IsBigging = false;
if(start.dist<=0)
start.IsBigging = true;
//此处的0.01f代表的是星星公转时候离心和向心运动的速度,即dist的变化速率 
if(start.IsBigging)
start.dist=start.dist + 0.01f;
else
start.dist=start.dist - 0.01f;
 
rotateY = rotateY + start.rotateSelf;
 
start.angle = start.angle +start.rotateElse;
 
}
 
 
 
}

 

posted @ 2016-10-16 20:26  Lammy  阅读(982)  评论(0编辑  收藏  举报