本文實例為大家分享了android使用OPENGL ES繪制圓柱體的具體代碼,供大家參考,具體內容如下
效果圖:
編寫jiem.java
*指定屏幕所要顯示的假面,并對見、界面進行相關設置
*為Activity設置恢復處理,當Acitvity恢復設置時顯示界面同樣應該恢復
*當Activity暫停設置時,顯示界面同樣應該暫停
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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實現場景加載和渲染功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
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
*設置圓柱體的控制屬性,主要包括紋理、高度、截面半徑、截面角度切分單位和高度切分單位,這些屬性用于控制圓柱體的大小
*定義各個圓柱體繪制類的三角形繪制方法和工具方法
*實現圓柱體的線性會執法,線性會執法和三角形會執法頂點的獲取方法相同,只是采用的繪制頂點順序和渲染方法不同,并且先行繪制沒有光照和紋理貼圖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
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; } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/liu3364575/article/details/78384170