【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方法,下面分别介绍这三个方法里都做了什么
SampleGLSurfaceView.java
public class SampleGLSurfaceView extends GLSurfaceView{
private SampleGLRenderer renderer ;
/* 编写渲染器SampleGLRenderer,实体类实GLSurfaceView.Renderer接口 class SampleGLRenderer implements Renderer{
@Override
//执行渲染工作
public void onDrawFrame(GL10 gl){}
@Override
// 渲染窗口大小发生改变或者屏幕方法发生变化时候回调
public void onSurfaceChanged(GL10 gl, int width, int height){}
@Override
//surface被创建后需要做的处理
public void onSurfaceCreated(GL10 gl, EGLConfig config){}
}
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试试:

【Android】用Cubism 2制作自己的Live2D——初探Live2D在Android上的运行!的更多相关文章
- [Android]Android Debug key 的制作
Android Debug key 的制作 背景 在Android App 开发过程中,我们经常会使用一些第三方的服务,但是很多的第三方服务都会要求我们提供包名,签名安装包,这时候,我们在日常调试时, ...
- Android - TabHost 与 Fragment 制作页面切换效果
Android - TabHost 与 Fragment 制作页面切换效果 Android API 19 , API 23 三个标签页置于顶端 效果图: 在文件BoardTabHost.java中定义 ...
- Android中怎样自己制作su
本文原博客:http://hubingforever.blog.163.com/blog/static/171040579201372915716149/ 在Android源代码的system\ext ...
- Android随笔之——闹钟制作铺垫之AlarmManager详解
说实话,之前写的两篇博客Android广播机制Broadcast详解.Android时间.日期相关类和方法以及现在要写的,都算是为之后要写的闹钟应用做铺垫,有兴趣的话,大家可以去看看前两篇博客. 一. ...
- [置顶] 我的Android进阶之旅------>Android中制作和查看自定义的Debug版本Android签名证书
Android应用开发接入各种SDK时会发现,有很多SDK是需要靠package name和的证书指纹SHA1码来识别的,如百度地图SDK.这样如果使用默认自动生成的debug的话就会给开发调试工作带 ...
- android 二维码制作,显示到UI,并保存SD卡,拿来就能用!!
转载请注明出处:王亟亟的大牛之路 如今二维码已经渗透了我们的生活.各种扫码关注啊.扫码下载的,今天上一个依据输入内容生成二维码的功能. 包结构: 界面截图: 功能:输入网址–>生成图片–> ...
- Android基础TOP7_1:ListView制作列表
结构: Activity: activity_main: <RelativeLayout xmlns:android="http://schemas.android.com/apk/r ...
- 【转】Pro Android学习笔记(七):了解Content Provider(下上)
我们通过一个Content Provider小例子进行详细说明.数据源是一个SQLite数据库,名字为books.db,该数据库只含有一个表格,名字为books.表格中含有name,isbn,auth ...
- Android中将xml布局文件转化为View树的过程分析(上)
有好几周没写东西了,一方面是因为前几个周末都有些事情,另外也是因为没能找到好的写作方向,或者说有些话题 值得分享.写作,可是自己积累还不够,没办法只好闷头继续研究了.这段时间一边在写代码,一边也在想A ...
随机推荐
- Winform/WPF中内嵌BeetleX的HTTP服务
在新版本的BeetleX.FastHttpApi加入了对netstandard2.0支持,如果程序基于.NetFramework4.6.1来构建WinForm或WPF桌面程序的情况下可以直接把Beet ...
- 『调错』OGG Error opening module ggjava_ue.dll
Win7 配置 OGG (GoldenGate) Adapter Java 时, 报错: ERROR OGG-01122 Oracle GoldenGate Capture, javaue.prm: ...
- 细说并发编程-TPL
本节导航 基本概念 并发编程 TPL 线程基础 windows为什么要支持线程 线程开销 CPU的发展 使用线程的理由 如何写一个简单Parallel.For循环 数据并行 Parallel.For剖 ...
- 18 章 CSS 链接、光标、 DHTML 、缩放
1.CSS 中链接的使用 2.CSS 中光标的使用 3.CSS 中 DHTML 的使用 4.CSS 中缩放的使用 1 18 8. .1 1 S CSS 中 链接的使用 超链接伪类属性 a:link ...
- 全新定义!免费开源ERP平台如何玩转工业互联网
简述 IoT Box通过Wifi.蓝牙.USB.网线等方式连接设备.IoT再通过互联网连接到Odoo服务器 Odoo的各种应用通过IoT操作各种设备.例如,PoS应用通过IoT操作小票打印机.银行刷卡 ...
- 2018-08-20 中文代码之Spring Boot集成H2内存数据库
续前文: 中文代码之Spring Boot添加基本日志, 源码库地址相同. 鉴于此项目中的数据总量不大(即使万条词条也在1MB之内), 当前选择轻量级而且配置简单易于部署的H2内存数据库比较合理. 此 ...
- LeetCode算法题-Prime Number of Set Bits in Binary Representation(Java实现)
这是悦乐书的第311次更新,第332篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第180题(顺位题号是762).给定两个正整数L和R,在[L,R]范围内,计算每个整数的 ...
- SpringBoot2.0之六 多环境配置
开发过程中面对不同的环境,例如数据库.redis服务器等的不同,可能会面临一直需要修改配置的麻烦中,在以前的项目中,曾通过Tomcat的配置来实现,有的项目甚至需要手动修改相关配置,这种方式费时费力, ...
- Jvm启动,关闭及对应钩子
很多时候应用服务启动或关闭会做一些预加载(比如缓存,定时任务启动等)或收尾处理工作(比如程序失败记录等) 1. 首先看下Spring框架服务启动加载操作实现,直接上代码 继承实现接口Applicati ...
- v-cloak的用法和注意事项
v-cloak是前端框架vue.js中的一个方法,作用是为了防止在页面加载时先出现变量名闪烁的情况,造成不好的用户体验, 例如:{{ v.name}} (闪一下)=> 张三 用法:html中:& ...