本文實例為大家分享了android使用OPENGL ES繪制圓柱體的具體代碼,供大家參考,具體內(nèi)容如下
效果圖:
編寫jiem.java
*指定屏幕所要顯示的假面,并對見、界面進行相關(guān)設(shè)置
*為Activity設(shè)置恢復處理,當Acitvity恢復設(shè)置時顯示界面同樣應(yīng)該恢復
*當Activity暫停設(shè)置時,顯示界面同樣應(yīng)該暫停
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 ); //設(shè)置為可觸控 mGLSurfaceView.requestFocus(); //獲取焦點 } @Override protected void onResume() { super .onResume(); mGLSurfaceView.onResume(); } @Override protected void onPause() { super .onPause(); mGLSurfaceView.onPause(); } } |
編寫MyGLSurfaceView.java實現(xiàn)場景加載和渲染功能
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(); //創(chuàng)建場景渲染器 setRenderer(mRenderer); //設(shè)置渲染器 setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); //設(shè)置渲染模式為主動渲染 } //觸摸事件回調(diào)方法 @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; //設(shè)置沿x軸旋轉(zhuǎn)角度 mRenderer.cylinder.mAngleZ += dx * suo; //設(shè)置沿z軸旋轉(zhuǎn)角度 requestRender(); //重繪畫面 } shangY = y; //記錄觸控筆位置 shangX = x; //記錄觸控筆位置 return true ; } private class SceneRenderer implements GLSurfaceView.Renderer { int textureId; //紋理名稱ID zhuCH cylinder; //創(chuàng)建圓柱體 public SceneRenderer() { } public void onDrawFrame(GL10 gl) { //清除顏色緩存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //設(shè)置當前矩陣為模式矩陣 gl.glMatrixMode(GL10.GL_MODELVIEW); //設(shè)置當前矩陣為單位矩陣 gl.glLoadIdentity(); gl.glPushMatrix(); //保護變換矩陣現(xiàn)場 float lx= 0 ; //設(shè)定光源的位置 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); //關(guān)燈 gl.glPopMatrix(); //恢復變換矩陣現(xiàn)場 } public void onSurfaceChanged(GL10 gl, int width, int height) { //設(shè)置視窗大小及位置 gl.glViewport( 0 , 0 , width, height); //設(shè)置當前矩陣為投影矩陣 gl.glMatrixMode(GL10.GL_PROJECTION); //設(shè)置當前矩陣為單位矩陣 gl.glLoadIdentity(); //計算透視投影的比例 float ratio = ( float ) width / height; //調(diào)用此方法計算產(chǎn)生透視投影矩陣 gl.glFrustumf(-ratio, ratio, - 1 , 1 , 1 , 100 ); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { //關(guān)閉抗抖動 gl.glDisable(GL10.GL_DITHER); //設(shè)置特定Hint項目的模式,這里為設(shè)置為使用快速模式 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST); //設(shè)置屏幕背景色黑色RGBA gl.glClearColor( 0 , 0 , 0 , 0 ); //設(shè)置著色模型為平滑著色 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); //創(chuàng)建圓柱體 } } //初始化白色燈 private void initLight(GL10 gl) { gl.glEnable(GL10.GL_LIGHTING); //允許光照 gl.glEnable(GL10.GL_LIGHT1); //打開1號燈 //環(huán)境光設(shè)置 float [] ambientParams={ 0 .2f, 0 .2f, 0 .2f, 1 .0f}; //光參數(shù) RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, ambientParams, 0 ); //散射光設(shè)置 float [] diffuseParams={1f,1f,1f, 1 .0f}; //光參數(shù) RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseParams, 0 ); //反射光設(shè)置 float [] specularParams={1f,1f,1f, 1 .0f}; //光參數(shù) RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_SPECULAR, specularParams, 0 ); } //關(guān)閉燈 private void closeLight(GL10 gl) { gl.glDisable(GL10.GL_LIGHT1); gl.glDisable(GL10.GL_LIGHTING); } //初始化材質(zhì) private void initMaterial(GL10 gl) { //環(huán)境光 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 ); //高光材質(zhì) 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
*設(shè)置圓柱體的控制屬性,主要包括紋理、高度、截面半徑、截面角度切分單位和高度切分單位,這些屬性用于控制圓柱體的大小
*定義各個圓柱體繪制類的三角形繪制方法和工具方法
*實現(xiàn)圓柱體的線性會執(zhí)法,線性會執(zhí)法和三角形會執(zhí)法頂點的獲取方法相同,只是采用的繪制頂點順序和渲染方法不同,并且先行繪制沒有光照和紋理貼圖
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; //頂點數(shù)量 float length; //圓柱長度 float circle_radius; //圓截環(huán)半徑 float degreespan; //圓截環(huán)每一份的度數(shù)大小 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) //循環(huán)行 { 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; //法向量規(guī)格化 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; //法向量規(guī)格化 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; //法向量規(guī)格化 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; //法向量規(guī)格化 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); //頂點對應(yīng)的法向量 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 ; //確定頂點數(shù)量 //頂點 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 ); //旋轉(zhuǎn) 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); //關(guān)閉緩沖 gl.glEnable(GL10.GL_TEXTURE_2D); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); } //法向量規(guī)格化,求模長度 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; } //自動切分紋理產(chǎn)生紋理數(shù)組的方法 public float [] generateTexCoor( int bh) { float [] result= new float [bh* 6 * 2 ]; float REPEAT= 2 ; float sizeh= 1 .0f/bh; //行數(shù) int c= 0 ; for ( int i= 0 ;i<bh;i++) { //每行列一個矩形,由兩個三角形構(gòu)成,共六個點,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; } } |
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/liu3364575/article/details/78384170