1 
2 #include "GraphicsServerExample.h"
3 #include "../CommonInterfaces/CommonGraphicsAppInterface.h"
4 #include "../CommonInterfaces/CommonRenderInterface.h"
5 #include "PosixSharedMemory.h"
6 #include "Win32SharedMemory.h"
7 #include "../CommonInterfaces/CommonExampleInterface.h"
8 #include "LinearMath/btTransform.h"
9 #include "../CommonInterfaces/CommonGUIHelperInterface.h"
10 #include "Bullet3Common/b3AlignedObjectArray.h"
11 #include "GraphicsSharedMemoryBlock.h"
12 #include "../CommonInterfaces/CommonGUIHelperInterface.h"
13 #include "SharedMemoryPublic.h"
14 #include "../MultiThreading/b3ThreadSupportInterface.h"
15 #include "../Utils/b3Clock.h"
16 
17 #ifdef BT_ENABLE_CLSOCKET
18 
19 #include "PassiveSocket.h"  // Include header for active socket object definition
20 #include <stdio.h>
21 #include "../CommonInterfaces/CommonGUIHelperInterface.h"
22 #include "Bullet3Common/b3CommandLineArgs.h"
23 #include "RemoteGUIHelper.h"
24 #include "GraphicsSharedMemoryPublic.h"
25 #include "GraphicsSharedMemoryCommands.h"
26 
27 
28 bool gVerboseNetworkMessagesServer = true;
29 
MySerializeInt(unsigned int sz,unsigned char * output)30 void MySerializeInt(unsigned int sz, unsigned char* output)
31 {
32 	unsigned int tmp = sz;
33 	output[0] = tmp & 255;
34 	tmp = tmp >> 8;
35 	output[1] = tmp & 255;
36 	tmp = tmp >> 8;
37 	output[2] = tmp & 255;
38 	tmp = tmp >> 8;
39 	output[3] = tmp & 255;
40 }
41 
submitStatus(CActiveSocket * pClient,GraphicsSharedMemoryStatus & serverStatus,b3AlignedObjectArray<char> & buffer)42 void submitStatus(CActiveSocket* pClient, GraphicsSharedMemoryStatus& serverStatus, b3AlignedObjectArray<char>& buffer)
43 {
44 	b3AlignedObjectArray<unsigned char> packetData;
45 	unsigned char* statBytes = (unsigned char*)&serverStatus;
46 
47 
48 	//create packetData with [int packetSizeInBytes, status, streamBytes)
49 	packetData.resize(4 + sizeof(GraphicsSharedMemoryStatus) + serverStatus.m_numDataStreamBytes);
50 	int sz = packetData.size();
51 	int curPos = 0;
52 
53 	if (gVerboseNetworkMessagesServer)
54 	{
55 		printf("buffer.size = %d\n", buffer.size());
56 		printf("serverStatus packed size = %d\n", sz);
57 	}
58 
59 	MySerializeInt(sz, &packetData[curPos]);
60 	curPos += 4;
61 	for (int i = 0; i < sizeof(GraphicsSharedMemoryStatus); i++)
62 	{
63 		packetData[i + curPos] = statBytes[i];
64 	}
65 	curPos += sizeof(GraphicsSharedMemoryStatus);
66 	if (gVerboseNetworkMessagesServer)
67    	 printf("serverStatus.m_numDataStreamBytes=%d\n", serverStatus.m_numDataStreamBytes);
68 	for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++)
69 	{
70 		packetData[i + curPos] = buffer[i];
71 	}
72 
73 	pClient->Send(&packetData[0], packetData.size());
74 	if (gVerboseNetworkMessagesServer)
75 		printf("pClient->Send serverStatus: %d\n", packetData.size());
76 }
77 
78 
79 #endif //BT_ENABLE_CLSOCKET
80 
81 
82 #define MAX_GRAPHICS_SHARED_MEMORY_BLOCKS 1
83 
84 
85 struct TCPArgs
86 {
TCPArgsTCPArgs87 	TCPArgs()
88 		: m_cs(0),
89 		m_port(6667),
90 		m_numClientCommands(0),
91 		m_numServerCommands(0),
92 		m_cmdPtr(0)
93 	{
94 		m_dataSlots.resize(10);
95 	}
96 
submitCommandTCPArgs97 	void submitCommand()
98 	{
99 		m_cs->lock();
100 		m_serverStatus.m_type = GFX_CMD_CLIENT_COMMAND_FAILED;
101 		m_serverStatus.m_numDataStreamBytes = 0;
102 		btAssert(m_numServerCommands == m_numClientCommands);
103 		m_numClientCommands++;
104 		m_cs->unlock();
105 	}
processCommandTCPArgs106 	void processCommand()
107 	{
108 		m_cs->lock();
109 		btAssert(m_numServerCommands == (m_numClientCommands - 1));
110 		m_numServerCommands++;
111 		m_cs->unlock();
112 	}
isCommandOutstandingTCPArgs113 	bool isCommandOutstanding()
114 	{
115 		m_cs->lock();
116 		bool result = m_numClientCommands > m_numServerCommands;
117 		m_cs->unlock();
118 		return result;
119 	}
120 
121 
122 	b3CriticalSection* m_cs;
123 	int m_port;
124 	b3AlignedObjectArray< b3AlignedObjectArray<unsigned char> > m_dataSlots;
125 	int m_numClientCommands;
126 	int m_numServerCommands;
127 	GraphicsSharedMemoryCommand* m_cmdPtr;
128 	GraphicsSharedMemoryStatus m_serverStatus;
129 };
130 
131 struct TCPThreadLocalStorage
132 {
133 	int threadId;
134 };
135 
136 
137 enum TCPCommunicationEnums
138 {
139 	eTCPRequestTerminate = 11,
140 	eTCPIsUnInitialized,
141 	eTCPIsInitialized,
142 	eTCPInitializationFailed,
143 	eTCPHasTerminated
144 };
145 
TCPThreadFunc(void * userPtr,void * lsMemory)146 void TCPThreadFunc(void* userPtr, void* lsMemory)
147 {
148 	printf("TCPThreadFunc thread started\n");
149 
150 	TCPArgs* args = (TCPArgs*)userPtr;
151 	//int workLeft = true;
152 	b3Clock clock;
153 	clock.reset();
154 	b3Clock sleepClock;
155 	bool init = true;
156 	if (init)
157 	{
158 		unsigned int cachedSharedParam = eTCPIsInitialized;
159 
160 		args->m_cs->lock();
161 		args->m_cs->setSharedParam(0, eTCPIsInitialized);
162 		args->m_cs->unlock();
163 
164 		double deltaTimeInSeconds = 0;
165 		int numCmdSinceSleep1ms = 0;
166 		unsigned long long int prevTime = clock.getTimeMicroseconds();
167 
168 #ifdef BT_ENABLE_CLSOCKET
169 		b3Clock clock;
170 		double timeOutInSeconds = 10;
171 
172 
173 		bool isPhysicsClientConnected = true;
174 		bool exitRequested = false;
175 
176 
177 		if (!isPhysicsClientConnected)
178 		{
179 			printf("TCP thread error connecting to shared memory. Machine needs a reboot?\n");
180 		}
181 		btAssert(isPhysicsClientConnected);
182 
183 		printf("Starting TCP server using port %d\n", args->m_port);
184 
185 		CPassiveSocket socket;
186 		CActiveSocket* pClient = NULL;
187 
188 		//--------------------------------------------------------------------------
189 		// Initialize our socket object
190 		//--------------------------------------------------------------------------
191 		socket.Initialize();
192 
193 		socket.Listen("localhost", args->m_port);
194 
195 		socket.SetBlocking();
196 
197 		int curNumErr = 0;
198 
199 #endif
200 
201 		do
202 		{
203 
204 			{
205 				b3Clock::usleep(0);
206 			}
207 			///////////////////////////////
208 
209 #ifdef BT_ENABLE_CLSOCKET
210 
211 			{
212 				b3Clock::usleep(0);
213 
214 				if ((pClient = socket.Accept()) != NULL)
215 				{
216 					socket.SetReceiveTimeout(60, 0);// (1, 0);
217 					socket.SetSendTimeout(60, 0);
218 
219 					b3AlignedObjectArray<char> bytesReceived;
220 
221 					int clientPort = socket.GetClientPort();
222 					if (gVerboseNetworkMessagesServer)
223 						printf("connected from %s:%d\n", socket.GetClientAddr(), clientPort);
224 
225 					if (pClient->Receive(4))
226 					{
227 						int clientKey = *(int*)pClient->GetData();
228 
229 						if (clientKey == GRAPHICS_SHARED_MEMORY_MAGIC_NUMBER)
230 						{
231 							printf("Client version OK %d\n", clientKey);
232 						}
233 						else
234 						{
235 							printf("Server version (%d) mismatches Client Version (%d)\n", GRAPHICS_SHARED_MEMORY_MAGIC_NUMBER, clientKey);
236 							continue;
237 						}
238 					}
239 
240 					//----------------------------------------------------------------------
241 					// Receive request from the client.
242 					//----------------------------------------------------------------------
243 
244 					while (cachedSharedParam != eTCPRequestTerminate)
245 					{
246 
247 						bool receivedData = false;
248 
249 						int maxLen = 4 + sizeof(GraphicsSharedMemoryCommand) + GRAPHICS_SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE;
250 
251 
252 						if (pClient->Receive(maxLen))
253 						{
254 
255 							//heuristic to detect disconnected clients
256 							CSimpleSocket::CSocketError err = pClient->GetSocketError();
257 
258 							if (err != CSimpleSocket::SocketSuccess || !pClient->IsSocketValid())
259 							{
260 								b3Clock::usleep(100);
261 
262 								curNumErr++;
263 
264 								if (curNumErr > 100)
265 								{
266 									///printf("TCP Connection error = %d, curNumErr = %d\n", (int)err, curNumErr);
267 
268 								}
269 							}
270 
271 							curNumErr = 0;
272 							char* msg2 = (char*)pClient->GetData();
273 							int numBytesRec2 = pClient->GetBytesReceived();
274 							if (gVerboseNetworkMessagesServer)
275 							  printf("numBytesRec2=%d\n", numBytesRec2);
276 							if (numBytesRec2 < 0)
277 							{
278 								numBytesRec2 = 0;
279 							}
280 							int curSize = bytesReceived.size();
281 							bytesReceived.resize(bytesReceived.size() + numBytesRec2);
282 							for (int i = 0; i < numBytesRec2; i++)
283 							{
284 								bytesReceived[curSize + i] = msg2[i];
285 							}
286 
287 							if (bytesReceived.size() >= 4)
288 							{
289 								int numBytesRec = bytesReceived.size();
290 								if (numBytesRec >= 10)
291 								{
292 									if (strncmp(&bytesReceived[0], "disconnect", 10) == 0)
293 									{
294 										printf("Disconnect request received\n");
295 										bytesReceived.clear();
296 										break;
297 									}
298 
299 
300 								}
301 
302 								if (gVerboseNetworkMessagesServer)
303 								{
304 									printf("received message length [%d]\n", numBytesRec);
305 								}
306 
307 								receivedData = true;
308 
309 
310 								args->m_cmdPtr = 0;
311 
312 
313 								int type = *(int*)&bytesReceived[0];
314 
315 
316 								if (numBytesRec == sizeof(GraphicsSharedMemoryCommand))
317 								{
318 									args->m_cmdPtr = (GraphicsSharedMemoryCommand*)&bytesReceived[0];
319 								}
320 
321 								if (args->m_cmdPtr)
322 								{
323 
324 									b3AlignedObjectArray<char> buffer;
325 									buffer.resize(GRAPHICS_SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
326 									bool hasStatus = true;
327 									if (gVerboseNetworkMessagesServer)
328 										printf("processing command:");
329 									switch (args->m_cmdPtr->m_type)
330 									{
331 									case GFX_CMD_0:
332 									{
333 										int axis = args->m_cmdPtr->m_upAxisYCommand.m_enableUpAxisY ? 1 : 2;
334 										args->submitCommand();
335 										while (args->isCommandOutstanding())
336 										{
337 											clock.usleep(0);
338 										}
339 										bool done = false;
340 										//guiHelper.setUpAxis(axis);
341 
342 
343 										if (gVerboseNetworkMessagesServer)
344 											printf("GFX_CMD_0\n");
345 										break;
346 									}
347 
348 									case GFX_CMD_SET_VISUALIZER_FLAG:
349 									{
350 										//disable single step rendering for GraphicsServer
351 										if (args->m_cmdPtr->m_visualizerFlagCommand.m_visualizerFlag == COV_ENABLE_SINGLE_STEP_RENDERING)
352 										{
353 											args->m_cmdPtr->m_visualizerFlagCommand.m_visualizerFlag = 0;
354 										}
355 										args->submitCommand();
356 										while (args->isCommandOutstanding())
357 										{
358 											clock.usleep(0);
359 										}
360 										//guiHelper.setVisualizerFlag(
361 										//	args->m_cmdPtr->m_visualizerFlagCommand.m_visualizerFlag,
362 										//	args->m_cmdPtr->m_visualizerFlagCommand.m_enable);
363 										//serverStatus.m_type = GFX_CMD_CLIENT_COMMAND_COMPLETED;
364 										if (gVerboseNetworkMessagesServer)
365 											printf("GFX_CMD_SET_VISUALIZER_FLAG\n");
366 										break;
367 									}
368 									case GFX_CMD_UPLOAD_DATA:
369 									{
370 										int slot = args->m_cmdPtr->m_uploadDataCommand.m_dataSlot;
371 
372 										int numBytes = args->m_cmdPtr->m_uploadDataCommand.m_numBytes;
373 
374 
375 										submitStatus(pClient, args->m_serverStatus, buffer);
376 
377 										//now receive numBytes
378 										if (gVerboseNetworkMessagesServer)
379 											printf("GFX_CMD_UPLOAD_DATA receiving data\n");
380 										int received = 0;
381 										int offset = 0;
382 										args->m_dataSlots[slot].resize(numBytes);
383 										while (received < numBytes)
384 										{
385 											if (pClient->Receive(args->m_cmdPtr->m_uploadDataCommand.m_numBytes))
386 											{
387 												//heuristic to detect disconnected clients
388 												CSimpleSocket::CSocketError err = pClient->GetSocketError();
389 												if (err != CSimpleSocket::SocketSuccess || !pClient->IsSocketValid())
390 												{
391 													curNumErr++;
392 													//printf("TCP Connection error = %d, curNumErr = %d\n", (int)err, curNumErr);
393 												}
394 												char* msg2 = (char*)pClient->GetData();
395 												int numBytesRec2 = pClient->GetBytesReceived();
396 												if (gVerboseNetworkMessagesServer)
397 													printf("received %d bytes (total=%d)\n", numBytesRec2, received);
398 
399 												for (int i = 0; i < numBytesRec2; i++)
400 												{
401 													args->m_dataSlots[slot][i+ offset] = msg2[i];
402 												}
403 												offset += numBytesRec2;
404 												received += numBytesRec2;
405 											}
406 										}
407 										if (gVerboseNetworkMessagesServer)
408 											printf("received all bytes!\n");
409 										args->m_serverStatus.m_type = GFX_CMD_CLIENT_COMMAND_COMPLETED;
410 										if (gVerboseNetworkMessagesServer)
411 											printf("GFX_CMD_UPLOAD_DATA\n");
412 										break;
413 									}
414 									case GFX_CMD_REGISTER_TEXTURE:
415 									{
416 										args->submitCommand();
417 										while (args->isCommandOutstanding())
418 										{
419 											clock.usleep(0);
420 										}
421 										//const unsigned char* texels = (const unsigned char*)&args->m_dataSlots[0][0];
422 										//args->m_serverStatus.m_registerTextureStatus.m_textureId = guiHelper.registerTexture(texels, args->m_cmdPtr->m_registerTextureCommand.m_width,
423 										//	args->m_cmdPtr->m_registerTextureCommand.m_height);
424 										//serverStatus.m_type = GFX_CMD_REGISTER_TEXTURE_COMPLETED;
425 										if (gVerboseNetworkMessagesServer)
426 											printf("GFX_CMD_REGISTER_TEXTURE\n");
427 										break;
428 									}
429 									case GFX_CMD_REGISTER_GRAPHICS_SHAPE:
430 									{
431 										args->submitCommand();
432 										while (args->isCommandOutstanding())
433 										{
434 											clock.usleep(0);
435 										}
436 										if (gVerboseNetworkMessagesServer)
437 											printf("GFX_CMD_REGISTER_GRAPHICS_SHAPE\n");
438 										break;
439 									}
440 									case GFX_CMD_REGISTER_GRAPHICS_INSTANCE:
441 									{
442 										args->submitCommand();
443 										while (args->isCommandOutstanding())
444 										{
445 											clock.usleep(0);
446 										}
447 
448 										if (gVerboseNetworkMessagesServer)
449 											printf("GFX_CMD_REGISTER_GRAPHICS_INSTANCE\n");
450 										break;
451 									}
452 									case GFX_CMD_SYNCHRONIZE_TRANSFORMS:
453 									{
454 										args->submitCommand();
455 										while (args->isCommandOutstanding())
456 										{
457 											clock.usleep(0);
458 										}
459 										if (gVerboseNetworkMessagesServer)
460 											printf("GFX_CMD_SYNCHRONIZE_TRANSFORMS\n");
461 										break;
462 									}
463 									case GFX_CMD_REMOVE_ALL_GRAPHICS_INSTANCES:
464 									{
465 										args->submitCommand();
466 										while (args->isCommandOutstanding())
467 										{
468 											clock.usleep(0);
469 										}
470 										if (gVerboseNetworkMessagesServer)
471 											printf("GFX_CMD_REMOVE_ALL_GRAPHICS_INSTANCES\n");
472 										break;
473 									}
474 									case GFX_CMD_REMOVE_SINGLE_GRAPHICS_INSTANCE:
475 									{
476 										args->submitCommand();
477 										while (args->isCommandOutstanding())
478 										{
479 											clock.usleep(0);
480 										}
481 										if (gVerboseNetworkMessagesServer)
482 											printf("GFX_CMD_REMOVE_SINGLE_GRAPHICS_INSTANCE\n");
483 										break;
484 									}
485 									case GFX_CMD_CHANGE_RGBA_COLOR:
486 									{
487 										args->submitCommand();
488 										while (args->isCommandOutstanding())
489 										{
490 											clock.usleep(0);
491 										}
492 										if (gVerboseNetworkMessagesServer)
493 											printf("GFX_CMD_CHANGE_RGBA_COLOR\n");
494 										break;
495 									}
496 									case GFX_CMD_CHANGE_SCALING:
497 									{
498 										args->submitCommand();
499 										while (args->isCommandOutstanding())
500 										{
501 											clock.usleep(0);
502 										}
503 										if (gVerboseNetworkMessagesServer)
504 											printf("GFX_CMD_CHANGE_SCALING\n");
505 										break;
506 									}
507 
508 									case GFX_CMD_GET_CAMERA_INFO:
509 									{
510 										args->submitCommand();
511 										while (args->isCommandOutstanding())
512 										{
513 											clock.usleep(0);
514 										}
515 										//bool RemoteGUIHelper::getCameraInfo(int* width, int* height,
516 										//	float viewMatrix[16], float projectionMatrix[16],
517 										//	float camUp[3], float camForward[3], float hor[3], float vert[3],
518 										//	float* yaw, float* pitch, float* camDist, float camTarget[3]) const
519 #if 0
520 										guiHelper.getCameraInfo(&serverStatus.m_getCameraInfoStatus.width,
521 											&serverStatus.m_getCameraInfoStatus.height,
522 											serverStatus.m_getCameraInfoStatus.viewMatrix,
523 											serverStatus.m_getCameraInfoStatus.projectionMatrix,
524 											serverStatus.m_getCameraInfoStatus.camUp,
525 											serverStatus.m_getCameraInfoStatus.camForward,
526 											serverStatus.m_getCameraInfoStatus.hor,
527 											serverStatus.m_getCameraInfoStatus.vert,
528 											&serverStatus.m_getCameraInfoStatus.yaw,
529 											&serverStatus.m_getCameraInfoStatus.pitch,
530 											&serverStatus.m_getCameraInfoStatus.camDist,
531 											serverStatus.m_getCameraInfoStatus.camTarget);
532 										serverStatus.m_type = GFX_CMD_GET_CAMERA_INFO_COMPLETED;
533 #endif
534 										if (gVerboseNetworkMessagesServer)
535 											printf("GFX_CMD_GET_CAMERA_INFO\n");
536 										break;
537 									}
538 
539 									case GFX_CMD_INVALID:
540 									case GFX_CMD_MAX_CLIENT_COMMANDS:
541 									default:
542 									{
543 										printf("UNKNOWN COMMAND!\n");
544 										btAssert(0);
545 										hasStatus = false;
546 									}
547 									}
548 
549 
550 									double startTimeSeconds = clock.getTimeInSeconds();
551 									double curTimeSeconds = clock.getTimeInSeconds();
552 
553 									if (gVerboseNetworkMessagesServer)
554 									{
555 										//printf("buffer.size = %d\n", buffer.size());
556 										printf("serverStatus.m_numDataStreamBytes = %d\n", args->m_serverStatus.m_numDataStreamBytes);
557 									}
558 									if (hasStatus)
559 									{
560 										submitStatus(pClient, args->m_serverStatus, buffer);
561 									}
562 
563 									bytesReceived.clear();
564 								}
565 								else
566 								{
567 									//likely an incomplete packet, let's append more bytes
568 									//printf("received packet with unknown contents\n");
569 								}
570 							}
571 						}
572 						if (!receivedData)
573 						{
574 							//printf("Didn't receive data.\n");
575 						}
576 					}
577 
578 					printf("Disconnecting client.\n");
579 					pClient->Close();
580 					delete pClient;
581 				}
582 			}
583 
584 #endif //BT_ENABLE_CLSOCKET
585 
586 
587 			///////////////////////////////
588 			args->m_cs->lock();
589 			cachedSharedParam = args->m_cs->getSharedParam(0);
590 			args->m_cs->unlock();
591 
592 		} while (cachedSharedParam != eTCPRequestTerminate);
593 #ifdef BT_ENABLE_CLSOCKET
594 		socket.Close();
595 		socket.Shutdown(CSimpleSocket::Both);
596 #endif
597 	}
598 	else
599 	{
600 		args->m_cs->lock();
601 		args->m_cs->setSharedParam(0, eTCPInitializationFailed);
602 		args->m_cs->unlock();
603 	}
604 
605 	printf("TCPThreadFunc thread exit\n");
606 	//do nothing
607 }
608 
TCPlsMemoryFunc()609 void* TCPlsMemoryFunc()
610 {
611 	//don't create local store memory, just return 0
612 	return new TCPThreadLocalStorage;
613 }
614 
TCPlsMemoryReleaseFunc(void * ptr)615 void TCPlsMemoryReleaseFunc(void* ptr)
616 {
617 	TCPThreadLocalStorage* p = (TCPThreadLocalStorage*)ptr;
618 	delete p;
619 }
620 
621 
622 #ifndef _WIN32
623 #include "../MultiThreading/b3PosixThreadSupport.h"
624 
createTCPThreadSupport(int numThreads)625 b3ThreadSupportInterface* createTCPThreadSupport(int numThreads)
626 {
627 	b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("TCPThreads",
628 		TCPThreadFunc,
629 		TCPlsMemoryFunc,
630 		TCPlsMemoryReleaseFunc,
631 		numThreads);
632 	b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo);
633 
634 	return threadSupport;
635 }
636 
637 #elif defined(_WIN32)
638 #include "../MultiThreading/b3Win32ThreadSupport.h"
639 
createTCPThreadSupport(int numThreads)640 b3ThreadSupportInterface* createTCPThreadSupport(int numThreads)
641 {
642 	b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("TCPThreads", TCPThreadFunc, TCPlsMemoryFunc, TCPlsMemoryReleaseFunc, numThreads);
643 	b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo);
644 	return threadSupport;
645 }
646 #endif
647 
648 
649 class GraphicsServerExample : public CommonExampleInterface
650 {
651 	CommonGraphicsApp* m_app;
652 	GUIHelperInterface* m_guiHelper;
653 
654 	bool m_verboseOutput;
655 
656 	float m_x;
657 	float m_y;
658 	float m_z;
659 
660 	b3ThreadSupportInterface* m_threadSupport;
661 	TCPArgs m_args;
662 
663 public:
GraphicsServerExample(GUIHelperInterface * guiHelper)664 	GraphicsServerExample(GUIHelperInterface* guiHelper)
665 		: m_guiHelper(guiHelper),
666 		  m_x(0),
667 		  m_y(0),
668 		  m_z(0)
669 	{
670 		m_verboseOutput = true;
671 
672 		m_app = guiHelper->getAppInterface();
673 		m_app->setUpAxis(2);
674 
675 		m_threadSupport = createTCPThreadSupport(1);
676 		m_args.m_cs = m_threadSupport->createCriticalSection();
677 		m_args.m_cs->setSharedParam(0, eTCPIsUnInitialized);
678 		m_threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*)&this->m_args, 0);
679 
680 		bool isUninitialized = true;
681 
682 		while (isUninitialized)
683 		{
684 			m_args.m_cs->lock();
685 			isUninitialized = (m_args.m_cs->getSharedParam(0) == eTCPIsUnInitialized);
686 			m_args.m_cs->unlock();
687 #ifdef _WIN32
688 			b3Clock::usleep(1000);
689 #endif
690 	}
691 
692 	}
~GraphicsServerExample()693 	virtual ~GraphicsServerExample()
694 	{
695 
696 		m_args.m_cs->setSharedParam(0, eTCPRequestTerminate);
697 
698 		int numActiveThreads = 1;
699 		while (numActiveThreads)
700 		{
701 			int arg0, arg1;
702 			if (m_threadSupport->isTaskCompleted(&arg0, &arg1, 0))
703 			{
704 				numActiveThreads--;
705 				printf("numActiveThreads = %d\n", numActiveThreads);
706 			}
707 			else
708 			{
709 				b3Clock::usleep(0);
710 			}
711 		};
712 
713 		m_threadSupport->deleteCriticalSection(m_args.m_cs);
714 
715 		delete m_threadSupport;
716 		m_threadSupport = 0;
717 
718 	}
719 
initPhysics()720 	virtual void initPhysics()
721 	{
722 	}
exitPhysics()723 	virtual void exitPhysics()
724 	{
725 	}
726 
submitServerStatus(GraphicsSharedMemoryStatus & status,int blockIndex)727 	void submitServerStatus(GraphicsSharedMemoryStatus& status, int blockIndex)
728 	{
729 	}
730 
processCommand(const struct GraphicsSharedMemoryCommand & clientCmd,struct GraphicsSharedMemoryStatus & serverStatusOut)731 	bool processCommand(const struct GraphicsSharedMemoryCommand& clientCmd, struct GraphicsSharedMemoryStatus& serverStatusOut)
732 	{
733 		//printf("processed command of type:%d\n", clientCmd.m_type);
734 		B3_PROFILE("processCommand");
735 		switch (clientCmd.m_type)
736 		{
737 			case GFX_CMD_0:
738 			{
739 				//either Y or Z can be up axis
740 				int upAxis = (clientCmd.m_upAxisYCommand.m_enableUpAxisY) ? 1 : 2;
741 				m_guiHelper->setUpAxis(upAxis);
742 				serverStatusOut.m_type = GFX_CMD_CLIENT_COMMAND_COMPLETED;
743 				m_args.processCommand();
744 				break;
745 			}
746 			case GFX_CMD_SET_VISUALIZER_FLAG:
747 			{
748 				if ((clientCmd.m_visualizerFlagCommand.m_visualizerFlag != COV_ENABLE_RENDERING) &&
749 					(clientCmd.m_visualizerFlagCommand.m_visualizerFlag != COV_ENABLE_SINGLE_STEP_RENDERING))
750 				{
751 					//printf("clientCmd.m_visualizerFlag.m_visualizerFlag: %d, clientCmd.m_visualizerFlag.m_enable %d\n",
752 					//	clientCmd.m_visualizerFlagCommand.m_visualizerFlag, clientCmd.m_visualizerFlagCommand.m_enable);
753 
754 					this->m_guiHelper->setVisualizerFlag(clientCmd.m_visualizerFlagCommand.m_visualizerFlag, clientCmd.m_visualizerFlagCommand.m_enable);
755 				}
756 				m_args.processCommand();
757 				break;
758 
759 			}
760 
761 			case GFX_CMD_UPLOAD_DATA:
762 			{
763 #if 0
764 				//printf("uploadData command: curSize=%d, offset=%d, slot=%d", clientCmd.m_uploadDataCommand.m_numBytes, clientCmd.m_uploadDataCommand.m_dataOffset, clientCmd.m_uploadDataCommand.m_dataSlot);
765 				int dataSlot = clientCmd.m_uploadDataCommand.m_dataSlot;
766 				int dataOffset = clientCmd.m_uploadDataCommand.m_dataOffset;
767 				m_dataSlots.resize(dataSlot + 1);
768 				btAssert(m_dataSlots[dataSlot].size() >= dataOffset);
769 				m_dataSlots[dataSlot].resize(clientCmd.m_uploadDataCommand.m_numBytes + clientCmd.m_uploadDataCommand.m_dataOffset);
770 				for (int i = 0; i < clientCmd.m_uploadDataCommand.m_numBytes; i++)
771 				{
772 					m_dataSlots[dataSlot][dataOffset + i] = bufferServerToClient[i];
773 				}
774 #endif
775 				break;
776 			}
777 			case GFX_CMD_REGISTER_TEXTURE:
778 			{
779 
780 				int dataSlot = 0;
781 				int sizeData = m_args.m_dataSlots[dataSlot].size();
782 				btAssert(sizeData > 0);
783 				serverStatusOut.m_type = GFX_CMD_REGISTER_TEXTURE_FAILED;
784 				if (sizeData)
785 				{
786 					unsigned char* texels = &m_args.m_dataSlots[dataSlot][0];
787 					int textureId = this->m_guiHelper->registerTexture(texels, clientCmd.m_registerTextureCommand.m_width, clientCmd.m_registerTextureCommand.m_height);
788 					serverStatusOut.m_type = GFX_CMD_REGISTER_TEXTURE_COMPLETED;
789 					serverStatusOut.m_registerTextureStatus.m_textureId = textureId;
790 				}
791 
792 				m_args.processCommand();
793 				break;
794 			}
795 
796 			case GFX_CMD_REGISTER_GRAPHICS_SHAPE:
797 			{
798 				int verticesSlot = 0;
799 				int indicesSlot = 1;
800 				serverStatusOut.m_type = GFX_CMD_REGISTER_GRAPHICS_SHAPE_FAILED;
801 				const float* vertices = (const float*)&m_args.m_dataSlots[verticesSlot][0];
802 				const int* indices = (const int*)&m_args.m_dataSlots[indicesSlot][0];
803 				int numVertices = clientCmd.m_registerGraphicsShapeCommand.m_numVertices;
804 				int numIndices = clientCmd.m_registerGraphicsShapeCommand.m_numIndices;
805 				int primitiveType = clientCmd.m_registerGraphicsShapeCommand.m_primitiveType;
806 				int textureId = clientCmd.m_registerGraphicsShapeCommand.m_textureId;
807 				int shapeId = this->m_guiHelper->registerGraphicsShape(vertices, numVertices, indices, numIndices, primitiveType, textureId);
808 				serverStatusOut.m_registerGraphicsShapeStatus.m_shapeId = shapeId;
809 				serverStatusOut.m_type = GFX_CMD_REGISTER_GRAPHICS_SHAPE_COMPLETED;
810 				m_args.processCommand();
811 				break;
812 			}
813 
814 			case GFX_CMD_REGISTER_GRAPHICS_INSTANCE:
815 			{
816 				int graphicsInstanceId = m_guiHelper->registerGraphicsInstance(clientCmd.m_registerGraphicsInstanceCommand.m_shapeIndex,
817 					clientCmd.m_registerGraphicsInstanceCommand.m_position,
818 					clientCmd.m_registerGraphicsInstanceCommand.m_quaternion,
819 					clientCmd.m_registerGraphicsInstanceCommand.m_color,
820 					clientCmd.m_registerGraphicsInstanceCommand.m_scaling);
821 				serverStatusOut.m_registerGraphicsInstanceStatus.m_graphicsInstanceId = graphicsInstanceId;
822 				serverStatusOut.m_type = GFX_CMD_REGISTER_GRAPHICS_INSTANCE_COMPLETED;
823 				m_args.processCommand();
824 				break;
825 			}
826 			case GFX_CMD_SYNCHRONIZE_TRANSFORMS:
827 			{
828 				GUISyncPosition* positions = (GUISyncPosition*)&m_args.m_dataSlots[0][0];
829 				for (int i = 0; i < clientCmd.m_syncTransformsCommand.m_numPositions; i++)
830 				{
831 					m_app->m_renderer->writeSingleInstanceTransformToCPU(positions[i].m_pos, positions[i].m_orn, positions[i].m_graphicsInstanceId);
832 				}
833 				m_args.processCommand();
834 				break;
835 			}
836 			case GFX_CMD_REMOVE_ALL_GRAPHICS_INSTANCES:
837 			{
838 				m_guiHelper->removeAllGraphicsInstances();
839 				m_args.processCommand();
840 				break;
841 			}
842 			case GFX_CMD_REMOVE_SINGLE_GRAPHICS_INSTANCE:
843 			{
844 				m_app->m_renderer->removeGraphicsInstance(clientCmd.m_removeGraphicsInstanceCommand.m_graphicsUid);
845 				m_args.processCommand();
846 				break;
847 			}
848 			case GFX_CMD_CHANGE_RGBA_COLOR:
849 			{
850 				m_guiHelper->changeRGBAColor(clientCmd.m_changeRGBAColorCommand.m_graphicsUid, clientCmd.m_changeRGBAColorCommand.m_rgbaColor);
851 				m_args.processCommand();
852 				break;
853 			}
854 
855 			case GFX_CMD_CHANGE_SCALING:
856 			{
857 				m_guiHelper->changeScaling(clientCmd.m_changeScalingCommand.m_graphicsUid, clientCmd.m_changeScalingCommand.m_scaling);
858 				m_args.processCommand();
859 				break;
860 			}
861 
862 			case GFX_CMD_GET_CAMERA_INFO:
863 			{
864 				serverStatusOut.m_type = GFX_CMD_GET_CAMERA_INFO_FAILED;
865 
866 				if (m_guiHelper->getCameraInfo(
867 					&serverStatusOut.m_getCameraInfoStatus.width,
868 					&serverStatusOut.m_getCameraInfoStatus.height,
869 					serverStatusOut.m_getCameraInfoStatus.viewMatrix,
870 					serverStatusOut.m_getCameraInfoStatus.projectionMatrix,
871 					serverStatusOut.m_getCameraInfoStatus.camUp,
872 					serverStatusOut.m_getCameraInfoStatus.camForward,
873 					serverStatusOut.m_getCameraInfoStatus.hor,
874 					serverStatusOut.m_getCameraInfoStatus.vert,
875 					&serverStatusOut.m_getCameraInfoStatus.yaw,
876 					&serverStatusOut.m_getCameraInfoStatus.pitch,
877 					&serverStatusOut.m_getCameraInfoStatus.camDist,
878 					serverStatusOut.m_getCameraInfoStatus.camTarget))
879 				{
880 					serverStatusOut.m_type = GFX_CMD_GET_CAMERA_INFO_COMPLETED;
881 				}
882 				m_args.processCommand();
883 
884 				break;
885 			}
886 			default:
887 			{
888 				printf("unsupported command:%d\n", clientCmd.m_type);
889 			}
890 		}
891 		return true;
892 	}
893 
processClientCommands()894 	void processClientCommands()
895 	{
896 		int timeStamp = 0;
897 		bool hasStatus = false;
898 		if (m_args.isCommandOutstanding())
899 		{
900 			processCommand(*m_args.m_cmdPtr, m_args.m_serverStatus);
901 		}
902 		//serverStatusOut.m_type = GFX_CMD_CLIENT_COMMAND_FAILED;
903 		//bool hasStatus = processCommand(clientCmd, serverStatusOut);
904 		if (hasStatus)
905 		{
906 			//submitServerStatus(serverStatusOut);
907 		}
908 	}
909 
stepSimulation(float deltaTime)910 	virtual void stepSimulation(float deltaTime)
911 	{
912 		B3_PROFILE("stepSimulation");
913 		processClientCommands();
914 		m_x += 0.01f;
915 		m_y += 0.01f;
916 		m_z += 0.01f;
917 	}
918 
919 
renderScene()920 	virtual void renderScene()
921 	{
922 		B3_PROFILE("renderScene");
923 		{
924 
925 			B3_PROFILE("writeTransforms");
926 			m_app->m_renderer->writeTransforms();
927 		}
928 		{
929 			B3_PROFILE("m_renderer->renderScene");
930 			m_app->m_renderer->renderScene();
931 		}
932 
933 	}
934 
935 
936 
physicsDebugDraw(int debugDrawFlags)937 	virtual void physicsDebugDraw(int debugDrawFlags)
938 	{
939 
940 	}
941 
mouseMoveCallback(float x,float y)942 	virtual bool mouseMoveCallback(float x, float y)
943 	{
944 		return false;
945 	}
mouseButtonCallback(int button,int state,float x,float y)946 	virtual bool mouseButtonCallback(int button, int state, float x, float y)
947 	{
948 		return false;
949 	}
keyboardCallback(int key,int state)950 	virtual bool keyboardCallback(int key, int state)
951 	{
952 		return false;
953 	}
954 
resetCamera()955 	virtual void resetCamera()
956 	{
957 		float dist = 3.5;
958 		float pitch = -32;
959 		float yaw = 136;
960 		float targetPos[3] = {0, 0, 0};
961 		if (m_app->m_renderer && m_app->m_renderer->getActiveCamera())
962 		{
963 			m_app->m_renderer->getActiveCamera()->setCameraDistance(dist);
964 			m_app->m_renderer->getActiveCamera()->setCameraPitch(pitch);
965 			m_app->m_renderer->getActiveCamera()->setCameraYaw(yaw);
966 			m_app->m_renderer->getActiveCamera()->setCameraTargetPosition(targetPos[0], targetPos[1], targetPos[2]);
967 		}
968 	}
969 
970 
971 };
972 
973 
974 
975 
976 
977 
978 
GraphicsServerCreateFuncBullet(struct CommonExampleOptions & options)979 CommonExampleInterface* GraphicsServerCreateFuncBullet(struct CommonExampleOptions& options)
980 {
981 	return new GraphicsServerExample(options.m_guiHelper);
982 }
983