~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CNullDriver.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 "CNullDriver.h"
 
6
#include "os.h"
 
7
#include "CImage.h"
 
8
#include "CAttributes.h"
 
9
#include "IReadFile.h"
 
10
#include "IWriteFile.h"
 
11
#include "IImageLoader.h"
 
12
#include "IImageWriter.h"
 
13
#include "IMaterialRenderer.h"
 
14
#include "IAnimatedMeshSceneNode.h"
 
15
#include "CMeshManipulator.h"
 
16
#include "CColorConverter.h"
 
17
#include "IAttributeExchangingObject.h"
 
18
 
 
19
 
 
20
namespace irr
 
21
{
 
22
namespace video
 
23
{
 
24
 
 
25
//! creates a loader which is able to load windows bitmaps
 
26
IImageLoader* createImageLoaderBMP();
 
27
 
 
28
//! creates a loader which is able to load jpeg images
 
29
IImageLoader* createImageLoaderJPG();
 
30
 
 
31
//! creates a loader which is able to load targa images
 
32
IImageLoader* createImageLoaderTGA();
 
33
 
 
34
//! creates a loader which is able to load psd images
 
35
IImageLoader* createImageLoaderPSD();
 
36
 
 
37
//! creates a loader which is able to load dds images
 
38
IImageLoader* createImageLoaderDDS();
 
39
 
 
40
//! creates a loader which is able to load pcx images
 
41
IImageLoader* createImageLoaderPCX();
 
42
 
 
43
//! creates a loader which is able to load png images
 
44
IImageLoader* createImageLoaderPNG();
 
45
 
 
46
//! creates a loader which is able to load WAL images
 
47
IImageLoader* createImageLoaderWAL();
 
48
 
 
49
//! creates a loader which is able to load halflife images
 
50
IImageLoader* createImageLoaderHalfLife();
 
51
 
 
52
//! creates a loader which is able to load lmp images
 
53
IImageLoader* createImageLoaderLMP();
 
54
 
 
55
//! creates a loader which is able to load ppm/pgm/pbm images
 
56
IImageLoader* createImageLoaderPPM();
 
57
 
 
58
//! creates a loader which is able to load rgb images
 
59
IImageLoader* createImageLoaderRGB();
 
60
 
 
61
 
 
62
//! creates a writer which is able to save bmp images
 
63
IImageWriter* createImageWriterBMP();
 
64
 
 
65
//! creates a writer which is able to save jpg images
 
66
IImageWriter* createImageWriterJPG();
 
67
 
 
68
//! creates a writer which is able to save tga images
 
69
IImageWriter* createImageWriterTGA();
 
70
 
 
71
//! creates a writer which is able to save psd images
 
72
IImageWriter* createImageWriterPSD();
 
73
 
 
74
//! creates a writer which is able to save pcx images
 
75
IImageWriter* createImageWriterPCX();
 
76
 
 
77
//! creates a writer which is able to save png images
 
78
IImageWriter* createImageWriterPNG();
 
79
 
 
80
//! creates a writer which is able to save ppm images
 
81
IImageWriter* createImageWriterPPM();
 
82
 
 
83
//! constructor
 
84
CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
 
85
: FileSystem(io), MeshManipulator(0), ViewPort(0,0,0,0), ScreenSize(screenSize),
 
86
        PrimitivesDrawn(0), MinVertexCountForVBO(500), TextureCreationFlags(0),
 
87
        OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false)
 
88
{
 
89
        #ifdef _DEBUG
 
90
        setDebugName("CNullDriver");
 
91
        #endif
 
92
 
 
93
        DriverAttributes = new io::CAttributes();
 
94
        DriverAttributes->addInt("MaxTextures", _IRR_MATERIAL_MAX_TEXTURES_);
 
95
        DriverAttributes->addInt("MaxSupportedTextures", _IRR_MATERIAL_MAX_TEXTURES_);
 
96
        DriverAttributes->addInt("MaxLights", getMaximalDynamicLightAmount());
 
97
        DriverAttributes->addInt("MaxAnisotropy", 1);
 
98
//      DriverAttributes->addInt("MaxUserClipPlanes", 0);
 
99
//      DriverAttributes->addInt("MaxAuxBuffers", 0);
 
100
        DriverAttributes->addInt("MaxMultipleRenderTargets", 1);
 
101
        DriverAttributes->addInt("MaxIndices", -1);
 
102
        DriverAttributes->addInt("MaxTextureSize", -1);
 
103
//      DriverAttributes->addInt("MaxGeometryVerticesOut", 0);
 
104
//      DriverAttributes->addFloat("MaxTextureLODBias", 0.f);
 
105
        DriverAttributes->addInt("Version", 1);
 
106
//      DriverAttributes->addInt("ShaderLanguageVersion", 0);
 
107
//      DriverAttributes->addInt("AntiAlias", 0);
 
108
 
 
109
        setFog();
 
110
 
 
111
        setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true);
 
112
        setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);
 
113
 
 
114
        ViewPort = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(screenSize));
 
115
 
 
116
        // create manipulator
 
117
        MeshManipulator = new scene::CMeshManipulator();
 
118
 
 
119
        if (FileSystem)
 
120
                FileSystem->grab();
 
121
 
 
122
        // create surface loader
 
123
 
 
124
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
 
125
        SurfaceLoader.push_back(video::createImageLoaderHalfLife());
 
126
#endif
 
127
#ifdef _IRR_COMPILE_WITH_WAL_LOADER_
 
128
        SurfaceLoader.push_back(video::createImageLoaderWAL());
 
129
#endif
 
130
#ifdef _IRR_COMPILE_WITH_LMP_LOADER_
 
131
        SurfaceLoader.push_back(video::createImageLoaderLMP());
 
132
#endif
 
133
#ifdef _IRR_COMPILE_WITH_PPM_LOADER_
 
134
        SurfaceLoader.push_back(video::createImageLoaderPPM());
 
135
#endif
 
136
#ifdef _IRR_COMPILE_WITH_RGB_LOADER_
 
137
        SurfaceLoader.push_back(video::createImageLoaderRGB());
 
138
#endif
 
139
#ifdef _IRR_COMPILE_WITH_PSD_LOADER_
 
140
        SurfaceLoader.push_back(video::createImageLoaderPSD());
 
141
#endif
 
142
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
 
143
        SurfaceLoader.push_back(video::createImageLoaderDDS());
 
144
#endif
 
145
#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
 
146
        SurfaceLoader.push_back(video::createImageLoaderPCX());
 
147
#endif
 
148
#ifdef _IRR_COMPILE_WITH_TGA_LOADER_
 
149
        SurfaceLoader.push_back(video::createImageLoaderTGA());
 
150
#endif
 
151
#ifdef _IRR_COMPILE_WITH_PNG_LOADER_
 
152
        SurfaceLoader.push_back(video::createImageLoaderPNG());
 
153
#endif
 
154
#ifdef _IRR_COMPILE_WITH_JPG_LOADER_
 
155
        SurfaceLoader.push_back(video::createImageLoaderJPG());
 
156
#endif
 
157
#ifdef _IRR_COMPILE_WITH_BMP_LOADER_
 
158
        SurfaceLoader.push_back(video::createImageLoaderBMP());
 
159
#endif
 
160
 
 
161
 
 
162
#ifdef _IRR_COMPILE_WITH_PPM_WRITER_
 
163
        SurfaceWriter.push_back(video::createImageWriterPPM());
 
164
#endif
 
165
#ifdef _IRR_COMPILE_WITH_PCX_WRITER_
 
166
        SurfaceWriter.push_back(video::createImageWriterPCX());
 
167
#endif
 
168
#ifdef _IRR_COMPILE_WITH_PSD_WRITER_
 
169
        SurfaceWriter.push_back(video::createImageWriterPSD());
 
170
#endif
 
171
#ifdef _IRR_COMPILE_WITH_TGA_WRITER_
 
172
        SurfaceWriter.push_back(video::createImageWriterTGA());
 
173
#endif
 
174
#ifdef _IRR_COMPILE_WITH_JPG_WRITER_
 
175
        SurfaceWriter.push_back(video::createImageWriterJPG());
 
176
#endif
 
177
#ifdef _IRR_COMPILE_WITH_PNG_WRITER_
 
178
        SurfaceWriter.push_back(video::createImageWriterPNG());
 
179
#endif
 
180
#ifdef _IRR_COMPILE_WITH_BMP_WRITER_
 
181
        SurfaceWriter.push_back(video::createImageWriterBMP());
 
182
#endif
 
183
 
 
184
 
 
185
        // set ExposedData to 0
 
186
        memset(&ExposedData, 0, sizeof(ExposedData));
 
187
        for (u32 i=0; i<video::EVDF_COUNT; ++i)
 
188
                FeatureEnabled[i]=true;
 
189
 
 
190
        InitMaterial2D.AntiAliasing=video::EAAM_OFF;
 
191
        InitMaterial2D.Lighting=false;
 
192
        InitMaterial2D.ZWriteEnable=false;
 
193
        InitMaterial2D.ZBuffer=video::ECFN_NEVER;
 
194
        InitMaterial2D.UseMipMaps=false;
 
195
        for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
 
196
        {
 
197
                InitMaterial2D.TextureLayer[i].BilinearFilter=false;
 
198
                InitMaterial2D.TextureLayer[i].TextureWrapU=video::ETC_REPEAT;
 
199
                InitMaterial2D.TextureLayer[i].TextureWrapV=video::ETC_REPEAT;
 
200
        }
 
201
        OverrideMaterial2D=InitMaterial2D;
 
202
}
 
203
 
 
204
 
 
205
//! destructor
 
206
CNullDriver::~CNullDriver()
 
207
{
 
208
        if (DriverAttributes)
 
209
                DriverAttributes->drop();
 
210
 
 
211
        if (FileSystem)
 
212
                FileSystem->drop();
 
213
 
 
214
        if (MeshManipulator)
 
215
                MeshManipulator->drop();
 
216
        deleteAllTextures();
 
217
 
 
218
        u32 i;
 
219
        for (i=0; i<SurfaceLoader.size(); ++i)
 
220
                SurfaceLoader[i]->drop();
 
221
 
 
222
        for (i=0; i<SurfaceWriter.size(); ++i)
 
223
                SurfaceWriter[i]->drop();
 
224
 
 
225
        // delete material renderers
 
226
        deleteMaterialRenders();
 
227
 
 
228
        // delete hardware mesh buffers
 
229
        removeAllHardwareBuffers();
 
230
}
 
231
 
 
232
 
 
233
//! Adds an external surface loader to the engine.
 
234
void CNullDriver::addExternalImageLoader(IImageLoader* loader)
 
235
{
 
236
        if (!loader)
 
237
                return;
 
238
 
 
239
        loader->grab();
 
240
        SurfaceLoader.push_back(loader);
 
241
}
 
242
 
 
243
 
 
244
//! Adds an external surface writer to the engine.
 
245
void CNullDriver::addExternalImageWriter(IImageWriter* writer)
 
246
{
 
247
        if (!writer)
 
248
                return;
 
249
 
 
250
        writer->grab();
 
251
        SurfaceWriter.push_back(writer);
 
252
}
 
253
 
 
254
 
 
255
//! Retrieve the number of image loaders
 
256
u32 CNullDriver::getImageLoaderCount() const
 
257
{
 
258
        return SurfaceLoader.size();
 
259
}
 
260
 
 
261
 
 
262
//! Retrieve the given image loader
 
263
IImageLoader* CNullDriver::getImageLoader(u32 n)
 
264
{
 
265
        if (n < SurfaceLoader.size())
 
266
                return SurfaceLoader[n];
 
267
        return 0;
 
268
}
 
269
 
 
270
 
 
271
//! Retrieve the number of image writers
 
272
u32 CNullDriver::getImageWriterCount() const
 
273
{
 
274
        return SurfaceWriter.size();
 
275
}
 
276
 
 
277
 
 
278
//! Retrieve the given image writer
 
279
IImageWriter* CNullDriver::getImageWriter(u32 n)
 
280
{
 
281
        if (n < SurfaceWriter.size())
 
282
                return SurfaceWriter[n];
 
283
        return 0;
 
284
}
 
285
 
 
286
 
 
287
//! deletes all textures
 
288
void CNullDriver::deleteAllTextures()
 
289
{
 
290
        // we need to remove previously set textures which might otherwise be kept in the
 
291
        // last set material member. Could be optimized to reduce state changes.
 
292
        setMaterial(SMaterial());
 
293
 
 
294
        for (u32 i=0; i<Textures.size(); ++i)
 
295
                Textures[i].Surface->drop();
 
296
 
 
297
        Textures.clear();
 
298
}
 
299
 
 
300
 
 
301
 
 
302
//! applications must call this method before performing any rendering. returns false if failed.
 
303
bool CNullDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
 
304
                const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
 
305
{
 
306
        core::clearFPUException();
 
307
        PrimitivesDrawn = 0;
 
308
        return true;
 
309
}
 
310
 
 
311
 
 
312
//! applications must call this method after performing any rendering. returns false if failed.
 
313
bool CNullDriver::endScene()
 
314
{
 
315
        FPSCounter.registerFrame(os::Timer::getRealTime(), PrimitivesDrawn);
 
316
        updateAllHardwareBuffers();
 
317
        updateAllOcclusionQueries();
 
318
        return true;
 
319
}
 
320
 
 
321
 
 
322
//! Disable a feature of the driver.
 
323
void CNullDriver::disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag)
 
324
{
 
325
        FeatureEnabled[feature]=!flag;
 
326
}
 
327
 
 
328
 
 
329
//! queries the features of the driver, returns true if feature is available
 
330
bool CNullDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
 
331
{
 
332
        return false;
 
333
}
 
334
 
 
335
 
 
336
//! Get attributes of the actual video driver
 
337
const io::IAttributes& CNullDriver::getDriverAttributes() const
 
338
{
 
339
        return *DriverAttributes;
 
340
}
 
341
 
 
342
 
 
343
//! sets transformation
 
344
void CNullDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
 
345
{
 
346
}
 
347
 
 
348
 
 
349
//! Returns the transformation set by setTransform
 
350
const core::matrix4& CNullDriver::getTransform(E_TRANSFORMATION_STATE state) const
 
351
{
 
352
        return TransformationMatrix;
 
353
}
 
354
 
 
355
 
 
356
//! sets a material
 
357
void CNullDriver::setMaterial(const SMaterial& material)
 
358
{
 
359
}
 
360
 
 
361
 
 
362
//! Removes a texture from the texture cache and deletes it, freeing lot of
 
363
//! memory.
 
364
void CNullDriver::removeTexture(ITexture* texture)
 
365
{
 
366
        if (!texture)
 
367
                return;
 
368
 
 
369
        for (u32 i=0; i<Textures.size(); ++i)
 
370
        {
 
371
                if (Textures[i].Surface == texture)
 
372
                {
 
373
                        texture->drop();
 
374
                        Textures.erase(i);
 
375
                }
 
376
        }
 
377
}
 
378
 
 
379
 
 
380
//! Removes all texture from the texture cache and deletes them, freeing lot of
 
381
//! memory.
 
382
void CNullDriver::removeAllTextures()
 
383
{
 
384
        setMaterial ( SMaterial() );
 
385
        deleteAllTextures();
 
386
}
 
387
 
 
388
 
 
389
//! Returns a texture by index
 
390
ITexture* CNullDriver::getTextureByIndex(u32 i)
 
391
{
 
392
        if ( i < Textures.size() )
 
393
                return Textures[i].Surface;
 
394
 
 
395
        return 0;
 
396
}
 
397
 
 
398
 
 
399
//! Returns amount of textures currently loaded
 
400
u32 CNullDriver::getTextureCount() const
 
401
{
 
402
        return Textures.size();
 
403
}
 
404
 
 
405
 
 
406
//! Renames a texture
 
407
void CNullDriver::renameTexture(ITexture* texture, const io::path& newName)
 
408
{
 
409
        // we can do a const_cast here safely, the name of the ITexture interface
 
410
        // is just readonly to prevent the user changing the texture name without invoking
 
411
        // this method, because the textures will need resorting afterwards
 
412
 
 
413
        io::SNamedPath& name = const_cast<io::SNamedPath&>(texture->getName());
 
414
        name.setPath(newName);
 
415
 
 
416
        Textures.sort();
 
417
}
 
418
 
 
419
 
 
420
//! loads a Texture
 
421
ITexture* CNullDriver::getTexture(const io::path& filename)
 
422
{
 
423
        // Identify textures by their absolute filenames if possible.
 
424
        const io::path absolutePath = FileSystem->getAbsolutePath(filename);
 
425
 
 
426
        ITexture* texture = findTexture(absolutePath);
 
427
        if (texture)
 
428
                return texture;
 
429
 
 
430
        // Then try the raw filename, which might be in an Archive
 
431
        texture = findTexture(filename);
 
432
        if (texture)
 
433
                return texture;
 
434
 
 
435
        // Now try to open the file using the complete path.
 
436
        io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath);
 
437
 
 
438
        if (!file)
 
439
        {
 
440
                // Try to open it using the raw filename.
 
441
                file = FileSystem->createAndOpenFile(filename);
 
442
        }
 
443
 
 
444
        if (file)
 
445
        {
 
446
                // Re-check name for actual archive names
 
447
                texture = findTexture(file->getFileName());
 
448
                if (texture)
 
449
                {
 
450
                        file->drop();
 
451
                        return texture;
 
452
                }
 
453
 
 
454
                texture = loadTextureFromFile(file);
 
455
                file->drop();
 
456
 
 
457
                if (texture)
 
458
                {
 
459
                        addTexture(texture);
 
460
                        texture->drop(); // drop it because we created it, one grab too much
 
461
                }
 
462
                else
 
463
                        os::Printer::log("Could not load texture", filename, ELL_ERROR);
 
464
                return texture;
 
465
        }
 
466
        else
 
467
        {
 
468
                os::Printer::log("Could not open file of texture", filename, ELL_WARNING);
 
469
                return 0;
 
470
        }
 
471
}
 
472
 
 
473
 
 
474
//! loads a Texture
 
475
ITexture* CNullDriver::getTexture(io::IReadFile* file)
 
476
{
 
477
        ITexture* texture = 0;
 
478
 
 
479
        if (file)
 
480
        {
 
481
                texture = findTexture(file->getFileName());
 
482
 
 
483
                if (texture)
 
484
                        return texture;
 
485
 
 
486
                texture = loadTextureFromFile(file);
 
487
 
 
488
                if (texture)
 
489
                {
 
490
                        addTexture(texture);
 
491
                        texture->drop(); // drop it because we created it, one grab too much
 
492
                }
 
493
 
 
494
                if (!texture)
 
495
                        os::Printer::log("Could not load texture", file->getFileName(), ELL_WARNING);
 
496
        }
 
497
 
 
498
        return texture;
 
499
}
 
500
 
 
501
 
 
502
//! opens the file and loads it into the surface
 
503
video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName )
 
504
{
 
505
        ITexture* texture = 0;
 
506
        IImage* image = createImageFromFile(file);
 
507
 
 
508
        if (image)
 
509
        {
 
510
                // create texture from surface
 
511
                texture = createDeviceDependentTexture(image, hashName.size() ? hashName : file->getFileName() );
 
512
                os::Printer::log("Loaded texture", file->getFileName());
 
513
                image->drop();
 
514
        }
 
515
 
 
516
        return texture;
 
517
}
 
518
 
 
519
 
 
520
//! adds a surface, not loaded or created by the Irrlicht Engine
 
521
void CNullDriver::addTexture(video::ITexture* texture)
 
522
{
 
523
        if (texture)
 
524
        {
 
525
                SSurface s;
 
526
                s.Surface = texture;
 
527
                texture->grab();
 
528
 
 
529
                Textures.push_back(s);
 
530
 
 
531
                // the new texture is now at the end of the texture list. when searching for
 
532
                // the next new texture, the texture array will be sorted and the index of this texture
 
533
                // will be changed. to let the order be more consistent to the user, sort
 
534
                // the textures now already although this isn't necessary:
 
535
 
 
536
                Textures.sort();
 
537
        }
 
538
}
 
539
 
 
540
 
 
541
//! looks if the image is already loaded
 
542
video::ITexture* CNullDriver::findTexture(const io::path& filename)
 
543
{
 
544
        SSurface s;
 
545
        SDummyTexture dummy(filename);
 
546
        s.Surface = &dummy;
 
547
 
 
548
        s32 index = Textures.binary_search(s);
 
549
        if (index != -1)
 
550
                return Textures[index].Surface;
 
551
 
 
552
        return 0;
 
553
}
 
554
 
 
555
 
 
556
//! Creates a texture from a loaded IImage.
 
557
ITexture* CNullDriver::addTexture(const io::path& name, IImage* image, void* mipmapData)
 
558
{
 
559
        if ( 0 == name.size() || !image)
 
560
                return 0;
 
561
 
 
562
        ITexture* t = createDeviceDependentTexture(image, name, mipmapData);
 
563
        if (t)
 
564
        {
 
565
                addTexture(t);
 
566
                t->drop();
 
567
        }
 
568
        return t;
 
569
}
 
570
 
 
571
 
 
572
//! creates a Texture
 
573
ITexture* CNullDriver::addTexture(const core::dimension2d<u32>& size,
 
574
                                  const io::path& name, ECOLOR_FORMAT format)
 
575
{
 
576
        if(IImage::isRenderTargetOnlyFormat(format))
 
577
        {
 
578
                os::Printer::log("Could not create ITexture, format only supported for render target textures.", ELL_WARNING);
 
579
                return 0;
 
580
        }
 
581
 
 
582
        if ( 0 == name.size () )
 
583
                return 0;
 
584
 
 
585
        IImage* image = new CImage(format, size);
 
586
        ITexture* t = createDeviceDependentTexture(image, name);
 
587
        image->drop();
 
588
        addTexture(t);
 
589
 
 
590
        if (t)
 
591
                t->drop();
 
592
 
 
593
        return t;
 
594
}
 
595
 
 
596
 
 
597
 
 
598
//! returns a device dependent texture from a software surface (IImage)
 
599
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
 
600
ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData)
 
601
{
 
602
        return new SDummyTexture(name);
 
603
}
 
604
 
 
605
 
 
606
//! set or reset special render targets
 
607
bool CNullDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
 
608
                        bool clearZBuffer, SColor color)
 
609
{
 
610
        if (ERT_FRAME_BUFFER==target)
 
611
                return setRenderTarget(0,clearTarget, clearZBuffer, color);
 
612
        else
 
613
                return false;
 
614
}
 
615
 
 
616
 
 
617
//! sets a render target
 
618
bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
 
619
                                        bool clearZBuffer, SColor color)
 
620
{
 
621
        return false;
 
622
}
 
623
 
 
624
 
 
625
//! Sets multiple render targets
 
626
bool CNullDriver::setRenderTarget(const core::array<video::IRenderTarget>& texture,
 
627
                                bool clearBackBuffer, bool clearZBuffer, SColor color)
 
628
{
 
629
        return false;
 
630
}
 
631
 
 
632
 
 
633
//! sets a viewport
 
634
void CNullDriver::setViewPort(const core::rect<s32>& area)
 
635
{
 
636
}
 
637
 
 
638
 
 
639
//! gets the area of the current viewport
 
640
const core::rect<s32>& CNullDriver::getViewPort() const
 
641
{
 
642
        return ViewPort;
 
643
}
 
644
 
 
645
 
 
646
//! draws a vertex primitive list
 
647
void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
 
648
{
 
649
        if ((iType==EIT_16BIT) && (vertexCount>65536))
 
650
                os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
 
651
        PrimitivesDrawn += primitiveCount;
 
652
}
 
653
 
 
654
 
 
655
//! draws a vertex primitive list in 2d
 
656
void CNullDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
 
657
{
 
658
        if ((iType==EIT_16BIT) && (vertexCount>65536))
 
659
                os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
 
660
        PrimitivesDrawn += primitiveCount;
 
661
}
 
662
 
 
663
 
 
664
//! Draws a 3d line.
 
665
void CNullDriver::draw3DLine(const core::vector3df& start,
 
666
                                const core::vector3df& end, SColor color)
 
667
{
 
668
}
 
669
 
 
670
 
 
671
//! Draws a 3d triangle.
 
672
void CNullDriver::draw3DTriangle(const core::triangle3df& triangle, SColor color)
 
673
{
 
674
        S3DVertex vertices[3];
 
675
        vertices[0].Pos=triangle.pointA;
 
676
        vertices[0].Color=color;
 
677
        vertices[0].Normal=triangle.getNormal().normalize();
 
678
        vertices[0].TCoords.set(0.f,0.f);
 
679
        vertices[1].Pos=triangle.pointB;
 
680
        vertices[1].Color=color;
 
681
        vertices[1].Normal=vertices[0].Normal;
 
682
        vertices[1].TCoords.set(0.5f,1.f);
 
683
        vertices[2].Pos=triangle.pointC;
 
684
        vertices[2].Color=color;
 
685
        vertices[2].Normal=vertices[0].Normal;
 
686
        vertices[2].TCoords.set(1.f,0.f);
 
687
        const u16 indexList[] = {0,1,2};
 
688
        drawVertexPrimitiveList(vertices, 3, indexList, 1, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT);
 
689
}
 
690
 
 
691
 
 
692
//! Draws a 3d axis aligned box.
 
693
void CNullDriver::draw3DBox(const core::aabbox3d<f32>& box, SColor color)
 
694
{
 
695
        core::vector3df edges[8];
 
696
        box.getEdges(edges);
 
697
 
 
698
        // TODO: optimize into one big drawIndexPrimitive call.
 
699
 
 
700
        draw3DLine(edges[5], edges[1], color);
 
701
        draw3DLine(edges[1], edges[3], color);
 
702
        draw3DLine(edges[3], edges[7], color);
 
703
        draw3DLine(edges[7], edges[5], color);
 
704
        draw3DLine(edges[0], edges[2], color);
 
705
        draw3DLine(edges[2], edges[6], color);
 
706
        draw3DLine(edges[6], edges[4], color);
 
707
        draw3DLine(edges[4], edges[0], color);
 
708
        draw3DLine(edges[1], edges[0], color);
 
709
        draw3DLine(edges[3], edges[2], color);
 
710
        draw3DLine(edges[7], edges[6], color);
 
711
        draw3DLine(edges[5], edges[4], color);
 
712
}
 
713
 
 
714
 
 
715
 
 
716
//! draws an 2d image
 
717
void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos)
 
718
{
 
719
        if (!texture)
 
720
                return;
 
721
 
 
722
        draw2DImage(texture,destPos, core::rect<s32>(core::position2d<s32>(0,0),
 
723
                                                                                                core::dimension2di(texture->getOriginalSize())));
 
724
}
 
725
 
 
726
 
 
727
 
 
728
//! draws a set of 2d images, using a color and the alpha channel of the
 
729
//! texture if desired. The images are drawn beginning at pos and concatenated
 
730
//! in one line. All drawings are clipped against clipRect (if != 0).
 
731
//! The subtextures are defined by the array of sourceRects and are chosen
 
732
//! by the indices given.
 
733
void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
 
734
                                const core::position2d<s32>& pos,
 
735
                                const core::array<core::rect<s32> >& sourceRects,
 
736
                                const core::array<s32>& indices,
 
737
                                s32 kerningWidth,
 
738
                                const core::rect<s32>* clipRect, SColor color,
 
739
                                bool useAlphaChannelOfTexture)
 
740
{
 
741
        core::position2d<s32> target(pos);
 
742
 
 
743
        for (u32 i=0; i<indices.size(); ++i)
 
744
        {
 
745
                draw2DImage(texture, target, sourceRects[indices[i]],
 
746
                                clipRect, color, useAlphaChannelOfTexture);
 
747
                target.X += sourceRects[indices[i]].getWidth();
 
748
                target.X += kerningWidth;
 
749
        }
 
750
}
 
751
 
 
752
//! draws a set of 2d images, using a color and the alpha channel of the
 
753
//! texture if desired.
 
754
void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
 
755
                                const core::array<core::position2d<s32> >& positions,
 
756
                                const core::array<core::rect<s32> >& sourceRects,
 
757
                                const core::rect<s32>* clipRect,
 
758
                                SColor color,
 
759
                                bool useAlphaChannelOfTexture)
 
760
{
 
761
        const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
 
762
 
 
763
        for (u32 i=0; i<drawCount; ++i)
 
764
        {
 
765
                draw2DImage(texture, positions[i], sourceRects[i],
 
766
                                clipRect, color, useAlphaChannelOfTexture);
 
767
        }
 
768
}
 
769
 
 
770
 
 
771
//! Draws a part of the texture into the rectangle.
 
772
void CNullDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
 
773
        const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
 
774
        const video::SColor* const colors, bool useAlphaChannelOfTexture)
 
775
{
 
776
        draw2DImage(texture, core::position2d<s32>(destRect.UpperLeftCorner),
 
777
                                sourceRect, clipRect, colors?colors[0]:video::SColor(0xffffffff),
 
778
                                useAlphaChannelOfTexture);
 
779
}
 
780
 
 
781
 
 
782
//! Draws a 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
 
783
void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
 
784
                                const core::rect<s32>& sourceRect,
 
785
                                const core::rect<s32>* clipRect, SColor color,
 
786
                                bool useAlphaChannelOfTexture)
 
787
{
 
788
}
 
789
 
 
790
 
 
791
//! Draws the outline of a 2d rectangle
 
792
void CNullDriver::draw2DRectangleOutline(const core::recti& pos, SColor color)
 
793
{
 
794
        draw2DLine(pos.UpperLeftCorner, core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), color);
 
795
        draw2DLine(core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), pos.LowerRightCorner, color);
 
796
        draw2DLine(pos.LowerRightCorner, core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), color);
 
797
        draw2DLine(core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), pos.UpperLeftCorner, color);
 
798
}
 
799
 
 
800
 
 
801
//! Draw a 2d rectangle
 
802
void CNullDriver::draw2DRectangle(SColor color, const core::rect<s32>& pos, const core::rect<s32>* clip)
 
803
{
 
804
        draw2DRectangle(pos, color, color, color, color, clip);
 
805
}
 
806
 
 
807
 
 
808
 
 
809
//! Draws a 2d rectangle with a gradient.
 
810
void CNullDriver::draw2DRectangle(const core::rect<s32>& pos,
 
811
        SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
 
812
        const core::rect<s32>* clip)
 
813
{
 
814
}
 
815
 
 
816
 
 
817
 
 
818
//! Draws a 2d line.
 
819
void CNullDriver::draw2DLine(const core::position2d<s32>& start,
 
820
                                const core::position2d<s32>& end, SColor color)
 
821
{
 
822
}
 
823
 
 
824
//! Draws a pixel
 
825
void CNullDriver::drawPixel(u32 x, u32 y, const SColor & color)
 
826
{
 
827
}
 
828
 
 
829
 
 
830
//! Draws a non filled concyclic regular 2d polyon.
 
831
void CNullDriver::draw2DPolygon(core::position2d<s32> center,
 
832
        f32 radius, video::SColor color, s32 count)
 
833
{
 
834
        if (count < 2)
 
835
                return;
 
836
 
 
837
        core::position2d<s32> first;
 
838
        core::position2d<s32> a,b;
 
839
 
 
840
        for (s32 j=0; j<count; ++j)
 
841
        {
 
842
                b = a;
 
843
 
 
844
                f32 p = j / (f32)count * (core::PI*2);
 
845
                a = center + core::position2d<s32>((s32)(sin(p)*radius), (s32)(cos(p)*radius));
 
846
 
 
847
                if (j==0)
 
848
                        first = a;
 
849
                else
 
850
                        draw2DLine(a, b, color);
 
851
        }
 
852
 
 
853
        draw2DLine(a, first, color);
 
854
}
 
855
 
 
856
 
 
857
//! returns color format
 
858
ECOLOR_FORMAT CNullDriver::getColorFormat() const
 
859
{
 
860
        return ECF_R5G6B5;
 
861
}
 
862
 
 
863
 
 
864
//! returns screen size
 
865
const core::dimension2d<u32>& CNullDriver::getScreenSize() const
 
866
{
 
867
        return ScreenSize;
 
868
}
 
869
 
 
870
 
 
871
//! returns the current render target size,
 
872
//! or the screen size if render targets are not implemented
 
873
const core::dimension2d<u32>& CNullDriver::getCurrentRenderTargetSize() const
 
874
{
 
875
        return ScreenSize;
 
876
}
 
877
 
 
878
 
 
879
// returns current frames per second value
 
880
s32 CNullDriver::getFPS() const
 
881
{
 
882
        return FPSCounter.getFPS();
 
883
}
 
884
 
 
885
 
 
886
 
 
887
//! returns amount of primitives (mostly triangles) were drawn in the last frame.
 
888
//! very useful method for statistics.
 
889
u32 CNullDriver::getPrimitiveCountDrawn( u32 param ) const
 
890
{
 
891
        return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage() : FPSCounter.getPrimitiveTotal();
 
892
}
 
893
 
 
894
 
 
895
 
 
896
//! Sets the dynamic ambient light color. The default color is
 
897
//! (0,0,0,0) which means it is dark.
 
898
//! \param color: New color of the ambient light.
 
899
void CNullDriver::setAmbientLight(const SColorf& color)
 
900
{
 
901
}
 
902
 
 
903
 
 
904
 
 
905
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
 
906
//! driver, it would return "Direct3D8".
 
907
 
 
908
const wchar_t* CNullDriver::getName() const
 
909
{
 
910
        return L"Irrlicht NullDevice";
 
911
}
 
912
 
 
913
 
 
914
 
 
915
//! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do
 
916
//! this: Frist, draw all geometry. Then use this method, to draw the shadow
 
917
//! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow.
 
918
void CNullDriver::drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail)
 
919
{
 
920
}
 
921
 
 
922
 
 
923
//! Fills the stencil shadow with color. After the shadow volume has been drawn
 
924
//! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
 
925
//! to draw the color of the shadow.
 
926
void CNullDriver::drawStencilShadow(bool clearStencilBuffer,
 
927
                video::SColor leftUpEdge, video::SColor rightUpEdge,
 
928
                video::SColor leftDownEdge, video::SColor rightDownEdge)
 
929
{
 
930
}
 
931
 
 
932
 
 
933
//! deletes all dynamic lights there are
 
934
void CNullDriver::deleteAllDynamicLights()
 
935
{
 
936
        Lights.set_used(0);
 
937
}
 
938
 
 
939
 
 
940
//! adds a dynamic light
 
941
s32 CNullDriver::addDynamicLight(const SLight& light)
 
942
{
 
943
        Lights.push_back(light);
 
944
        return Lights.size() - 1;
 
945
}
 
946
 
 
947
//! Turns a dynamic light on or off
 
948
//! \param lightIndex: the index returned by addDynamicLight
 
949
//! \param turnOn: true to turn the light on, false to turn it off
 
950
void CNullDriver::turnLightOn(s32 lightIndex, bool turnOn)
 
951
{
 
952
        // Do nothing
 
953
}
 
954
 
 
955
 
 
956
//! returns the maximal amount of dynamic lights the device can handle
 
957
u32 CNullDriver::getMaximalDynamicLightAmount() const
 
958
{
 
959
        return 0;
 
960
}
 
961
 
 
962
 
 
963
//! Returns current amount of dynamic lights set
 
964
//! \return Current amount of dynamic lights set
 
965
u32 CNullDriver::getDynamicLightCount() const
 
966
{
 
967
        return Lights.size();
 
968
}
 
969
 
 
970
 
 
971
//! Returns light data which was previously set by IVideoDriver::addDynamicLight().
 
972
//! \param idx: Zero based index of the light. Must be greater than 0 and smaller
 
973
//! than IVideoDriver()::getDynamicLightCount.
 
974
//! \return Light data.
 
975
const SLight& CNullDriver::getDynamicLight(u32 idx) const
 
976
{
 
977
        if ( idx < Lights.size() )
 
978
                return Lights[idx];
 
979
        else
 
980
                return *((SLight*)0);
 
981
}
 
982
 
 
983
 
 
984
//! Creates a boolean alpha channel of the texture based of an color key.
 
985
void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
 
986
                                                                        video::SColor color,
 
987
                                                                        bool zeroTexels) const
 
988
{
 
989
        if (!texture)
 
990
                return;
 
991
 
 
992
        if (texture->getColorFormat() != ECF_A1R5G5B5 &&
 
993
                texture->getColorFormat() != ECF_A8R8G8B8 )
 
994
        {
 
995
                os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
 
996
                return;
 
997
        }
 
998
 
 
999
        if (texture->getColorFormat() == ECF_A1R5G5B5)
 
1000
        {
 
1001
                u16 *p = (u16*)texture->lock();
 
1002
 
 
1003
                if (!p)
 
1004
                {
 
1005
                        os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
 
1006
                        return;
 
1007
                }
 
1008
 
 
1009
                const core::dimension2d<u32> dim = texture->getSize();
 
1010
                const u32 pitch = texture->getPitch() / 2;
 
1011
 
 
1012
                // color with alpha disabled (i.e. fully transparent)
 
1013
                const u16 refZeroAlpha = (0x7fff & color.toA1R5G5B5());
 
1014
 
 
1015
                const u32 pixels = pitch * dim.Height;
 
1016
 
 
1017
                for (u32 pixel = 0; pixel < pixels; ++ pixel)
 
1018
                {
 
1019
                        // If the colour matches the reference colour, ignoring alphas,
 
1020
                        // set the alpha to zero.
 
1021
                        if(((*p) & 0x7fff) == refZeroAlpha)
 
1022
                        {
 
1023
                                if(zeroTexels)
 
1024
                                        (*p) = 0;
 
1025
                                else
 
1026
                                        (*p) = refZeroAlpha;
 
1027
                        }
 
1028
 
 
1029
                        ++p;
 
1030
                }
 
1031
 
 
1032
                texture->unlock();
 
1033
        }
 
1034
        else
 
1035
        {
 
1036
                u32 *p = (u32*)texture->lock();
 
1037
 
 
1038
                if (!p)
 
1039
                {
 
1040
                        os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
 
1041
                        return;
 
1042
                }
 
1043
 
 
1044
                core::dimension2d<u32> dim = texture->getSize();
 
1045
                u32 pitch = texture->getPitch() / 4;
 
1046
 
 
1047
                // color with alpha disabled (fully transparent)
 
1048
                const u32 refZeroAlpha = 0x00ffffff & color.color;
 
1049
 
 
1050
                const u32 pixels = pitch * dim.Height;
 
1051
                for (u32 pixel = 0; pixel < pixels; ++ pixel)
 
1052
                {
 
1053
                        // If the colour matches the reference colour, ignoring alphas,
 
1054
                        // set the alpha to zero.
 
1055
                        if(((*p) & 0x00ffffff) == refZeroAlpha)
 
1056
                        {
 
1057
                                if(zeroTexels)
 
1058
                                        (*p) = 0;
 
1059
                                else
 
1060
                                        (*p) = refZeroAlpha;
 
1061
                        }
 
1062
 
 
1063
                        ++p;
 
1064
                }
 
1065
 
 
1066
                texture->unlock();
 
1067
        }
 
1068
}
 
1069
 
 
1070
 
 
1071
 
 
1072
//! Creates an boolean alpha channel of the texture based of an color key position.
 
1073
void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
 
1074
                                        core::position2d<s32> colorKeyPixelPos,
 
1075
                                        bool zeroTexels) const
 
1076
{
 
1077
        if (!texture)
 
1078
                return;
 
1079
 
 
1080
        if (texture->getColorFormat() != ECF_A1R5G5B5 &&
 
1081
                texture->getColorFormat() != ECF_A8R8G8B8 )
 
1082
        {
 
1083
                os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
 
1084
                return;
 
1085
        }
 
1086
 
 
1087
        SColor colorKey;
 
1088
 
 
1089
        if (texture->getColorFormat() == ECF_A1R5G5B5)
 
1090
        {
 
1091
                u16 *p = (u16*)texture->lock(ETLM_READ_ONLY);
 
1092
 
 
1093
                if (!p)
 
1094
                {
 
1095
                        os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
 
1096
                        return;
 
1097
                }
 
1098
 
 
1099
                u32 pitch = texture->getPitch() / 2;
 
1100
 
 
1101
                const u16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
 
1102
 
 
1103
                colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit);
 
1104
        }
 
1105
        else
 
1106
        {
 
1107
                u32 *p = (u32*)texture->lock(ETLM_READ_ONLY);
 
1108
 
 
1109
                if (!p)
 
1110
                {
 
1111
                        os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
 
1112
                        return;
 
1113
                }
 
1114
 
 
1115
                u32 pitch = texture->getPitch() / 4;
 
1116
                colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
 
1117
        }
 
1118
 
 
1119
        texture->unlock();
 
1120
        makeColorKeyTexture(texture, colorKey, zeroTexels);
 
1121
}
 
1122
 
 
1123
 
 
1124
 
 
1125
//! Creates a normal map from a height map texture.
 
1126
//! \param amplitude: Constant value by which the height information is multiplied.
 
1127
void CNullDriver::makeNormalMapTexture(video::ITexture* texture, f32 amplitude) const
 
1128
{
 
1129
        if (!texture)
 
1130
                return;
 
1131
 
 
1132
        if (texture->getColorFormat() != ECF_A1R5G5B5 &&
 
1133
                texture->getColorFormat() != ECF_A8R8G8B8 )
 
1134
        {
 
1135
                os::Printer::log("Error: Unsupported texture color format for making normal map.", ELL_ERROR);
 
1136
                return;
 
1137
        }
 
1138
 
 
1139
        core::dimension2d<u32> dim = texture->getSize();
 
1140
        amplitude = amplitude / 255.0f;
 
1141
        f32 vh = dim.Height / (f32)dim.Width;
 
1142
        f32 hh = dim.Width / (f32)dim.Height;
 
1143
 
 
1144
        if (texture->getColorFormat() == ECF_A8R8G8B8)
 
1145
        {
 
1146
                // ECF_A8R8G8B8 version
 
1147
 
 
1148
                s32 *p = (s32*)texture->lock();
 
1149
 
 
1150
                if (!p)
 
1151
                {
 
1152
                        os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR);
 
1153
                        return;
 
1154
                }
 
1155
 
 
1156
                // copy texture
 
1157
 
 
1158
                u32 pitch = texture->getPitch() / 4;
 
1159
 
 
1160
                s32* in = new s32[dim.Height * pitch];
 
1161
                memcpy(in, p, dim.Height * pitch * 4);
 
1162
 
 
1163
                for (s32 x=0; x < s32(pitch); ++x)
 
1164
                        for (s32 y=0; y < s32(dim.Height); ++y)
 
1165
                        {
 
1166
                                // TODO: this could be optimized really a lot
 
1167
 
 
1168
                                core::vector3df h1((x-1)*hh, nml32(x-1, y, pitch, dim.Height, in)*amplitude, y*vh);
 
1169
                                core::vector3df h2((x+1)*hh, nml32(x+1, y, pitch, dim.Height, in)*amplitude, y*vh);
 
1170
                                //core::vector3df v1(x*hh, nml32(x, y-1, pitch, dim.Height, in)*amplitude, (y-1)*vh);
 
1171
                                //core::vector3df v2(x*hh, nml32(x, y+1, pitch, dim.Height, in)*amplitude, (y+1)*vh);
 
1172
                                core::vector3df v1(x*hh, nml32(x, y+1, pitch, dim.Height, in)*amplitude, (y-1)*vh);
 
1173
                                core::vector3df v2(x*hh, nml32(x, y-1, pitch, dim.Height, in)*amplitude, (y+1)*vh);
 
1174
 
 
1175
                                core::vector3df v = v1-v2;
 
1176
                                core::vector3df h = h1-h2;
 
1177
 
 
1178
                                core::vector3df n = v.crossProduct(h);
 
1179
                                n.normalize();
 
1180
                                n *= 0.5f;
 
1181
                                n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1
 
1182
                                n *= 255.0f;
 
1183
 
 
1184
                                s32 height = (s32)nml32(x, y, pitch, dim.Height, in);
 
1185
                                p[y*pitch + x] = video::SColor(
 
1186
                                        height, // store height in alpha
 
1187
                                        (s32)n.X, (s32)n.Z, (s32)n.Y).color;
 
1188
                        }
 
1189
 
 
1190
                delete [] in;
 
1191
                texture->unlock();
 
1192
        }
 
1193
        else
 
1194
        {
 
1195
                // ECF_A1R5G5B5 version
 
1196
 
 
1197
                s16 *p = (s16*)texture->lock();
 
1198
 
 
1199
                if (!p)
 
1200
                {
 
1201
                        os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR);
 
1202
                        return;
 
1203
                }
 
1204
 
 
1205
                u32 pitch = texture->getPitch() / 2;
 
1206
 
 
1207
                // copy texture
 
1208
 
 
1209
                s16* in = new s16[dim.Height * pitch];
 
1210
                memcpy(in, p, dim.Height * pitch * 2);
 
1211
 
 
1212
                for (s32 x=0; x < s32(pitch); ++x)
 
1213
                        for (s32 y=0; y < s32(dim.Height); ++y)
 
1214
                        {
 
1215
                                // TODO: this could be optimized really a lot
 
1216
 
 
1217
                                core::vector3df h1((x-1)*hh, nml16(x-1, y, pitch, dim.Height, in)*amplitude, y*vh);
 
1218
                                core::vector3df h2((x+1)*hh, nml16(x+1, y, pitch, dim.Height, in)*amplitude, y*vh);
 
1219
                                core::vector3df v1(x*hh, nml16(x, y-1, pitch, dim.Height, in)*amplitude, (y-1)*vh);
 
1220
                                core::vector3df v2(x*hh, nml16(x, y+1, pitch, dim.Height, in)*amplitude, (y+1)*vh);
 
1221
 
 
1222
                                core::vector3df v = v1-v2;
 
1223
                                core::vector3df h = h1-h2;
 
1224
 
 
1225
                                core::vector3df n = v.crossProduct(h);
 
1226
                                n.normalize();
 
1227
                                n *= 0.5f;
 
1228
                                n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1
 
1229
                                n *= 255.0f;
 
1230
 
 
1231
                                p[y*pitch + x] = video::RGBA16((u32)n.X, (u32)n.Z, (u32)n.Y);
 
1232
                        }
 
1233
 
 
1234
                delete [] in;
 
1235
                texture->unlock();
 
1236
        }
 
1237
 
 
1238
        texture->regenerateMipMapLevels();
 
1239
}
 
1240
 
 
1241
 
 
1242
//! Returns the maximum amount of primitives (mostly vertices) which
 
1243
//! the device is able to render with one drawIndexedTriangleList
 
1244
//! call.
 
1245
u32 CNullDriver::getMaximalPrimitiveCount() const
 
1246
{
 
1247
        return 0xFFFFFFFF;
 
1248
}
 
1249
 
 
1250
 
 
1251
//! checks triangle count and print warning if wrong
 
1252
bool CNullDriver::checkPrimitiveCount(u32 prmCount) const
 
1253
{
 
1254
        const u32 m = getMaximalPrimitiveCount();
 
1255
 
 
1256
        if (prmCount > m)
 
1257
        {
 
1258
                char tmp[1024];
 
1259
                sprintf(tmp,"Could not draw triangles, too many primitives(%u), maxium is %u.", prmCount, m);
 
1260
                os::Printer::log(tmp, ELL_ERROR);
 
1261
                return false;
 
1262
        }
 
1263
 
 
1264
        return true;
 
1265
}
 
1266
 
 
1267
//! Enables or disables a texture creation flag.
 
1268
void CNullDriver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled)
 
1269
{
 
1270
        if (enabled && ((flag == ETCF_ALWAYS_16_BIT) || (flag == ETCF_ALWAYS_32_BIT)
 
1271
                || (flag == ETCF_OPTIMIZED_FOR_QUALITY) || (flag == ETCF_OPTIMIZED_FOR_SPEED)))
 
1272
        {
 
1273
                // disable other formats
 
1274
                setTextureCreationFlag(ETCF_ALWAYS_16_BIT, false);
 
1275
                setTextureCreationFlag(ETCF_ALWAYS_32_BIT, false);
 
1276
                setTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY, false);
 
1277
                setTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED, false);
 
1278
        }
 
1279
 
 
1280
        // set flag
 
1281
        TextureCreationFlags = (TextureCreationFlags & (~flag)) |
 
1282
                ((((u32)!enabled)-1) & flag);
 
1283
}
 
1284
 
 
1285
 
 
1286
//! Returns if a texture creation flag is enabled or disabled.
 
1287
bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const
 
1288
{
 
1289
        return (TextureCreationFlags & flag)!=0;
 
1290
}
 
1291
 
 
1292
 
 
1293
//! Creates a software image from a file.
 
1294
IImage* CNullDriver::createImageFromFile(const io::path& filename)
 
1295
{
 
1296
        if (!filename.size())
 
1297
                return 0;
 
1298
 
 
1299
        IImage* image = 0;
 
1300
        io::IReadFile* file = FileSystem->createAndOpenFile(filename);
 
1301
 
 
1302
        if (file)
 
1303
        {
 
1304
                image = createImageFromFile(file);
 
1305
                file->drop();
 
1306
        }
 
1307
        else
 
1308
                os::Printer::log("Could not open file of image", filename, ELL_WARNING);
 
1309
 
 
1310
        return image;
 
1311
}
 
1312
 
 
1313
 
 
1314
//! Creates a software image from a file.
 
1315
IImage* CNullDriver::createImageFromFile(io::IReadFile* file)
 
1316
{
 
1317
        if (!file)
 
1318
                return 0;
 
1319
 
 
1320
        IImage* image = 0;
 
1321
 
 
1322
        s32 i;
 
1323
 
 
1324
        // try to load file based on file extension
 
1325
        for (i=SurfaceLoader.size()-1; i>=0; --i)
 
1326
        {
 
1327
                if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
 
1328
                {
 
1329
                        // reset file position which might have changed due to previous loadImage calls
 
1330
                        file->seek(0);
 
1331
                        image = SurfaceLoader[i]->loadImage(file);
 
1332
                        if (image)
 
1333
                                return image;
 
1334
                }
 
1335
        }
 
1336
 
 
1337
        // try to load file based on what is in it
 
1338
        for (i=SurfaceLoader.size()-1; i>=0; --i)
 
1339
        {
 
1340
                // dito
 
1341
                file->seek(0);
 
1342
                if (SurfaceLoader[i]->isALoadableFileFormat(file))
 
1343
                {
 
1344
                        file->seek(0);
 
1345
                        image = SurfaceLoader[i]->loadImage(file);
 
1346
                        if (image)
 
1347
                                return image;
 
1348
                }
 
1349
        }
 
1350
 
 
1351
        return 0; // failed to load
 
1352
}
 
1353
 
 
1354
 
 
1355
//! Writes the provided image to disk file
 
1356
bool CNullDriver::writeImageToFile(IImage* image, const io::path& filename,u32 param)
 
1357
{
 
1358
        io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
 
1359
        if(!file)
 
1360
                return false;
 
1361
 
 
1362
        bool result = writeImageToFile(image, file, param);
 
1363
        file->drop();
 
1364
 
 
1365
        return result;
 
1366
}
 
1367
 
 
1368
//! Writes the provided image to a file.
 
1369
bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param)
 
1370
{
 
1371
        if(!file)
 
1372
                return false;
 
1373
 
 
1374
        for (s32 i=SurfaceWriter.size()-1; i>=0; --i)
 
1375
        {
 
1376
                if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName()))
 
1377
                {
 
1378
                        bool written = SurfaceWriter[i]->writeImage(file, image, param);
 
1379
                        if (written)
 
1380
                                return true;
 
1381
                }
 
1382
        }
 
1383
        return false; // failed to write
 
1384
}
 
1385
 
 
1386
 
 
1387
//! Creates a software image from a byte array.
 
1388
IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format,
 
1389
                                        const core::dimension2d<u32>& size,
 
1390
                                        void *data, bool ownForeignMemory,
 
1391
                                        bool deleteMemory)
 
1392
{
 
1393
        if(IImage::isRenderTargetOnlyFormat(format))
 
1394
        {
 
1395
                os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING);
 
1396
                return 0;
 
1397
        }
 
1398
 
 
1399
        return new CImage(format, size, data, ownForeignMemory, deleteMemory);
 
1400
}
 
1401
 
 
1402
 
 
1403
//! Creates an empty software image.
 
1404
IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
 
1405
{
 
1406
        if(IImage::isRenderTargetOnlyFormat(format))
 
1407
        {
 
1408
                os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING);
 
1409
                return 0;
 
1410
        }
 
1411
 
 
1412
        return new CImage(format, size);
 
1413
}
 
1414
 
 
1415
 
 
1416
//! Creates a software image from another image.
 
1417
IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy)
 
1418
{
 
1419
        os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
 
1420
        if(IImage::isRenderTargetOnlyFormat(format))
 
1421
        {
 
1422
                os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING);
 
1423
                return 0;
 
1424
        }
 
1425
 
 
1426
        CImage* tmp = new CImage(format, imageToCopy->getDimension());
 
1427
        imageToCopy->copyTo(tmp);
 
1428
        return tmp;
 
1429
}
 
1430
 
 
1431
 
 
1432
//! Creates a software image from part of another image.
 
1433
IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
 
1434
{
 
1435
        os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
 
1436
        CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension());
 
1437
        imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size));
 
1438
        return tmp;
 
1439
}
 
1440
 
 
1441
 
 
1442
//! Creates a software image from part of a texture.
 
1443
IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
 
1444
{
 
1445
        if ((pos==core::position2di(0,0)) && (size == texture->getSize()))
 
1446
        {
 
1447
                IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(ETLM_READ_ONLY), false);
 
1448
                texture->unlock();
 
1449
                return image;
 
1450
        }
 
1451
        else
 
1452
        {
 
1453
                // make sure to avoid buffer overruns
 
1454
                // make the vector a separate variable for g++ 3.x
 
1455
                const core::vector2d<u32> leftUpper(core::clamp(static_cast<u32>(pos.X), 0u, texture->getSize().Width),
 
1456
                                        core::clamp(static_cast<u32>(pos.Y), 0u, texture->getSize().Height));
 
1457
                const core::rect<u32> clamped(leftUpper,
 
1458
                                        core::dimension2du(core::clamp(static_cast<u32>(size.Width), 0u, texture->getSize().Width),
 
1459
                                        core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height)));
 
1460
                if (!clamped.isValid())
 
1461
                        return 0;
 
1462
                u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY));
 
1463
                if (!src)
 
1464
                        return 0;
 
1465
                IImage* image = new CImage(texture->getColorFormat(), clamped.getSize());
 
1466
                u8* dst = static_cast<u8*>(image->lock());
 
1467
                src += clamped.UpperLeftCorner.Y * texture->getPitch() + image->getBytesPerPixel() * clamped.UpperLeftCorner.X;
 
1468
                for (u32 i=0; i<clamped.getHeight(); ++i)
 
1469
                {
 
1470
                        video::CColorConverter::convert_viaFormat(src, texture->getColorFormat(), clamped.getWidth(), dst, image->getColorFormat());
 
1471
                        src += texture->getPitch();
 
1472
                        dst += image->getPitch();
 
1473
                }
 
1474
                image->unlock();
 
1475
                texture->unlock();
 
1476
                return image;
 
1477
        }
 
1478
}
 
1479
 
 
1480
 
 
1481
//! Sets the fog mode.
 
1482
void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end,
 
1483
                f32 density, bool pixelFog, bool rangeFog)
 
1484
{
 
1485
        FogColor = color;
 
1486
        FogType = fogType;
 
1487
        FogStart = start;
 
1488
        FogEnd = end;
 
1489
        FogDensity = density;
 
1490
        PixelFog = pixelFog;
 
1491
        RangeFog = rangeFog;
 
1492
}
 
1493
 
 
1494
//! Gets the fog mode.
 
1495
void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end,
 
1496
                f32& density, bool& pixelFog, bool& rangeFog)
 
1497
{
 
1498
        color = FogColor;
 
1499
        fogType = FogType;
 
1500
        start = FogStart;
 
1501
        end = FogEnd;
 
1502
        density = FogDensity;
 
1503
        pixelFog = PixelFog;
 
1504
        rangeFog = RangeFog;
 
1505
}
 
1506
 
 
1507
//! Draws a mesh buffer
 
1508
void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb)
 
1509
{
 
1510
        if (!mb)
 
1511
                return;
 
1512
 
 
1513
        //IVertexBuffer and IIndexBuffer later
 
1514
        SHWBufferLink *HWBuffer=getBufferLink(mb);
 
1515
 
 
1516
        if (HWBuffer)
 
1517
                drawHardwareBuffer(HWBuffer);
 
1518
        else
 
1519
                drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType());
 
1520
}
 
1521
 
 
1522
 
 
1523
CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb)
 
1524
{
 
1525
        if (!mb || !isHardwareBufferRecommend(mb))
 
1526
                return 0;
 
1527
 
 
1528
        //search for hardware links
 
1529
        core::map< const scene::IMeshBuffer*,SHWBufferLink* >::Node* node = HWBufferMap.find(mb);
 
1530
        if (node)
 
1531
                return node->getValue();
 
1532
 
 
1533
        return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it
 
1534
}
 
1535
 
 
1536
 
 
1537
//! Update all hardware buffers, remove unused ones
 
1538
void CNullDriver::updateAllHardwareBuffers()
 
1539
{
 
1540
        core::map<const scene::IMeshBuffer*,SHWBufferLink*>::ParentFirstIterator Iterator=HWBufferMap.getParentFirstIterator();
 
1541
 
 
1542
        for (;!Iterator.atEnd();Iterator++)
 
1543
        {
 
1544
                SHWBufferLink *Link=Iterator.getNode()->getValue();
 
1545
 
 
1546
                Link->LastUsed++;
 
1547
                if (Link->LastUsed>20000)
 
1548
                {
 
1549
                        deleteHardwareBuffer(Link);
 
1550
 
 
1551
                        // todo: needs better fix
 
1552
                        Iterator = HWBufferMap.getParentFirstIterator();
 
1553
                }
 
1554
        }
 
1555
}
 
1556
 
 
1557
 
 
1558
void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
 
1559
{
 
1560
        if (!HWBuffer)
 
1561
                return;
 
1562
        HWBufferMap.remove(HWBuffer->MeshBuffer);
 
1563
        delete HWBuffer;
 
1564
}
 
1565
 
 
1566
 
 
1567
//! Remove hardware buffer
 
1568
void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb)
 
1569
{
 
1570
        core::map<const scene::IMeshBuffer*,SHWBufferLink*>::Node* node = HWBufferMap.find(mb);
 
1571
        if (node)
 
1572
                deleteHardwareBuffer(node->getValue());
 
1573
}
 
1574
 
 
1575
 
 
1576
//! Remove all hardware buffers
 
1577
void CNullDriver::removeAllHardwareBuffers()
 
1578
{
 
1579
        while (HWBufferMap.size())
 
1580
                deleteHardwareBuffer(HWBufferMap.getRoot()->getValue());
 
1581
}
 
1582
 
 
1583
 
 
1584
bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb)
 
1585
{
 
1586
        if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
 
1587
                return false;
 
1588
 
 
1589
        if (mb->getVertexCount()<MinVertexCountForVBO)
 
1590
                return false;
 
1591
 
 
1592
        return true;
 
1593
}
 
1594
 
 
1595
 
 
1596
//! Create occlusion query.
 
1597
/** Use node for identification and mesh for occlusion test. */
 
1598
void CNullDriver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh)
 
1599
{
 
1600
        if (!node)
 
1601
                return;
 
1602
        if (!mesh)
 
1603
        {
 
1604
                if ((node->getType() != scene::ESNT_MESH) && (node->getType() != scene::ESNT_ANIMATED_MESH))
 
1605
                        return;
 
1606
                else if (node->getType() == scene::ESNT_MESH)
 
1607
                        mesh = static_cast<scene::IMeshSceneNode*>(node)->getMesh();
 
1608
                else
 
1609
                        mesh = static_cast<scene::IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0);
 
1610
                if (!mesh)
 
1611
                        return;
 
1612
        }
 
1613
 
 
1614
        //search for query
 
1615
        s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1616
        if (index != -1)
 
1617
        {
 
1618
                if (OcclusionQueries[index].Mesh != mesh)
 
1619
                {
 
1620
                        OcclusionQueries[index].Mesh->drop();
 
1621
                        OcclusionQueries[index].Mesh = mesh;
 
1622
                        mesh->grab();
 
1623
                }
 
1624
        }
 
1625
        else
 
1626
        {
 
1627
                OcclusionQueries.push_back(SOccQuery(node, mesh));
 
1628
                node->setAutomaticCulling(node->getAutomaticCulling() | scene::EAC_OCC_QUERY);
 
1629
        }
 
1630
}
 
1631
 
 
1632
 
 
1633
//! Remove occlusion query.
 
1634
void CNullDriver::removeOcclusionQuery(scene::ISceneNode* node)
 
1635
{
 
1636
        //search for query
 
1637
        s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1638
        if (index != -1)
 
1639
        {
 
1640
                node->setAutomaticCulling(node->getAutomaticCulling() & ~scene::EAC_OCC_QUERY);
 
1641
                OcclusionQueries.erase(index);
 
1642
        }
 
1643
}
 
1644
 
 
1645
 
 
1646
//! Remove all occlusion queries.
 
1647
void CNullDriver::removeAllOcclusionQueries()
 
1648
{
 
1649
        for (s32 i=OcclusionQueries.size()-1; i>=0; --i)
 
1650
        {
 
1651
                removeOcclusionQuery(OcclusionQueries[i].Node);
 
1652
        }
 
1653
}
 
1654
 
 
1655
 
 
1656
//! Run occlusion query. Draws mesh stored in query.
 
1657
/** If the mesh shall be rendered visible, use
 
1658
flag to enable the proper material setting. */
 
1659
void CNullDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
 
1660
{
 
1661
        if(!node)
 
1662
                return;
 
1663
        s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1664
        if (index==-1)
 
1665
                return;
 
1666
        OcclusionQueries[index].Run=0;
 
1667
        if (!visible)
 
1668
        {
 
1669
                SMaterial mat;
 
1670
                mat.Lighting=false;
 
1671
                mat.AntiAliasing=0;
 
1672
                mat.ColorMask=ECP_NONE;
 
1673
                mat.GouraudShading=false;
 
1674
                mat.ZWriteEnable=false;
 
1675
                setMaterial(mat);
 
1676
        }
 
1677
        setTransform(video::ETS_WORLD, node->getAbsoluteTransformation());
 
1678
        const scene::IMesh* mesh = OcclusionQueries[index].Mesh;
 
1679
        for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
 
1680
        {
 
1681
                if (visible)
 
1682
                        setMaterial(mesh->getMeshBuffer(i)->getMaterial());
 
1683
                drawMeshBuffer(mesh->getMeshBuffer(i));
 
1684
        }
 
1685
}
 
1686
 
 
1687
 
 
1688
//! Run all occlusion queries. Draws all meshes stored in queries.
 
1689
/** If the meshes shall not be rendered visible, use
 
1690
overrideMaterial to disable the color and depth buffer. */
 
1691
void CNullDriver::runAllOcclusionQueries(bool visible)
 
1692
{
 
1693
        for (u32 i=0; i<OcclusionQueries.size(); ++i)
 
1694
                runOcclusionQuery(OcclusionQueries[i].Node, visible);
 
1695
}
 
1696
 
 
1697
 
 
1698
//! Update occlusion query. Retrieves results from GPU.
 
1699
/** If the query shall not block, set the flag to false.
 
1700
Update might not occur in this case, though */
 
1701
void CNullDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
 
1702
{
 
1703
}
 
1704
 
 
1705
 
 
1706
//! Update all occlusion queries. Retrieves results from GPU.
 
1707
/** If the query shall not block, set the flag to false.
 
1708
Update might not occur in this case, though */
 
1709
void CNullDriver::updateAllOcclusionQueries(bool block)
 
1710
{
 
1711
        for (u32 i=0; i<OcclusionQueries.size(); ++i)
 
1712
        {
 
1713
                if (OcclusionQueries[i].Run==u32(~0))
 
1714
                        continue;
 
1715
                updateOcclusionQuery(OcclusionQueries[i].Node, block);
 
1716
                ++OcclusionQueries[i].Run;
 
1717
                if (OcclusionQueries[i].Run>1000)
 
1718
                        removeOcclusionQuery(OcclusionQueries[i].Node);
 
1719
        }
 
1720
}
 
1721
 
 
1722
 
 
1723
//! Return query result.
 
1724
/** Return value is the number of visible pixels/fragments.
 
1725
The value is a safe approximation, i.e. can be larger then the
 
1726
actual value of pixels. */
 
1727
u32 CNullDriver::getOcclusionQueryResult(scene::ISceneNode* node) const
 
1728
{
 
1729
        return ~0;
 
1730
}
 
1731
 
 
1732
 
 
1733
//! Only used by the internal engine. Used to notify the driver that
 
1734
//! the window was resized.
 
1735
void CNullDriver::OnResize(const core::dimension2d<u32>& size)
 
1736
{
 
1737
        if (ViewPort.getWidth() == (s32)ScreenSize.Width &&
 
1738
                ViewPort.getHeight() == (s32)ScreenSize.Height)
 
1739
                ViewPort = core::rect<s32>(core::position2d<s32>(0,0),
 
1740
                                                                        core::dimension2di(size));
 
1741
 
 
1742
        ScreenSize = size;
 
1743
}
 
1744
 
 
1745
 
 
1746
// adds a material renderer and drops it afterwards. To be used for internal creation
 
1747
s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m)
 
1748
{
 
1749
        s32 i = addMaterialRenderer(m);
 
1750
 
 
1751
        if (m)
 
1752
                m->drop();
 
1753
 
 
1754
        return i;
 
1755
}
 
1756
 
 
1757
 
 
1758
//! Adds a new material renderer to the video device.
 
1759
s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* name)
 
1760
{
 
1761
        if (!renderer)
 
1762
                return -1;
 
1763
 
 
1764
        SMaterialRenderer r;
 
1765
        r.Renderer = renderer;
 
1766
        r.Name = name;
 
1767
 
 
1768
        if (name == 0 && (MaterialRenderers.size() < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ))
 
1769
        {
 
1770
                // set name of built in renderer so that we don't have to implement name
 
1771
                // setting in all available renderers.
 
1772
                r.Name = sBuiltInMaterialTypeNames[MaterialRenderers.size()];
 
1773
        }
 
1774
 
 
1775
        MaterialRenderers.push_back(r);
 
1776
        renderer->grab();
 
1777
 
 
1778
        return MaterialRenderers.size()-1;
 
1779
}
 
1780
 
 
1781
 
 
1782
//! Sets the name of a material renderer.
 
1783
void CNullDriver::setMaterialRendererName(s32 idx, const char* name)
 
1784
{
 
1785
        if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
 
1786
                idx >= (s32)MaterialRenderers.size())
 
1787
                return;
 
1788
 
 
1789
        MaterialRenderers[idx].Name = name;
 
1790
}
 
1791
 
 
1792
 
 
1793
//! Creates material attributes list from a material, usable for serialization and more.
 
1794
io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMaterial& material,
 
1795
        io::SAttributeReadWriteOptions* options)
 
1796
{
 
1797
        io::CAttributes* attr = new io::CAttributes(this);
 
1798
 
 
1799
        attr->addEnum("Type", material.MaterialType, sBuiltInMaterialTypeNames);
 
1800
 
 
1801
        attr->addColor("Ambient", material.AmbientColor);
 
1802
        attr->addColor("Diffuse", material.DiffuseColor);
 
1803
        attr->addColor("Emissive", material.EmissiveColor);
 
1804
        attr->addColor("Specular", material.SpecularColor);
 
1805
 
 
1806
        attr->addFloat("Shininess", material.Shininess);
 
1807
        attr->addFloat("Param1", material.MaterialTypeParam);
 
1808
        attr->addFloat("Param2", material.MaterialTypeParam2);
 
1809
 
 
1810
        core::stringc prefix="Texture";
 
1811
        u32 i;
 
1812
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1813
        {
 
1814
                if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename && material.getTexture(i))
 
1815
                {
 
1816
                        io::path path = FileSystem->getRelativeFilename(
 
1817
                                FileSystem->getAbsolutePath(material.getTexture(i)->getName()), options->Filename);
 
1818
                        attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i), path);
 
1819
                }
 
1820
                else
 
1821
                        attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i));
 
1822
        }
 
1823
 
 
1824
        attr->addBool("Wireframe", material.Wireframe);
 
1825
        attr->addBool("GouraudShading", material.GouraudShading);
 
1826
        attr->addBool("Lighting", material.Lighting);
 
1827
        attr->addBool("ZWriteEnable", material.ZWriteEnable);
 
1828
        attr->addInt("ZBuffer", material.ZBuffer);
 
1829
        attr->addBool("BackfaceCulling", material.BackfaceCulling);
 
1830
        attr->addBool("FrontfaceCulling", material.FrontfaceCulling);
 
1831
        attr->addBool("FogEnable", material.FogEnable);
 
1832
        attr->addBool("NormalizeNormals", material.NormalizeNormals);
 
1833
        attr->addBool("UseMipMaps", material.UseMipMaps);
 
1834
        attr->addInt("AntiAliasing", material.AntiAliasing);
 
1835
        attr->addInt("ColorMask", material.ColorMask);
 
1836
 
 
1837
        prefix = "BilinearFilter";
 
1838
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1839
                attr->addBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].BilinearFilter);
 
1840
        prefix = "TrilinearFilter";
 
1841
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1842
                attr->addBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TrilinearFilter);
 
1843
        prefix = "AnisotropicFilter";
 
1844
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1845
                attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].AnisotropicFilter);
 
1846
        prefix="TextureWrapU";
 
1847
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1848
                attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapU, aTextureClampNames);
 
1849
        prefix="TextureWrapV";
 
1850
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1851
                attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapV, aTextureClampNames);
 
1852
        prefix="LODBias";
 
1853
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1854
                attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].LODBias);
 
1855
 
 
1856
        return attr;
 
1857
}
 
1858
 
 
1859
 
 
1860
//! Fills an SMaterial structure from attributes.
 
1861
void CNullDriver::fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attr)
 
1862
{
 
1863
        outMaterial.MaterialType = video::EMT_SOLID;
 
1864
 
 
1865
        core::stringc name = attr->getAttributeAsString("Type");
 
1866
 
 
1867
        u32 i;
 
1868
 
 
1869
        for ( i=0; i < MaterialRenderers.size(); ++i)
 
1870
                if ( name == MaterialRenderers[i].Name )
 
1871
                {
 
1872
                        outMaterial.MaterialType = (video::E_MATERIAL_TYPE)i;
 
1873
                        break;
 
1874
                }
 
1875
 
 
1876
        outMaterial.AmbientColor = attr->getAttributeAsColor("Ambient");
 
1877
        outMaterial.DiffuseColor = attr->getAttributeAsColor("Diffuse");
 
1878
        outMaterial.EmissiveColor = attr->getAttributeAsColor("Emissive");
 
1879
        outMaterial.SpecularColor = attr->getAttributeAsColor("Specular");
 
1880
 
 
1881
        outMaterial.Shininess = attr->getAttributeAsFloat("Shininess");
 
1882
        outMaterial.MaterialTypeParam = attr->getAttributeAsFloat("Param1");
 
1883
        outMaterial.MaterialTypeParam2 = attr->getAttributeAsFloat("Param2");
 
1884
 
 
1885
        core::stringc prefix="Texture";
 
1886
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1887
                outMaterial.setTexture(i, attr->getAttributeAsTexture((prefix+core::stringc(i+1)).c_str()));
 
1888
 
 
1889
        outMaterial.Wireframe = attr->getAttributeAsBool("Wireframe");
 
1890
        outMaterial.GouraudShading = attr->getAttributeAsBool("GouraudShading");
 
1891
        outMaterial.Lighting = attr->getAttributeAsBool("Lighting");
 
1892
        outMaterial.ZWriteEnable = attr->getAttributeAsBool("ZWriteEnable");
 
1893
        outMaterial.ZBuffer = (u8)attr->getAttributeAsInt("ZBuffer");
 
1894
        outMaterial.BackfaceCulling = attr->getAttributeAsBool("BackfaceCulling");
 
1895
        outMaterial.FrontfaceCulling = attr->getAttributeAsBool("FrontfaceCulling");
 
1896
        outMaterial.FogEnable = attr->getAttributeAsBool("FogEnable");
 
1897
        outMaterial.NormalizeNormals = attr->getAttributeAsBool("NormalizeNormals");
 
1898
        if (attr->existsAttribute("UseMipMaps")) // legacy
 
1899
                outMaterial.UseMipMaps = attr->getAttributeAsBool("UseMipMaps");
 
1900
        else
 
1901
                outMaterial.UseMipMaps = true;
 
1902
 
 
1903
        // default 0 is ok
 
1904
        outMaterial.AntiAliasing = attr->getAttributeAsInt("AntiAliasing");
 
1905
        if (attr->existsAttribute("ColorMask"))
 
1906
                outMaterial.ColorMask = attr->getAttributeAsInt("ColorMask");
 
1907
        prefix = "BilinearFilter";
 
1908
        if (attr->existsAttribute(prefix.c_str())) // legacy
 
1909
                outMaterial.setFlag(EMF_BILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str()));
 
1910
        else
 
1911
                for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1912
                        outMaterial.TextureLayer[i].BilinearFilter = attr->getAttributeAsBool((prefix+core::stringc(i+1)).c_str());
 
1913
 
 
1914
        prefix = "TrilinearFilter";
 
1915
        if (attr->existsAttribute(prefix.c_str())) // legacy
 
1916
                outMaterial.setFlag(EMF_TRILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str()));
 
1917
        else
 
1918
                for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1919
                        outMaterial.TextureLayer[i].TrilinearFilter = attr->getAttributeAsBool((prefix+core::stringc(i+1)).c_str());
 
1920
 
 
1921
        prefix = "AnisotropicFilter";
 
1922
        if (attr->existsAttribute(prefix.c_str())) // legacy
 
1923
                outMaterial.setFlag(EMF_ANISOTROPIC_FILTER, attr->getAttributeAsBool(prefix.c_str()));
 
1924
        else
 
1925
                for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1926
                        outMaterial.TextureLayer[i].AnisotropicFilter = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str());
 
1927
 
 
1928
        prefix = "TextureWrap";
 
1929
        if (attr->existsAttribute(prefix.c_str())) // legacy
 
1930
        {
 
1931
                for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1932
                {
 
1933
                        outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames);
 
1934
                        outMaterial.TextureLayer[i].TextureWrapV = outMaterial.TextureLayer[i].TextureWrapU;
 
1935
                }
 
1936
        }
 
1937
        else
 
1938
        {
 
1939
                for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1940
                {
 
1941
                        outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"U"+core::stringc(i+1)).c_str(), aTextureClampNames);
 
1942
                        outMaterial.TextureLayer[i].TextureWrapV = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"V"+core::stringc(i+1)).c_str(), aTextureClampNames);
 
1943
                }
 
1944
        }
 
1945
 
 
1946
        // default 0 is ok
 
1947
        prefix="LODBias";
 
1948
        for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
1949
                outMaterial.TextureLayer[i].LODBias = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str());
 
1950
}
 
1951
 
 
1952
 
 
1953
//! Returns driver and operating system specific data about the IVideoDriver.
 
1954
const SExposedVideoData& CNullDriver::getExposedVideoData()
 
1955
{
 
1956
        return ExposedData;
 
1957
}
 
1958
 
 
1959
 
 
1960
//! Returns type of video driver
 
1961
E_DRIVER_TYPE CNullDriver::getDriverType() const
 
1962
{
 
1963
        return EDT_NULL;
 
1964
}
 
1965
 
 
1966
 
 
1967
//! deletes all material renderers
 
1968
void CNullDriver::deleteMaterialRenders()
 
1969
{
 
1970
        // delete material renderers
 
1971
        for (u32 i=0; i<MaterialRenderers.size(); ++i)
 
1972
                if (MaterialRenderers[i].Renderer)
 
1973
                        MaterialRenderers[i].Renderer->drop();
 
1974
 
 
1975
        MaterialRenderers.clear();
 
1976
}
 
1977
 
 
1978
 
 
1979
//! Returns pointer to material renderer or null
 
1980
IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx)
 
1981
{
 
1982
        if ( idx < MaterialRenderers.size() )
 
1983
                return MaterialRenderers[idx].Renderer;
 
1984
        else
 
1985
                return 0;
 
1986
}
 
1987
 
 
1988
 
 
1989
//! Returns amount of currently available material renderers.
 
1990
u32 CNullDriver::getMaterialRendererCount() const
 
1991
{
 
1992
        return MaterialRenderers.size();
 
1993
}
 
1994
 
 
1995
 
 
1996
//! Returns name of the material renderer
 
1997
const char* CNullDriver::getMaterialRendererName(u32 idx) const
 
1998
{
 
1999
        if ( idx < MaterialRenderers.size() )
 
2000
                return MaterialRenderers[idx].Name.c_str();
 
2001
 
 
2002
        return 0;
 
2003
}
 
2004
 
 
2005
 
 
2006
//! Returns pointer to the IGPUProgrammingServices interface.
 
2007
IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices()
 
2008
{
 
2009
        return this;
 
2010
}
 
2011
 
 
2012
 
 
2013
//! Adds a new material renderer to the VideoDriver, based on a high level shading language.
 
2014
s32 CNullDriver::addHighLevelShaderMaterial(
 
2015
        const c8* vertexShaderProgram,
 
2016
        const c8* vertexShaderEntryPointName,
 
2017
        E_VERTEX_SHADER_TYPE vsCompileTarget,
 
2018
        const c8* pixelShaderProgram,
 
2019
        const c8* pixelShaderEntryPointName,
 
2020
        E_PIXEL_SHADER_TYPE psCompileTarget,
 
2021
        const c8* geometryShaderProgram,
 
2022
        const c8* geometryShaderEntryPointName,
 
2023
        E_GEOMETRY_SHADER_TYPE gsCompileTarget,
 
2024
        scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
 
2025
        u32 verticesOut,
 
2026
        IShaderConstantSetCallBack* callback,
 
2027
        E_MATERIAL_TYPE baseMaterial,
 
2028
        s32 userData)
 
2029
{
 
2030
        os::Printer::log("High level shader materials not available (yet) in this driver, sorry");
 
2031
        return -1;
 
2032
}
 
2033
 
 
2034
 
 
2035
//! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
 
2036
//! but tries to load the programs from files.
 
2037
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
 
2038
                const io::path& vertexShaderProgramFileName,
 
2039
                const c8* vertexShaderEntryPointName,
 
2040
                E_VERTEX_SHADER_TYPE vsCompileTarget,
 
2041
                const io::path& pixelShaderProgramFileName,
 
2042
                const c8* pixelShaderEntryPointName,
 
2043
                E_PIXEL_SHADER_TYPE psCompileTarget,
 
2044
                const io::path& geometryShaderProgramFileName,
 
2045
                const c8* geometryShaderEntryPointName,
 
2046
                E_GEOMETRY_SHADER_TYPE gsCompileTarget,
 
2047
                scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
 
2048
                u32 verticesOut,
 
2049
                IShaderConstantSetCallBack* callback,
 
2050
                E_MATERIAL_TYPE baseMaterial,
 
2051
                s32 userData)
 
2052
{
 
2053
        io::IReadFile* vsfile = 0;
 
2054
        io::IReadFile* psfile = 0;
 
2055
        io::IReadFile* gsfile = 0;
 
2056
 
 
2057
        if (vertexShaderProgramFileName.size() )
 
2058
        {
 
2059
                vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
 
2060
                if (!vsfile)
 
2061
                {
 
2062
                        os::Printer::log("Could not open vertex shader program file",
 
2063
                                vertexShaderProgramFileName, ELL_WARNING);
 
2064
                }
 
2065
        }
 
2066
 
 
2067
        if (pixelShaderProgramFileName.size() )
 
2068
        {
 
2069
                psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
 
2070
                if (!psfile)
 
2071
                {
 
2072
                        os::Printer::log("Could not open pixel shader program file",
 
2073
                                pixelShaderProgramFileName, ELL_WARNING);
 
2074
                }
 
2075
        }
 
2076
 
 
2077
        if (geometryShaderProgramFileName.size() )
 
2078
        {
 
2079
                gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName);
 
2080
                if (!gsfile)
 
2081
                {
 
2082
                        os::Printer::log("Could not open geometry shader program file",
 
2083
                                geometryShaderProgramFileName, ELL_WARNING);
 
2084
                }
 
2085
        }
 
2086
 
 
2087
        s32 result = addHighLevelShaderMaterialFromFiles(
 
2088
                vsfile, vertexShaderEntryPointName, vsCompileTarget,
 
2089
                psfile, pixelShaderEntryPointName, psCompileTarget,
 
2090
                gsfile, geometryShaderEntryPointName, gsCompileTarget,
 
2091
                inType, outType, verticesOut,
 
2092
                callback, baseMaterial, userData);
 
2093
 
 
2094
        if (psfile)
 
2095
                psfile->drop();
 
2096
 
 
2097
        if (vsfile)
 
2098
                vsfile->drop();
 
2099
 
 
2100
        if (gsfile)
 
2101
                gsfile->drop();
 
2102
 
 
2103
        return result;
 
2104
}
 
2105
 
 
2106
 
 
2107
//! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
 
2108
//! but tries to load the programs from files.
 
2109
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
 
2110
                io::IReadFile* vertexShaderProgram,
 
2111
                const c8* vertexShaderEntryPointName,
 
2112
                E_VERTEX_SHADER_TYPE vsCompileTarget,
 
2113
                io::IReadFile* pixelShaderProgram,
 
2114
                const c8* pixelShaderEntryPointName,
 
2115
                E_PIXEL_SHADER_TYPE psCompileTarget,
 
2116
                io::IReadFile* geometryShaderProgram,
 
2117
                const c8* geometryShaderEntryPointName,
 
2118
                E_GEOMETRY_SHADER_TYPE gsCompileTarget,
 
2119
                scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
 
2120
                u32 verticesOut,
 
2121
                IShaderConstantSetCallBack* callback,
 
2122
                E_MATERIAL_TYPE baseMaterial,
 
2123
                s32 userData)
 
2124
{
 
2125
        c8* vs = 0;
 
2126
        c8* ps = 0;
 
2127
        c8* gs = 0;
 
2128
 
 
2129
        if (vertexShaderProgram)
 
2130
        {
 
2131
                const long size = vertexShaderProgram->getSize();
 
2132
                if (size)
 
2133
                {
 
2134
                        vs = new c8[size+1];
 
2135
                        vertexShaderProgram->read(vs, size);
 
2136
                        vs[size] = 0;
 
2137
                }
 
2138
        }
 
2139
 
 
2140
        if (pixelShaderProgram)
 
2141
        {
 
2142
                const long size = pixelShaderProgram->getSize();
 
2143
                if (size)
 
2144
                {
 
2145
                        // if both handles are the same we must reset the file
 
2146
                        if (pixelShaderProgram==vertexShaderProgram)
 
2147
                                pixelShaderProgram->seek(0);
 
2148
                        ps = new c8[size+1];
 
2149
                        pixelShaderProgram->read(ps, size);
 
2150
                        ps[size] = 0;
 
2151
                }
 
2152
        }
 
2153
 
 
2154
        if (geometryShaderProgram)
 
2155
        {
 
2156
                const long size = geometryShaderProgram->getSize();
 
2157
                if (size)
 
2158
                {
 
2159
                        // if both handles are the same we must reset the file
 
2160
                        if ((geometryShaderProgram==vertexShaderProgram) ||
 
2161
                                        (geometryShaderProgram==pixelShaderProgram))
 
2162
                                geometryShaderProgram->seek(0);
 
2163
                        gs = new c8[size+1];
 
2164
                        geometryShaderProgram->read(gs, size);
 
2165
                        gs[size] = 0;
 
2166
                }
 
2167
        }
 
2168
 
 
2169
        s32 result = this->addHighLevelShaderMaterial(
 
2170
                vs, vertexShaderEntryPointName, vsCompileTarget,
 
2171
                ps, pixelShaderEntryPointName, psCompileTarget,
 
2172
                gs, geometryShaderEntryPointName, gsCompileTarget,
 
2173
                inType, outType, verticesOut,
 
2174
                callback, baseMaterial, userData);
 
2175
 
 
2176
        delete [] vs;
 
2177
        delete [] ps;
 
2178
        delete [] gs;
 
2179
 
 
2180
        return result;
 
2181
}
 
2182
 
 
2183
 
 
2184
//! Adds a new material renderer to the VideoDriver, using pixel and/or
 
2185
//! vertex shaders to render geometry.
 
2186
s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram,
 
2187
        const c8* pixelShaderProgram,
 
2188
        IShaderConstantSetCallBack* callback,
 
2189
        E_MATERIAL_TYPE baseMaterial,
 
2190
        s32 userData)
 
2191
{
 
2192
        os::Printer::log("Shader materials not implemented yet in this driver, sorry.");
 
2193
        return -1;
 
2194
}
 
2195
 
 
2196
 
 
2197
//! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
 
2198
//! programs from files.
 
2199
s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram,
 
2200
        io::IReadFile* pixelShaderProgram,
 
2201
        IShaderConstantSetCallBack* callback,
 
2202
        E_MATERIAL_TYPE baseMaterial,
 
2203
        s32 userData)
 
2204
{
 
2205
        c8* vs = 0;
 
2206
        c8* ps = 0;
 
2207
 
 
2208
        if (vertexShaderProgram)
 
2209
        {
 
2210
                const long size = vertexShaderProgram->getSize();
 
2211
                if (size)
 
2212
                {
 
2213
                        vs = new c8[size+1];
 
2214
                        vertexShaderProgram->read(vs, size);
 
2215
                        vs[size] = 0;
 
2216
                }
 
2217
        }
 
2218
 
 
2219
        if (pixelShaderProgram)
 
2220
        {
 
2221
                const long size = pixelShaderProgram->getSize();
 
2222
                if (size)
 
2223
                {
 
2224
                        ps = new c8[size+1];
 
2225
                        pixelShaderProgram->read(ps, size);
 
2226
                        ps[size] = 0;
 
2227
                }
 
2228
        }
 
2229
 
 
2230
        s32 result = addShaderMaterial(vs, ps, callback, baseMaterial, userData);
 
2231
 
 
2232
        delete [] vs;
 
2233
        delete [] ps;
 
2234
 
 
2235
        return result;
 
2236
}
 
2237
 
 
2238
 
 
2239
//! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
 
2240
//! programs from files.
 
2241
s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName,
 
2242
        const io::path& pixelShaderProgramFileName,
 
2243
        IShaderConstantSetCallBack* callback,
 
2244
        E_MATERIAL_TYPE baseMaterial,
 
2245
        s32 userData)
 
2246
{
 
2247
        io::IReadFile* vsfile = 0;
 
2248
        io::IReadFile* psfile = 0;
 
2249
 
 
2250
        if (vertexShaderProgramFileName.size())
 
2251
        {
 
2252
                vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
 
2253
                if (!vsfile)
 
2254
                {
 
2255
                        os::Printer::log("Could not open vertex shader program file",
 
2256
                                vertexShaderProgramFileName, ELL_WARNING);
 
2257
                        return -1;
 
2258
                }
 
2259
        }
 
2260
 
 
2261
        if (pixelShaderProgramFileName.size())
 
2262
        {
 
2263
                psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
 
2264
                if (!psfile)
 
2265
                {
 
2266
                        os::Printer::log("Could not open pixel shader program file",
 
2267
                                pixelShaderProgramFileName, ELL_WARNING);
 
2268
                        if (vsfile)
 
2269
                                vsfile->drop();
 
2270
                        return -1;
 
2271
                }
 
2272
        }
 
2273
 
 
2274
        s32 result = addShaderMaterialFromFiles(vsfile, psfile, callback,
 
2275
                baseMaterial, userData);
 
2276
 
 
2277
        if (psfile)
 
2278
                psfile->drop();
 
2279
 
 
2280
        if (vsfile)
 
2281
                vsfile->drop();
 
2282
 
 
2283
        return result;
 
2284
}
 
2285
 
 
2286
 
 
2287
//! Creates a render target texture.
 
2288
ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d<u32>& size,
 
2289
                const io::path&name, const ECOLOR_FORMAT format)
 
2290
{
 
2291
        return 0;
 
2292
}
 
2293
 
 
2294
 
 
2295
//! Clears the ZBuffer.
 
2296
void CNullDriver::clearZBuffer()
 
2297
{
 
2298
}
 
2299
 
 
2300
 
 
2301
//! Returns a pointer to the mesh manipulator.
 
2302
scene::IMeshManipulator* CNullDriver::getMeshManipulator()
 
2303
{
 
2304
        return MeshManipulator;
 
2305
}
 
2306
 
 
2307
 
 
2308
//! Returns an image created from the last rendered frame.
 
2309
IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
 
2310
{
 
2311
        return 0;
 
2312
}
 
2313
 
 
2314
 
 
2315
// prints renderer version
 
2316
void CNullDriver::printVersion()
 
2317
{
 
2318
        core::stringw namePrint = L"Using renderer: ";
 
2319
        namePrint += getName();
 
2320
        os::Printer::log(namePrint.c_str(), ELL_INFORMATION);
 
2321
}
 
2322
 
 
2323
 
 
2324
//! creates a video driver
 
2325
IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
 
2326
{
 
2327
        CNullDriver* nullDriver = new CNullDriver(io, screenSize);
 
2328
 
 
2329
        // create empty material renderers
 
2330
        for(u32 i=0; sBuiltInMaterialTypeNames[i]; ++i)
 
2331
        {
 
2332
                IMaterialRenderer* imr = new IMaterialRenderer();
 
2333
                nullDriver->addMaterialRenderer(imr);
 
2334
                imr->drop();
 
2335
        }
 
2336
 
 
2337
        return nullDriver;
 
2338
}
 
2339
 
 
2340
 
 
2341
//! Set/unset a clipping plane.
 
2342
//! There are at least 6 clipping planes available for the user to set at will.
 
2343
//! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
 
2344
//! \param plane: The plane itself.
 
2345
//! \param enable: If true, enable the clipping plane else disable it.
 
2346
bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
 
2347
{
 
2348
        return false;
 
2349
}
 
2350
 
 
2351
 
 
2352
//! Enable/disable a clipping plane.
 
2353
void CNullDriver::enableClipPlane(u32 index, bool enable)
 
2354
{
 
2355
        // not necessary
 
2356
}
 
2357
 
 
2358
 
 
2359
ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d<u32>& size,
 
2360
                const c8* name)
 
2361
{
 
2362
        os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead");
 
2363
        ITexture* tex = addRenderTargetTexture(size, name);
 
2364
        tex->grab();
 
2365
        return tex;
 
2366
}
 
2367
 
 
2368
 
 
2369
void CNullDriver::setMinHardwareBufferVertexCount(u32 count)
 
2370
{
 
2371
        MinVertexCountForVBO = count;
 
2372
}
 
2373
 
 
2374
 
 
2375
SOverrideMaterial& CNullDriver::getOverrideMaterial()
 
2376
{
 
2377
        return OverrideMaterial;
 
2378
}
 
2379
 
 
2380
 
 
2381
//! Get the 2d override material for altering its values
 
2382
SMaterial& CNullDriver::getMaterial2D()
 
2383
{
 
2384
        return OverrideMaterial2D;
 
2385
}
 
2386
 
 
2387
 
 
2388
//! Enable the 2d override material
 
2389
void CNullDriver::enableMaterial2D(bool enable)
 
2390
{
 
2391
        OverrideMaterial2DEnabled=enable;
 
2392
}
 
2393
 
 
2394
 
 
2395
core::dimension2du CNullDriver::getMaxTextureSize() const
 
2396
{
 
2397
        return core::dimension2du(0x10000,0x10000); // maybe large enough
 
2398
}
 
2399
 
 
2400
 
 
2401
//! Color conversion convenience function
 
2402
/** Convert an image (as array of pixels) from source to destination
 
2403
array, thereby converting the color format. The pixel size is
 
2404
determined by the color formats.
 
2405
\param sP Pointer to source
 
2406
\param sF Color format of source
 
2407
\param sN Number of pixels to convert, both array must be large enough
 
2408
\param dP Pointer to destination
 
2409
\param dF Color format of destination
 
2410
*/
 
2411
void CNullDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN,
 
2412
                void* dP, ECOLOR_FORMAT dF) const
 
2413
{
 
2414
        video::CColorConverter::convert_viaFormat(sP, sF, sN, dP, dF);
 
2415
}
 
2416
 
 
2417
 
 
2418
} // end namespace
 
2419
} // end namespace