总体设计方案
Matlab模型跑完后把身体数据文件保存到指定路径,webserver程序网络传输方案选用websocket传文件的形式。Pc端的webserver开放指定端口后等待客户端的接入,待客户端接入后开启一个线程, 把两个文件以流的形式传输给客户端。安卓端则把文件存储到本地,再读取到内存中,开始渲染3d模型。
架构图
总工作量:安卓端代码约450行,服务端代码约150行。
服务端细节
程序结构如图所示,MyServer为主类,每当接收到一个连接请求就开启一个ServerThread线程,进行文件传输相关操作。
建立Socket连接
//创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket serverSocket = new ServerSocket(SOCKET_PORT);
while(true) {
//每当接收到客户端的Socket请求,服务器端也相应的创建一个Socket
Socket socket = serverSocket.accept();
System.out.println("建立连接成功!");
socketList.add(socket);
//每连接一个客户端,启动一个ServerThread线程为该客户端服务
new Thread(new ServerThread(socket)).start();
}
文件传输
dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(file1.getName());
dos.flush();
dos.writeLong(file1.length());
dos.flush();
fis = new FileInputStream(file1);
byte[] bytes = new byte[1024];
int length = 0;
while((length = fis.read(bytes, 0, bytes.length)) != -1) {
dos.write(bytes, 0, length);
dos.flush();
}
安卓端细节
MainActivity中的onCreat函数为主函数,将网络部分进行之后再调用其他两个类进行绘制图像的工作。MyRenderer中包含绘制前的准备工作,Square包含了绘制的细节部分。
由于安卓的设计原则,主线程不能访问网络,子线程不能修改界面,我们在程序启动时先开启一个线程来进行socket连接和文件接收工作。
private void initSocket(){
//初始化Socket
new Thread(new Runnable() {
//利用子线程访问网络
public void run() {
try {
socket = new Socket("192.168.1.110", 50001);
clientThread = new ClientThread(socket);
clientThread.run();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
然后创建GLSurfaceView的实例和MyRenderer的实例,并将GLSurfaceView设置为界面内容。
MyRenderer的构造函数中把本地已经下载好的两个文件信息读取到内存中。再以三角形的方式渲染出来。
void draw(GL10 gl) {
// Counter-clockwise winding.
gl.glFrontFace(GL10.GL_CCW);
// Enable face culling.
gl.glEnable(GL10.GL_CULL_FACE);
// What faces to remove with the face culling.
gl.glCullFace(GL10.GL_BACK);
// 启用顶点缓冲区以进行写入并在渲染期间使用。
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 指定渲染时要使用的顶点坐标数组的位置和数据格式。
gl.glVertexPointer(3, GL10.GL_FLOAT, 0,
vertexBuffer);
// 开始绘制(GL_TRIANGLES的方式)
gl.glDrawElements(GL10.GL_TRIANGLES, shorts.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
// Disable the vertices buffer.
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
// Disable face culling.
gl.glDisable(GL10.GL_CULL_FACE);
效果展示
桌面上的两个txt文件(分别存储了立方体的点和三角形信息)