android用openGl ES绘制任意方程的三维空间图形

最近在写一个数值计算数学软件,用于矩阵分析、线性、非线性方程(组)求解、数值积分的求解,二维、三维绘图。

其中的三维绘图,用OpenGl渲染,本来打算用原生的方法实现,但是能力有限,且对OpenGl不太熟悉,就直接用java实现啦。效率还行。

实现机制是:先传入空间几何体的方程 (z=f(x,y)、x=u(t),y=v(t),z=w(t)) 其中包括显示方程和参数方程。以及变量x y的取值范围。在绘制的时候,对x y进行 分割 ,取相邻的四个点组成两个三角形进行绘制.具体代码如下:

1.

package com.example.plot;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;

public class MySurefaceView extends GLSurfaceView 
{
	private final float SUO=180.f/320 ;//缩放比例
	private SceneRenderer mRenderer ;
	private float shangX ;
	private float shangY ;
	
	public MySurefaceView(Context context)
	{
		super(context);
		mRenderer=new SceneRenderer();
		setRenderer(mRenderer);
		setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY) ;//设置为主动渲染
	}
	//触摸事件
	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		float x=event.getX();
		float y=event.getY() ;
		if(event.getAction()==MotionEvent.ACTION_MOVE)
		{
			float dx=x-shangX ;
			float dy=y-shangY ;
			mRenderer.funcView.angleY+=dx*SUO ;
			mRenderer.funcView.angleZ+=dy*SUO ;
			requestRender() ;
		}
		shangX=x ;
		shangY=y ;
		return true;
	}

	private class SceneRenderer implements Renderer ,IFunc
	{
		FuncView funcView ;
		@Override
		public void onSurfaceCreated(GL10 gl, EGLConfig config)
		{
			gl.glDisable(GL10.GL_DITHER) ;// 闭关抗抖动
			gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST) ;
			gl.glClearColor(0, 0, 0, 0) ;
			gl.glShadeModel(GL10.GL_SMOOTH) ;//平滑着色
			gl.glEnable(GL10.GL_DEPTH_TEST) ;//深度测试
			gl.glColor4f(1, 0, 0, 1);
			funcView=new FuncView(-1, 1, 0, 2*Math.PI,this) ;  //实例画 传入x y的范围和方程函数接口
		}

		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height)
		{
			gl.glViewport(0, 0, width, height);
			gl.glMatrixMode(GL10.GL_PROJECTION) ;// 设置当前矩阵为投影矩阵
			gl.glLoadIdentity() ; //设置当前矩阵为单位矩阵
			float ratio=(float)width/height;
			gl.glFrustumf(-ratio, ratio, -0.5f, 1.5f, 1, 100) ; //调用次方法计算产生透视投影矩阵
//			gl.glOrthof(-ratio, ratio, -0.5f, 1.5f, 1, 100) ; //产生正交投影矩阵
//			GLU.gluLookAt(gl,-1.0f,0.6f,3.0f,1.3f,-2.4f,2f,0f,1.0f,0.0f);
		}

		@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.glPushMatrix() ;
			gl.glTranslatef(0, 0, -4f);
			funcView.draw(gl);
			gl.glPopMatrix() ;
		}
		//传入的方程
		@Override
		public float getX(double x, double y)
		{
			return (float) x;
		}

		@Override
		public float getY(double x, double y)
		{
			return  (float)( Math.pow(Math.E, -(x*Math.cos(4*x))*(x*Math.cos(4*x)))*Math.cos(y));
		}

		@Override
		public float getZ(double x, double y)
		{
			return (float)( Math.pow(Math.E, -(x*Math.cos(4*x))*(x*Math.cos(4*x)))*Math.sin(y));
		}
		
	}
}
2.分割和绘制代码

package com.example.plot;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;

public class FuncView 
{
	
	public float angleX;
	public float angleY;
	public float angleZ;
	
	private int vCount=0;  //顶点个数
	private FloatBuffer vBuf;
	// f(z)=cos(x)-x*sin(x) x[0,2pi] y[0,2pi]
	public FuncView(double xLow,double xHeight,double yLow,double yHeight,IFunc func)
	{
		double stepX = (xHeight-xLow)/100 ;
		double stepY=(yHeight-yLow)/100 ;
		ArrayList<Float> val=new ArrayList<Float>(); //存放顶点的列表
		float x=(float) xLow ;
		float y=(float) yLow ;
		for (int i = 0; i <=100; i++, x += stepX)
		{
			for (int j = 0; j <= 100; j++, y += stepY)
			{
				
				float x1= func.getX(x, y) ;
				float y1= func.getY(x, y) ;
				float z1= func.getZ(x, y) ;
				
				float x2= func.getX(x+stepX, y) ;
				float y2= func.getY(x+stepX, y) ;
				float z2= func.getZ(x+stepX, y) ;
				
				float x3= func.getX(x+stepX, y+stepY) ;
				float y3= func.getY(x+stepX, y+stepY) ;
				float z3= func.getZ(x+stepX, y+stepY) ;
				
				float x4= func.getX(x, y+stepY) ;
				float y4= func.getY(x, y+stepY) ;
				float z4= func.getZ(x, y+stepY) ;			
				val.add(x1) ;val.add(y1) ;val.add(z1) ;
				val.add(x2) ;val.add(y2) ;val.add(z2) ;
				val.add(x4) ;val.add(y4) ;val.add(z4) ;
				
				val.add(x2) ;val.add(y2) ;val.add(z2) ;
				val.add(x3) ;val.add(y3) ;val.add(z3) ;
				val.add(x4) ;val.add(y4) ;val.add(z4) ;
				
			}

		}		
		vCount=val.size()/3 ;
		float[] vertexs = new float[vCount*3];  //存放顶点数据
		for(int i=0;i<vCount;i++)
		{
			vertexs[i*3]=val.get(i*3);
			vertexs[i*3+1]=val.get(i*3+1);
			vertexs[i*3+2]=val.get(i*3+2);
		}
		ByteBuffer vbb;
		vbb = ByteBuffer.allocateDirect(vertexs.length  * 4);
		vbb.order(ByteOrder.nativeOrder());
		vBuf = vbb.asFloatBuffer();
		vBuf.put(vertexs);
		vBuf.position(0);
	}

	public void draw(GL10 gl)
	{
		gl.glRotatef(angleX, 1, 0, 0);
		gl.glRotatef(angleY, 0, 1, 0);
		gl.glRotatef(angleZ, 0, 0, 1);
		gl.glScalef(0.8F, 0.8F, 0.8F) ;	
		gl.glRotatef(-90, 1, 0, 0);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vCount);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
	}

	
	
}

3.方程接口

package com.example.plot;

public interface IFunc
{
	public float getX(double x,double y) ;
	public float getY(double x,double y) ;
	public float getZ(double x,double y) ;
}

4.主Activity

package com.example.plot;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;

public class MainActivity extends ActionBarActivity
{
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(new MySurefaceView(this));
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值