Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / samples / 3d / cluster_viewer / main.cpp
blob201271fce59d9719b39917bc7f2e83937f95efff
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 // ---------------------------------------------------------------------------
22 // Includes
23 // ---------------------------------------------------------------------------
26 #include "nel/misc/types_nl.h"
28 #include "nel/misc/file.h"
29 #include "nel/misc/common.h"
30 #include "nel/misc/path.h"
31 #include "nel/misc/bitmap.h"
32 #include "nel/misc/events.h"
33 #include "nel/misc/time_nl.h"
34 #include "nel/misc/event_server.h"
35 #include "nel/misc/event_listener.h"
37 #include "nel/3d/nelu.h"
38 #include "nel/3d/driver.h"
39 #include "nel/3d/scene_group.h"
40 #include "nel/3d/text_context.h"
41 #include "nel/3d/transform_shape.h"
42 #include "nel/3d/event_mouse_listener.h"
44 #ifdef NL_OS_WINDOWS
45 # ifndef NL_COMP_MINGW
46 # define NOMINMAX
47 # endif
48 # include <windows.h>
49 #endif // NL_OS_WINDOWS
51 #ifndef CV_DIR
52 # define CV_DIR "."
53 #endif
55 using namespace std;
56 using namespace NL3D;
57 using namespace NLMISC;
60 // ---------------------------------------------------------------------------
61 struct SDispCS
63 string Name;
64 CInstanceGroup *pIG;
68 // ---------------------------------------------------------------------------
69 // ---------------------------------------------------------------------------
70 char *readLine (char*out, char*in)
72 out[0] = 0;
74 while ((*in != '\r') && (*in != '\n') && (*in != 0))
76 *out = *in;
77 ++out;
78 ++in;
79 *out = 0;
82 while ((*in == '\r') || (*in == '\n'))
83 ++in;
84 return in;
88 // ---------------------------------------------------------------------------
89 // ---------------------------------------------------------------------------
90 CInstanceGroup* LoadInstanceGroup(const char* sFilename)
92 CIFile file;
93 CInstanceGroup *newIG = new CInstanceGroup;
95 if( file.open( CPath::lookup( string(sFilename) ) ) )
97 try
99 // Serial the skeleton
100 newIG->serial (file);
101 // All is good
103 catch (const Exception &)
105 // Cannot save the file
106 delete newIG;
107 return NULL;
110 return newIG;
113 // ---------------------------------------------------------------------------
114 // ---------------------------------------------------------------------------
115 void LoadSceneScript (const char *ScriptName, CScene* pScene, vector<SDispCS> &DispCS, CVector &CameraStart,
116 vector<CInstanceGroup*> &vIGs)
118 char nameIG[256];
119 float posx, posy, posz;
120 float roti, rotj, rotk;
122 FILE *f = nlfopen (CPath::lookup(ScriptName), "rb");
123 fseek (f, 0, SEEK_END);
124 uint file_size = ftell (f);
125 fseek (f, 0, SEEK_SET);
126 char *file_buf = (char*)malloc(file_size+1);
127 if (fread (file_buf, 1, file_size, f) != file_size)
128 nlwarning("Can't read %d elements", file_size);
130 file_buf[file_size] = 0;
131 ++file_size;
132 fclose (f);
133 char *buf_ptr = file_buf;
134 sint nLastNbPlus = 0;
135 vector<CInstanceGroup*> pile;
136 pile.clear ();
137 pile.push_back (pScene->getGlobalInstanceGroup());
138 pile.push_back (pScene->getGlobalInstanceGroup());
142 char Line[256], *line_ptr;
143 sint nNbPlus = 0;
144 line_ptr = &Line[0];
145 buf_ptr = readLine (line_ptr, buf_ptr);
147 while ((*line_ptr == '\t') || (*line_ptr == ' ') || (*line_ptr == '+'))
149 if (*line_ptr == '+')
150 ++nNbPlus;
151 ++line_ptr;
154 if (strlen (line_ptr) == 0)
155 continue;
157 if (*line_ptr == '/')
158 continue;
160 posx = posy = posz = roti = rotj = rotk = 0.0f;
161 sscanf (line_ptr, "%s %f %f %f %f %f %f", nameIG, &posx, &posy, &posz, &roti, &rotj, &rotk);
163 if (stricmp (nameIG, "CAMERA_START") == 0)
165 CameraStart = CVector(posx, posy, posz);
167 else
169 if (nLastNbPlus >= nNbPlus)
170 for (int i = 0; i < ((nLastNbPlus-nNbPlus)+1); ++i)
171 pile.pop_back();
173 nLastNbPlus = nNbPlus;
175 CInstanceGroup *father = pile.back();
177 CInstanceGroup *ITemp = LoadInstanceGroup (nameIG);
178 if (ITemp != NULL)
180 SDispCS dcsTemp;
181 dcsTemp.Name = "";
182 for (sint32 i = 0; i < (1+nNbPlus); ++i)
183 dcsTemp.Name += " ";
184 dcsTemp.Name += nameIG;
185 dcsTemp.pIG = ITemp;
186 DispCS.push_back (dcsTemp);
188 ITemp->createRoot (*pScene);
189 ITemp->setPos (CVector(posx, posy, posz));
190 ITemp->setRotQuat (ITemp->getRotQuat() * CQuat(CVector::I, roti));
191 ITemp->setRotQuat (ITemp->getRotQuat() * CQuat(CVector::J, rotj));
192 ITemp->setRotQuat (ITemp->getRotQuat() * CQuat(CVector::K, rotk));
193 ITemp->setClusterSystemForInstances (father);
194 ITemp->addToScene (*pScene);
195 vIGs.push_back (ITemp);
197 pile.push_back (ITemp);
200 //while (strlen(buf_ptr) > 0);
201 while (buf_ptr < (file_buf+file_size-1));
202 free (file_buf);
206 // ---------------------------------------------------------------------------
207 // Main
208 // ---------------------------------------------------------------------------
209 #ifdef NL_OS_WINDOWS
210 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
211 #else
212 int main()
213 #endif
215 double rGlobalTime = 0;
216 double rOldGlobalTime = 0;
217 double rDeltaTime = 0;
219 vector<SDispCS> DispCS;
221 bool bAutoDetect = true;
222 bool bDisplay = true;
223 sint32 nSelected = 0;
225 SDispCS dcsTemp;
227 vector<CInstanceGroup*> vAllIGs;
228 // 2 dynamics objects
229 CTransformShape *pDynObj_InRoot;
230 CTransformShape *pDynObj_InCS;
232 CNELU::init (800, 600, CViewport(), 32, true);
234 CNELU::Scene->enableLightingSystem(true);
235 CNELU::Scene->setAmbientGlobal(CRGBA(128,128,128));
237 CPath::addSearchPath(CV_DIR);
238 CPath::addSearchPath(CV_DIR"/shapes");
239 CPath::addSearchPath(CV_DIR"/groups");
240 CPath::addSearchPath(CV_DIR"/fonts");
242 CFontManager FontManager;
243 CTextContext TextContext;
245 TextContext.init (CNELU::Driver, &FontManager);
246 TextContext.setFontGenerator (NLMISC::CPath::lookup("n019003l.pfb"));
247 TextContext.setHotSpot (CComputedString::TopLeft);
248 TextContext.setColor (CRGBA(255,255,255));
249 TextContext.setFontSize (20);
251 CEvent3dMouseListener MouseListener;
252 MouseListener.addToServer (CNELU::EventServer);
253 MouseListener.setFrustrum (CNELU::Camera->getFrustum());
254 MouseListener.setMouseMode (CEvent3dMouseListener::firstPerson);
256 CNELU::Camera->setTransformMode (ITransformable::DirectMatrix);
257 // Force to automatically find the cluster system
258 CNELU::Camera->setClusterSystem ((CInstanceGroup*)-1);
260 CClipTrav *pClipTrav = (CClipTrav*)&(CNELU::Scene->getClipTrav());
261 dcsTemp.Name = "Root";
262 dcsTemp.pIG = NULL;
263 DispCS.push_back (dcsTemp);
265 // Add all instance that create the scene
266 // --------------------------------------
267 // Beginning of script reading
268 CVector CameraStart;
270 LoadSceneScript ("main.cvs", CNELU::Scene, DispCS, CameraStart, vAllIGs);
272 CMatrix m = MouseListener.getViewMatrix();
273 m.setPos (CameraStart);
274 MouseListener.setMatrix (m);
275 // End of script reading
277 // Put a dynamic object in the root
278 pDynObj_InRoot = CNELU::Scene->createInstance ("sphere01.shape");
279 pDynObj_InRoot->setPos (0.0f, 0.0f, 0.0f);
280 // Put a dynamic object inside
281 pDynObj_InCS = CNELU::Scene->createInstance ("sphere01.shape");
282 pDynObj_InCS->setPos (50.0f, 50.0f, 25.0f);
283 // No automatic detection for moving objects - setup in street
284 pDynObj_InCS->setClusterSystem (vAllIGs[0]);
287 // Main loop
290 rGlobalTime = CTime::ticksToSecond(CTime::getPerformanceTime());
291 rDeltaTime = rGlobalTime - rOldGlobalTime;
292 rOldGlobalTime = rGlobalTime;
294 pDynObj_InRoot->setPos (-20.0f+20.0f*sinf((float)rGlobalTime),
295 -20.0f+20.0f*cosf((float)rGlobalTime*1.2f),
296 20.0f*sinf((float)rGlobalTime*1.1f+0.5f));
298 pDynObj_InCS->setPos (25.0f+5.0f*sinf((float)rGlobalTime*1.4f),
299 -25.0f+5.0f*cosf((float)rGlobalTime*1.3f),
300 25.0f+2.0f*sinf((float)rGlobalTime*1.2f+0.7f));
303 CNELU::Scene->animate ((float)rGlobalTime);
305 CNELU::EventServer.pump();
307 CNELU::clearBuffers (CRGBA(0,0,0));
309 CNELU::Scene->render ();
311 // -----------------------------------------------------
312 // -----------------------------------------------------
313 if (bDisplay)
315 vector<CCluster*> vCluster;
316 DispCS[0].pIG = pClipTrav->RootCluster->Group;
317 TextContext.setColor (CRGBA(255,255,255,255));
318 if (bAutoDetect)
320 TextContext.printfAt (0, 1, "AutoDetect : ON");
322 pClipTrav->fullSearch (vCluster, pClipTrav->CamPos);
324 for (uint32 i = 0; i < DispCS.size(); ++i)
326 TextContext.setColor (CRGBA(255,255,255,255));
327 for( uint32 j = 0; j < vCluster.size(); ++j)
329 if (DispCS[i].pIG == vCluster[j]->Group)
331 TextContext.setColor (CRGBA(255,0,0,255));
332 break;
336 TextContext.printfAt (0, 1-(i+2)*0.028f, DispCS[i].Name.c_str());
340 else
342 TextContext.printfAt (0, 1, "AutoDetect : OFF");
344 CInstanceGroup *pCurIG = CNELU::Camera->getClusterSystem();
345 for (uint32 i = 0; i < DispCS.size(); ++i)
347 if (DispCS[i].pIG == pCurIG)
348 TextContext.setColor (CRGBA(255,0,0,255));
349 else
350 TextContext.setColor (CRGBA(255,255,255,255));
352 TextContext.printfAt (0, 1-(i+2)*0.028f, DispCS[i].Name.c_str());
355 TextContext.setColor (CRGBA(255,255,255,255));
357 pClipTrav->Accel.select (pClipTrav->CamPos, pClipTrav->CamPos);
358 CQuadGrid<CCluster*>::CIterator itAcc = pClipTrav->Accel.begin();
359 while (itAcc != pClipTrav->Accel.end())
361 CCluster *pCluster = *itAcc;
362 if (pCluster->Group == pClipTrav->Camera->getClusterSystem())
363 if (pCluster->isIn (pClipTrav->CamPos))
365 vCluster.push_back (pCluster);
367 ++itAcc;
369 if (vCluster.empty() && (DispCS[0].pIG == pCurIG))
371 vCluster.push_back (pClipTrav->RootCluster);
376 TextContext.setColor (CRGBA(255,255,255,255));
378 string sAllClusters = "";
379 for( uint32 j = 0; j < vCluster.size(); ++j)
381 sAllClusters += vCluster[j]->Name;
382 if (j < (vCluster.size()-1))
383 sAllClusters += ", ";
385 TextContext.printfAt (0, 1-0.028f, sAllClusters.c_str());
388 // -----------------------------------------------------
389 // -----------------------------------------------------
391 CNELU::Driver->swapBuffers ();
393 // Keys management
394 // ---------------
396 if (CNELU::AsyncListener.isKeyDown (KeySHIFT))
397 MouseListener.setSpeed (50.0f);
398 else
399 MouseListener.setSpeed (10.0f);
401 CNELU::Camera->setMatrix (MouseListener.getViewMatrix());
403 if (CNELU::AsyncListener.isKeyPushed(KeyL))
405 CNELU::Driver->setPolygonMode (IDriver::Line);
408 if (CNELU::AsyncListener.isKeyPushed (KeyP))
410 CNELU::Driver->setPolygonMode (IDriver::Filled);
413 if (CNELU::AsyncListener.isKeyPushed (KeyTAB))
414 bDisplay = !bDisplay;
416 if (CNELU::AsyncListener.isKeyPushed (KeyA))
418 if (bAutoDetect)
420 bAutoDetect = false;
421 CNELU::Camera->setClusterSystem (NULL);
422 nSelected = 0;
424 else
426 bAutoDetect = true;
427 CNELU::Camera->setClusterSystem ((CInstanceGroup*)-1);
431 if (!bAutoDetect)
433 if (CNELU::AsyncListener.isKeyPushed (KeyZ))
435 nSelected--;
436 if(nSelected == -1)
437 nSelected = (sint32)DispCS.size()-1;
439 if (CNELU::AsyncListener.isKeyPushed (KeyS))
441 nSelected++;
442 if(nSelected == (sint32)DispCS.size())
443 nSelected = 0;
445 CNELU::Camera->setClusterSystem (DispCS[nSelected].pIG);
449 while ((!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)) && CNELU::Driver->isActive());
451 return EXIT_SUCCESS;