[66] | 1 | package com.framsticks.net.client3D; |
---|
| 2 | |
---|
| 3 | import java.io.IOException; |
---|
| 4 | import java.util.ArrayList; |
---|
| 5 | |
---|
| 6 | import pl.vorg.mowa.core.graphics.FloatVertexAttrib; |
---|
| 7 | import pl.vorg.mowa.core.graphics.Geometry; |
---|
| 8 | import pl.vorg.mowa.core.graphics.GeometryUtils; |
---|
| 9 | import pl.vorg.mowa.core.graphics.IndexBuffer; |
---|
| 10 | import pl.vorg.mowa.core.graphics.PrimitiveType; |
---|
| 11 | import pl.vorg.mowa.core.graphics.VertexStream; |
---|
| 12 | |
---|
| 13 | import com.framsticks.net.client3D.Creature.ModelType; |
---|
| 14 | |
---|
| 15 | //TODO: ACT przejscie klienta na eventHandlery (simulation start/stop, creatures, error) |
---|
| 16 | /** |
---|
| 17 | * Framstick network client. It sends requests to the server and interprets the |
---|
| 18 | * responses. |
---|
| 19 | * |
---|
| 20 | * @author vorg |
---|
| 21 | */ |
---|
| 22 | public class Client { |
---|
| 23 | private Communication comm; |
---|
| 24 | |
---|
| 25 | public Client() { |
---|
| 26 | } |
---|
| 27 | |
---|
| 28 | public void send(String request) { |
---|
| 29 | try { |
---|
| 30 | printResponse(sendRequest(request)); |
---|
| 31 | } catch (Exception e) { |
---|
| 32 | Log.getInstance().log("err", e.toString()); |
---|
| 33 | } |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | private ArrayList<String> sendRequest(String request) throws IOException, |
---|
| 37 | CommunicationErrorException { |
---|
| 38 | if (comm == null) { |
---|
| 39 | Log.getInstance().log("wrn", |
---|
| 40 | "Sending request failed. You are not connected!"); |
---|
| 41 | return new ArrayList<String>(); |
---|
| 42 | } |
---|
| 43 | comm.sendMessage(request); |
---|
| 44 | ArrayList<String> respond = null; |
---|
| 45 | try { |
---|
| 46 | respond = comm.readMessage(); |
---|
| 47 | } catch (InterruptedException e) { |
---|
| 48 | Log.getInstance().log("err", e.getMessage()); |
---|
| 49 | return new ArrayList<String>(); |
---|
| 50 | } |
---|
| 51 | return respond; |
---|
| 52 | } |
---|
| 53 | |
---|
| 54 | private void printResponse(ArrayList<String> response) { |
---|
| 55 | if (response == null) { |
---|
| 56 | Log.getInstance().log("err", "Response is null"); |
---|
| 57 | return; |
---|
| 58 | } |
---|
| 59 | for (int i = 0; i < response.size(); i++) { |
---|
| 60 | Log.getInstance().log("<<<", response.get(i)); |
---|
| 61 | } |
---|
| 62 | } |
---|
| 63 | |
---|
| 64 | /** |
---|
| 65 | * Inits connection with the mock server. |
---|
| 66 | */ |
---|
| 67 | public void initConnectionMock() { |
---|
| 68 | comm = new CommunicationMock(); |
---|
| 69 | Log.getInstance().log("dbg", "Client.init"); |
---|
| 70 | try { |
---|
| 71 | Log.getInstance().log("dbg", "Connecting to mock"); |
---|
| 72 | comm.connect("127.0.0.1", 9009); |
---|
| 73 | } catch (Exception e) { |
---|
| 74 | e.printStackTrace(); |
---|
| 75 | } |
---|
| 76 | } |
---|
| 77 | |
---|
| 78 | public void initConnection(String host, int port) { |
---|
| 79 | comm = new Communication(); |
---|
| 80 | Log.getInstance().log("dbg", "Client.init"); |
---|
| 81 | try { |
---|
| 82 | Log.getInstance().log("dbg", "Connecting to " + host + ":" + port); |
---|
| 83 | comm.connect(host, port); |
---|
| 84 | } catch (Exception e) { |
---|
| 85 | e.printStackTrace(); |
---|
| 86 | } |
---|
| 87 | } |
---|
| 88 | |
---|
| 89 | public void closeConnection() { |
---|
| 90 | try { |
---|
| 91 | if (comm != null) { |
---|
| 92 | comm.disconnect(); |
---|
| 93 | comm = null; |
---|
| 94 | } |
---|
| 95 | } catch (IOException e) { |
---|
| 96 | e.printStackTrace(); |
---|
| 97 | } |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | public Creature[] readCreatures() throws IOException, |
---|
| 101 | CommunicationErrorException { |
---|
| 102 | return readCreatures(-1, -1, true); |
---|
| 103 | } |
---|
| 104 | |
---|
| 105 | public Creature[] readCreatures(int groupNo, int creatureNo, boolean neurons) |
---|
| 106 | throws IOException, CommunicationErrorException { |
---|
| 107 | ArrayList<Creature> creatures = new ArrayList<Creature>(); |
---|
| 108 | String request; |
---|
| 109 | String creatureFields = neurons ? "name,parts{x,y,z},mechparts{x,y,z},joints{p1,p2},neurodefs{p,j,d}" |
---|
| 110 | : "name,parts{x,y,z},mechparts{x,y,z},joints{p1,p2}"; |
---|
| 111 | if (groupNo == -1 || creatureNo == -1) { |
---|
| 112 | request = "get /simulator/populations/groups/+/creatures/+/(" |
---|
| 113 | + creatureFields + ")"; |
---|
| 114 | } else { |
---|
| 115 | request = "get /simulator/populations/groups/" |
---|
| 116 | + Integer.toString(groupNo) + "/creatures/" |
---|
| 117 | + Integer.toString(creatureNo) + "/(" + creatureFields |
---|
| 118 | + ")"; |
---|
| 119 | } |
---|
| 120 | String line = null; |
---|
| 121 | ArrayList<String> response = null; |
---|
| 122 | response = sendRequest(request); |
---|
| 123 | printResponse(response); |
---|
| 124 | final int INIT = 0; |
---|
| 125 | final int PARTS = 1; |
---|
| 126 | final int MECHPARTS = 2; |
---|
| 127 | final int JOINTS = 3; |
---|
| 128 | final int NEURODEFS = 4; |
---|
| 129 | int mode = INIT; |
---|
| 130 | Creature creature = null; |
---|
| 131 | ArrayList<float[]> parts = null; |
---|
| 132 | ArrayList<float[]> mechParts = null; |
---|
| 133 | ArrayList<int[]> joints = null; |
---|
| 134 | ArrayList<NeuroDef> neurodefs = null; |
---|
| 135 | float[] part = new float[3]; |
---|
| 136 | float[] mechPart = new float[3]; |
---|
| 137 | int[] joint = new int[2]; |
---|
| 138 | NeuroDef ndef = new NeuroDef(); |
---|
| 139 | for (int k = 0; k < response.size(); ++k) { |
---|
| 140 | line = response.get(k).toString(); |
---|
| 141 | if (line.startsWith("file")) { |
---|
| 142 | String groupsStr = "groups/"; |
---|
| 143 | int groupBegin = line.indexOf(groupsStr) + groupsStr.length(); |
---|
| 144 | int groupEnd = line.indexOf("/", groupBegin); |
---|
| 145 | if (groupBegin < 0 || groupEnd < 0) { |
---|
| 146 | |
---|
| 147 | System.out.println(line); |
---|
| 148 | System.out.println("groupBegin=" + groupBegin |
---|
| 149 | + "; groupEnd=" + groupEnd); |
---|
| 150 | System.out.println("request=" + request); |
---|
| 151 | System.out.println("groupNo=" + groupNo + "; creatureNo=" |
---|
| 152 | + creatureNo); |
---|
| 153 | |
---|
| 154 | } |
---|
| 155 | |
---|
| 156 | int group = Integer.parseInt(line.substring(groupBegin, |
---|
| 157 | groupEnd)); |
---|
| 158 | String creaturesStr = "creatures/"; |
---|
| 159 | int creatureIndexBegin = line.indexOf(creaturesStr) |
---|
| 160 | + creaturesStr.length(); |
---|
| 161 | int creatureIndexEnd = line.indexOf("/", creatureIndexBegin); |
---|
| 162 | int creatureIndex = Integer.parseInt(line.substring( |
---|
| 163 | creatureIndexBegin, creatureIndexEnd)); |
---|
| 164 | |
---|
| 165 | creature = null; |
---|
| 166 | for (Creature c : creatures) { |
---|
| 167 | if ((c.getGroup() == group) |
---|
| 168 | && (c.getIndex() == creatureIndex)) { |
---|
| 169 | creature = c; |
---|
| 170 | break; |
---|
| 171 | } |
---|
| 172 | } |
---|
| 173 | if (creature == null) { |
---|
| 174 | creature = new Creature("", group, creatureIndex); |
---|
| 175 | creatures.add(creature); |
---|
| 176 | } |
---|
| 177 | |
---|
| 178 | if (line.indexOf("/parts") > -1) { |
---|
| 179 | mode = PARTS; |
---|
| 180 | parts = new ArrayList<float[]>(); |
---|
| 181 | } else if (line.indexOf("/mechparts") > -1) { |
---|
| 182 | mode = MECHPARTS; |
---|
| 183 | mechParts = new ArrayList<float[]>(); |
---|
| 184 | } else if (line.indexOf("/joints") > -1) { |
---|
| 185 | mode = JOINTS; |
---|
| 186 | joints = new ArrayList<int[]>(); |
---|
| 187 | } else if (line.indexOf("/neurodefs") > -1) { |
---|
| 188 | mode = NEURODEFS; |
---|
| 189 | neurodefs = new ArrayList<NeuroDef>(); |
---|
| 190 | } |
---|
| 191 | } else if (line.startsWith("x")) { |
---|
| 192 | float value = Float.parseFloat(line |
---|
| 193 | .substring(line.indexOf(":") + 1)); |
---|
| 194 | if (mode == PARTS) |
---|
| 195 | part[0] = value; |
---|
| 196 | else if (mode == MECHPARTS) |
---|
| 197 | mechPart[0] = value; |
---|
| 198 | } else if (line.startsWith("y")) { |
---|
| 199 | float value = Float.parseFloat(line |
---|
| 200 | .substring(line.indexOf(":") + 1)); |
---|
| 201 | if (mode == PARTS) |
---|
| 202 | part[2] = value; // y and z swap |
---|
| 203 | else if (mode == MECHPARTS) |
---|
| 204 | mechPart[2] = value; // y and z swap |
---|
| 205 | } else if (line.startsWith("z")) { |
---|
| 206 | float value = Float.parseFloat(line |
---|
| 207 | .substring(line.indexOf(":") + 1)); |
---|
| 208 | if (mode == PARTS) { |
---|
| 209 | part[1] = value; // z and y swap |
---|
| 210 | parts.add(part); |
---|
| 211 | part = new float[3]; |
---|
| 212 | } else if (mode == MECHPARTS) { |
---|
| 213 | mechPart[1] = value; // z and y swap |
---|
| 214 | mechParts.add(mechPart); |
---|
| 215 | mechPart = new float[3]; |
---|
| 216 | } |
---|
| 217 | } else if (line.startsWith("p1")) { |
---|
| 218 | int p1 = Integer |
---|
| 219 | .parseInt(line.substring(line.indexOf(":") + 1)); |
---|
| 220 | joint[0] = p1; |
---|
| 221 | } else if (line.startsWith("p2")) { |
---|
| 222 | int p2 = Integer |
---|
| 223 | .parseInt(line.substring(line.indexOf(":") + 1)); |
---|
| 224 | joint[1] = p2; |
---|
| 225 | joints.add(joint); |
---|
| 226 | joint = new int[2]; |
---|
| 227 | } else if ((mode == NEURODEFS) && (line.startsWith("p:"))) { |
---|
| 228 | int index = Integer.parseInt(line |
---|
| 229 | .substring(line.indexOf(":") + 1)); |
---|
| 230 | if (index >= 0) { |
---|
| 231 | ndef.locationIndex = index; |
---|
| 232 | ndef.locationType = NeuroDef.LocationType.Part; |
---|
| 233 | } |
---|
| 234 | } else if ((mode == NEURODEFS) && (line.startsWith("j:"))) { |
---|
| 235 | int index = Integer.parseInt(line |
---|
| 236 | .substring(line.indexOf(":") + 1)); |
---|
| 237 | if (index >= 0) { |
---|
| 238 | ndef.locationIndex = index; |
---|
| 239 | ndef.locationType = NeuroDef.LocationType.Joint; |
---|
| 240 | } |
---|
| 241 | } else if ((mode == NEURODEFS) && (line.startsWith("d:"))) { |
---|
| 242 | ndef.def = line.substring(2); |
---|
| 243 | neurodefs.add(ndef); |
---|
| 244 | ndef = new NeuroDef(); |
---|
| 245 | } else if (line.startsWith("eof")) { |
---|
| 246 | if (mode == PARTS) { |
---|
| 247 | creature.setParts(parts.toArray(new float[][] {}), |
---|
| 248 | Creature.ModelType.Parts); |
---|
| 249 | } else if (mode == MECHPARTS) { |
---|
| 250 | creature.setParts((mechParts.toArray(new float[][] {})), |
---|
| 251 | Creature.ModelType.MechParts); |
---|
| 252 | } else if (mode == JOINTS) { |
---|
| 253 | creature.setJoints(joints.toArray(new int[][] {})); |
---|
| 254 | } else if (mode == NEURODEFS) { |
---|
| 255 | creature.setNeuroDefs(neurodefs.toArray(new NeuroDef[] {})); |
---|
| 256 | } |
---|
| 257 | } |
---|
| 258 | } |
---|
| 259 | Log.getInstance().log("dbg", |
---|
| 260 | "" + creatures.size() + " creatures loaded"); |
---|
| 261 | |
---|
| 262 | ArrayList<Creature> invalidCreatures = new ArrayList<Creature>(); |
---|
| 263 | for (Creature c : creatures) { |
---|
| 264 | if ((c.getJoints() == null) |
---|
| 265 | || (c.getParts(ModelType.Parts) == null) |
---|
| 266 | || (c.getParts(ModelType.MechParts) == null)) { |
---|
| 267 | invalidCreatures.add(c); |
---|
| 268 | Log.getInstance().log("wrn", "Invalid creature found"); |
---|
| 269 | } |
---|
| 270 | } |
---|
| 271 | for (Creature c : invalidCreatures) { |
---|
| 272 | creatures.remove(c); |
---|
| 273 | } |
---|
| 274 | invalidCreatures.clear(); |
---|
| 275 | return creatures.toArray(new Creature[] {}); |
---|
| 276 | } |
---|
| 277 | |
---|
| 278 | public World readWorld() throws IOException, CommunicationErrorException { |
---|
| 279 | final int INIT = 0; |
---|
| 280 | final int POINTS = 1; |
---|
| 281 | final int FACES = 2; |
---|
| 282 | World world = new World(); |
---|
| 283 | |
---|
| 284 | String line = null; |
---|
| 285 | String request = "get /simulator/world wrldbnd,wrldwat,faces"; |
---|
| 286 | ArrayList<String> response = null; |
---|
| 287 | |
---|
| 288 | response = sendRequest(request); |
---|
| 289 | printResponse(response); |
---|
| 290 | |
---|
| 291 | ArrayList<Float> points = new ArrayList<Float>(); |
---|
| 292 | ArrayList<Integer> faces = new ArrayList<Integer>(); |
---|
| 293 | PrimitiveType primitiveType = PrimitiveType.None; |
---|
| 294 | PrimitiveType facePrimitiveType; |
---|
| 295 | int mode = INIT; |
---|
| 296 | |
---|
| 297 | for (int k = 0; k < response.size(); ++k) { |
---|
| 298 | line = response.get(k); |
---|
| 299 | if (line.startsWith("wrldbnd")) { |
---|
| 300 | world.setBoundaries(Integer.parseInt(line.substring(line |
---|
| 301 | .indexOf(":") + 1))); |
---|
| 302 | continue; |
---|
| 303 | } else if (line.startsWith("wrldwat")) { |
---|
| 304 | world.setWaterLevel(Float.parseFloat(line.substring(line |
---|
| 305 | .indexOf(":") + 1))); |
---|
| 306 | continue; |
---|
| 307 | } else if (line.trim().equals("p")) { |
---|
| 308 | mode = POINTS; |
---|
| 309 | continue; |
---|
| 310 | } else if (line.trim().equals("f")) { |
---|
| 311 | mode = FACES; |
---|
| 312 | continue; |
---|
| 313 | } else if (line.trim().equals("~")) { |
---|
| 314 | break; |
---|
| 315 | } |
---|
| 316 | |
---|
| 317 | if (mode == POINTS) { |
---|
| 318 | String[] tokens = line.split(" "); |
---|
| 319 | points.add(Float.parseFloat(tokens[0])); |
---|
| 320 | points.add(Float.parseFloat(tokens[2])); // y and z swap |
---|
| 321 | points.add(Float.parseFloat(tokens[1])); // z and y swap |
---|
| 322 | } else if (mode == FACES) { |
---|
| 323 | String[] tokens = line.split(" "); |
---|
| 324 | if (tokens.length == 3) |
---|
| 325 | facePrimitiveType = PrimitiveType.Triangles; |
---|
| 326 | else if (tokens.length == 4) |
---|
| 327 | facePrimitiveType = PrimitiveType.Quads; |
---|
| 328 | else |
---|
| 329 | facePrimitiveType = PrimitiveType.None; |
---|
| 330 | |
---|
| 331 | if (primitiveType == PrimitiveType.None) { |
---|
| 332 | primitiveType = facePrimitiveType; |
---|
| 333 | } else if (primitiveType != facePrimitiveType) { |
---|
| 334 | Log.getInstance().log( |
---|
| 335 | "err", |
---|
| 336 | "Unsupported terrain type (" + primitiveType + "!=" |
---|
| 337 | + primitiveType + ")"); |
---|
| 338 | return world; |
---|
| 339 | } |
---|
| 340 | |
---|
| 341 | for (String token : tokens) { |
---|
| 342 | faces.add(Integer.parseInt(token)); |
---|
| 343 | } |
---|
| 344 | } |
---|
| 345 | } |
---|
| 346 | |
---|
| 347 | float[] positions = new float[points.size()]; |
---|
| 348 | for (int i = 0; i < positions.length; i++) { |
---|
| 349 | positions[i] = points.get(i); |
---|
| 350 | } |
---|
| 351 | |
---|
| 352 | int[] indices = new int[faces.size()]; |
---|
| 353 | for (int i = 0; i < indices.length; i++) { |
---|
| 354 | indices[i] = faces.get(i); |
---|
| 355 | } |
---|
| 356 | |
---|
| 357 | Geometry geometry = new Geometry(); |
---|
| 358 | VertexStream vs = new VertexStream(); |
---|
| 359 | geometry.setVertexStream(vs); |
---|
| 360 | geometry.setPrimitiveType(primitiveType); |
---|
| 361 | |
---|
| 362 | IndexBuffer ib = new IndexBuffer(); |
---|
| 363 | ib.setBuffer(indices); |
---|
| 364 | vs.setIndexBuffer(ib); |
---|
| 365 | |
---|
| 366 | FloatVertexAttrib posAttrib = new FloatVertexAttrib("pos"); |
---|
| 367 | posAttrib.setBuffer(positions); |
---|
| 368 | vs.addAttrib(posAttrib); |
---|
| 369 | |
---|
| 370 | geometry.updateBoundingBox(); |
---|
| 371 | |
---|
| 372 | GeometryUtils.generateNormals(geometry); |
---|
| 373 | |
---|
| 374 | world.setGeometry(geometry); |
---|
| 375 | |
---|
| 376 | return world; |
---|
| 377 | } |
---|
| 378 | |
---|
| 379 | public Boolean isConnected() { |
---|
| 380 | return comm.isConnected(); |
---|
| 381 | } |
---|
[65] | 382 | } |
---|