利用OpenGL ES、手機傳感器、相機和調用百度語音包服務,實現AR+語音播報導航功能(導航功能爲模擬,Android)

Demo展示:

幾個重要模塊

GLSurfaceView:

1.首先需要自定義類實現GlsurfaceView.Renderer接口

public abstract class AbstractMyRender implements GLSurfaceView.Renderer {

    public float ratio;
//    圍繞X軸旋轉的角度
    public float xrotate = 0f;
//    圍繞Y軸旋轉的角度
    public float yrotate = 0f;
//    圍繞Z軸旋轉的角度
    public float zrotate = 0f;
    /*
            這是第一步
     */

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
//        清屏色
        gl10.glClearColor(0f,0f,0f,1f);
//        啓用頂點緩衝區數組
        gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    }
    /*
            這是第二步
     */
    @Override
    public void onSurfaceChanged(GL10 gl10, int i, int i1) {
//設置視口
        gl10.glViewport(0,0,i,i1);
        ratio = (float)i/(float)i1;
//      投影矩陣
        gl10.glMatrixMode(GL10.GL_PROJECTION);
//      加載單位矩陣
        gl10.glLoadIdentity();
//      設置平截頭體
        gl10.glFrustumf(-ratio,ratio,-1,1,3f,7f);
    }
    /*
            這是第三步
     */
    public  abstract void onDrawFrame(GL10 gl10);
}

2.定義子類繼承自定義類並複寫其中的方法(可以繪製不同的圖案),例如繪製顏色立方體可以定義子類MyColorCubeRenderer

public class MyColorCubeRenderer extends AbstractMyRender {
    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
//        清屏色
        gl10.glColor4f(0,0,0,1f);
//        啓動頂點緩衝區數組
        gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//        顏色緩衝區
        gl10.glEnableClientState(GL10.GL_COLOR_ARRAY);
//        啓用深度測試
        gl10.glEnable(GL10.GL_DEPTH_TEST);
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int i, int i1) {
//        設置視口
        gl10.glViewport(0,0,i,i1);
        ratio = (float)i/(float)i1;
//        投影矩陣
        gl10.glMatrixMode(GL10.GL_PROJECTION);
//        加載單位矩陣
        gl10.glLoadIdentity();
//        設置平截頭體
        gl10.glFrustumf(-ratio,ratio,-1f,1f,3f,7f);
    }

    @Override
    public void onDrawFrame(GL10 gl10) {
        gl10.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
        gl10.glColor4f(1f,0f,0f,1f);
//        模型視圖矩陣
        gl10.glMatrixMode(GL10.GL_MODELVIEW);
        gl10.glLoadIdentity();
        GLU.gluLookAt(gl10,0,0,5,0,0,0,0,1,0);
        gl10.glRotatef(xrotate,1,0,0);
        gl10.glRotatef(yrotate,0,1,0);
        gl10.glRotatef(zrotate,0,0,1);
        float r = 0.4f;
//        定義點座標
        float[] coords = {
//                前面四個點座標,分別是左上,左下,右上,右下
                -r,r,r,
                -r,-r,r,
                r,r,r,
                r,-r,r,
//                後面四個點座標
                -r,r,-r,
                -r,-r,-r,
                r,r,-r,
                r,-r,-r
        };
//        定義頂點索引位置
        byte[] indices = {
                0,1,2,2,1,3,//front
                4,5,6,6,5,7,//back
                0,1,4,4,1,5,//left
                2,3,6,6,3,7,//right
                4,0,2,4,2,6,//top
                5,1,3,5,3,7//bottom
        };
//        定義顏色
        float[] colors = {
                0f,1f,1f,1f,//青色
                0,1,0,1,
                1,1,1,1,//白色
                1,1,0,1,//黃色
                0,0,1,1,//4
                0,0,0,1,//5
                1,0,1,1,//6
                1,0,0,1//7
        };
        gl10.glColorPointer(4,GL10.GL_FLOAT,0, BufferUtil.arr2ByteBuffer(colors));
        gl10.glVertexPointer(3,GL10.GL_FLOAT,0,BufferUtil.arr2ByteBuffer(coords));
//        使用頂點索引方式繪製
        gl10.glDrawElements(GL10.GL_TRIANGLES,indices.length, GL10.GL_UNSIGNED_BYTE,BufferUtil.arr2ByteBuffer(indices));
//        使用頂點數組索引方式繪製
//        gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,coords.length/3);

    }
}

在本例中使用的MultiArrow類渲染的圖案。(詳細代碼我會放置於我的github主頁上https://github.com/slpslpslp,我渲染類寫了有幾個,有渲染立方體、渲染線、渲染圓環和球,詳細的Android使用opengles教程可以參照https://blog.csdn.net/column/details/apidemoopengl.html

Camera(相機已被Google棄用,可選擇替代)

1.相機預覽功能函數

    private void startPreview() {
        camera = Camera.open();
        try {
            camera.setPreviewDisplay(cameraPreview.getHolder());
            camera.setDisplayOrientation(90);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.相機預覽回調函數

private Camera camera;
private SurfaceHolder.Callback cameraPreviewcallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            startPreview();
            Log.i(TAG, "surfaceCreated" + Thread.currentThread().getName());
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            Log.i(TAG, "surfaceChanged");
            camera.startPreview();
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            Log.i(TAG, "surfaceDestoryed");
            if (camera != null) {
                camera.stopPreview();
                camera.release();//釋放相機資源
                camera = null;
            }
        }
    };

3.設置相機預覽SurfaceView

        cameraPreview = new SurfaceView(this);
        cameraPreview.getHolder().addCallback(cameraPreviewcallback);
        cameraPreview.getHolder().setFormat(PixelFormat.TRANSPARENT);

SensorManager

1.開啓傳感器服務

SensorManager sensorManager;
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

2.在方向傳感器(TYPE_OPIENTATION,已被棄用,可以選擇替代)變化的同時,請求渲染

@Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        int sensorType = sensorEvent.sensor.getType();
        switch (sensorType) {
            case Sensor.TYPE_ORIENTATION:
//                獲取繞三軸的角度
                float degreeZ = sensorEvent.values[0];
                float degreeX = sensorEvent.values[1];
                float degreeY = sensorEvent.values[2];
                render.xrotate = degreeX;
                render.zrotate = degreeZ;
//                render.yrotate = degreeY;
                glSurfaceView.requestRender();    //請求渲染,和髒渲染配合使用
                break;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {
    }

SpeechSynthesizerListener

百度語音合成接口Api(http://ai.baidu.com/docs#/TTS-Android-SDK/top),下載Android SDK,申請獲得APP_ID,API_KEY,SECRET_KEY,填入即可直接使用

    private static final String APP_ID = "YOUR_APP_ID";
    private static final String API_KEY = "YOUR API_KEY";
    private static final String SECRET_KEY = "YOUR SECRET_KEY";

後記:

           這個demo是我當初爲了做AR導航做的一個小項目,是自己模擬的一段導航路徑,主要是實現打開攝像頭將路徑進行渲染,通過方向傳感器,在手機擺動時而保持導航路徑絕對方向不變,在本demo中並沒有實際的路網。另外這是一年半以前的代碼了,代碼寫的也比較稚嫩,且現在已忘記很多。所以其中的細節我也沒法在這裏講解了,有興趣的可以下載下來進行擴展改進。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章