輕松實(shí)現(xiàn)Android3D效果通俗易懂
文章最后將會(huì)貼出源碼(照顧新手附加注釋)
一、先看看聊天(需求)

二、實(shí)現(xiàn)效果

三、實(shí)現(xiàn)
前五步傳感器內(nèi)容。
1.通過(guò)getSystemService獲得SensorManager實(shí)例對(duì)象
mSensorManager = (SensorManager)context.getSystemService(SENSOR_SERVICE);
2.通過(guò)SensorManager實(shí)例對(duì)象獲得想要的傳感器對(duì)象:參數(shù)決定獲取哪個(gè)傳感器
mRotationVectorSensor = mSensorManager.getDefaultSensor(
Sensor.TYPE_ROTATION_VECTOR);
3.在獲得焦點(diǎn)時(shí)注冊(cè)傳感器并讓本類(lèi)實(shí)現(xiàn)SensorEventListener接口
mSensorManager.registerListener(this, mRotationVectorSensor, 10000);
- 第一個(gè)參數(shù):SensorEventListener接口的實(shí)例對(duì)象
- 第二個(gè)參數(shù):需要注冊(cè)的傳感器實(shí)例
- 第三個(gè)參數(shù):傳感器獲取傳感器事件event值頻率:
SensorManager.SENSOR_DELAY_FASTEST = 0:對(duì)應(yīng)0微秒的更新間隔,最快,1微秒 = 1 % 1000000秒
SensorManager.SENSOR_DELAY_GAME = 1:對(duì)應(yīng)20000微秒的更新間隔,游戲中常用
SensorManager.SENSOR_DELAY_UI = 2:對(duì)應(yīng)60000微秒的更新間隔
SensorManager.SENSOR_DELAY_NORMAL = 3:對(duì)應(yīng)200000微秒的更新間隔
鍵入自定義的int值x時(shí):對(duì)應(yīng)x微秒的更新間隔
4.必須重寫(xiě)的兩個(gè)方法
onAccuracyChanged和onSensorChanged
onSensorChanged: 傳感器事件值改變時(shí)的回調(diào)接口:執(zhí)行此方法的頻率與注冊(cè)傳感器時(shí)的頻率有關(guān).
onAccuracyChanged:傳感器精度發(fā)生改變的回調(diào)接口
5.在失去焦點(diǎn)時(shí)注銷(xiāo)傳感器(為Activity提供調(diào)用)
public void stop() {
mSensorManager.unregisterListener(this);
}
6.draw方法中的方發(fā)詳解
本案例(opengl坐標(biāo)系中采用的是3維坐標(biāo))
- glEnable:?jiǎn)⒂梅?wù)器端GL功能。
- glFrontFace:定義多邊形的正面和背面。多邊形正面的方向。GL_CW和GL_CCW被允許,初始值為GL_CCW。
- glShadeModel:選擇恒定或光滑著色模式。GL圖元可以采用恒定或者光滑著色模式,默認(rèn)值為光滑著色模式。當(dāng)圖元進(jìn)行光柵化的時(shí)候,將引起插入頂點(diǎn)顏色計(jì)算,不同顏色將被均勻分布到各個(gè)像素片段。允許的值有GL_FLAT 和GL_SMOOTH,初始值為GL_SMOOTH。
- glVertexPointer:定義一個(gè)頂點(diǎn)坐標(biāo)矩陣。(后續(xù)源碼中會(huì)貼上各個(gè)參數(shù)以及需要注意的地方)。
- glColorPointer:定義一個(gè)顏色矩陣。size指明每個(gè)顏色的元素?cái)?shù)量,必須為4。type指明每個(gè)顏色元素的數(shù)據(jù)類(lèi)型,stride指明從一個(gè)顏色到下一個(gè)允許的頂點(diǎn)的字節(jié)增幅,并且屬性值被擠入簡(jiǎn)單矩陣或存儲(chǔ)在單獨(dú)的矩陣中(簡(jiǎn)單矩陣存儲(chǔ)可能在一些版本中更有效率)。
- glDrawElements:由矩陣數(shù)據(jù)渲染圖元
更多建議參考Android官方文檔。
四、需求中的青黃色參數(shù)
final float colors[] = {
0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 1,
};
五、源碼
TdRenderer.java
public class TdRenderer implements GLSurfaceView.Renderer, SensorEventListener {
//傳感器
private SensorManager mSensorManager;
private Sensor mRotationVectorSensor;
private Cube mCube;
private final float[] mRotationMatrix = new float[16];
public TdRenderer(Context context) {
//第一步:通過(guò)getSystemService獲得SensorManager實(shí)例對(duì)象
mSensorManager = (SensorManager)context.getSystemService(SENSOR_SERVICE);
//第二步:通過(guò)SensorManager實(shí)例對(duì)象獲得想要的傳感器對(duì)象:參數(shù)決定獲取哪個(gè)傳感器
mRotationVectorSensor = mSensorManager.getDefaultSensor(
Sensor.TYPE_ROTATION_VECTOR);
mCube = new Cube();
mRotationMatrix[ 0] = 1;
mRotationMatrix[ 4] = 1;
mRotationMatrix[ 8] = 1;
mRotationMatrix[12] = 1;
}
// 第三步:在獲得焦點(diǎn)時(shí)注冊(cè)傳感器并讓本類(lèi)實(shí)現(xiàn)SensorEventListener接口
public void start() {
/*
*第一個(gè)參數(shù):SensorEventListener接口的實(shí)例對(duì)象
*第二個(gè)參數(shù):需要注冊(cè)的傳感器實(shí)例
*第三個(gè)參數(shù):傳感器獲取傳感器事件event值頻率:
* SensorManager.SENSOR_DELAY_FASTEST = 0:對(duì)應(yīng)0微秒的更新間隔,最快,1微秒 = 1 % 1000000秒
* SensorManager.SENSOR_DELAY_GAME = 1:對(duì)應(yīng)20000微秒的更新間隔,游戲中常用
* SensorManager.SENSOR_DELAY_UI = 2:對(duì)應(yīng)60000微秒的更新間隔
* SensorManager.SENSOR_DELAY_NORMAL = 3:對(duì)應(yīng)200000微秒的更新間隔
* 鍵入自定義的int值x時(shí):對(duì)應(yīng)x微秒的更新間隔
*
*/
mSensorManager.registerListener(this, mRotationVectorSensor, 10000);
}
//第四步:必須重寫(xiě)的兩個(gè)方法:onAccuracyChanged,onSensorChanged
//第五步:在失去焦點(diǎn)時(shí)注銷(xiāo)傳感器(為Activity提供調(diào)用)
public void stop() {
mSensorManager.unregisterListener(this);
}
//傳感器事件值改變時(shí)的回調(diào)接口:執(zhí)行此方法的頻率與注冊(cè)傳感器時(shí)的頻率有關(guān)
public void onSensorChanged(SensorEvent event) {
// 大部分傳感器會(huì)返回三個(gè)軸方向x,y,x的event值
//float x = event.values[0];
//float y = event.values[1];
//float z = event.values[2];
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
SensorManager.getRotationMatrixFromVector(
mRotationMatrix , event.values);
}
}
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -3.0f);
gl.glMultMatrixf(mRotationMatrix, 0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
mCube.draw(gl);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glDisable(GL10.GL_DITHER);
//指定顏色緩沖區(qū)的清理值
gl.glClearColor(1,1,1,1);
}
public class Cube {
//opengl坐標(biāo)系中采用的是3維坐標(biāo):
private FloatBuffer mVertexBuffer;
private FloatBuffer mColorBuffer;
private ByteBuffer mIndexBuffer;
public Cube() {
final float vertices[] = {
-1, -1, -1, 1, -1, -1,
1, 1, -1, -1, 1, -1,
-1, -1, 1, 1, -1, 1,
1, 1, 1, -1, 1, 1,
};
final float colors[] = {
0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 1,
};
final byte indices[] = {
0, 4, 5, 0, 5, 1,
1, 5, 6, 1, 6, 2,
2, 6, 7, 2, 7, 3,
3, 7, 4, 3, 4, 0,
4, 7, 6, 4, 6, 5,
3, 0, 1, 3, 1, 2
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());
mColorBuffer = cbb.asFloatBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);
mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
}
public void draw(GL10 gl) {
//啟用服務(wù)器端GL功能。
gl.glEnable(GL10.GL_CULL_FACE);
//定義多邊形的正面和背面。
//參數(shù):
//mode——多邊形正面的方向。GL_CW和GL_CCW被允許,初始值為GL_CCW。
gl.glFrontFace(GL10.GL_CW);
//選擇恒定或光滑著色模式。
//GL圖元可以采用恒定或者光滑著色模式,默認(rèn)值為光滑著色模式。當(dāng)圖元進(jìn)行光柵化的時(shí)候,將引起插入頂點(diǎn)顏色計(jì)算,不同顏色將被均勻分布到各個(gè)像素片段。
//參數(shù):
//mode——指明一個(gè)符號(hào)常量來(lái)代表要使用的著色技術(shù)。允許的值有GL_FLAT 和GL_SMOOTH,初始值為GL_SMOOTH。
gl.glShadeModel(GL10.GL_SMOOTH);
//定義一個(gè)頂點(diǎn)坐標(biāo)矩陣。
//參數(shù):
//
//size——每個(gè)頂點(diǎn)的坐標(biāo)維數(shù),必須是2, 3或者4,初始值是4。
//
//type——指明每個(gè)頂點(diǎn)坐標(biāo)的數(shù)據(jù)類(lèi)型,允許的符號(hào)常量有GL_BYTE, GL_SHORT, GL_FIXED和GL_FLOAT,初始值為GL_FLOAT。
//
//stride——指明連續(xù)頂點(diǎn)間的位偏移,如果為0,頂點(diǎn)被認(rèn)為是緊密壓入矩陣,初始值為0。
//
//pointer——指明頂點(diǎn)坐標(biāo)的緩沖區(qū),如果為null,則沒(méi)有設(shè)置緩沖區(qū)。
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
//定義一個(gè)顏色矩陣。
//size指明每個(gè)顏色的元素?cái)?shù)量,必須為4。type指明每個(gè)顏色元素的數(shù)據(jù)類(lèi)型,stride指明從一個(gè)顏色到下一個(gè)允許的頂點(diǎn)的字節(jié)增幅,并且屬性值被擠入簡(jiǎn)單矩陣或存儲(chǔ)在單獨(dú)的矩陣中(簡(jiǎn)單矩陣存儲(chǔ)可能在一些版本中更有效率)。
gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
//由矩陣數(shù)據(jù)渲染圖元
//可以事先指明獨(dú)立的頂點(diǎn)、法線、顏色和紋理坐標(biāo)矩陣并且可以通過(guò)調(diào)用glDrawElements方法來(lái)使用它們創(chuàng)建序列圖元。
gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
}
}
//傳感器精度發(fā)生改變的回調(diào)接口
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//在傳感器精度發(fā)生改變時(shí)做些操作,accuracy為當(dāng)前傳感器精度
}
}
ThreeDimensionsRotation,java(Activity記得注冊(cè))
public class ThreeDimensionsRotation extends Activity {
private GLSurfaceView mGLSurfaceView;
private TdRenderer tdRenderer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tdRenderer=new TdRenderer(this);
// 創(chuàng)建預(yù)覽視圖,并將其設(shè)置為Activity的內(nèi)容
mGLSurfaceView = new GLSurfaceView(this);
mGLSurfaceView.setRenderer(tdRenderer);
setContentView(mGLSurfaceView);
}
@Override
protected void onResume() {
super.onResume();
tdRenderer.start();
mGLSurfaceView.onResume();
}
@Override
protected void onPause() {
super.onPause();
tdRenderer.stop();
mGLSurfaceView.onPause();
}
}
到此這篇關(guān)于輕松實(shí)現(xiàn)Android3D效果通俗易懂的文章就介紹到這了,更多相關(guān)Android 3D效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IOS開(kāi)發(fā)向右滑動(dòng)返回前一個(gè)頁(yè)面功能(demo)
本文給大家介紹使用android實(shí)現(xiàn)向右滑動(dòng)返回一個(gè)頁(yè)面的功能,大家都知道在ios7中,蘋(píng)果的原生態(tài)應(yīng)用幾乎都能夠通過(guò)向右滑動(dòng)來(lái)返回到前一個(gè)頁(yè)面,這樣可以避免用戶在單手操作時(shí)用大拇指去點(diǎn)擊那個(gè)遙遠(yuǎn)的返回鍵,下面小編就給帶來(lái)了實(shí)現(xiàn)代碼,有需要的朋友可以參考下2016-06-06
基于Android ContentProvider的總結(jié)詳解
本篇文章是對(duì)Android ContentProvider進(jìn)行了詳細(xì)的總結(jié)與分析,需要的朋友參考下2013-05-05
Android 3.0引入的異步加載機(jī)制Loader
Loader裝載器從android3.0開(kāi)始引進(jìn)。它使得在activity或fragment中異步加載數(shù)據(jù)變得簡(jiǎn)單。下面我們就來(lái)詳細(xì)講解下2017-12-12
android實(shí)現(xiàn)指紋識(shí)別功能
這篇文章主要介紹了android指紋識(shí)別功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
Android Activity中onStart()和onResume()的區(qū)別分析
這篇文章主要介紹了Android Activity中onStart()和onResume()的區(qū)別,結(jié)合Activity的四種狀態(tài)簡(jiǎn)單分析了Android Activity中onStart()和onResume()方法的作用,并補(bǔ)充說(shuō)明了Activity中六個(gè)常用函數(shù),需要的朋友可以參考下2016-01-01
Android使用Canvas對(duì)象實(shí)現(xiàn)刮刮樂(lè)效果
這篇文章主要介紹了Android使用Canvas對(duì)象實(shí)現(xiàn)刮刮樂(lè)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Android 實(shí)現(xiàn)旋轉(zhuǎn)木馬的音樂(lè)效果
大家一定在百度音樂(lè)上在線聽(tīng)過(guò)歌,有沒(méi)有注意到那個(gè)旋轉(zhuǎn)的唱片,本篇文章主要介紹在Android上如何實(shí)現(xiàn)這樣的功能,有需要的小伙伴可以參考下2016-07-07
android Imageview 圖片覆蓋具體實(shí)現(xiàn)
android Imageview 圖片覆蓋實(shí)現(xiàn)及注意事項(xiàng)如下,感興趣的朋友可以參考下哈2013-06-06

