~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CSceneManager.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
#include "IrrCompileConfig.h"
 
6
#include "CSceneManager.h"
 
7
#include "IVideoDriver.h"
 
8
#include "IFileSystem.h"
 
9
#include "SAnimatedMesh.h"
 
10
#include "CMeshCache.h"
 
11
#include "IXMLWriter.h"
 
12
#include "ISceneUserDataSerializer.h"
 
13
#include "IGUIEnvironment.h"
 
14
#include "IMaterialRenderer.h"
 
15
#include "IReadFile.h"
 
16
#include "IWriteFile.h"
 
17
#include "ISceneLoader.h"
 
18
 
 
19
#include "os.h"
 
20
 
 
21
// We need this include for the case of skinned mesh support without
 
22
// any such loader
 
23
#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
 
24
#include "CSkinnedMesh.h"
 
25
#endif
 
26
 
 
27
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
 
28
#include "CIrrMeshFileLoader.h"
 
29
#endif
 
30
 
 
31
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
 
32
#include "CBSPMeshFileLoader.h"
 
33
#endif
 
34
 
 
35
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
 
36
#include "CMD2MeshFileLoader.h"
 
37
#endif
 
38
 
 
39
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
 
40
#include "CAnimatedMeshHalfLife.h"
 
41
#endif
 
42
 
 
43
#ifdef _IRR_COMPILE_WITH_MS3D_LOADER_
 
44
#include "CMS3DMeshFileLoader.h"
 
45
#endif
 
46
 
 
47
#ifdef _IRR_COMPILE_WITH_3DS_LOADER_
 
48
#include "C3DSMeshFileLoader.h"
 
49
#endif
 
50
 
 
51
#ifdef _IRR_COMPILE_WITH_X_LOADER_
 
52
#include "CXMeshFileLoader.h"
 
53
#endif
 
54
 
 
55
#ifdef _IRR_COMPILE_WITH_OCT_LOADER_
 
56
#include "COCTLoader.h"
 
57
#endif
 
58
 
 
59
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
 
60
#include "CCSMLoader.h"
 
61
#endif
 
62
 
 
63
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
 
64
#include "CLMTSMeshFileLoader.h"
 
65
#endif
 
66
 
 
67
#ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
 
68
#include "CMY3DMeshFileLoader.h"
 
69
#endif
 
70
 
 
71
#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
 
72
#include "CColladaFileLoader.h"
 
73
#endif
 
74
 
 
75
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
 
76
#include "CDMFLoader.h"
 
77
#endif
 
78
 
 
79
#ifdef _IRR_COMPILE_WITH_OGRE_LOADER_
 
80
#include "COgreMeshFileLoader.h"
 
81
#endif
 
82
 
 
83
#ifdef _IRR_COMPILE_WITH_OBJ_LOADER_
 
84
#include "COBJMeshFileLoader.h"
 
85
#endif
 
86
 
 
87
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
 
88
#include "CMD3MeshFileLoader.h"
 
89
#endif
 
90
 
 
91
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
 
92
#include "CB3DMeshFileLoader.h"
 
93
#endif
 
94
 
 
95
#ifdef _IRR_COMPILE_WITH_LWO_LOADER_
 
96
#include "CLWOMeshFileLoader.h"
 
97
#endif
 
98
 
 
99
#ifdef _IRR_COMPILE_WITH_STL_LOADER_
 
100
#include "CSTLMeshFileLoader.h"
 
101
#endif
 
102
 
 
103
#ifdef _IRR_COMPILE_WITH_PLY_LOADER_
 
104
#include "CPLYMeshFileLoader.h"
 
105
#endif
 
106
 
 
107
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
 
108
#include "CSMFMeshFileLoader.h"
 
109
#endif
 
110
 
 
111
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
 
112
#include "CSceneLoaderIrr.h"
 
113
#endif
 
114
 
 
115
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
 
116
#include "CColladaMeshWriter.h"
 
117
#endif
 
118
 
 
119
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
 
120
#include "CIrrMeshWriter.h"
 
121
#endif
 
122
 
 
123
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
 
124
#include "CSTLMeshWriter.h"
 
125
#endif
 
126
 
 
127
#ifdef _IRR_COMPILE_WITH_OBJ_WRITER_
 
128
#include "COBJMeshWriter.h"
 
129
#endif
 
130
 
 
131
#ifdef _IRR_COMPILE_WITH_PLY_WRITER_
 
132
#include "CPLYMeshWriter.h"
 
133
#endif
 
134
 
 
135
#include "CCubeSceneNode.h"
 
136
#include "CSphereSceneNode.h"
 
137
#include "CAnimatedMeshSceneNode.h"
 
138
#include "COctreeSceneNode.h"
 
139
#include "CCameraSceneNode.h"
 
140
#include "CLightSceneNode.h"
 
141
#include "CBillboardSceneNode.h"
 
142
#include "CMeshSceneNode.h"
 
143
#include "CSkyBoxSceneNode.h"
 
144
#include "CSkyDomeSceneNode.h"
 
145
#include "CParticleSystemSceneNode.h"
 
146
#include "CDummyTransformationSceneNode.h"
 
147
#include "CWaterSurfaceSceneNode.h"
 
148
#include "CTerrainSceneNode.h"
 
149
#include "CEmptySceneNode.h"
 
150
#include "CTextSceneNode.h"
 
151
#include "CQuake3ShaderSceneNode.h"
 
152
#include "CVolumeLightSceneNode.h"
 
153
 
 
154
#include "CDefaultSceneNodeFactory.h"
 
155
 
 
156
#include "CSceneCollisionManager.h"
 
157
#include "CTriangleSelector.h"
 
158
#include "COctreeTriangleSelector.h"
 
159
#include "CTriangleBBSelector.h"
 
160
#include "CMetaTriangleSelector.h"
 
161
#include "CTerrainTriangleSelector.h"
 
162
 
 
163
#include "CSceneNodeAnimatorRotation.h"
 
164
#include "CSceneNodeAnimatorFlyCircle.h"
 
165
#include "CSceneNodeAnimatorFlyStraight.h"
 
166
#include "CSceneNodeAnimatorTexture.h"
 
167
#include "CSceneNodeAnimatorCollisionResponse.h"
 
168
#include "CSceneNodeAnimatorDelete.h"
 
169
#include "CSceneNodeAnimatorFollowSpline.h"
 
170
#include "CSceneNodeAnimatorCameraFPS.h"
 
171
#include "CSceneNodeAnimatorCameraMaya.h"
 
172
#include "CDefaultSceneNodeAnimatorFactory.h"
 
173
 
 
174
#include "CGeometryCreator.h"
 
175
 
 
176
//! Enable debug features
 
177
#define SCENEMANAGER_DEBUG
 
178
 
 
179
namespace irr
 
180
{
 
181
namespace scene
 
182
{
 
183
 
 
184
//! constructor
 
185
CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
 
186
                gui::ICursorControl* cursorControl, IMeshCache* cache,
 
187
                gui::IGUIEnvironment* gui)
 
188
: ISceneNode(0, 0), Driver(driver), FileSystem(fs), GUIEnvironment(gui),
 
189
        CursorControl(cursorControl), CollisionManager(0),
 
190
        ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0),
 
191
        MeshCache(cache), CurrentRendertime(ESNRP_NONE), LightManager(0),
 
192
        IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type")
 
193
{
 
194
        #ifdef _DEBUG
 
195
        ISceneManager::setDebugName("CSceneManager ISceneManager");
 
196
        ISceneNode::setDebugName("CSceneManager ISceneNode");
 
197
        #endif
 
198
 
 
199
        // root node's scene manager
 
200
        SceneManager = this;
 
201
 
 
202
        // set scene parameters
 
203
        Parameters.setAttribute( DEBUG_NORMAL_LENGTH, 1.f );
 
204
        Parameters.setAttribute( DEBUG_NORMAL_COLOR, video::SColor(255, 34, 221, 221));
 
205
 
 
206
        if (Driver)
 
207
                Driver->grab();
 
208
 
 
209
        if (FileSystem)
 
210
                FileSystem->grab();
 
211
 
 
212
        if (CursorControl)
 
213
                CursorControl->grab();
 
214
 
 
215
        if (GUIEnvironment)
 
216
                GUIEnvironment->grab();
 
217
 
 
218
        // create mesh cache if not there already
 
219
        if (!MeshCache)
 
220
                MeshCache = new CMeshCache();
 
221
        else
 
222
                MeshCache->grab();
 
223
 
 
224
        // create collision manager
 
225
        CollisionManager = new CSceneCollisionManager(this, Driver);
 
226
 
 
227
        // create geometry creator
 
228
        GeometryCreator = new CGeometryCreator();
 
229
 
 
230
        // add file format loaders. add the least commonly used ones first,
 
231
        // as these are checked last
 
232
 
 
233
        // TODO: now that we have multiple scene managers, these should be
 
234
        // shallow copies from the previous manager if there is one.
 
235
 
 
236
        #ifdef _IRR_COMPILE_WITH_STL_LOADER_
 
237
        MeshLoaderList.push_back(new CSTLMeshFileLoader());
 
238
        #endif
 
239
        #ifdef _IRR_COMPILE_WITH_PLY_LOADER_
 
240
        MeshLoaderList.push_back(new CPLYMeshFileLoader());
 
241
        #endif
 
242
        #ifdef _IRR_COMPILE_WITH_SMF_LOADER_
 
243
        MeshLoaderList.push_back(new CSMFMeshFileLoader(Driver));
 
244
        #endif
 
245
        #ifdef _IRR_COMPILE_WITH_OCT_LOADER_
 
246
        MeshLoaderList.push_back(new COCTLoader(this, FileSystem));
 
247
        #endif
 
248
        #ifdef _IRR_COMPILE_WITH_CSM_LOADER_
 
249
        MeshLoaderList.push_back(new CCSMLoader(this, FileSystem));
 
250
        #endif
 
251
        #ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
 
252
        MeshLoaderList.push_back(new CLMTSMeshFileLoader(FileSystem, Driver, &Parameters));
 
253
        #endif
 
254
        #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
 
255
        MeshLoaderList.push_back(new CMY3DMeshFileLoader(this, FileSystem));
 
256
        #endif
 
257
        #ifdef _IRR_COMPILE_WITH_DMF_LOADER_
 
258
        MeshLoaderList.push_back(new CDMFLoader(this, FileSystem));
 
259
        #endif
 
260
        #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_
 
261
        MeshLoaderList.push_back(new COgreMeshFileLoader(FileSystem, Driver));
 
262
        #endif
 
263
        #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
 
264
        MeshLoaderList.push_back(new CHalflifeMDLMeshFileLoader( this ));
 
265
        #endif
 
266
        #ifdef _IRR_COMPILE_WITH_MD3_LOADER_
 
267
        MeshLoaderList.push_back(new CMD3MeshFileLoader( this));
 
268
        #endif
 
269
        #ifdef _IRR_COMPILE_WITH_LWO_LOADER_
 
270
        MeshLoaderList.push_back(new CLWOMeshFileLoader(this, FileSystem));
 
271
        #endif
 
272
        #ifdef _IRR_COMPILE_WITH_MD2_LOADER_
 
273
        MeshLoaderList.push_back(new CMD2MeshFileLoader());
 
274
        #endif
 
275
        #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
 
276
        MeshLoaderList.push_back(new CIrrMeshFileLoader(this, FileSystem));
 
277
        #endif
 
278
        #ifdef _IRR_COMPILE_WITH_BSP_LOADER_
 
279
        MeshLoaderList.push_back(new CBSPMeshFileLoader(this, FileSystem));
 
280
        #endif
 
281
        #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
 
282
        MeshLoaderList.push_back(new CColladaFileLoader(this, FileSystem));
 
283
        #endif
 
284
        #ifdef _IRR_COMPILE_WITH_3DS_LOADER_
 
285
        MeshLoaderList.push_back(new C3DSMeshFileLoader(this, FileSystem));
 
286
        #endif
 
287
        #ifdef _IRR_COMPILE_WITH_X_LOADER_
 
288
        MeshLoaderList.push_back(new CXMeshFileLoader(this, FileSystem));
 
289
        #endif
 
290
        #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_
 
291
        MeshLoaderList.push_back(new CMS3DMeshFileLoader(Driver));
 
292
        #endif
 
293
        #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_
 
294
        MeshLoaderList.push_back(new COBJMeshFileLoader(this, FileSystem));
 
295
        #endif
 
296
        #ifdef _IRR_COMPILE_WITH_B3D_LOADER_
 
297
        MeshLoaderList.push_back(new CB3DMeshFileLoader(this));
 
298
        #endif
 
299
 
 
300
        // scene loaders
 
301
        #ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
 
302
        SceneLoaderList.push_back(new CSceneLoaderIrr(this, FileSystem));
 
303
        #endif
 
304
 
 
305
 
 
306
        // factories
 
307
        ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this);
 
308
        registerSceneNodeFactory(factory);
 
309
        factory->drop();
 
310
 
 
311
        ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this, CursorControl);
 
312
        registerSceneNodeAnimatorFactory(animatorFactory);
 
313
        animatorFactory->drop();
 
314
}
 
315
 
 
316
 
 
317
//! destructor
 
318
CSceneManager::~CSceneManager()
 
319
{
 
320
        clearDeletionList();
 
321
 
 
322
        //! force to remove hardwareTextures from the driver
 
323
        //! because Scenes may hold internally data bounded to sceneNodes
 
324
        //! which may be destroyed twice
 
325
        if (Driver)
 
326
                Driver->removeAllHardwareBuffers();
 
327
 
 
328
        if (FileSystem)
 
329
                FileSystem->drop();
 
330
 
 
331
        if (CursorControl)
 
332
                CursorControl->drop();
 
333
 
 
334
        if (CollisionManager)
 
335
                CollisionManager->drop();
 
336
 
 
337
        if (GeometryCreator)
 
338
                GeometryCreator->drop();
 
339
 
 
340
        if (GUIEnvironment)
 
341
                GUIEnvironment->drop();
 
342
 
 
343
        u32 i;
 
344
        for (i=0; i<MeshLoaderList.size(); ++i)
 
345
                MeshLoaderList[i]->drop();
 
346
 
 
347
        for (i=0; i<SceneLoaderList.size(); ++i)
 
348
                SceneLoaderList[i]->drop();
 
349
 
 
350
        if (ActiveCamera)
 
351
                ActiveCamera->drop();
 
352
        ActiveCamera = 0;
 
353
 
 
354
        if (MeshCache)
 
355
                MeshCache->drop();
 
356
 
 
357
        for (i=0; i<SceneNodeFactoryList.size(); ++i)
 
358
                SceneNodeFactoryList[i]->drop();
 
359
 
 
360
        for (i=0; i<SceneNodeAnimatorFactoryList.size(); ++i)
 
361
                SceneNodeAnimatorFactoryList[i]->drop();
 
362
 
 
363
        if (LightManager)
 
364
                LightManager->drop();
 
365
 
 
366
        // remove all nodes and animators before dropping the driver
 
367
        // as render targets may be destroyed twice
 
368
 
 
369
        removeAll();
 
370
        removeAnimators();
 
371
 
 
372
        if (Driver)
 
373
                Driver->drop();
 
374
}
 
375
 
 
376
 
 
377
//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped.
 
378
IAnimatedMesh* CSceneManager::getMesh(const io::path& filename)
 
379
{
 
380
        IAnimatedMesh* msh = MeshCache->getMeshByName(filename);
 
381
        if (msh)
 
382
                return msh;
 
383
 
 
384
        io::IReadFile* file = FileSystem->createAndOpenFile(filename);
 
385
        if (!file)
 
386
        {
 
387
                os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR);
 
388
                return 0;
 
389
        }
 
390
 
 
391
        // iterate the list in reverse order so user-added loaders can override the built-in ones
 
392
        s32 count = MeshLoaderList.size();
 
393
        for (s32 i=count-1; i>=0; --i)
 
394
        {
 
395
                if (MeshLoaderList[i]->isALoadableFileExtension(filename))
 
396
                {
 
397
                        // reset file to avoid side effects of previous calls to createMesh
 
398
                        file->seek(0);
 
399
                        msh = MeshLoaderList[i]->createMesh(file);
 
400
                        if (msh)
 
401
                        {
 
402
                                MeshCache->addMesh(filename, msh);
 
403
                                msh->drop();
 
404
                                break;
 
405
                        }
 
406
                }
 
407
        }
 
408
 
 
409
        file->drop();
 
410
 
 
411
        if (!msh)
 
412
                os::Printer::log("Could not load mesh, file format seems to be unsupported", filename, ELL_ERROR);
 
413
        else
 
414
                os::Printer::log("Loaded mesh", filename, ELL_INFORMATION);
 
415
 
 
416
        return msh;
 
417
}
 
418
 
 
419
 
 
420
//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped.
 
421
IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file)
 
422
{
 
423
        if (!file)
 
424
                return 0;
 
425
 
 
426
        io::path name = file->getFileName();
 
427
        IAnimatedMesh* msh = MeshCache->getMeshByName(file->getFileName());
 
428
        if (msh)
 
429
                return msh;
 
430
 
 
431
        // iterate the list in reverse order so user-added loaders can override the built-in ones
 
432
        s32 count = MeshLoaderList.size();
 
433
        for (s32 i=count-1; i>=0; --i)
 
434
        {
 
435
                if (MeshLoaderList[i]->isALoadableFileExtension(name))
 
436
                {
 
437
                        // reset file to avoid side effects of previous calls to createMesh
 
438
                        file->seek(0);
 
439
                        msh = MeshLoaderList[i]->createMesh(file);
 
440
                        if (msh)
 
441
                        {
 
442
                                MeshCache->addMesh(file->getFileName(), msh);
 
443
                                msh->drop();
 
444
                                break;
 
445
                        }
 
446
                }
 
447
        }
 
448
 
 
449
        if (!msh)
 
450
                os::Printer::log("Could not load mesh, file format seems to be unsupported", file->getFileName(), ELL_ERROR);
 
451
        else
 
452
                os::Printer::log("Loaded mesh", file->getFileName(), ELL_INFORMATION);
 
453
 
 
454
        return msh;
 
455
}
 
456
 
 
457
 
 
458
//! returns the video driver
 
459
video::IVideoDriver* CSceneManager::getVideoDriver()
 
460
{
 
461
        return Driver;
 
462
}
 
463
 
 
464
 
 
465
//! returns the GUI Environment
 
466
gui::IGUIEnvironment* CSceneManager::getGUIEnvironment()
 
467
{
 
468
        return GUIEnvironment;
 
469
}
 
470
 
 
471
//! Get the active FileSystem
 
472
/** \return Pointer to the FileSystem
 
473
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
 
474
io::IFileSystem* CSceneManager::getFileSystem()
 
475
{
 
476
        return FileSystem;
 
477
}
 
478
 
 
479
//! Adds a text scene node, which is able to display
 
480
//! 2d text at a position in three dimensional space
 
481
ITextSceneNode* CSceneManager::addTextSceneNode(gui::IGUIFont* font,
 
482
                const wchar_t* text, video::SColor color, ISceneNode* parent,
 
483
                const core::vector3df& position, s32 id)
 
484
{
 
485
        if (!font)
 
486
                return 0;
 
487
 
 
488
        if (!parent)
 
489
                parent = this;
 
490
 
 
491
        ITextSceneNode* t = new CTextSceneNode(parent, this, id, font,
 
492
                getSceneCollisionManager(), position, text, color);
 
493
        t->drop();
 
494
 
 
495
        return t;
 
496
}
 
497
 
 
498
 
 
499
//! Adds a text scene node, which uses billboards
 
500
IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* font,
 
501
                const wchar_t* text, ISceneNode* parent,
 
502
                const core::dimension2d<f32>& size,
 
503
                const core::vector3df& position, s32 id,
 
504
                video::SColor colorTop, video::SColor colorBottom)
 
505
{
 
506
        if (!font && GUIEnvironment)
 
507
                font = GUIEnvironment->getBuiltInFont();
 
508
 
 
509
        if (!font)
 
510
                return 0;
 
511
 
 
512
        if (!parent)
 
513
                parent = this;
 
514
 
 
515
        IBillboardTextSceneNode* node = new CBillboardTextSceneNode(parent, this, id, font, text, position, size,
 
516
                colorTop, colorBottom);
 
517
        node->drop();
 
518
 
 
519
        return node;
 
520
 
 
521
}
 
522
 
 
523
 
 
524
//! Adds a scene node, which can render a quake3 shader
 
525
IMeshSceneNode* CSceneManager::addQuake3SceneNode(const IMeshBuffer* meshBuffer,
 
526
                                        const quake3::IShader * shader,
 
527
                                        ISceneNode* parent, s32 id )
 
528
{
 
529
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
 
530
        if (!shader)
 
531
                return 0;
 
532
 
 
533
        if (!parent)
 
534
                parent = this;
 
535
 
 
536
        CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent,
 
537
                this, id, FileSystem,
 
538
                meshBuffer, shader );
 
539
        node->drop();
 
540
 
 
541
        return node;
 
542
#else
 
543
        return 0;
 
544
#endif
 
545
}
 
546
 
 
547
 
 
548
//! adds Volume Lighting Scene Node.
 
549
//! the returned pointer must not be dropped.
 
550
IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode(
 
551
                ISceneNode* parent, s32 id,
 
552
                const u32 subdivU, const u32 subdivV,
 
553
                const video::SColor foot, const video::SColor tail,
 
554
                const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale)
 
555
{
 
556
        if (!parent)
 
557
                parent = this;
 
558
 
 
559
        IVolumeLightSceneNode* node = new CVolumeLightSceneNode(parent, this, id, subdivU, subdivV, foot, tail, position, rotation, scale);
 
560
        node->drop();
 
561
 
 
562
        return node;
 
563
}
 
564
 
 
565
 
 
566
//! adds a test scene node for test purposes to the scene. It is a simple cube of (1,1,1) size.
 
567
//! the returned pointer must not be dropped.
 
568
IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent,
 
569
                s32 id, const core::vector3df& position,
 
570
                const core::vector3df& rotation, const core::vector3df& scale)
 
571
{
 
572
        if (!parent)
 
573
                parent = this;
 
574
 
 
575
        IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale);
 
576
        node->drop();
 
577
 
 
578
        return node;
 
579
}
 
580
 
 
581
 
 
582
//! Adds a sphere scene node for test purposes to the scene.
 
583
IMeshSceneNode* CSceneManager::addSphereSceneNode(f32 radius, s32 polyCount,
 
584
                ISceneNode* parent, s32 id, const core::vector3df& position,
 
585
                const core::vector3df& rotation, const core::vector3df& scale)
 
586
{
 
587
        if (!parent)
 
588
                parent = this;
 
589
 
 
590
        IMeshSceneNode* node = new CSphereSceneNode(radius, polyCount, polyCount, parent, this, id, position, rotation, scale);
 
591
        node->drop();
 
592
 
 
593
        return node;
 
594
}
 
595
 
 
596
 
 
597
//! adds a scene node for rendering a static mesh
 
598
//! the returned pointer must not be dropped.
 
599
IMeshSceneNode* CSceneManager::addMeshSceneNode(IMesh* mesh, ISceneNode* parent, s32 id,
 
600
        const core::vector3df& position, const core::vector3df& rotation,
 
601
        const core::vector3df& scale, bool alsoAddIfMeshPointerZero)
 
602
{
 
603
        if (!alsoAddIfMeshPointerZero && !mesh)
 
604
                return 0;
 
605
 
 
606
        if (!parent)
 
607
                parent = this;
 
608
 
 
609
        IMeshSceneNode* node = new CMeshSceneNode(mesh, parent, this, id, position, rotation, scale);
 
610
        node->drop();
 
611
 
 
612
        return node;
 
613
}
 
614
 
 
615
 
 
616
//! Adds a scene node for rendering a animated water surface mesh.
 
617
ISceneNode* CSceneManager::addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 waveLength,
 
618
        ISceneNode* parent, s32 id, const core::vector3df& position,
 
619
        const core::vector3df& rotation, const core::vector3df& scale)
 
620
{
 
621
        if (!parent)
 
622
                parent = this;
 
623
 
 
624
        ISceneNode* node = new CWaterSurfaceSceneNode(waveHeight, waveSpeed, waveLength,
 
625
                mesh, parent, this, id, position, rotation, scale);
 
626
 
 
627
        node->drop();
 
628
 
 
629
        return node;
 
630
}
 
631
 
 
632
 
 
633
//! adds a scene node for rendering an animated mesh model
 
634
IAnimatedMeshSceneNode* CSceneManager::addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id,
 
635
        const core::vector3df& position, const core::vector3df& rotation,
 
636
        const core::vector3df& scale, bool alsoAddIfMeshPointerZero)
 
637
{
 
638
        if (!alsoAddIfMeshPointerZero && !mesh)
 
639
                return 0;
 
640
 
 
641
        if (!parent)
 
642
                parent = this;
 
643
 
 
644
        IAnimatedMeshSceneNode* node =
 
645
                new CAnimatedMeshSceneNode(mesh, parent, this, id, position, rotation, scale);
 
646
        node->drop();
 
647
 
 
648
        return node;
 
649
}
 
650
 
 
651
 
 
652
//! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering
 
653
//! scenes with lots of geometry. The Octree is built on the fly from the mesh, much
 
654
//! faster then a bsp tree.
 
655
IMeshSceneNode* CSceneManager::addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent,
 
656
                        s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero)
 
657
{
 
658
        if (!alsoAddIfMeshPointerZero && (!mesh || !mesh->getFrameCount()))
 
659
                return 0;
 
660
 
 
661
        return addOctreeSceneNode(mesh ? mesh->getMesh(0) : 0,
 
662
                                parent, id, minimalPolysPerNode,
 
663
                                alsoAddIfMeshPointerZero);
 
664
}
 
665
 
 
666
 
 
667
//! Adds a scene node for rendering using a octree. This a good method for rendering
 
668
//! scenes with lots of geometry. The Octree is built on the fly from the mesh, much
 
669
//! faster then a bsp tree.
 
670
IMeshSceneNode* CSceneManager::addOctreeSceneNode(IMesh* mesh, ISceneNode* parent,
 
671
                s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero)
 
672
{
 
673
        if (!alsoAddIfMeshPointerZero && !mesh)
 
674
                return 0;
 
675
 
 
676
        if (!parent)
 
677
                parent = this;
 
678
 
 
679
        COctreeSceneNode* node = new COctreeSceneNode(parent, this, id, minimalPolysPerNode);
 
680
 
 
681
        if (node)
 
682
        {
 
683
                node->setMesh(mesh);
 
684
                node->drop();
 
685
        }
 
686
 
 
687
        return node;
 
688
}
 
689
 
 
690
 
 
691
//! Adds a camera scene node to the tree and sets it as active camera.
 
692
//! \param position: Position of the space relative to its parent where the camera will be placed.
 
693
//! \param lookat: Position where the camera will look at. Also known as target.
 
694
//! \param parent: Parent scene node of the camera. Can be null. If the parent moves,
 
695
//! the camera will move too.
 
696
//! \return Returns pointer to interface to camera
 
697
ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent,
 
698
        const core::vector3df& position, const core::vector3df& lookat, s32 id,
 
699
        bool makeActive)
 
700
{
 
701
        if (!parent)
 
702
                parent = this;
 
703
 
 
704
        ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat);
 
705
 
 
706
        if (makeActive)
 
707
                setActiveCamera(node);
 
708
        node->drop();
 
709
 
 
710
        return node;
 
711
}
 
712
 
 
713
 
 
714
//! Adds a camera scene node which is able to be controlled with the mouse similar
 
715
//! to in the 3D Software Maya by Alias Wavefront.
 
716
//! The returned pointer must not be dropped.
 
717
ICameraSceneNode* CSceneManager::addCameraSceneNodeMaya(ISceneNode* parent,
 
718
        f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id,
 
719
        bool makeActive)
 
720
{
 
721
        ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(),
 
722
                        core::vector3df(0,0,100), id, makeActive);
 
723
        if (node)
 
724
        {
 
725
                ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraMaya(CursorControl,
 
726
                        rotateSpeed, zoomSpeed, translationSpeed);
 
727
 
 
728
                node->addAnimator(anm);
 
729
                anm->drop();
 
730
        }
 
731
 
 
732
        return node;
 
733
}
 
734
 
 
735
 
 
736
//! Adds a camera scene node which is able to be controlled with the mouse and keys
 
737
//! like in most first person shooters (FPS):
 
738
ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent,
 
739
        f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray,
 
740
        s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed,
 
741
        bool invertMouseY, bool makeActive)
 
742
{
 
743
        ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(),
 
744
                        core::vector3df(0,0,100), id, makeActive);
 
745
        if (node)
 
746
        {
 
747
                ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl,
 
748
                                rotateSpeed, moveSpeed, jumpSpeed,
 
749
                                keyMapArray, keyMapSize, noVerticalMovement, invertMouseY);
 
750
 
 
751
                // Bind the node's rotation to its target. This is consistent with 1.4.2 and below.
 
752
                node->bindTargetAndRotation(true);
 
753
                node->addAnimator(anm);
 
754
                anm->drop();
 
755
        }
 
756
 
 
757
        return node;
 
758
}
 
759
 
 
760
 
 
761
//! Adds a dynamic light scene node. The light will cast dynamic light on all
 
762
//! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING
 
763
//! turned on. (This is the default setting in most scene nodes).
 
764
ILightSceneNode* CSceneManager::addLightSceneNode(ISceneNode* parent,
 
765
        const core::vector3df& position, video::SColorf color, f32 range, s32 id)
 
766
{
 
767
        if (!parent)
 
768
                parent = this;
 
769
 
 
770
        ILightSceneNode* node = new CLightSceneNode(parent, this, id, position, color, range);
 
771
        node->drop();
 
772
 
 
773
        return node;
 
774
}
 
775
 
 
776
 
 
777
//! Adds a billboard scene node to the scene. A billboard is like a 3d sprite: A 2d element,
 
778
//! which always looks to the camera. It is usually used for things like explosions, fire,
 
779
//! lensflares and things like that.
 
780
IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent,
 
781
        const core::dimension2d<f32>& size, const core::vector3df& position, s32 id,
 
782
        video::SColor colorTop, video::SColor colorBottom
 
783
        )
 
784
{
 
785
        if (!parent)
 
786
                parent = this;
 
787
 
 
788
        IBillboardSceneNode* node = new CBillboardSceneNode(parent, this, id, position, size,
 
789
                colorTop, colorBottom);
 
790
        node->drop();
 
791
 
 
792
        return node;
 
793
}
 
794
 
 
795
 
 
796
//! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and
 
797
//! is drawn around the camera position.
 
798
ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom,
 
799
        video::ITexture* left, video::ITexture* right, video::ITexture* front,
 
800
        video::ITexture* back, ISceneNode* parent, s32 id)
 
801
{
 
802
        if (!parent)
 
803
                parent = this;
 
804
 
 
805
        ISceneNode* node = new CSkyBoxSceneNode(top, bottom, left, right,
 
806
                        front, back, parent, this, id);
 
807
 
 
808
        node->drop();
 
809
        return node;
 
810
}
 
811
 
 
812
 
 
813
//! Adds a skydome scene node. A skydome is a large (half-) sphere with a
 
814
//! panoramic texture on it and is drawn around the camera position.
 
815
ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture,
 
816
        u32 horiRes, u32 vertRes, f32 texturePercentage,f32 spherePercentage, f32 radius,
 
817
        ISceneNode* parent, s32 id)
 
818
{
 
819
        if (!parent)
 
820
                parent = this;
 
821
 
 
822
        ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes,
 
823
                texturePercentage, spherePercentage, radius, parent, this, id);
 
824
 
 
825
        node->drop();
 
826
        return node;
 
827
}
 
828
 
 
829
 
 
830
//! Adds a particle system scene node.
 
831
IParticleSystemSceneNode* CSceneManager::addParticleSystemSceneNode(
 
832
        bool withDefaultEmitter, ISceneNode* parent, s32 id,
 
833
        const core::vector3df& position, const core::vector3df& rotation,
 
834
        const core::vector3df& scale)
 
835
{
 
836
        if (!parent)
 
837
                parent = this;
 
838
 
 
839
        IParticleSystemSceneNode* node = new CParticleSystemSceneNode(withDefaultEmitter,
 
840
                parent, this, id, position, rotation, scale);
 
841
        node->drop();
 
842
 
 
843
        return node;
 
844
}
 
845
 
 
846
 
 
847
//! Adds a terrain scene node to the scene graph.
 
848
ITerrainSceneNode* CSceneManager::addTerrainSceneNode(
 
849
        const io::path& heightMapFileName,
 
850
        ISceneNode* parent, s32 id,
 
851
        const core::vector3df& position,
 
852
        const core::vector3df& rotation,
 
853
        const core::vector3df& scale,
 
854
        video::SColor vertexColor,
 
855
        s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize, s32 smoothFactor,
 
856
        bool addAlsoIfHeightmapEmpty)
 
857
{
 
858
        io::IReadFile* file = FileSystem->createAndOpenFile(heightMapFileName);
 
859
 
 
860
        if (!file && !addAlsoIfHeightmapEmpty)
 
861
        {
 
862
                os::Printer::log("Could not load terrain, because file could not be opened.",
 
863
                heightMapFileName, ELL_ERROR);
 
864
                return 0;
 
865
        }
 
866
 
 
867
        ITerrainSceneNode* terrain = addTerrainSceneNode(file, parent, id,
 
868
                position, rotation, scale, vertexColor, maxLOD, patchSize,
 
869
                smoothFactor, addAlsoIfHeightmapEmpty);
 
870
 
 
871
        if (file)
 
872
                file->drop();
 
873
 
 
874
        return terrain;
 
875
}
 
876
 
 
877
//! Adds a terrain scene node to the scene graph.
 
878
ITerrainSceneNode* CSceneManager::addTerrainSceneNode(
 
879
        io::IReadFile* heightMapFile,
 
880
        ISceneNode* parent, s32 id,
 
881
        const core::vector3df& position,
 
882
        const core::vector3df& rotation,
 
883
        const core::vector3df& scale,
 
884
        video::SColor vertexColor,
 
885
        s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize,
 
886
        s32 smoothFactor,
 
887
        bool addAlsoIfHeightmapEmpty)
 
888
{
 
889
        if (!parent)
 
890
                parent = this;
 
891
 
 
892
        if (!heightMapFile && !addAlsoIfHeightmapEmpty)
 
893
        {
 
894
                os::Printer::log("Could not load terrain, because file could not be opened.", ELL_ERROR);
 
895
                return 0;
 
896
        }
 
897
 
 
898
        CTerrainSceneNode* node = new CTerrainSceneNode(parent, this, FileSystem, id,
 
899
                maxLOD, patchSize, position, rotation, scale);
 
900
 
 
901
        if (!node->loadHeightMap(heightMapFile, vertexColor, smoothFactor))
 
902
        {
 
903
                if (!addAlsoIfHeightmapEmpty)
 
904
                {
 
905
                        node->remove();
 
906
                        node->drop();
 
907
                        return 0;
 
908
                }
 
909
        }
 
910
 
 
911
        node->drop();
 
912
        return node;
 
913
}
 
914
 
 
915
 
 
916
//! Adds an empty scene node.
 
917
ISceneNode* CSceneManager::addEmptySceneNode(ISceneNode* parent, s32 id)
 
918
{
 
919
        if (!parent)
 
920
                parent = this;
 
921
 
 
922
        ISceneNode* node = new CEmptySceneNode(parent, this, id);
 
923
        node->drop();
 
924
 
 
925
        return node;
 
926
}
 
927
 
 
928
 
 
929
//! Adds a dummy transformation scene node to the scene graph.
 
930
IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode(
 
931
        ISceneNode* parent, s32 id)
 
932
{
 
933
        if (!parent)
 
934
                parent = this;
 
935
 
 
936
        IDummyTransformationSceneNode* node = new CDummyTransformationSceneNode(
 
937
                parent, this, id);
 
938
        node->drop();
 
939
 
 
940
        return node;
 
941
}
 
942
 
 
943
//! Adds a Hill Plane mesh to the mesh pool. The mesh is generated on the fly
 
944
//! and looks like a plane with some hills on it. You can specify how many hills
 
945
//! there should be on the plane and how high they should be. Also you must
 
946
//! specify a name for the mesh, because the mesh is added to the mesh pool,
 
947
//! and can be retrieved again using ISceneManager::getMesh with the name as
 
948
//! parameter.
 
949
IAnimatedMesh* CSceneManager::addHillPlaneMesh(const io::path& name,
 
950
                const core::dimension2d<f32>& tileSize,
 
951
                const core::dimension2d<u32>& tileCount,
 
952
                video::SMaterial* material, f32 hillHeight,
 
953
                const core::dimension2d<f32>& countHills,
 
954
                const core::dimension2d<f32>& textureRepeatCount)
 
955
{
 
956
        if (MeshCache->isMeshLoaded(name))
 
957
                return MeshCache->getMeshByName(name);
 
958
 
 
959
        IMesh* mesh = GeometryCreator->createHillPlaneMesh(tileSize,
 
960
                        tileCount, material, hillHeight, countHills,
 
961
                        textureRepeatCount);
 
962
        if (!mesh)
 
963
                return 0;
 
964
 
 
965
        SAnimatedMesh* animatedMesh = new SAnimatedMesh();
 
966
        if (!animatedMesh)
 
967
        {
 
968
                mesh->drop();
 
969
                return 0;
 
970
        }
 
971
 
 
972
        animatedMesh->addMesh(mesh);
 
973
        mesh->drop();
 
974
        animatedMesh->recalculateBoundingBox();
 
975
 
 
976
        MeshCache->addMesh(name, animatedMesh);
 
977
        animatedMesh->drop();
 
978
 
 
979
        return animatedMesh;
 
980
}
 
981
 
 
982
 
 
983
//! Adds a terrain mesh to the mesh pool.
 
984
IAnimatedMesh* CSceneManager::addTerrainMesh(const io::path& name,
 
985
        video::IImage* texture, video::IImage* heightmap,
 
986
        const core::dimension2d<f32>& stretchSize,
 
987
        f32 maxHeight,
 
988
        const core::dimension2d<u32>& defaultVertexBlockSize)
 
989
{
 
990
        if (MeshCache->isMeshLoaded(name))
 
991
                return MeshCache->getMeshByName(name);
 
992
 
 
993
        const bool debugBorders=false;
 
994
        IMesh* mesh = GeometryCreator->createTerrainMesh(texture, heightmap,
 
995
                        stretchSize, maxHeight, getVideoDriver(),
 
996
                        defaultVertexBlockSize, debugBorders);
 
997
        if (!mesh)
 
998
                return 0;
 
999
 
 
1000
        SAnimatedMesh* animatedMesh = new SAnimatedMesh();
 
1001
        if (!animatedMesh)
 
1002
        {
 
1003
                mesh->drop();
 
1004
                return 0;
 
1005
        }
 
1006
 
 
1007
        animatedMesh->addMesh(mesh);
 
1008
        mesh->drop();
 
1009
        animatedMesh->recalculateBoundingBox();
 
1010
 
 
1011
        MeshCache->addMesh(name, animatedMesh);
 
1012
        animatedMesh->drop();
 
1013
 
 
1014
        return animatedMesh;
 
1015
}
 
1016
 
 
1017
 
 
1018
//! Adds an arrow mesh to the mesh pool.
 
1019
IAnimatedMesh* CSceneManager::addArrowMesh(const io::path& name,
 
1020
                video::SColor vtxColor0, video::SColor vtxColor1,
 
1021
                u32 tesselationCylinder, u32 tesselationCone, f32 height,
 
1022
                f32 cylinderHeight, f32 width0,f32 width1)
 
1023
{
 
1024
        if (MeshCache->isMeshLoaded(name))
 
1025
                return MeshCache->getMeshByName(name);
 
1026
 
 
1027
        IMesh* mesh = GeometryCreator->createArrowMesh( tesselationCylinder,
 
1028
                        tesselationCone, height, cylinderHeight, width0,width1,
 
1029
                        vtxColor0, vtxColor1);
 
1030
        if (!mesh)
 
1031
                return 0;
 
1032
 
 
1033
        SAnimatedMesh* animatedMesh = new SAnimatedMesh();
 
1034
        if (!animatedMesh)
 
1035
        {
 
1036
                mesh->drop();
 
1037
                return 0;
 
1038
        }
 
1039
 
 
1040
        animatedMesh->addMesh(mesh);
 
1041
        mesh->drop();
 
1042
        animatedMesh->recalculateBoundingBox();
 
1043
 
 
1044
        MeshCache->addMesh(name, animatedMesh);
 
1045
        animatedMesh->drop();
 
1046
 
 
1047
        return animatedMesh;
 
1048
}
 
1049
 
 
1050
 
 
1051
//! Adds a static sphere mesh to the mesh pool.
 
1052
IAnimatedMesh* CSceneManager::addSphereMesh(const io::path& name,
 
1053
                f32 radius, u32 polyCountX, u32 polyCountY)
 
1054
{
 
1055
        if (MeshCache->isMeshLoaded(name))
 
1056
                return MeshCache->getMeshByName(name);
 
1057
 
 
1058
        IMesh* mesh = GeometryCreator->createSphereMesh(radius, polyCountX, polyCountY);
 
1059
        if (!mesh)
 
1060
                return 0;
 
1061
 
 
1062
        SAnimatedMesh* animatedMesh = new SAnimatedMesh();
 
1063
        if (!animatedMesh)
 
1064
        {
 
1065
                mesh->drop();
 
1066
                return 0;
 
1067
        }
 
1068
 
 
1069
        animatedMesh->addMesh(mesh);
 
1070
        mesh->drop();
 
1071
        animatedMesh->recalculateBoundingBox();
 
1072
 
 
1073
        MeshCache->addMesh(name, animatedMesh);
 
1074
        animatedMesh->drop();
 
1075
 
 
1076
        return animatedMesh;
 
1077
}
 
1078
 
 
1079
 
 
1080
 
 
1081
//! Adds a static volume light mesh to the mesh pool.
 
1082
IAnimatedMesh* CSceneManager::addVolumeLightMesh(const io::path& name,
 
1083
                const u32 SubdivideU, const u32 SubdivideV,
 
1084
                const video::SColor FootColor, const video::SColor TailColor)
 
1085
{
 
1086
        if (MeshCache->isMeshLoaded(name))
 
1087
                return MeshCache->getMeshByName(name);
 
1088
 
 
1089
        IMesh* mesh = GeometryCreator->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor);
 
1090
        if (!mesh)
 
1091
                return 0;
 
1092
 
 
1093
        SAnimatedMesh* animatedMesh = new SAnimatedMesh();
 
1094
        if (!animatedMesh)
 
1095
        {
 
1096
                mesh->drop();
 
1097
                return 0;
 
1098
        }
 
1099
 
 
1100
        animatedMesh->addMesh(mesh);
 
1101
        mesh->drop();
 
1102
        animatedMesh->recalculateBoundingBox();
 
1103
 
 
1104
        MeshCache->addMesh(name, animatedMesh);
 
1105
        animatedMesh->drop();
 
1106
 
 
1107
        return animatedMesh;
 
1108
}
 
1109
 
 
1110
 
 
1111
//! Returns the root scene node. This is the scene node wich is parent
 
1112
//! of all scene nodes. The root scene node is a special scene node which
 
1113
//! only exists to manage all scene nodes. It is not rendered and cannot
 
1114
//! be removed from the scene.
 
1115
//! \return Returns a pointer to the root scene node.
 
1116
ISceneNode* CSceneManager::getRootSceneNode()
 
1117
{
 
1118
        return this;
 
1119
}
 
1120
 
 
1121
 
 
1122
//! Returns the current active camera.
 
1123
//! \return The active camera is returned. Note that this can be NULL, if there
 
1124
//! was no camera created yet.
 
1125
ICameraSceneNode* CSceneManager::getActiveCamera() const
 
1126
{
 
1127
        return ActiveCamera;
 
1128
}
 
1129
 
 
1130
 
 
1131
//! Sets the active camera. The previous active camera will be deactivated.
 
1132
//! \param camera: The new camera which should be active.
 
1133
void CSceneManager::setActiveCamera(ICameraSceneNode* camera)
 
1134
{
 
1135
        if (camera)
 
1136
                camera->grab();
 
1137
        if (ActiveCamera)
 
1138
                ActiveCamera->drop();
 
1139
 
 
1140
        ActiveCamera = camera;
 
1141
}
 
1142
 
 
1143
 
 
1144
//! renders the node.
 
1145
void CSceneManager::render()
 
1146
{
 
1147
}
 
1148
 
 
1149
 
 
1150
//! returns the axis aligned bounding box of this node
 
1151
const core::aabbox3d<f32>& CSceneManager::getBoundingBox() const
 
1152
{
 
1153
        _IRR_DEBUG_BREAK_IF(true) // Bounding Box of Scene Manager wanted.
 
1154
 
 
1155
        // should never be used.
 
1156
        return *((core::aabbox3d<f32>*)0);
 
1157
}
 
1158
 
 
1159
 
 
1160
//! returns if node is culled
 
1161
bool CSceneManager::isCulled(const ISceneNode* node) const
 
1162
{
 
1163
        const ICameraSceneNode* cam = getActiveCamera();
 
1164
        if (!cam)
 
1165
        {
 
1166
                _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
1167
                return false;
 
1168
        }
 
1169
        bool result = false;
 
1170
 
 
1171
        // has occlusion query information
 
1172
        if (node->getAutomaticCulling() & scene::EAC_OCC_QUERY)
 
1173
        {
 
1174
                result = (Driver->getOcclusionQueryResult(const_cast<ISceneNode*>(node))==0);
 
1175
        }
 
1176
 
 
1177
        // can be seen by a bounding box ?
 
1178
        if (!result && (node->getAutomaticCulling() & scene::EAC_BOX))
 
1179
        {
 
1180
                core::aabbox3d<f32> tbox = node->getBoundingBox();
 
1181
                node->getAbsoluteTransformation().transformBoxEx(tbox);
 
1182
                result = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox() ));
 
1183
        }
 
1184
 
 
1185
        // can be seen by a bounding sphere
 
1186
        if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_SPHERE))
 
1187
        { // requires bbox diameter
 
1188
        }
 
1189
 
 
1190
        // can be seen by cam pyramid planes ?
 
1191
        if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_BOX))
 
1192
        {
 
1193
                SViewFrustum frust = *cam->getViewFrustum();
 
1194
 
 
1195
                //transform the frustum to the node's current absolute transformation
 
1196
                core::matrix4 invTrans(node->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE);
 
1197
                //invTrans.makeInverse();
 
1198
                frust.transform(invTrans);
 
1199
 
 
1200
                core::vector3df edges[8];
 
1201
                node->getBoundingBox().getEdges(edges);
 
1202
 
 
1203
                for (s32 i=0; i<scene::SViewFrustum::VF_PLANE_COUNT; ++i)
 
1204
                {
 
1205
                        bool boxInFrustum=false;
 
1206
                        for (u32 j=0; j<8; ++j)
 
1207
                        {
 
1208
                                if (frust.planes[i].classifyPointRelation(edges[j]) != core::ISREL3D_FRONT)
 
1209
                                {
 
1210
                                        boxInFrustum=true;
 
1211
                                        break;
 
1212
                                }
 
1213
                        }
 
1214
 
 
1215
                        if (!boxInFrustum)
 
1216
                        {
 
1217
                                result = true;
 
1218
                                break;
 
1219
                        }
 
1220
                }
 
1221
        }
 
1222
 
 
1223
        _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
1224
        return result;
 
1225
}
 
1226
 
 
1227
 
 
1228
//! registers a node for rendering it at a specific time.
 
1229
u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass)
 
1230
{
 
1231
        u32 taken = 0;
 
1232
 
 
1233
        switch(pass)
 
1234
        {
 
1235
                // take camera if it is not already registered
 
1236
        case ESNRP_CAMERA:
 
1237
                {
 
1238
                        taken = 1;
 
1239
                        for (u32 i = 0; i != CameraList.size(); ++i)
 
1240
                        {
 
1241
                                if (CameraList[i] == node)
 
1242
                                {
 
1243
                                        taken = 0;
 
1244
                                        break;
 
1245
                                }
 
1246
                        }
 
1247
                        if (taken)
 
1248
                        {
 
1249
                                CameraList.push_back(node);
 
1250
                        }
 
1251
                }
 
1252
                break;
 
1253
 
 
1254
        case ESNRP_LIGHT:
 
1255
                // TODO: Point Light culling..
 
1256
                // Lighting model in irrlicht has to be redone..
 
1257
                //if (!isCulled(node))
 
1258
                {
 
1259
                        LightList.push_back(node);
 
1260
                        taken = 1;
 
1261
                }
 
1262
                break;
 
1263
 
 
1264
        case ESNRP_SKY_BOX:
 
1265
                SkyBoxList.push_back(node);
 
1266
                taken = 1;
 
1267
                break;
 
1268
        case ESNRP_SOLID:
 
1269
                if (!isCulled(node))
 
1270
                {
 
1271
                        SolidNodeList.push_back(node);
 
1272
                        taken = 1;
 
1273
                }
 
1274
                break;
 
1275
        case ESNRP_TRANSPARENT:
 
1276
                if (!isCulled(node))
 
1277
                {
 
1278
                        TransparentNodeList.push_back(TransparentNodeEntry(node, camWorldPos));
 
1279
                        taken = 1;
 
1280
                }
 
1281
                break;
 
1282
        case ESNRP_TRANSPARENT_EFFECT:
 
1283
                if (!isCulled(node))
 
1284
                {
 
1285
                        TransparentEffectNodeList.push_back(TransparentNodeEntry(node, camWorldPos));
 
1286
                        taken = 1;
 
1287
                }
 
1288
                break;
 
1289
        case ESNRP_AUTOMATIC:
 
1290
                if (!isCulled(node))
 
1291
                {
 
1292
                        const u32 count = node->getMaterialCount();
 
1293
 
 
1294
                        taken = 0;
 
1295
                        for (u32 i=0; i<count; ++i)
 
1296
                        {
 
1297
                                video::IMaterialRenderer* rnd =
 
1298
                                        Driver->getMaterialRenderer(node->getMaterial(i).MaterialType);
 
1299
                                if (rnd && rnd->isTransparent())
 
1300
                                {
 
1301
                                        // register as transparent node
 
1302
                                        TransparentNodeEntry e(node, camWorldPos);
 
1303
                                        TransparentNodeList.push_back(e);
 
1304
                                        taken = 1;
 
1305
                                        break;
 
1306
                                }
 
1307
                        }
 
1308
 
 
1309
                        // not transparent, register as solid
 
1310
                        if (!taken)
 
1311
                        {
 
1312
                                SolidNodeList.push_back(node);
 
1313
                                taken = 1;
 
1314
                        }
 
1315
                }
 
1316
                break;
 
1317
        case ESNRP_SHADOW:
 
1318
                if (!isCulled(node))
 
1319
                {
 
1320
                        ShadowNodeList.push_back(node);
 
1321
                        taken = 1;
 
1322
                }
 
1323
                break;
 
1324
 
 
1325
        case ESNRP_NONE: // ignore this one
 
1326
                break;
 
1327
        }
 
1328
 
 
1329
#ifdef SCENEMANAGER_DEBUG
 
1330
        s32 index = Parameters.findAttribute ( "calls" );
 
1331
        Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 );
 
1332
 
 
1333
        if (!taken)
 
1334
        {
 
1335
                index = Parameters.findAttribute ( "culled" );
 
1336
                Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 );
 
1337
        }
 
1338
#endif
 
1339
 
 
1340
        return taken;
 
1341
}
 
1342
 
 
1343
 
 
1344
//! This method is called just before the rendering process of the whole scene.
 
1345
//! draws all scene nodes
 
1346
void CSceneManager::drawAll()
 
1347
{
 
1348
        if (!Driver)
 
1349
                return;
 
1350
 
 
1351
        // reset attributes
 
1352
        Parameters.setAttribute ( "culled", 0 );
 
1353
        Parameters.setAttribute ( "calls", 0 );
 
1354
        Parameters.setAttribute ( "drawn_solid", 0 );
 
1355
        Parameters.setAttribute ( "drawn_transparent", 0 );
 
1356
        Parameters.setAttribute ( "drawn_transparent_effect", 0 );
 
1357
 
 
1358
        u32 i; // new ISO for scoping problem in some compilers
 
1359
 
 
1360
        // reset all transforms
 
1361
        video::IVideoDriver* driver = getVideoDriver();
 
1362
        if (driver)
 
1363
        {
 
1364
                driver->setMaterial(video::SMaterial());
 
1365
                driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix );
 
1366
                driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix );
 
1367
                driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix );
 
1368
                for (i=video::ETS_COUNT-1; i>=video::ETS_TEXTURE_0; --i)
 
1369
                        driver->setTransform ( (video::E_TRANSFORMATION_STATE)i, core::IdentityMatrix );
 
1370
        }
 
1371
 
 
1372
        driver->setAllowZWriteOnTransparent(Parameters.getAttributeAsBool( ALLOW_ZWRITE_ON_TRANSPARENT) );
 
1373
 
 
1374
        // do animations and other stuff.
 
1375
        OnAnimate(os::Timer::getTime());
 
1376
 
 
1377
        /*!
 
1378
                First Scene Node for prerendering should be the active camera
 
1379
                consistent Camera is needed for culling
 
1380
        */
 
1381
        camWorldPos.set(0,0,0);
 
1382
        if (ActiveCamera)
 
1383
        {
 
1384
                ActiveCamera->render();
 
1385
                camWorldPos = ActiveCamera->getAbsolutePosition();
 
1386
        }
 
1387
 
 
1388
        // let all nodes register themselves
 
1389
        OnRegisterSceneNode();
 
1390
 
 
1391
        if (LightManager)
 
1392
                LightManager->OnPreRender(LightList);
 
1393
 
 
1394
        //render camera scenes
 
1395
        {
 
1396
                CurrentRendertime = ESNRP_CAMERA;
 
1397
                Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
 
1398
 
 
1399
                if (LightManager)
 
1400
                        LightManager->OnRenderPassPreRender(CurrentRendertime);
 
1401
 
 
1402
                for (i=0; i<CameraList.size(); ++i)
 
1403
                        CameraList[i]->render();
 
1404
 
 
1405
                CameraList.set_used(0);
 
1406
 
 
1407
                if (LightManager)
 
1408
                        LightManager->OnRenderPassPostRender(CurrentRendertime);
 
1409
        }
 
1410
 
 
1411
        //render lights scenes
 
1412
        {
 
1413
                CurrentRendertime = ESNRP_LIGHT;
 
1414
                Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
 
1415
 
 
1416
                if (LightManager)
 
1417
                {
 
1418
                        LightManager->OnRenderPassPreRender(CurrentRendertime);
 
1419
                }
 
1420
                else
 
1421
                {
 
1422
                        // Sort the lights by distance from the camera
 
1423
                        core::vector3df camWorldPos(0, 0, 0);
 
1424
                        if (ActiveCamera)
 
1425
                                camWorldPos = ActiveCamera->getAbsolutePosition();
 
1426
 
 
1427
                        core::array<DistanceNodeEntry> SortedLights;
 
1428
                        SortedLights.set_used(LightList.size());
 
1429
                        for (s32 light = (s32)LightList.size() - 1; light >= 0; --light)
 
1430
                                SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos);
 
1431
 
 
1432
                        SortedLights.set_sorted(false);
 
1433
                        SortedLights.sort();
 
1434
 
 
1435
                        for(s32 light = (s32)LightList.size() - 1; light >= 0; --light)
 
1436
                                LightList[light] = SortedLights[light].Node;
 
1437
                }
 
1438
 
 
1439
                Driver->deleteAllDynamicLights();
 
1440
 
 
1441
                Driver->setAmbientLight(AmbientLight);
 
1442
 
 
1443
                u32 maxLights = LightList.size();
 
1444
 
 
1445
                if (!LightManager)
 
1446
                        maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights);
 
1447
 
 
1448
                for (i=0; i< maxLights; ++i)
 
1449
                        LightList[i]->render();
 
1450
 
 
1451
                if (LightManager)
 
1452
                        LightManager->OnRenderPassPostRender(CurrentRendertime);
 
1453
        }
 
1454
 
 
1455
        // render skyboxes
 
1456
        {
 
1457
                CurrentRendertime = ESNRP_SKY_BOX;
 
1458
                Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
 
1459
 
 
1460
                if (LightManager)
 
1461
                {
 
1462
                        LightManager->OnRenderPassPreRender(CurrentRendertime);
 
1463
                        for (i=0; i<SkyBoxList.size(); ++i)
 
1464
                        {
 
1465
                                ISceneNode* node = SkyBoxList[i];
 
1466
                                LightManager->OnNodePreRender(node);
 
1467
                                node->render();
 
1468
                                LightManager->OnNodePostRender(node);
 
1469
                        }
 
1470
                }
 
1471
                else
 
1472
                {
 
1473
                        for (i=0; i<SkyBoxList.size(); ++i)
 
1474
                                SkyBoxList[i]->render();
 
1475
                }
 
1476
 
 
1477
                SkyBoxList.set_used(0);
 
1478
 
 
1479
                if (LightManager)
 
1480
                        LightManager->OnRenderPassPostRender(CurrentRendertime);
 
1481
        }
 
1482
 
 
1483
 
 
1484
        // render default objects
 
1485
        {
 
1486
                CurrentRendertime = ESNRP_SOLID;
 
1487
                Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
 
1488
 
 
1489
                SolidNodeList.sort(); // sort by textures
 
1490
 
 
1491
                if (LightManager)
 
1492
                {
 
1493
                        LightManager->OnRenderPassPreRender(CurrentRendertime);
 
1494
                        for (i=0; i<SolidNodeList.size(); ++i)
 
1495
                        {
 
1496
                                ISceneNode* node = SolidNodeList[i].Node;
 
1497
                                LightManager->OnNodePreRender(node);
 
1498
                                node->render();
 
1499
                                LightManager->OnNodePostRender(node);
 
1500
                        }
 
1501
                }
 
1502
                else
 
1503
                {
 
1504
                        for (i=0; i<SolidNodeList.size(); ++i)
 
1505
                                SolidNodeList[i].Node->render();
 
1506
                }
 
1507
 
 
1508
                Parameters.setAttribute("drawn_solid", (s32) SolidNodeList.size() );
 
1509
                SolidNodeList.set_used(0);
 
1510
 
 
1511
                if (LightManager)
 
1512
                        LightManager->OnRenderPassPostRender(CurrentRendertime);
 
1513
        }
 
1514
 
 
1515
        // render shadows
 
1516
        {
 
1517
                CurrentRendertime = ESNRP_SHADOW;
 
1518
                Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
 
1519
 
 
1520
                if (LightManager)
 
1521
                {
 
1522
                        LightManager->OnRenderPassPreRender(CurrentRendertime);
 
1523
                        for (i=0; i<ShadowNodeList.size(); ++i)
 
1524
                        {
 
1525
                                ISceneNode* node = ShadowNodeList[i];
 
1526
                                LightManager->OnNodePreRender(node);
 
1527
                                node->render();
 
1528
                                LightManager->OnNodePostRender(node);
 
1529
                        }
 
1530
                }
 
1531
                else
 
1532
                {
 
1533
                        for (i=0; i<ShadowNodeList.size(); ++i)
 
1534
                                ShadowNodeList[i]->render();
 
1535
                }
 
1536
 
 
1537
                if (!ShadowNodeList.empty())
 
1538
                        Driver->drawStencilShadow(true,ShadowColor, ShadowColor,
 
1539
                                ShadowColor, ShadowColor);
 
1540
 
 
1541
                ShadowNodeList.set_used(0);
 
1542
 
 
1543
                if (LightManager)
 
1544
                        LightManager->OnRenderPassPostRender(CurrentRendertime);
 
1545
        }
 
1546
 
 
1547
        // render transparent objects.
 
1548
        {
 
1549
                CurrentRendertime = ESNRP_TRANSPARENT;
 
1550
                Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
 
1551
 
 
1552
                TransparentNodeList.sort(); // sort by distance from camera
 
1553
                if (LightManager)
 
1554
                {
 
1555
                        LightManager->OnRenderPassPreRender(CurrentRendertime);
 
1556
 
 
1557
                        for (i=0; i<TransparentNodeList.size(); ++i)
 
1558
                        {
 
1559
                                ISceneNode* node = TransparentNodeList[i].Node;
 
1560
                                LightManager->OnNodePreRender(node);
 
1561
                                node->render();
 
1562
                                LightManager->OnNodePostRender(node);
 
1563
                        }
 
1564
                }
 
1565
                else
 
1566
                {
 
1567
                        for (i=0; i<TransparentNodeList.size(); ++i)
 
1568
                                TransparentNodeList[i].Node->render();
 
1569
                }
 
1570
 
 
1571
                Parameters.setAttribute ( "drawn_transparent", (s32) TransparentNodeList.size() );
 
1572
                TransparentNodeList.set_used(0);
 
1573
 
 
1574
                if (LightManager)
 
1575
                        LightManager->OnRenderPassPostRender(CurrentRendertime);
 
1576
        }
 
1577
 
 
1578
        // render transparent effect objects.
 
1579
        {
 
1580
                CurrentRendertime = ESNRP_TRANSPARENT_EFFECT;
 
1581
                Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
 
1582
 
 
1583
                TransparentEffectNodeList.sort(); // sort by distance from camera
 
1584
 
 
1585
                if (LightManager)
 
1586
                {
 
1587
                        LightManager->OnRenderPassPreRender(CurrentRendertime);
 
1588
 
 
1589
                        for (i=0; i<TransparentEffectNodeList.size(); ++i)
 
1590
                        {
 
1591
                                ISceneNode* node = TransparentEffectNodeList[i].Node;
 
1592
                                LightManager->OnNodePreRender(node);
 
1593
                                node->render();
 
1594
                                LightManager->OnNodePostRender(node);
 
1595
                        }
 
1596
                }
 
1597
                else
 
1598
                {
 
1599
                        for (i=0; i<TransparentEffectNodeList.size(); ++i)
 
1600
                                TransparentEffectNodeList[i].Node->render();
 
1601
                }
 
1602
 
 
1603
                Parameters.setAttribute ( "drawn_transparent_effect", (s32) TransparentEffectNodeList.size() );
 
1604
                TransparentEffectNodeList.set_used(0);
 
1605
        }
 
1606
 
 
1607
        if (LightManager)
 
1608
                LightManager->OnPostRender();
 
1609
 
 
1610
        LightList.set_used(0);
 
1611
        clearDeletionList();
 
1612
 
 
1613
        CurrentRendertime = ESNRP_NONE;
 
1614
}
 
1615
 
 
1616
void CSceneManager::setLightManager(ILightManager* lightManager)
 
1617
{
 
1618
    if (lightManager)
 
1619
        lightManager->grab();
 
1620
        if (LightManager)
 
1621
                LightManager->drop();
 
1622
 
 
1623
        LightManager = lightManager;
 
1624
}
 
1625
 
 
1626
 
 
1627
//! Sets the color of stencil buffers shadows drawn by the scene manager.
 
1628
void CSceneManager::setShadowColor(video::SColor color)
 
1629
{
 
1630
        ShadowColor = color;
 
1631
}
 
1632
 
 
1633
 
 
1634
//! Returns the current color of shadows.
 
1635
video::SColor CSceneManager::getShadowColor() const
 
1636
{
 
1637
        return ShadowColor;
 
1638
}
 
1639
 
 
1640
 
 
1641
//! creates a rotation animator, which rotates the attached scene node around itself.
 
1642
ISceneNodeAnimator* CSceneManager::createRotationAnimator(const core::vector3df& rotationPerSecond)
 
1643
{
 
1644
        ISceneNodeAnimator* anim = new CSceneNodeAnimatorRotation(os::Timer::getTime(),
 
1645
                rotationPerSecond);
 
1646
 
 
1647
        return anim;
 
1648
}
 
1649
 
 
1650
 
 
1651
//! creates a fly circle animator, which lets the attached scene node fly around a center.
 
1652
ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator(
 
1653
                const core::vector3df& center, f32 radius, f32 speed,
 
1654
                const core::vector3df& direction,
 
1655
                f32 startPosition,
 
1656
                f32 radiusEllipsoid)
 
1657
{
 
1658
        const f32 orbitDurationMs = (core::DEGTORAD * 360.f) / speed;
 
1659
        const u32 effectiveTime = os::Timer::getTime() + (u32)(orbitDurationMs * startPosition);
 
1660
 
 
1661
        ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyCircle(
 
1662
                        effectiveTime, center,
 
1663
                        radius, speed, direction,radiusEllipsoid);
 
1664
        return anim;
 
1665
}
 
1666
 
 
1667
 
 
1668
//! Creates a fly straight animator, which lets the attached scene node
 
1669
//! fly or move along a line between two points.
 
1670
ISceneNodeAnimator* CSceneManager::createFlyStraightAnimator(const core::vector3df& startPoint,
 
1671
                                        const core::vector3df& endPoint, u32 timeForWay, bool loop,bool pingpong)
 
1672
{
 
1673
        ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyStraight(startPoint,
 
1674
                endPoint, timeForWay, loop, os::Timer::getTime(), pingpong);
 
1675
 
 
1676
        return anim;
 
1677
}
 
1678
 
 
1679
 
 
1680
//! Creates a texture animator, which switches the textures of the target scene
 
1681
//! node based on a list of textures.
 
1682
ISceneNodeAnimator* CSceneManager::createTextureAnimator(const core::array<video::ITexture*>& textures,
 
1683
        s32 timePerFrame, bool loop)
 
1684
{
 
1685
        ISceneNodeAnimator* anim = new CSceneNodeAnimatorTexture(textures,
 
1686
                timePerFrame, loop, os::Timer::getTime());
 
1687
 
 
1688
        return anim;
 
1689
}
 
1690
 
 
1691
 
 
1692
//! Creates a scene node animator, which deletes the scene node after
 
1693
//! some time automaticly.
 
1694
ISceneNodeAnimator* CSceneManager::createDeleteAnimator(u32 when)
 
1695
{
 
1696
        return new CSceneNodeAnimatorDelete(this, os::Timer::getTime() + when);
 
1697
}
 
1698
 
 
1699
 
 
1700
//! Creates a special scene node animator for doing automatic collision detection
 
1701
//! and response.
 
1702
ISceneNodeAnimatorCollisionResponse* CSceneManager::createCollisionResponseAnimator(
 
1703
        ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius,
 
1704
        const core::vector3df& gravityPerSecond,
 
1705
        const core::vector3df& ellipsoidTranslation, f32 slidingValue)
 
1706
{
 
1707
        ISceneNodeAnimatorCollisionResponse* anim = new
 
1708
                CSceneNodeAnimatorCollisionResponse(this, world, sceneNode,
 
1709
                        ellipsoidRadius, gravityPerSecond,
 
1710
                        ellipsoidTranslation, slidingValue);
 
1711
 
 
1712
        return anim;
 
1713
}
 
1714
 
 
1715
 
 
1716
//! Creates a follow spline animator.
 
1717
ISceneNodeAnimator* CSceneManager::createFollowSplineAnimator(s32 startTime,
 
1718
        const core::array< core::vector3df >& points,
 
1719
        f32 speed, f32 tightness, bool loop, bool pingpong)
 
1720
{
 
1721
        ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points,
 
1722
                speed, tightness, loop, pingpong);
 
1723
        return a;
 
1724
}
 
1725
 
 
1726
 
 
1727
//! Adds an external mesh loader.
 
1728
void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader)
 
1729
{
 
1730
        if (!externalLoader)
 
1731
                return;
 
1732
 
 
1733
        externalLoader->grab();
 
1734
        MeshLoaderList.push_back(externalLoader);
 
1735
}
 
1736
 
 
1737
 
 
1738
//! Returns the number of mesh loaders supported by Irrlicht at this time
 
1739
u32 CSceneManager::getMeshLoaderCount() const
 
1740
{
 
1741
        return MeshLoaderList.size();
 
1742
}
 
1743
 
 
1744
 
 
1745
//! Retrieve the given mesh loader
 
1746
IMeshLoader* CSceneManager::getMeshLoader(u32 index) const
 
1747
{
 
1748
        if (index < MeshLoaderList.size())
 
1749
                return MeshLoaderList[index];
 
1750
        else
 
1751
                return 0;
 
1752
}
 
1753
 
 
1754
 
 
1755
//! Adds an external scene loader.
 
1756
void CSceneManager::addExternalSceneLoader(ISceneLoader* externalLoader)
 
1757
{
 
1758
        if (!externalLoader)
 
1759
                return;
 
1760
 
 
1761
        externalLoader->grab();
 
1762
        SceneLoaderList.push_back(externalLoader);
 
1763
}
 
1764
 
 
1765
 
 
1766
//! Returns the number of scene loaders
 
1767
u32 CSceneManager::getSceneLoaderCount() const
 
1768
{
 
1769
        return SceneLoaderList.size();
 
1770
}
 
1771
 
 
1772
 
 
1773
//! Retrieve the given scene loader
 
1774
ISceneLoader* CSceneManager::getSceneLoader(u32 index) const
 
1775
{
 
1776
        if (index < SceneLoaderList.size())
 
1777
                return SceneLoaderList[index];
 
1778
        else
 
1779
                return 0;
 
1780
}
 
1781
 
 
1782
 
 
1783
//! Returns a pointer to the scene collision manager.
 
1784
ISceneCollisionManager* CSceneManager::getSceneCollisionManager()
 
1785
{
 
1786
        return CollisionManager;
 
1787
}
 
1788
 
 
1789
 
 
1790
//! Returns a pointer to the mesh manipulator.
 
1791
IMeshManipulator* CSceneManager::getMeshManipulator()
 
1792
{
 
1793
        return Driver->getMeshManipulator();
 
1794
}
 
1795
 
 
1796
 
 
1797
//! Creates a simple ITriangleSelector, based on a mesh.
 
1798
ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node)
 
1799
{
 
1800
        if (!mesh)
 
1801
                return 0;
 
1802
 
 
1803
        return new CTriangleSelector(mesh, node);
 
1804
}
 
1805
 
 
1806
 
 
1807
//! Creates a simple and updatable ITriangleSelector, based on a the mesh owned by an
 
1808
//! animated scene node
 
1809
ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node)
 
1810
{
 
1811
        if (!node || !node->getMesh())
 
1812
                return 0;
 
1813
 
 
1814
        return new CTriangleSelector(node);
 
1815
}
 
1816
 
 
1817
 
 
1818
//! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box.
 
1819
ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNode* node)
 
1820
{
 
1821
        if (!node)
 
1822
                return 0;
 
1823
 
 
1824
        return new CTriangleBBSelector(node);
 
1825
}
 
1826
 
 
1827
 
 
1828
//! Creates a simple ITriangleSelector, based on a mesh.
 
1829
ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh,
 
1830
                                                        ISceneNode* node, s32 minimalPolysPerNode)
 
1831
{
 
1832
        if (!mesh)
 
1833
                return 0;
 
1834
 
 
1835
        return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode);
 
1836
}
 
1837
 
 
1838
 
 
1839
//! Creates a meta triangle selector.
 
1840
IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector()
 
1841
{
 
1842
        return new CMetaTriangleSelector();
 
1843
}
 
1844
 
 
1845
 
 
1846
//! Creates a triangle selector which can select triangles from a terrain scene node
 
1847
ITriangleSelector* CSceneManager::createTerrainTriangleSelector(
 
1848
        ITerrainSceneNode* node, s32 LOD)
 
1849
{
 
1850
        return new CTerrainTriangleSelector(node, LOD);
 
1851
}
 
1852
 
 
1853
 
 
1854
 
 
1855
//! Adds a scene node to the deletion queue.
 
1856
void CSceneManager::addToDeletionQueue(ISceneNode* node)
 
1857
{
 
1858
        if (!node)
 
1859
                return;
 
1860
 
 
1861
        node->grab();
 
1862
        DeletionList.push_back(node);
 
1863
}
 
1864
 
 
1865
 
 
1866
//! clears the deletion list
 
1867
void CSceneManager::clearDeletionList()
 
1868
{
 
1869
        if (DeletionList.empty())
 
1870
                return;
 
1871
 
 
1872
        for (u32 i=0; i<DeletionList.size(); ++i)
 
1873
        {
 
1874
                DeletionList[i]->remove();
 
1875
                DeletionList[i]->drop();
 
1876
        }
 
1877
 
 
1878
        DeletionList.clear();
 
1879
}
 
1880
 
 
1881
 
 
1882
//! Returns the first scene node with the specified name.
 
1883
ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* start)
 
1884
{
 
1885
        if (start == 0)
 
1886
                start = getRootSceneNode();
 
1887
 
 
1888
        if (!strcmp(start->getName(),name))
 
1889
                return start;
 
1890
 
 
1891
        ISceneNode* node = 0;
 
1892
 
 
1893
        const ISceneNodeList& list = start->getChildren();
 
1894
        ISceneNodeList::ConstIterator it = list.begin();
 
1895
        for (; it!=list.end(); ++it)
 
1896
        {
 
1897
                node = getSceneNodeFromName(name, *it);
 
1898
                if (node)
 
1899
                        return node;
 
1900
        }
 
1901
 
 
1902
        return 0;
 
1903
}
 
1904
 
 
1905
 
 
1906
//! Returns the first scene node with the specified id.
 
1907
ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start)
 
1908
{
 
1909
        if (start == 0)
 
1910
                start = getRootSceneNode();
 
1911
 
 
1912
        if (start->getID() == id)
 
1913
                return start;
 
1914
 
 
1915
        ISceneNode* node = 0;
 
1916
 
 
1917
        const ISceneNodeList& list = start->getChildren();
 
1918
        ISceneNodeList::ConstIterator it = list.begin();
 
1919
        for (; it!=list.end(); ++it)
 
1920
        {
 
1921
                node = getSceneNodeFromId(id, *it);
 
1922
                if (node)
 
1923
                        return node;
 
1924
        }
 
1925
 
 
1926
        return 0;
 
1927
}
 
1928
 
 
1929
 
 
1930
//! Returns the first scene node with the specified type.
 
1931
ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start)
 
1932
{
 
1933
        if (start == 0)
 
1934
                start = getRootSceneNode();
 
1935
 
 
1936
        if (start->getType() == type || ESNT_ANY == type)
 
1937
                return start;
 
1938
 
 
1939
        ISceneNode* node = 0;
 
1940
 
 
1941
        const ISceneNodeList& list = start->getChildren();
 
1942
        ISceneNodeList::ConstIterator it = list.begin();
 
1943
        for (; it!=list.end(); ++it)
 
1944
        {
 
1945
                node = getSceneNodeFromType(type, *it);
 
1946
                if (node)
 
1947
                        return node;
 
1948
        }
 
1949
 
 
1950
        return 0;
 
1951
}
 
1952
 
 
1953
 
 
1954
//! returns scene nodes by type.
 
1955
void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array<scene::ISceneNode*>& outNodes, ISceneNode* start)
 
1956
{
 
1957
        if (start == 0)
 
1958
                start = getRootSceneNode();
 
1959
 
 
1960
        if (start->getType() == type || ESNT_ANY == type)
 
1961
                outNodes.push_back(start);
 
1962
 
 
1963
        const ISceneNodeList& list = start->getChildren();
 
1964
        ISceneNodeList::ConstIterator it = list.begin();
 
1965
 
 
1966
        for (; it!=list.end(); ++it)
 
1967
        {
 
1968
                getSceneNodesFromType(type, outNodes, *it);
 
1969
        }
 
1970
}
 
1971
 
 
1972
 
 
1973
//! Posts an input event to the environment. Usually you do not have to
 
1974
//! use this method, it is used by the internal engine.
 
1975
bool CSceneManager::postEventFromUser(const SEvent& event)
 
1976
{
 
1977
        bool ret = false;
 
1978
        ICameraSceneNode* cam = getActiveCamera();
 
1979
        if (cam)
 
1980
                ret = cam->OnEvent(event);
 
1981
 
 
1982
        _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
1983
        return ret;
 
1984
}
 
1985
 
 
1986
 
 
1987
//! Removes all children of this scene node
 
1988
void CSceneManager::removeAll()
 
1989
{
 
1990
        ISceneNode::removeAll();
 
1991
        setActiveCamera(0);
 
1992
        // Make sure the driver is reset, might need a more complex method at some point
 
1993
        if (Driver)
 
1994
                Driver->setMaterial(video::SMaterial());
 
1995
}
 
1996
 
 
1997
 
 
1998
//! Clears the whole scene. All scene nodes are removed.
 
1999
void CSceneManager::clear()
 
2000
{
 
2001
        removeAll();
 
2002
}
 
2003
 
 
2004
 
 
2005
//! Returns interface to the parameters set in this scene.
 
2006
io::IAttributes* CSceneManager::getParameters()
 
2007
{
 
2008
        return &Parameters;
 
2009
}
 
2010
 
 
2011
 
 
2012
//! Returns current render pass.
 
2013
E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const
 
2014
{
 
2015
        return CurrentRendertime;
 
2016
}
 
2017
 
 
2018
 
 
2019
//! Returns an interface to the mesh cache which is shared beween all existing scene managers.
 
2020
IMeshCache* CSceneManager::getMeshCache()
 
2021
{
 
2022
        return MeshCache;
 
2023
}
 
2024
 
 
2025
 
 
2026
//! Creates a new scene manager.
 
2027
ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent)
 
2028
{
 
2029
        CSceneManager* manager = new CSceneManager(Driver, FileSystem, CursorControl, MeshCache, GUIEnvironment);
 
2030
 
 
2031
        if (cloneContent)
 
2032
                manager->cloneMembers(this, manager);
 
2033
 
 
2034
        return manager;
 
2035
}
 
2036
 
 
2037
 
 
2038
//! Returns the default scene node factory which can create all built in scene nodes
 
2039
ISceneNodeFactory* CSceneManager::getDefaultSceneNodeFactory()
 
2040
{
 
2041
        return getSceneNodeFactory(0);
 
2042
}
 
2043
 
 
2044
 
 
2045
//! Adds a scene node factory to the scene manager.
 
2046
void CSceneManager::registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd)
 
2047
{
 
2048
        if (factoryToAdd)
 
2049
        {
 
2050
                factoryToAdd->grab();
 
2051
                SceneNodeFactoryList.push_back(factoryToAdd);
 
2052
        }
 
2053
}
 
2054
 
 
2055
 
 
2056
//! Returns amount of registered scene node factories.
 
2057
u32 CSceneManager::getRegisteredSceneNodeFactoryCount() const
 
2058
{
 
2059
        return SceneNodeFactoryList.size();
 
2060
}
 
2061
 
 
2062
 
 
2063
//! Returns a scene node factory by index
 
2064
ISceneNodeFactory* CSceneManager::getSceneNodeFactory(u32 index)
 
2065
{
 
2066
        if (index < SceneNodeFactoryList.size())
 
2067
                return SceneNodeFactoryList[index];
 
2068
 
 
2069
        return 0;
 
2070
}
 
2071
 
 
2072
 
 
2073
//! Returns the default scene node animator factory which can create all built-in scene node animators
 
2074
ISceneNodeAnimatorFactory* CSceneManager::getDefaultSceneNodeAnimatorFactory()
 
2075
{
 
2076
        return getSceneNodeAnimatorFactory(0);
 
2077
}
 
2078
 
 
2079
//! Adds a scene node animator factory to the scene manager.
 
2080
void CSceneManager::registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd)
 
2081
{
 
2082
        if (factoryToAdd)
 
2083
        {
 
2084
                factoryToAdd->grab();
 
2085
                SceneNodeAnimatorFactoryList.push_back(factoryToAdd);
 
2086
        }
 
2087
}
 
2088
 
 
2089
 
 
2090
//! Returns amount of registered scene node animator factories.
 
2091
u32 CSceneManager::getRegisteredSceneNodeAnimatorFactoryCount() const
 
2092
{
 
2093
        return SceneNodeAnimatorFactoryList.size();
 
2094
}
 
2095
 
 
2096
 
 
2097
//! Returns a scene node animator factory by index
 
2098
ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index)
 
2099
{
 
2100
        if (index < SceneNodeAnimatorFactoryList.size())
 
2101
                return SceneNodeAnimatorFactoryList[index];
 
2102
 
 
2103
        return 0;
 
2104
}
 
2105
 
 
2106
 
 
2107
//! Saves the current scene into a file.
 
2108
//! \param filename: Name of the file .
 
2109
bool CSceneManager::saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
 
2110
{
 
2111
        bool ret = false;
 
2112
        io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
 
2113
        if (file)
 
2114
        {
 
2115
                ret = saveScene(file, userDataSerializer, node);
 
2116
                file->drop();
 
2117
        }
 
2118
        _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
2119
        return ret;
 
2120
}
 
2121
 
 
2122
 
 
2123
//! Saves the current scene into a file.
 
2124
bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
 
2125
{
 
2126
        if (!file)
 
2127
        {
 
2128
                _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
2129
                return false;
 
2130
        }
 
2131
 
 
2132
        io::IXMLWriter* writer = FileSystem->createXMLWriter(file);
 
2133
        if (!writer)
 
2134
        {
 
2135
                _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
2136
                return false;
 
2137
        }
 
2138
        if (!node)
 
2139
                node=this;
 
2140
 
 
2141
        writer->writeXMLHeader();
 
2142
        writeSceneNode(writer, node, userDataSerializer, FileSystem->getFileDir(FileSystem->getAbsolutePath(file->getFileName())).c_str(), true);
 
2143
        writer->drop();
 
2144
 
 
2145
        return true;
 
2146
}
 
2147
 
 
2148
 
 
2149
//! Loads a scene.
 
2150
bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode)
 
2151
{
 
2152
        bool ret = false;
 
2153
 
 
2154
        io::IReadFile* file = FileSystem->createAndOpenFile(filename);
 
2155
 
 
2156
        if (!file)
 
2157
        {
 
2158
                os::Printer::log("Unable to open scene file", filename.c_str(), ELL_ERROR);
 
2159
                _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
2160
                return false;
 
2161
        }
 
2162
 
 
2163
        // try scene loaders in reverse order
 
2164
        s32 i = SceneLoaderList.size()-1;
 
2165
        for (; i >= 0 && !ret; --i)
 
2166
                if (SceneLoaderList[i]->isALoadableFileExtension(filename))
 
2167
                        ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode);
 
2168
 
 
2169
        if (!ret)
 
2170
                os::Printer::log("Could not load scene file, perhaps the format is unsupported: ", filename.c_str(), ELL_ERROR);
 
2171
 
 
2172
 
 
2173
        _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
2174
        return ret;
 
2175
}
 
2176
 
 
2177
 
 
2178
//! Loads a scene. Note that the current scene is not cleared before.
 
2179
bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode)
 
2180
{
 
2181
        if (!file)
 
2182
        {
 
2183
                os::Printer::log("Unable to open scene file", ELL_ERROR);
 
2184
                _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
2185
                return false;
 
2186
        }
 
2187
 
 
2188
        bool ret = false;
 
2189
 
 
2190
        // try scene loaders in reverse order
 
2191
        s32 i = SceneLoaderList.size()-1;
 
2192
        for (; i >= 0 && !ret; --i)
 
2193
                if (SceneLoaderList[i]->isALoadableFileFormat(file))
 
2194
                        ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode);
 
2195
 
 
2196
        if (!ret)
 
2197
                os::Printer::log("Could not load scene file, perhaps the format is unsupported: ", file->getFileName().c_str(), ELL_ERROR);
 
2198
 
 
2199
        _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
2200
        return ret;
 
2201
}
 
2202
 
 
2203
//! writes a scene node
 
2204
void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer,
 
2205
                const fschar_t* currentPath, bool init)
 
2206
{
 
2207
        if (!writer || !node || node->isDebugObject())
 
2208
                return;
 
2209
 
 
2210
        const wchar_t* name;
 
2211
        ISceneNode* tmpNode=node;
 
2212
 
 
2213
        if (init)
 
2214
        {
 
2215
                name = IRR_XML_FORMAT_SCENE.c_str();
 
2216
                writer->writeElement(name, false);
 
2217
                node=this;
 
2218
        }
 
2219
        else
 
2220
        {
 
2221
                name = IRR_XML_FORMAT_NODE.c_str();
 
2222
                writer->writeElement(name, false, IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str(),
 
2223
                        core::stringw(getSceneNodeTypeName(node->getType())).c_str());
 
2224
        }
 
2225
 
 
2226
        writer->writeLineBreak();
 
2227
 
 
2228
        // write properties
 
2229
 
 
2230
        io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver);
 
2231
        io::SAttributeReadWriteOptions options;
 
2232
        if (currentPath)
 
2233
        {
 
2234
                options.Filename=currentPath;
 
2235
                options.Flags|=io::EARWF_USE_RELATIVE_PATHS;
 
2236
        }
 
2237
        node->serializeAttributes(attr, &options);
 
2238
 
 
2239
        if (attr->getAttributeCount() != 0)
 
2240
        {
 
2241
                attr->write(writer);
 
2242
                writer->writeLineBreak();
 
2243
        }
 
2244
 
 
2245
        // write materials
 
2246
 
 
2247
        if (node->getMaterialCount() && getVideoDriver())
 
2248
        {
 
2249
                const wchar_t* materialElement = L"materials";
 
2250
 
 
2251
                writer->writeElement(materialElement);
 
2252
                writer->writeLineBreak();
 
2253
 
 
2254
                for (u32 i=0; i < node->getMaterialCount(); ++i)
 
2255
                {
 
2256
                        io::IAttributes* tmp_attr =
 
2257
                                getVideoDriver()->createAttributesFromMaterial(node->getMaterial(i), &options);
 
2258
                        tmp_attr->write(writer);
 
2259
                        tmp_attr->drop();
 
2260
                }
 
2261
 
 
2262
                writer->writeClosingTag(materialElement);
 
2263
                writer->writeLineBreak();
 
2264
        }
 
2265
 
 
2266
        // write animators
 
2267
 
 
2268
        if (!node->getAnimators().empty())
 
2269
        {
 
2270
                const wchar_t* animatorElement = L"animators";
 
2271
                writer->writeElement(animatorElement);
 
2272
                writer->writeLineBreak();
 
2273
 
 
2274
                ISceneNodeAnimatorList::ConstIterator it = node->getAnimators().begin();
 
2275
                for (; it != node->getAnimators().end(); ++it)
 
2276
                {
 
2277
                        attr->clear();
 
2278
                        attr->addString("Type", getAnimatorTypeName((*it)->getType()));
 
2279
 
 
2280
                        (*it)->serializeAttributes(attr);
 
2281
 
 
2282
                        attr->write(writer);
 
2283
                }
 
2284
 
 
2285
                writer->writeClosingTag(animatorElement);
 
2286
                writer->writeLineBreak();
 
2287
        }
 
2288
 
 
2289
        // write possible user data
 
2290
 
 
2291
        if (userDataSerializer)
 
2292
        {
 
2293
                io::IAttributes* userData = userDataSerializer->createUserData(node);
 
2294
                if (userData)
 
2295
                {
 
2296
                        const wchar_t* userDataElement = L"userData";
 
2297
 
 
2298
                        writer->writeLineBreak();
 
2299
                        writer->writeElement(userDataElement);
 
2300
                        writer->writeLineBreak();
 
2301
 
 
2302
                        userData->write(writer);
 
2303
 
 
2304
                        writer->writeClosingTag(userDataElement);
 
2305
                        writer->writeLineBreak();
 
2306
                        writer->writeLineBreak();
 
2307
 
 
2308
                        userData->drop();
 
2309
                }
 
2310
        }
 
2311
        // reset to actual root node
 
2312
        if (init)
 
2313
                node=tmpNode;
 
2314
 
 
2315
        // write children once root node is written
 
2316
        // if parent is not scene manager, we need to write out node first
 
2317
        if (init && (node != this))
 
2318
        {
 
2319
                writeSceneNode(writer, node, userDataSerializer, currentPath);
 
2320
        }
 
2321
        else
 
2322
        {
 
2323
                ISceneNodeList::ConstIterator it = node->getChildren().begin();
 
2324
                for (; it != node->getChildren().end(); ++it)
 
2325
                        writeSceneNode(writer, (*it), userDataSerializer, currentPath);
 
2326
        }
 
2327
 
 
2328
        attr->drop();
 
2329
 
 
2330
        writer->writeClosingTag(name);
 
2331
        writer->writeLineBreak();
 
2332
        writer->writeLineBreak();
 
2333
}
 
2334
 
 
2335
 
 
2336
//! Returns a typename from a scene node type or null if not found
 
2337
const c8* CSceneManager::getSceneNodeTypeName(ESCENE_NODE_TYPE type)
 
2338
{
 
2339
        const char* name = 0;
 
2340
 
 
2341
        for (s32 i=(s32)SceneNodeFactoryList.size()-1; !name && i>=0; --i)
 
2342
                name = SceneNodeFactoryList[i]->getCreateableSceneNodeTypeName(type);
 
2343
 
 
2344
        return name;
 
2345
}
 
2346
 
 
2347
//! Adds a scene node to the scene by name
 
2348
ISceneNode* CSceneManager::addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent)
 
2349
{
 
2350
        ISceneNode* node = 0;
 
2351
 
 
2352
        for (s32 i=(s32)SceneNodeFactoryList.size()-1; i>=0 && !node; --i)
 
2353
                        node = SceneNodeFactoryList[i]->addSceneNode(sceneNodeTypeName, parent);
 
2354
 
 
2355
        return node;
 
2356
}
 
2357
 
 
2358
ISceneNodeAnimator* CSceneManager::createSceneNodeAnimator(const char* typeName, ISceneNode* target)
 
2359
{
 
2360
        ISceneNodeAnimator *animator = 0;
 
2361
 
 
2362
        for (s32 i=(s32)SceneNodeAnimatorFactoryList.size()-1; i>=0 && !animator; --i)
 
2363
                animator = SceneNodeAnimatorFactoryList[i]->createSceneNodeAnimator(typeName, target);
 
2364
 
 
2365
        return animator;
 
2366
}
 
2367
 
 
2368
 
 
2369
//! Returns a typename from a scene node animator type or null if not found
 
2370
const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type)
 
2371
{
 
2372
        const char* name = 0;
 
2373
 
 
2374
        for (s32 i=SceneNodeAnimatorFactoryList.size()-1; !name && i >= 0; --i)
 
2375
                name = SceneNodeAnimatorFactoryList[i]->getCreateableSceneNodeAnimatorTypeName(type);
 
2376
 
 
2377
        return name;
 
2378
}
 
2379
 
 
2380
 
 
2381
//! Writes attributes of the scene node.
 
2382
void CSceneManager::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
 
2383
{
 
2384
        out->addString  ("Name", Name.c_str());
 
2385
        out->addInt     ("Id", ID );
 
2386
        out->addColorf  ("AmbientLight", AmbientLight);
 
2387
 
 
2388
        // fog attributes from video driver
 
2389
        video::SColor color;
 
2390
        video::E_FOG_TYPE fogType;
 
2391
        f32 start, end, density;
 
2392
        bool pixelFog, rangeFog;
 
2393
 
 
2394
        Driver->getFog(color, fogType, start, end, density, pixelFog, rangeFog);
 
2395
 
 
2396
        out->addEnum("FogType", fogType, video::FogTypeNames);
 
2397
        out->addColorf("FogColor", color);
 
2398
        out->addFloat("FogStart", start);
 
2399
        out->addFloat("FogEnd", end);
 
2400
        out->addFloat("FogDensity", density);
 
2401
        out->addBool("FogPixel", pixelFog);
 
2402
        out->addBool("FogRange", rangeFog);
 
2403
}
 
2404
 
 
2405
//! Reads attributes of the scene node.
 
2406
void CSceneManager::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
 
2407
{
 
2408
        Name = in->getAttributeAsString("Name");
 
2409
        ID = in->getAttributeAsInt("Id");
 
2410
        AmbientLight = in->getAttributeAsColorf("AmbientLight");
 
2411
 
 
2412
        // fog attributes
 
2413
        video::SColor color;
 
2414
        video::E_FOG_TYPE fogType;
 
2415
        f32 start, end, density;
 
2416
        bool pixelFog, rangeFog;
 
2417
        if (in->existsAttribute("FogType"))
 
2418
        {
 
2419
                fogType = (video::E_FOG_TYPE) in->getAttributeAsEnumeration("FogType", video::FogTypeNames);
 
2420
                color = in->getAttributeAsColorf("FogColor").toSColor();
 
2421
                start = in->getAttributeAsFloat("FogStart");
 
2422
                end = in->getAttributeAsFloat("FogEnd");
 
2423
                density = in->getAttributeAsFloat("FogDensity");
 
2424
                pixelFog = in->getAttributeAsBool("FogPixel");
 
2425
                rangeFog = in->getAttributeAsBool("FogRange");
 
2426
                Driver->setFog(color, fogType, start, end, density, pixelFog, rangeFog);
 
2427
        }
 
2428
 
 
2429
        RelativeTranslation.set(0,0,0);
 
2430
        RelativeRotation.set(0,0,0);
 
2431
        RelativeScale.set(1,1,1);
 
2432
        IsVisible = true;
 
2433
        AutomaticCullingState = scene::EAC_BOX;
 
2434
        DebugDataVisible = scene::EDS_OFF;
 
2435
        IsDebugObject = false;
 
2436
 
 
2437
        updateAbsolutePosition();
 
2438
}
 
2439
 
 
2440
 
 
2441
//! Sets ambient color of the scene
 
2442
void CSceneManager::setAmbientLight(const video::SColorf &ambientColor)
 
2443
{
 
2444
        AmbientLight = ambientColor;
 
2445
}
 
2446
 
 
2447
 
 
2448
//! Returns ambient color of the scene
 
2449
const video::SColorf& CSceneManager::getAmbientLight() const
 
2450
{
 
2451
        return AmbientLight;
 
2452
}
 
2453
 
 
2454
 
 
2455
//! Get a skinned mesh, which is not available as header-only code
 
2456
ISkinnedMesh* CSceneManager::createSkinnedMesh()
 
2457
{
 
2458
#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
 
2459
        return new CSkinnedMesh();
 
2460
#else
 
2461
        return 0;
 
2462
#endif
 
2463
}
 
2464
 
 
2465
//! Returns a mesh writer implementation if available
 
2466
IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type)
 
2467
{
 
2468
        switch(type)
 
2469
        {
 
2470
        case EMWT_IRR_MESH:
 
2471
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
 
2472
                return new CIrrMeshWriter(Driver, FileSystem);
 
2473
#else
 
2474
                return 0;
 
2475
#endif
 
2476
        case EMWT_COLLADA:
 
2477
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
 
2478
                return new CColladaMeshWriter(this, Driver, FileSystem);
 
2479
#else
 
2480
                return 0;
 
2481
#endif
 
2482
        case EMWT_STL:
 
2483
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
 
2484
                return new CSTLMeshWriter(this);
 
2485
#else
 
2486
                return 0;
 
2487
#endif
 
2488
        case EMWT_OBJ:
 
2489
#ifdef _IRR_COMPILE_WITH_OBJ_WRITER_
 
2490
                return new COBJMeshWriter(this, FileSystem);
 
2491
#else
 
2492
                return 0;
 
2493
#endif
 
2494
 
 
2495
        case EMWT_PLY:
 
2496
#ifdef _IRR_COMPILE_WITH_PLY_WRITER_
 
2497
                return new CPLYMeshWriter();
 
2498
#else
 
2499
                return 0;
 
2500
#endif
 
2501
        }
 
2502
 
 
2503
        return 0;
 
2504
}
 
2505
 
 
2506
 
 
2507
// creates a scenemanager
 
2508
ISceneManager* createSceneManager(video::IVideoDriver* driver,
 
2509
                io::IFileSystem* fs, gui::ICursorControl* cursorcontrol,
 
2510
                gui::IGUIEnvironment *guiEnvironment)
 
2511
{
 
2512
        return new CSceneManager(driver, fs, cursorcontrol, 0, guiEnvironment );
 
2513
}
 
2514
 
 
2515
 
 
2516
} // end namespace scene
 
2517
} // end namespace irr
 
2518