总体设计方案
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文件(分别存储了立方体的点和三角形信息)