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 | } |
---|
382 | } |
---|