【Android】用Cubism 2制作自己的Live2D——初探Live2D在Android上的運行!


前言-

上一次我們成功運行了官方給我們的樣本,是不是很有干勁啊?!這次我們就來看看Live2D是怎么在手機上運行的!

准備-

上次運行成功的官方樣本——第一次我們先看簡單的,就是那個名字叫Sample的項目,看起來就很見到不是么?!她的目錄里除了lib庫中的Live2D的jar包之外,就剩兩個類了,看來這就是今天的全部工作量了!爭取不加班!

 

 

順便我們還要看看這個項目跑出來的樣子,大概就是這樣,在屏幕中間繪制模型,然后讓模型的頭橫擺?!

開工-

依舊還是從簡單的着手,

SampleActivity.java:

public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        //初始化Live2D
        Live2D.init();
        //建立一個View繼承自GLSurfaceView,並把它顯示出來
        SampleGLSurfaceView     view = new SampleGLSurfaceView(this) ;
        setContentView( view ) ;
    }

這里根據官方的解說文檔

Live2D.init();方法必須在程序開始使用Live2D前至少調用一次,一調用一次或者連續調用都會是程序不穩定。

在初始化的時候會顯示如下的標准Live2D版本信息

Live2D version 1.0.00 for Platform 

這里我可找到了

當然有初始化肯定就會有對應的注銷方法dispose();這里沒用到,但是中文版的說明書里給了這樣的注釋

當呼叫dispose函數後就會釋放Live2D所佔有的所有資源。
呼叫init前請不要呼叫此函數。
基本上使用於應用程式結束時呼叫。
可應用於記憶體極少的例外環境。
不需要或是欲完全切斷函式庫連結時,可以呼叫此函數釋放資源。於下次要使用時再呼叫init初始化

 

還有一個自定義的類SampleGLSurfaceView,它繼承自GLSurfaceView,這個類就是核心了(廢話一共就兩個,第一個就沒啥東西)

從下一行

setContentView(view);

 可以看出SampleGLSurfaceView是一個自已繪制的View,她又繼承自GLSurfaceView。這個GLSurfaceView可就厲害了, 在Android端使用OpenGL ES的過程中,GLSurfaceView就扮演者一個重要的角色,通過OpenGL進行繪制,可在SurfaceView所提供的Surface進行繪制。而渲染工作主要由GLSurfaceView.Renderer負責渲染。

下面看看

SampleGLSurfaceView.java 的大概結構,里面有個內部類SampleGLRenderer是渲染器,實現GLSurfaceView.Renderer接口並實現onDrawFrame、onSurfaceChanged、onSurfaceChanged方法,下面分別介紹這三個方法里都做了什么
 1 SampleGLSurfaceView.java
 2 public class SampleGLSurfaceView extends GLSurfaceView{
 3     private SampleGLRenderer        renderer ;
 4     /*    編寫渲染器SampleGLRenderer,實體類實GLSurfaceView.Renderer接口
 5 
 6     class SampleGLRenderer implements Renderer{
 7         @Override
 8     //執行渲染工作
 9     public void onDrawFrame(GL10 gl){}
10         @Override
11     // 渲染窗口大小發生改變或者屏幕方法發生變化時候回調
12     public void onSurfaceChanged(GL10 gl, int width, int height){}
13         @Override
14     //surface被創建后需要做的處理
15     public void onSurfaceCreated(GL10 gl, EGLConfig config){}
16 }



onDrawFrame()方法執行渲染的工作

@Override
        //執行渲染工作
        public void onDrawFrame(GL10 gl)
        {
            gl.glMatrixMode(GL10.GL_MODELVIEW ) ;
            gl.glLoadIdentity() ;
            gl.glClear( GL10.GL_COLOR_BUFFER_BIT ) ;

            double t = (UtSystem.getUserTimeMSec()/1000.0) * 2 * Math.PI  ;
            double cycle=3.0;
            double sin=Math.sin( t/cycle );
            live2DModel.setParamFloat( "PARAM_ANGLE_X" , (float) (30 * sin) ) ;

            live2DModel.setGL( gl ) ;

            live2DModel.update() ;
            live2DModel.draw() ;
        }
>>gl.glMatrixMode(GL10.GL_MODELVIEW ):對接下來要做什么進行一下聲明,有三個參數GL_PROJECTION 投影,GL_MODELVIEW 模型視圖,GL_TEXTURE 紋理.我們要渲染的是.moc文件,這里的參數是模型視圖GL_MODELVIEW
>>gl10.glLoadIdentity():該命令是一個無參的無值函數,其功能是用一個4×4的單位矩陣來替換當前矩陣,實際上就是對當前矩陣進行初始化
>>gl10.glClear(GL10.GL_COLOR_BUFFER_BIT):清除當前緩沖區的緩沖值 ,4個可選參數GL_COLOR_BUFFER_BIT當前可寫的顏色緩沖、GL_DEPTH_BUFFER_BIT深度緩沖、GL_ACCUM_BUFFER_BIT累積緩沖、GL_STENCIL_BUFFER_BIT模板緩沖。

下面這些運算一概是讓模型里的腦袋左右偏移的偏移量的計算,setParamFloat傳入偏移的參數setGL(gl10)設置GL、update()更新draw()繪制
P.S這些方法需要去啃Live2djar包的文檔,如果看到這些我回來填上
 
        


onSurfaceCreated(GL10 gl10, EGLConfig eglConfig)——
surface被創建后需要做的處理

      private Live2DModelAndroid live2DModel;
      private final String MODLE_PATH="mei/model.moc";
      private final String TEXTURE_PATHS[] = {
                        "mei/textures/texture_00.png"
       } ;    
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
            try {
                InputStream in = getContext().getAssets().open( MODLE_PATH ) ;
                live2DModel = Live2DModelAndroid.loadModel( in ) ;
                in.close() ;

                for (int i = 0 ; i < TEXTURE_PATHS.length ; i++ )
                {
                    InputStream tin = getContext().getAssets().open( TEXTURE_PATHS[i] ) ;
                    int texNo = UtOpenGL.loadTexture(gl10 , tin , true ) ;
                    live2DModel.setTexture( i , texNo ) ;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

這個就很好看懂了,讀.moc后loadModel,然后循環去獲取Texture中的圖片然后loadTexture(),然后與.moc捆綁

這個texture理解不了的話看看文件就知道是什么了,就是模型的貼圖。

 



 

onSurfaceChanged(GL10 gl, int width, int height)——渲染窗口大小發生改變或者屏幕方法發生變化時候回調

@Override
        public void onSurfaceChanged(GL10 gl10, int width, int height) {
            gl10.glViewport(0,0,width,height);
            gl10.glMatrixMode((GL10.GL_PROJECTION));
            gl10.glLoadIdentity();
            float modelWidth=live2DModel.getCanvasWidth();
            float aspect=(float)width/height;
            //這個glorthof好像很厲害的樣子!!
            gl10.glOrthof(0,modelWidth,modelWidth/aspect,0,0.5f,-0.5f);
        }

onSurfaceChanged(GL10 gl, int width, int height)本身是告訴了我們這張紙有多高多寬。這點很重要。因為在onSurfaceCreated的時候我們是不知道紙的寬高的,所以有一些和長寬相關的初始化工作還得在此函數中來做。

P.S  (一次性) 當GLSurfaceView大小改變時,對應的Surface大小也會改變。值得注意的是,在Surface剛創建的時候,它的size其實是0,也就是說在畫第一次圖之前它也會被調用一次的。(而且對於很多時候,Surface的大小是不會改變的,那么此函數就只在創建之初被調用一次而已)

>>glViewport(0,0,width,height):X,Y——以像素為單位,指定了視口的左下角(在第一象限內,以(0,0)為原點的)位置。width,height——表示這個視口矩形的寬度和高度,根據窗口的實時變化重繪窗口。
>>glMatrixMode()、glLoadIdentity()這兩個方法在onDrawFrame()中介紹過了。但是這里的GL10.GL_PROJECTION參數表示是投影的意思,就是要對投影相關進行操作,也就是把物體投影到一個平面上,就像我們照相一樣
>>glOrthof(left, right, bottom, top, near, far);正射投影,又叫平行投影。這種投影的視景體是一個矩形的平行管道,也就是一個長方體。
這里看到一張圖非常好,很直觀的說明這個函數的參數都是什么意思:

 


如圖所示。正射投影的最大一個特點是無論物體距離相機多遠,投影后的物體大小尺寸不變。這種投影通常用在建築藍圖繪制和計算機輔助設計等方面,這些行業要求投影后的物體尺寸及相互間的角度不變,以便施工或制造時物體比例大小正確。glOrthof就是一個正射投影函數。
它創建一個平行視景體。實際上這個函數的操作是創建一個正射投影矩陣,並且用這個矩陣乘以當前矩陣。
其中近裁剪平面是一個矩形,矩形左下角點三維空間坐標是(left,bottom,-near),右上角點是(right,top,-near);
遠裁剪平面也是一個矩形,左下角點空間坐標是(left,bottom,-far),右上角點是(right,top,-far)。
所有的near和far值同時為正或同時為負。如果沒有其他變換,正射投影的方向平行於Z軸,且視點朝向Z負軸。這意味着物體在視點前面時far和near都為負值,物體在視點后面時far和near都為正值
(我看着反正懵得很,但是我第一次仿寫代碼的是后敲成了gl10.glOrthof(0,modelWidth,modelWidth/aspect,0,0.5f,0.5f),就是最后一個參數的正負錯了,結果沒有模型顯示出來。這里我有點自己的見解但是不清楚是否正確,待我確定后再作說明吧!)




最后防着寫了一下然后換上自己的moc試試:

 

 
        
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM