您好,登錄后才能下訂單哦!
如何在android中使用OPENGL ES繪制一個圓柱體?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
編寫jiem.java
*指定屏幕所要顯示的假面,并對見、界面進行相關設置
*為Activity設置恢復處理,當Acitvity恢復設置時顯示界面同樣應該恢復
*當Activity暫停設置時,顯示界面同樣應該暫停
package com.scout.eeeeeee; import android.app.Activity; import android.os.Bundle; import android.app.Activity; import android.os.Bundle; import android.app.Activity; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; public class jiem extends Activity { private MyGLSurfaceView mGLSurfaceView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); mGLSurfaceView = new MyGLSurfaceView(this); setContentView(mGLSurfaceView); mGLSurfaceView.setFocusableInTouchMode(true);//設置為可觸控 mGLSurfaceView.requestFocus();//獲取焦點 } @Override protected void onResume() { super.onResume(); mGLSurfaceView.onResume(); } @Override protected void onPause() { super.onPause(); mGLSurfaceView.onPause(); } }
編寫MyGLSurfaceView.java實現場景加載和渲染功能
package com.scout.eeeeeee; /** * Created by liuguodong on 2017/10/29. */ import java.io.IOException; import java.io.InputStream; import android.opengl.GLSurfaceView; import android.opengl.GLUtils; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.MotionEvent; public class MyGLSurfaceView extends GLSurfaceView { private final float suo = 180.0f/320;//角度縮放比例 private SceneRenderer mRenderer;//場景渲染器 private float shangY;//上次的觸控位置Y坐標 private float shangX;//上次的觸控位置Y坐標 private int lightAngle=90;//燈的當前角度 public MyGLSurfaceView(Context context) { super(context); mRenderer = new SceneRenderer(); //創建場景渲染器 setRenderer(mRenderer); //設置渲染器 setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//設置渲染模式為主動渲染 } //觸摸事件回調方法 @Override public boolean onTouchEvent(MotionEvent e) { float y = e.getY(); float x = e.getX(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: float dy = y - shangY;//計算觸控筆Y位移 float dx = x - shangX;//計算觸控筆Y位移 mRenderer.cylinder.mAngleX += dy * suo;//設置沿x軸旋轉角度 mRenderer.cylinder.mAngleZ += dx * suo;//設置沿z軸旋轉角度 requestRender();//重繪畫面 } shangY = y;//記錄觸控筆位置 shangX = x;//記錄觸控筆位置 return true; } private class SceneRenderer implements GLSurfaceView.Renderer { int textureId;//紋理名稱ID zhuCH cylinder;//創建圓柱體 public SceneRenderer() { } 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();//保護變換矩陣現場 float lx=0; //設定光源的位置 float ly=(float)(7*Math.cos(Math.toRadians(lightAngle))); float lz=(float)(7*Math.sin(Math.toRadians(lightAngle))); float[] positionParamsRed={lx,ly,lz,0}; gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionParamsRed,0); initMaterial(gl);//初始化紋理 gl.glTranslatef(0, 0, -10f);//平移 initLight(gl);//開燈 cylinder.drawSelf(gl);//繪制 closeLight(gl);//關燈 gl.glPopMatrix();//恢復變換矩陣現場 } 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, -1, 1, 1, 100); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { //關閉抗抖動 gl.glDisable(GL10.GL_DITHER); //設置特定Hint項目的模式,這里為設置為使用快速模式 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST); //設置屏幕背景色黑色RGBA gl.glClearColor(0,0,0,0); //設置著色模型為平滑著色 gl.glShadeModel(GL10.GL_SMOOTH); //啟用深度測試 gl.glEnable(GL10.GL_DEPTH_TEST); textureId=initTexture(gl,R.drawable.stone);//紋理ID cylinder=new zhuCH(10f,2f,18f,textureId);//創建圓柱體 } } //初始化白色燈 private void initLight(GL10 gl) { gl.glEnable(GL10.GL_LIGHTING);//允許光照 gl.glEnable(GL10.GL_LIGHT1);//打開1號燈 //環境光設置 float[] ambientParams={0.2f,0.2f,0.2f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, ambientParams,0); //散射光設置 float[] diffuseParams={1f,1f,1f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseParams,0); //反射光設置 float[] specularParams={1f,1f,1f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_SPECULAR, specularParams,0); } //關閉燈 private void closeLight(GL10 gl) { gl.glDisable(GL10.GL_LIGHT1); gl.glDisable(GL10.GL_LIGHTING); } //初始化材質 private void initMaterial(GL10 gl) { //環境光 float ambientMaterial[] = {248f/255f, 242f/255f, 144f/255f, 1.0f}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, ambientMaterial,0); //散射光 float diffuseMaterial[] = {248f/255f, 242f/255f, 144f/255f, 1.0f}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffuseMaterial,0); //高光材質 float specularMaterial[] = {248f/255f, 242f/255f, 144f/255f, 1.0f}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, specularMaterial,0); gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 100.0f); } //初始化紋理 public int initTexture(GL10 gl,int drawableId)//textureId { //生成紋理ID int[] textures = new int[1]; gl.glGenTextures(1, textures, 0); int currTextureId=textures[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR_MIPMAP_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR_MIPMAP_LINEAR); ((GL11)gl).glTexParameterf(GL10.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL10.GL_TRUE); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT); InputStream is = this.getResources().openRawResource(drawableId); Bitmap bitmapTmp; try { bitmapTmp = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch(IOException e) { e.printStackTrace(); } } GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0); bitmapTmp.recycle(); return currTextureId; } }
編寫zgyCH.java
*設置圓柱體的控制屬性,主要包括紋理、高度、截面半徑、截面角度切分單位和高度切分單位,這些屬性用于控制圓柱體的大小
*定義各個圓柱體繪制類的三角形繪制方法和工具方法
*實現圓柱體的線性會執法,線性會執法和三角形會執法頂點的獲取方法相同,只是采用的繪制頂點順序和渲染方法不同,并且先行繪制沒有光照和紋理貼圖
package com.scout.eeeeeee; /** * Created by liuguodong on 2017/10/29. */ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.ArrayList; import javax.microedition.khronos.opengles.GL10; public class zhuCH { private FloatBuffer dingBuffer;//頂點坐標緩沖 private FloatBuffer myNormalBuffer;//向量緩沖 private FloatBuffer myTexture;//紋理緩沖 int textureId; int vCount;//頂點數量 float length;//圓柱長度 float circle_radius;//圓截環半徑 float degreespan; //圓截環每一份的度數大小 public float mAngleX; public float mAngleY; public float mAngleZ; public zhuCH(float length,float circle_radius,float degreespan,int textureId) { this.circle_radius=circle_radius; this.length=length; this.degreespan=degreespan; this.textureId=textureId; float collength=(float)length;//圓柱每塊所占的長度 int spannum=(int)(360.0f/degreespan); ArrayList<Float> val=new ArrayList<Float>();//頂點存放列表 ArrayList<Float> ial=new ArrayList<Float>();//法向量存放列表 for(float circle_degree=180.0f;circle_degree>0.0f;circle_degree-=degreespan)//循環行 { float x1 =(float)(-length/2); float y1=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree))); float z1=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree))); float a1=0; float b1=y1; float c1=z1; float l1=getVectorLength(a1, b1, c1);//模長 a1=a1/l1;//法向量規格化 b1=b1/l1; c1=c1/l1; float x2 =(float)(-length/2); float y2=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree-degreespan))); float z2=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree-degreespan))); float a2=0; float b2=y2; float c2=z2; float l2=getVectorLength(a2, b2, c2);//模長 a2=a2/l2;//法向量規格化 b2=b2/l2; c2=c2/l2; float x3 =(float)(length/2); float y3=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree-degreespan))); float z3=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree-degreespan))); float a3=0; float b3=y3; float c3=z3; float l3=getVectorLength(a3, b3, c3);//模長 a3=a3/l3;//法向量規格化 b3=b3/l3; c3=c3/l3; float x4 =(float)(length/2); float y4=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree))); float z4=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree))); float a4=0; float b4=y4; float c4=z4; float l4=getVectorLength(a4, b4, c4);//模長 a4=a4/l4;//法向量規格化 b4=b4/l4; c4=c4/l4; val.add(x1);val.add(y1);val.add(z1);//兩個三角形,共6個頂點的坐標 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); ial.add(a1);ial.add(b1);ial.add(c1);//頂點對應的法向量 ial.add(a2);ial.add(b2);ial.add(c2); ial.add(a4);ial.add(b4);ial.add(c4); ial.add(a2);ial.add(b2);ial.add(c2); ial.add(a3);ial.add(b3);ial.add(c3); ial.add(a4);ial.add(b4);ial.add(c4); } vCount=val.size()/3;//確定頂點數量 //頂點 float[] vertexs=new float[vCount*3]; for(int i=0;i<vCount*3;i++) { vertexs[i]=val.get(i); } ByteBuffer vbb=ByteBuffer.allocateDirect(vertexs.length*4); vbb.order(ByteOrder.nativeOrder()); dingBuffer=vbb.asFloatBuffer(); dingBuffer.put(vertexs); dingBuffer.position(0); //法向量 float[] normals=new float[vCount*3]; for(int i=0;i<vCount*3;i++) { normals[i]=ial.get(i); } ByteBuffer ibb=ByteBuffer.allocateDirect(normals.length*4); ibb.order(ByteOrder.nativeOrder()); myNormalBuffer=ibb.asFloatBuffer(); myNormalBuffer.put(normals); myNormalBuffer.position(0); //紋理 float[] textures=generateTexCoor(spannum); ByteBuffer tbb=ByteBuffer.allocateDirect(textures.length*4); tbb.order(ByteOrder.nativeOrder()); myTexture=tbb.asFloatBuffer(); myTexture.put(textures); myTexture.position(0); } public void drawSelf(GL10 gl) { gl.glRotatef(mAngleX, 1, 0, 0);//旋轉 gl.glRotatef(mAngleY, 0, 1, 0); gl.glRotatef(mAngleZ, 0, 0, 1); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//打開頂點緩沖 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, dingBuffer);//指定頂點緩沖 gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);//打開法向量緩沖 gl.glNormalPointer(GL10.GL_FLOAT, 0, myNormalBuffer);//指定法向量緩沖 gl.glEnable(GL10.GL_TEXTURE_2D); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, myTexture); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vCount);//繪制圖像 gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//關閉緩沖 gl.glEnable(GL10.GL_TEXTURE_2D); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); } //法向量規格化,求模長度 public float getVectorLength(float x,float y,float z) { float pingfang=x*x+y*y+z*z; float length=(float) Math.sqrt(pingfang); return length; } //自動切分紋理產生紋理數組的方法 public float[] generateTexCoor(int bh) { float[] result=new float[bh*6*2]; float REPEAT=2; float sizeh=1.0f/bh;//行數 int c=0; for(int i=0;i<bh;i++) { //每行列一個矩形,由兩個三角形構成,共六個點,12個紋理坐標 float t=i*sizeh; result[c++]=0; result[c++]=t; result[c++]=0; result[c++]=t+sizeh; result[c++]=REPEAT; result[c++]=t; result[c++]=0; result[c++]=t+sizeh; result[c++]=REPEAT; result[c++]=t+sizeh; result[c++]=REPEAT; result[c++]=t; } return result; } }
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。