做了2个简单的类 一个是描述球的 一个是平面圆的
public class Ball { private int slices = 36; //越大越圆滑 private int stacks = 24; //同↑ private FloatBuffer[] normalsBuffers; private FloatBuffer[] slicesBuffers; private float yAngle; private float zAngle; float radius = 1.3f; public Ball() { slicesBuffers = new FloatBuffer[slices]; normalsBuffers = new FloatBuffer[slices]; for (int i = 0; i < slices; i++) { float[] vertexCoords = new float[6 * (stacks + 1)]; float[] normalCoords = new float[6 * (stacks + 1)]; double alpha0 = i * (2 * Math.PI) / slices; double alpha1 = (i + 1) * (2 * Math.PI) / slices; float cosAlpha0 = (float) Math.cos(alpha0); float sinAlpha0 = (float) Math.sin(alpha0); float cosAlpha1 = (float) Math.cos(alpha1); float sinAlpha1 = (float) Math.sin(alpha1); for (int j = 0; j <= stacks; j++) { double beta = j * Math.PI / stacks - Math.PI / 2; float cosBeta = (float) Math.cos(beta); float sinBeta = (float) Math.sin(beta); setXYZ(vertexCoords, 6 * j, radius * cosBeta * cosAlpha1, radius * sinBeta, radius * cosBeta * sinAlpha1); setXYZ(vertexCoords, 6 * j + 3, radius * cosBeta * cosAlpha0, radius * sinBeta, radius * cosBeta * sinAlpha0); setXYZ(normalCoords, 6 * j, cosBeta * cosAlpha1, sinBeta, cosBeta * sinAlpha1); setXYZ(normalCoords, 6 * j + 3, cosBeta * cosAlpha0, sinBeta, cosBeta * sinAlpha0); } slicesBuffers[i] = FloatBuffer.wrap(vertexCoords); normalsBuffers[i] = FloatBuffer.wrap(normalCoords); } } public void setXYZ(float[] vector, int offset, float x, float y, float z) { vector[offset] = x; vector[offset + 1] = y; vector[offset + 2] = z; } public void draw(GL10 gl) { gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -7.0f); gl.glColor4f(1.0f, 0.2f, 0.3f, 1.0f); gl.glRotatef(yAngle, 1.0f, 0.0f, 0.0f); gl.glRotatef(zAngle, 0.0f, 1.0f, 0.0f); for (int i = 0; i < slices; i++) { gl.glVertexPointer(3, GL10.GL_FLOAT, 0, slicesBuffers[i]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 2 * (stacks + 1)); } gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); } public void setyAngle(float yAngle) { this.yAngle = yAngle; } public void setzAngle(float zAngle) { this.zAngle = zAngle; } }
public class Oval { private float[] vertices = new float[720]; private FloatBuffer verBuffer ; private float yAngle; private float zAngle; public Oval() { //初始化圆形数据 for (int i = 0; i < 720; i += 2) { // x 坐标 vertices[i] = (float) (Math.cos(DegToRad(i)) * 1); // y 坐标 vertices[i+1] = (float) (Math.sin(DegToRad(i)) * 1); } //设置圆形顶点数据 ByteBuffer qbb = ByteBuffer.allocateDirect(vertices.length * 4); qbb.order(ByteOrder.nativeOrder()); verBuffer = qbb.asFloatBuffer(); verBuffer.put(vertices); verBuffer.position(0); } public float DegToRad(float deg) { return (float) (3.14159265358979323846 * deg / 180.0); } public void draw(GL10 gl) { //重置投影矩阵 gl.glLoadIdentity(); // 移动操作,移入屏幕(Z轴)5个像素, x, y , z gl.glTranslatef(0.0f, 0.0f, -5.0f); //旋转, angle, x, y , z gl.glRotatef(yAngle, 0.0f, 1.0f, 0.0f); gl.glRotatef(zAngle, 1.0f, 0.0f, 0.0f); // 设置当前色为红色, R, G, B, Alpha gl.glColor4f(1.0f, 0.1f, 0.1f, 1.0f); //设置顶点类型为浮点坐标 gl.glVertexPointer(2, GL10.GL_FLOAT, 0, verBuffer); //打开顶点数组 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); //向OGL发送实际画图指令 gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 360); //画图结束 gl.glFinish(); } public void setyAngle(float yAngle) { this.yAngle = yAngle; } public void setzAngle(float zAngle) { this.zAngle = zAngle; } }
这个是renderer类 声明了Ball 和 Oval 变量
public class GLRender implements Renderer{ Oval o = new Oval(); Ball b = new Ball(); //度到弧度的转换 @Override public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glEnable(GL10.GL_CULL_FACE); gl.glLightModelx(GL10.GL_LIGHT_MODEL_TWO_SIDE, GL10.GL_FALSE); //o.draw(gl); //------画圆 b.draw(gl); //------画球 } public void setyAngle(float yAngle) { b.setyAngle(yAngle); o.setyAngle(yAngle); } public void setzAngle(float zAngle) { b.setzAngle(zAngle); o.setzAngle(zAngle); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { if (height == 0) height = 1; gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 1.0f, 100.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_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); gl.glCullFace(GL10.GL_BACK); gl.glEnable(GL10.GL_LIGHT0); } }
最后是GLSurfaceView类
public class MyGLSurfaceView extends GLSurfaceView { GLRender myRenderer;// 自定义的渲染器 private final float TOUCH_SCALE_FACTOR = 180.0f / 320;// 角度缩放比例 private float mPreviousY;// 上次的触控位置Y坐标 private float mPreviousX;// 上次的触控位置X坐标 float yAngle = 0;// 绕y轴旋转的角度 float zAngle = 0;// 绕z轴旋转的角度 public MyGLSurfaceView(Context context) { super(context); myRenderer = new GLRender();// 创建渲染器 this.setRenderer(myRenderer);// 设置渲染器 this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);// 设置渲染模式 } @Override public boolean onTouchEvent(MotionEvent e) { // 触摸事件的回调方法 float x = e.getX();// 得到x坐标 float y = e.getY();// 得到y坐标 switch (e.getAction()) { case MotionEvent.ACTION_MOVE:// 触控笔移动 float dy = y - mPreviousY;// 计算触控笔Y位移 float dx = x - mPreviousX;// 计算触控笔X位移 yAngle += dx * TOUCH_SCALE_FACTOR;// 设置沿y轴旋转角度 zAngle += dy * TOUCH_SCALE_FACTOR;// 设置沿z轴旋转角度 myRenderer.setyAngle(yAngle); myRenderer.setzAngle(zAngle); requestRender();// 重绘画面 } mPreviousY = y;// 记录触控笔位置 mPreviousX = x;// 记录触控笔位置 return true;// 返回true } }
重写了ontouch 事件 通过x y 计算出变化的角度 可以让图形做简单的转动 改一改就可以平动了
不过球因为没有做处理 只是用单一颜色绘制的 所以看起来和圆差不多 可以加上颜色数组 就比较明显了