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