diff options
author | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
commit | 7028cbe09c688437910a25623098762bf0fa592d (patch) | |
tree | 10b5af58277d9880380c2251f109325542c4e6eb /libraries/irrlicht-1.8.1/source/Irrlicht/CNullDriver.cpp | |
parent | Move lemon to the src/others directory. (diff) | |
download | SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.zip SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.gz SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.bz2 SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.xz |
Move Irrlicht to src/others.
Diffstat (limited to 'libraries/irrlicht-1.8.1/source/Irrlicht/CNullDriver.cpp')
-rw-r--r-- | libraries/irrlicht-1.8.1/source/Irrlicht/CNullDriver.cpp | 2448 |
1 files changed, 0 insertions, 2448 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CNullDriver.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CNullDriver.cpp deleted file mode 100644 index 3d02abe..0000000 --- a/libraries/irrlicht-1.8.1/source/Irrlicht/CNullDriver.cpp +++ /dev/null | |||
@@ -1,2448 +0,0 @@ | |||
1 | // Copyright (C) 2002-2012 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 | if (destRect.isValid()) | ||
777 | draw2DImage(texture, core::position2d<s32>(destRect.UpperLeftCorner), | ||
778 | sourceRect, clipRect, colors?colors[0]:video::SColor(0xffffffff), | ||
779 | useAlphaChannelOfTexture); | ||
780 | } | ||
781 | |||
782 | |||
783 | //! 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. | ||
784 | void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos, | ||
785 | const core::rect<s32>& sourceRect, | ||
786 | const core::rect<s32>* clipRect, SColor color, | ||
787 | bool useAlphaChannelOfTexture) | ||
788 | { | ||
789 | } | ||
790 | |||
791 | |||
792 | //! Draws the outline of a 2d rectangle | ||
793 | void CNullDriver::draw2DRectangleOutline(const core::recti& pos, SColor color) | ||
794 | { | ||
795 | draw2DLine(pos.UpperLeftCorner, core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), color); | ||
796 | draw2DLine(core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), pos.LowerRightCorner, color); | ||
797 | draw2DLine(pos.LowerRightCorner, core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), color); | ||
798 | draw2DLine(core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), pos.UpperLeftCorner, color); | ||
799 | } | ||
800 | |||
801 | |||
802 | //! Draw a 2d rectangle | ||
803 | void CNullDriver::draw2DRectangle(SColor color, const core::rect<s32>& pos, const core::rect<s32>* clip) | ||
804 | { | ||
805 | draw2DRectangle(pos, color, color, color, color, clip); | ||
806 | } | ||
807 | |||
808 | |||
809 | |||
810 | //! Draws a 2d rectangle with a gradient. | ||
811 | void CNullDriver::draw2DRectangle(const core::rect<s32>& pos, | ||
812 | SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, | ||
813 | const core::rect<s32>* clip) | ||
814 | { | ||
815 | } | ||
816 | |||
817 | |||
818 | |||
819 | //! Draws a 2d line. | ||
820 | void CNullDriver::draw2DLine(const core::position2d<s32>& start, | ||
821 | const core::position2d<s32>& end, SColor color) | ||
822 | { | ||
823 | } | ||
824 | |||
825 | //! Draws a pixel | ||
826 | void CNullDriver::drawPixel(u32 x, u32 y, const SColor & color) | ||
827 | { | ||
828 | } | ||
829 | |||
830 | |||
831 | //! Draws a non filled concyclic regular 2d polyon. | ||
832 | void CNullDriver::draw2DPolygon(core::position2d<s32> center, | ||
833 | f32 radius, video::SColor color, s32 count) | ||
834 | { | ||
835 | if (count < 2) | ||
836 | return; | ||
837 | |||
838 | core::position2d<s32> first; | ||
839 | core::position2d<s32> a,b; | ||
840 | |||
841 | for (s32 j=0; j<count; ++j) | ||
842 | { | ||
843 | b = a; | ||
844 | |||
845 | f32 p = j / (f32)count * (core::PI*2); | ||
846 | a = center + core::position2d<s32>((s32)(sin(p)*radius), (s32)(cos(p)*radius)); | ||
847 | |||
848 | if (j==0) | ||
849 | first = a; | ||
850 | else | ||
851 | draw2DLine(a, b, color); | ||
852 | } | ||
853 | |||
854 | draw2DLine(a, first, color); | ||
855 | } | ||
856 | |||
857 | |||
858 | //! returns color format | ||
859 | ECOLOR_FORMAT CNullDriver::getColorFormat() const | ||
860 | { | ||
861 | return ECF_R5G6B5; | ||
862 | } | ||
863 | |||
864 | |||
865 | //! returns screen size | ||
866 | const core::dimension2d<u32>& CNullDriver::getScreenSize() const | ||
867 | { | ||
868 | return ScreenSize; | ||
869 | } | ||
870 | |||
871 | |||
872 | //! returns the current render target size, | ||
873 | //! or the screen size if render targets are not implemented | ||
874 | const core::dimension2d<u32>& CNullDriver::getCurrentRenderTargetSize() const | ||
875 | { | ||
876 | return ScreenSize; | ||
877 | } | ||
878 | |||
879 | |||
880 | // returns current frames per second value | ||
881 | s32 CNullDriver::getFPS() const | ||
882 | { | ||
883 | return FPSCounter.getFPS(); | ||
884 | } | ||
885 | |||
886 | |||
887 | |||
888 | //! returns amount of primitives (mostly triangles) were drawn in the last frame. | ||
889 | //! very useful method for statistics. | ||
890 | u32 CNullDriver::getPrimitiveCountDrawn( u32 param ) const | ||
891 | { | ||
892 | return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage() : FPSCounter.getPrimitiveTotal(); | ||
893 | } | ||
894 | |||
895 | |||
896 | |||
897 | //! Sets the dynamic ambient light color. The default color is | ||
898 | //! (0,0,0,0) which means it is dark. | ||
899 | //! \param color: New color of the ambient light. | ||
900 | void CNullDriver::setAmbientLight(const SColorf& color) | ||
901 | { | ||
902 | } | ||
903 | |||
904 | |||
905 | |||
906 | //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 | ||
907 | //! driver, it would return "Direct3D8". | ||
908 | |||
909 | const wchar_t* CNullDriver::getName() const | ||
910 | { | ||
911 | return L"Irrlicht NullDevice"; | ||
912 | } | ||
913 | |||
914 | |||
915 | |||
916 | //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do | ||
917 | //! this: Frist, draw all geometry. Then use this method, to draw the shadow | ||
918 | //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. | ||
919 | void CNullDriver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible) | ||
920 | { | ||
921 | } | ||
922 | |||
923 | |||
924 | //! Fills the stencil shadow with color. After the shadow volume has been drawn | ||
925 | //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this | ||
926 | //! to draw the color of the shadow. | ||
927 | void CNullDriver::drawStencilShadow(bool clearStencilBuffer, | ||
928 | video::SColor leftUpEdge, video::SColor rightUpEdge, | ||
929 | video::SColor leftDownEdge, video::SColor rightDownEdge) | ||
930 | { | ||
931 | } | ||
932 | |||
933 | |||
934 | //! deletes all dynamic lights there are | ||
935 | void CNullDriver::deleteAllDynamicLights() | ||
936 | { | ||
937 | Lights.set_used(0); | ||
938 | } | ||
939 | |||
940 | |||
941 | //! adds a dynamic light | ||
942 | s32 CNullDriver::addDynamicLight(const SLight& light) | ||
943 | { | ||
944 | Lights.push_back(light); | ||
945 | return Lights.size() - 1; | ||
946 | } | ||
947 | |||
948 | //! Turns a dynamic light on or off | ||
949 | //! \param lightIndex: the index returned by addDynamicLight | ||
950 | //! \param turnOn: true to turn the light on, false to turn it off | ||
951 | void CNullDriver::turnLightOn(s32 lightIndex, bool turnOn) | ||
952 | { | ||
953 | // Do nothing | ||
954 | } | ||
955 | |||
956 | |||
957 | //! returns the maximal amount of dynamic lights the device can handle | ||
958 | u32 CNullDriver::getMaximalDynamicLightAmount() const | ||
959 | { | ||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | |||
964 | //! Returns current amount of dynamic lights set | ||
965 | //! \return Current amount of dynamic lights set | ||
966 | u32 CNullDriver::getDynamicLightCount() const | ||
967 | { | ||
968 | return Lights.size(); | ||
969 | } | ||
970 | |||
971 | |||
972 | //! Returns light data which was previously set by IVideoDriver::addDynamicLight(). | ||
973 | //! \param idx: Zero based index of the light. Must be greater than 0 and smaller | ||
974 | //! than IVideoDriver()::getDynamicLightCount. | ||
975 | //! \return Light data. | ||
976 | const SLight& CNullDriver::getDynamicLight(u32 idx) const | ||
977 | { | ||
978 | if ( idx < Lights.size() ) | ||
979 | return Lights[idx]; | ||
980 | else | ||
981 | return *((SLight*)0); | ||
982 | } | ||
983 | |||
984 | |||
985 | //! Creates a boolean alpha channel of the texture based of an color key. | ||
986 | void CNullDriver::makeColorKeyTexture(video::ITexture* texture, | ||
987 | video::SColor color, | ||
988 | bool zeroTexels) const | ||
989 | { | ||
990 | if (!texture) | ||
991 | return; | ||
992 | |||
993 | if (texture->getColorFormat() != ECF_A1R5G5B5 && | ||
994 | texture->getColorFormat() != ECF_A8R8G8B8 ) | ||
995 | { | ||
996 | os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR); | ||
997 | return; | ||
998 | } | ||
999 | |||
1000 | if (texture->getColorFormat() == ECF_A1R5G5B5) | ||
1001 | { | ||
1002 | u16 *p = (u16*)texture->lock(); | ||
1003 | |||
1004 | if (!p) | ||
1005 | { | ||
1006 | os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); | ||
1007 | return; | ||
1008 | } | ||
1009 | |||
1010 | const core::dimension2d<u32> dim = texture->getSize(); | ||
1011 | const u32 pitch = texture->getPitch() / 2; | ||
1012 | |||
1013 | // color with alpha disabled (i.e. fully transparent) | ||
1014 | const u16 refZeroAlpha = (0x7fff & color.toA1R5G5B5()); | ||
1015 | |||
1016 | const u32 pixels = pitch * dim.Height; | ||
1017 | |||
1018 | for (u32 pixel = 0; pixel < pixels; ++ pixel) | ||
1019 | { | ||
1020 | // If the color matches the reference color, ignoring alphas, | ||
1021 | // set the alpha to zero. | ||
1022 | if(((*p) & 0x7fff) == refZeroAlpha) | ||
1023 | { | ||
1024 | if(zeroTexels) | ||
1025 | (*p) = 0; | ||
1026 | else | ||
1027 | (*p) = refZeroAlpha; | ||
1028 | } | ||
1029 | |||
1030 | ++p; | ||
1031 | } | ||
1032 | |||
1033 | texture->unlock(); | ||
1034 | } | ||
1035 | else | ||
1036 | { | ||
1037 | u32 *p = (u32*)texture->lock(); | ||
1038 | |||
1039 | if (!p) | ||
1040 | { | ||
1041 | os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); | ||
1042 | return; | ||
1043 | } | ||
1044 | |||
1045 | core::dimension2d<u32> dim = texture->getSize(); | ||
1046 | u32 pitch = texture->getPitch() / 4; | ||
1047 | |||
1048 | // color with alpha disabled (fully transparent) | ||
1049 | const u32 refZeroAlpha = 0x00ffffff & color.color; | ||
1050 | |||
1051 | const u32 pixels = pitch * dim.Height; | ||
1052 | for (u32 pixel = 0; pixel < pixels; ++ pixel) | ||
1053 | { | ||
1054 | // If the color matches the reference color, ignoring alphas, | ||
1055 | // set the alpha to zero. | ||
1056 | if(((*p) & 0x00ffffff) == refZeroAlpha) | ||
1057 | { | ||
1058 | if(zeroTexels) | ||
1059 | (*p) = 0; | ||
1060 | else | ||
1061 | (*p) = refZeroAlpha; | ||
1062 | } | ||
1063 | |||
1064 | ++p; | ||
1065 | } | ||
1066 | |||
1067 | texture->unlock(); | ||
1068 | } | ||
1069 | texture->regenerateMipMapLevels(); | ||
1070 | } | ||
1071 | |||
1072 | |||
1073 | |||
1074 | //! Creates an boolean alpha channel of the texture based of an color key position. | ||
1075 | void CNullDriver::makeColorKeyTexture(video::ITexture* texture, | ||
1076 | core::position2d<s32> colorKeyPixelPos, | ||
1077 | bool zeroTexels) const | ||
1078 | { | ||
1079 | if (!texture) | ||
1080 | return; | ||
1081 | |||
1082 | if (texture->getColorFormat() != ECF_A1R5G5B5 && | ||
1083 | texture->getColorFormat() != ECF_A8R8G8B8 ) | ||
1084 | { | ||
1085 | os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR); | ||
1086 | return; | ||
1087 | } | ||
1088 | |||
1089 | SColor colorKey; | ||
1090 | |||
1091 | if (texture->getColorFormat() == ECF_A1R5G5B5) | ||
1092 | { | ||
1093 | u16 *p = (u16*)texture->lock(ETLM_READ_ONLY); | ||
1094 | |||
1095 | if (!p) | ||
1096 | { | ||
1097 | os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); | ||
1098 | return; | ||
1099 | } | ||
1100 | |||
1101 | u32 pitch = texture->getPitch() / 2; | ||
1102 | |||
1103 | const u16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X]; | ||
1104 | |||
1105 | colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit); | ||
1106 | } | ||
1107 | else | ||
1108 | { | ||
1109 | u32 *p = (u32*)texture->lock(ETLM_READ_ONLY); | ||
1110 | |||
1111 | if (!p) | ||
1112 | { | ||
1113 | os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); | ||
1114 | return; | ||
1115 | } | ||
1116 | |||
1117 | u32 pitch = texture->getPitch() / 4; | ||
1118 | colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X]; | ||
1119 | } | ||
1120 | |||
1121 | texture->unlock(); | ||
1122 | makeColorKeyTexture(texture, colorKey, zeroTexels); | ||
1123 | } | ||
1124 | |||
1125 | |||
1126 | |||
1127 | //! Creates a normal map from a height map texture. | ||
1128 | //! \param amplitude: Constant value by which the height information is multiplied. | ||
1129 | void CNullDriver::makeNormalMapTexture(video::ITexture* texture, f32 amplitude) const | ||
1130 | { | ||
1131 | if (!texture) | ||
1132 | return; | ||
1133 | |||
1134 | if (texture->getColorFormat() != ECF_A1R5G5B5 && | ||
1135 | texture->getColorFormat() != ECF_A8R8G8B8 ) | ||
1136 | { | ||
1137 | os::Printer::log("Error: Unsupported texture color format for making normal map.", ELL_ERROR); | ||
1138 | return; | ||
1139 | } | ||
1140 | |||
1141 | core::dimension2d<u32> dim = texture->getSize(); | ||
1142 | amplitude = amplitude / 255.0f; | ||
1143 | f32 vh = dim.Height / (f32)dim.Width; | ||
1144 | f32 hh = dim.Width / (f32)dim.Height; | ||
1145 | |||
1146 | if (texture->getColorFormat() == ECF_A8R8G8B8) | ||
1147 | { | ||
1148 | // ECF_A8R8G8B8 version | ||
1149 | |||
1150 | s32 *p = (s32*)texture->lock(); | ||
1151 | |||
1152 | if (!p) | ||
1153 | { | ||
1154 | os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR); | ||
1155 | return; | ||
1156 | } | ||
1157 | |||
1158 | // copy texture | ||
1159 | |||
1160 | u32 pitch = texture->getPitch() / 4; | ||
1161 | |||
1162 | s32* in = new s32[dim.Height * pitch]; | ||
1163 | memcpy(in, p, dim.Height * pitch * 4); | ||
1164 | |||
1165 | for (s32 x=0; x < s32(pitch); ++x) | ||
1166 | for (s32 y=0; y < s32(dim.Height); ++y) | ||
1167 | { | ||
1168 | // TODO: this could be optimized really a lot | ||
1169 | |||
1170 | core::vector3df h1((x-1)*hh, nml32(x-1, y, pitch, dim.Height, in)*amplitude, y*vh); | ||
1171 | core::vector3df h2((x+1)*hh, nml32(x+1, y, pitch, dim.Height, in)*amplitude, y*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 | core::vector3df v1(x*hh, nml32(x, y+1, pitch, dim.Height, in)*amplitude, (y-1)*vh); | ||
1175 | core::vector3df v2(x*hh, nml32(x, y-1, pitch, dim.Height, in)*amplitude, (y+1)*vh); | ||
1176 | |||
1177 | core::vector3df v = v1-v2; | ||
1178 | core::vector3df h = h1-h2; | ||
1179 | |||
1180 | core::vector3df n = v.crossProduct(h); | ||
1181 | n.normalize(); | ||
1182 | n *= 0.5f; | ||
1183 | n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1 | ||
1184 | n *= 255.0f; | ||
1185 | |||
1186 | s32 height = (s32)nml32(x, y, pitch, dim.Height, in); | ||
1187 | p[y*pitch + x] = video::SColor( | ||
1188 | height, // store height in alpha | ||
1189 | (s32)n.X, (s32)n.Z, (s32)n.Y).color; | ||
1190 | } | ||
1191 | |||
1192 | delete [] in; | ||
1193 | texture->unlock(); | ||
1194 | } | ||
1195 | else | ||
1196 | { | ||
1197 | // ECF_A1R5G5B5 version | ||
1198 | |||
1199 | s16 *p = (s16*)texture->lock(); | ||
1200 | |||
1201 | if (!p) | ||
1202 | { | ||
1203 | os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR); | ||
1204 | return; | ||
1205 | } | ||
1206 | |||
1207 | u32 pitch = texture->getPitch() / 2; | ||
1208 | |||
1209 | // copy texture | ||
1210 | |||
1211 | s16* in = new s16[dim.Height * pitch]; | ||
1212 | memcpy(in, p, dim.Height * pitch * 2); | ||
1213 | |||
1214 | for (s32 x=0; x < s32(pitch); ++x) | ||
1215 | for (s32 y=0; y < s32(dim.Height); ++y) | ||
1216 | { | ||
1217 | // TODO: this could be optimized really a lot | ||
1218 | |||
1219 | core::vector3df h1((x-1)*hh, nml16(x-1, y, pitch, dim.Height, in)*amplitude, y*vh); | ||
1220 | core::vector3df h2((x+1)*hh, nml16(x+1, y, pitch, dim.Height, in)*amplitude, y*vh); | ||
1221 | core::vector3df v1(x*hh, nml16(x, y-1, pitch, dim.Height, in)*amplitude, (y-1)*vh); | ||
1222 | core::vector3df v2(x*hh, nml16(x, y+1, pitch, dim.Height, in)*amplitude, (y+1)*vh); | ||
1223 | |||
1224 | core::vector3df v = v1-v2; | ||
1225 | core::vector3df h = h1-h2; | ||
1226 | |||
1227 | core::vector3df n = v.crossProduct(h); | ||
1228 | n.normalize(); | ||
1229 | n *= 0.5f; | ||
1230 | n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1 | ||
1231 | n *= 255.0f; | ||
1232 | |||
1233 | p[y*pitch + x] = video::RGBA16((u32)n.X, (u32)n.Z, (u32)n.Y); | ||
1234 | } | ||
1235 | |||
1236 | delete [] in; | ||
1237 | texture->unlock(); | ||
1238 | } | ||
1239 | |||
1240 | texture->regenerateMipMapLevels(); | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | //! Returns the maximum amount of primitives (mostly vertices) which | ||
1245 | //! the device is able to render with one drawIndexedTriangleList | ||
1246 | //! call. | ||
1247 | u32 CNullDriver::getMaximalPrimitiveCount() const | ||
1248 | { | ||
1249 | return 0xFFFFFFFF; | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | //! checks triangle count and print warning if wrong | ||
1254 | bool CNullDriver::checkPrimitiveCount(u32 prmCount) const | ||
1255 | { | ||
1256 | const u32 m = getMaximalPrimitiveCount(); | ||
1257 | |||
1258 | if (prmCount > m) | ||
1259 | { | ||
1260 | char tmp[1024]; | ||
1261 | sprintf(tmp,"Could not draw triangles, too many primitives(%u), maxium is %u.", prmCount, m); | ||
1262 | os::Printer::log(tmp, ELL_ERROR); | ||
1263 | return false; | ||
1264 | } | ||
1265 | |||
1266 | return true; | ||
1267 | } | ||
1268 | |||
1269 | //! Enables or disables a texture creation flag. | ||
1270 | void CNullDriver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled) | ||
1271 | { | ||
1272 | if (enabled && ((flag == ETCF_ALWAYS_16_BIT) || (flag == ETCF_ALWAYS_32_BIT) | ||
1273 | || (flag == ETCF_OPTIMIZED_FOR_QUALITY) || (flag == ETCF_OPTIMIZED_FOR_SPEED))) | ||
1274 | { | ||
1275 | // disable other formats | ||
1276 | setTextureCreationFlag(ETCF_ALWAYS_16_BIT, false); | ||
1277 | setTextureCreationFlag(ETCF_ALWAYS_32_BIT, false); | ||
1278 | setTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY, false); | ||
1279 | setTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED, false); | ||
1280 | } | ||
1281 | |||
1282 | // set flag | ||
1283 | TextureCreationFlags = (TextureCreationFlags & (~flag)) | | ||
1284 | ((((u32)!enabled)-1) & flag); | ||
1285 | } | ||
1286 | |||
1287 | |||
1288 | //! Returns if a texture creation flag is enabled or disabled. | ||
1289 | bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const | ||
1290 | { | ||
1291 | return (TextureCreationFlags & flag)!=0; | ||
1292 | } | ||
1293 | |||
1294 | |||
1295 | //! Creates a software image from a file. | ||
1296 | IImage* CNullDriver::createImageFromFile(const io::path& filename) | ||
1297 | { | ||
1298 | if (!filename.size()) | ||
1299 | return 0; | ||
1300 | |||
1301 | IImage* image = 0; | ||
1302 | io::IReadFile* file = FileSystem->createAndOpenFile(filename); | ||
1303 | |||
1304 | if (file) | ||
1305 | { | ||
1306 | image = createImageFromFile(file); | ||
1307 | file->drop(); | ||
1308 | } | ||
1309 | else | ||
1310 | os::Printer::log("Could not open file of image", filename, ELL_WARNING); | ||
1311 | |||
1312 | return image; | ||
1313 | } | ||
1314 | |||
1315 | |||
1316 | //! Creates a software image from a file. | ||
1317 | IImage* CNullDriver::createImageFromFile(io::IReadFile* file) | ||
1318 | { | ||
1319 | if (!file) | ||
1320 | return 0; | ||
1321 | |||
1322 | IImage* image = 0; | ||
1323 | |||
1324 | s32 i; | ||
1325 | |||
1326 | // try to load file based on file extension | ||
1327 | for (i=SurfaceLoader.size()-1; i>=0; --i) | ||
1328 | { | ||
1329 | if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName())) | ||
1330 | { | ||
1331 | // reset file position which might have changed due to previous loadImage calls | ||
1332 | file->seek(0); | ||
1333 | image = SurfaceLoader[i]->loadImage(file); | ||
1334 | if (image) | ||
1335 | return image; | ||
1336 | } | ||
1337 | } | ||
1338 | |||
1339 | // try to load file based on what is in it | ||
1340 | for (i=SurfaceLoader.size()-1; i>=0; --i) | ||
1341 | { | ||
1342 | // dito | ||
1343 | file->seek(0); | ||
1344 | if (SurfaceLoader[i]->isALoadableFileFormat(file)) | ||
1345 | { | ||
1346 | file->seek(0); | ||
1347 | image = SurfaceLoader[i]->loadImage(file); | ||
1348 | if (image) | ||
1349 | return image; | ||
1350 | } | ||
1351 | } | ||
1352 | |||
1353 | return 0; // failed to load | ||
1354 | } | ||
1355 | |||
1356 | |||
1357 | //! Writes the provided image to disk file | ||
1358 | bool CNullDriver::writeImageToFile(IImage* image, const io::path& filename,u32 param) | ||
1359 | { | ||
1360 | io::IWriteFile* file = FileSystem->createAndWriteFile(filename); | ||
1361 | if(!file) | ||
1362 | return false; | ||
1363 | |||
1364 | bool result = writeImageToFile(image, file, param); | ||
1365 | file->drop(); | ||
1366 | |||
1367 | return result; | ||
1368 | } | ||
1369 | |||
1370 | //! Writes the provided image to a file. | ||
1371 | bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param) | ||
1372 | { | ||
1373 | if(!file) | ||
1374 | return false; | ||
1375 | |||
1376 | for (s32 i=SurfaceWriter.size()-1; i>=0; --i) | ||
1377 | { | ||
1378 | if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName())) | ||
1379 | { | ||
1380 | bool written = SurfaceWriter[i]->writeImage(file, image, param); | ||
1381 | if (written) | ||
1382 | return true; | ||
1383 | } | ||
1384 | } | ||
1385 | return false; // failed to write | ||
1386 | } | ||
1387 | |||
1388 | |||
1389 | //! Creates a software image from a byte array. | ||
1390 | IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format, | ||
1391 | const core::dimension2d<u32>& size, | ||
1392 | void *data, bool ownForeignMemory, | ||
1393 | bool deleteMemory) | ||
1394 | { | ||
1395 | if(IImage::isRenderTargetOnlyFormat(format)) | ||
1396 | { | ||
1397 | os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); | ||
1398 | return 0; | ||
1399 | } | ||
1400 | |||
1401 | return new CImage(format, size, data, ownForeignMemory, deleteMemory); | ||
1402 | } | ||
1403 | |||
1404 | |||
1405 | //! Creates an empty software image. | ||
1406 | IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) | ||
1407 | { | ||
1408 | if(IImage::isRenderTargetOnlyFormat(format)) | ||
1409 | { | ||
1410 | os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); | ||
1411 | return 0; | ||
1412 | } | ||
1413 | |||
1414 | return new CImage(format, size); | ||
1415 | } | ||
1416 | |||
1417 | |||
1418 | //! Creates a software image from another image. | ||
1419 | IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy) | ||
1420 | { | ||
1421 | os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING); | ||
1422 | if(IImage::isRenderTargetOnlyFormat(format)) | ||
1423 | { | ||
1424 | os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); | ||
1425 | return 0; | ||
1426 | } | ||
1427 | |||
1428 | CImage* tmp = new CImage(format, imageToCopy->getDimension()); | ||
1429 | imageToCopy->copyTo(tmp); | ||
1430 | return tmp; | ||
1431 | } | ||
1432 | |||
1433 | |||
1434 | //! Creates a software image from part of another image. | ||
1435 | IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d<s32>& pos, const core::dimension2d<u32>& size) | ||
1436 | { | ||
1437 | os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING); | ||
1438 | CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension()); | ||
1439 | imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size)); | ||
1440 | return tmp; | ||
1441 | } | ||
1442 | |||
1443 | |||
1444 | //! Creates a software image from part of a texture. | ||
1445 | IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& pos, const core::dimension2d<u32>& size) | ||
1446 | { | ||
1447 | if ((pos==core::position2di(0,0)) && (size == texture->getSize())) | ||
1448 | { | ||
1449 | IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(ETLM_READ_ONLY), false); | ||
1450 | texture->unlock(); | ||
1451 | return image; | ||
1452 | } | ||
1453 | else | ||
1454 | { | ||
1455 | // make sure to avoid buffer overruns | ||
1456 | // make the vector a separate variable for g++ 3.x | ||
1457 | const core::vector2d<u32> leftUpper(core::clamp(static_cast<u32>(pos.X), 0u, texture->getSize().Width), | ||
1458 | core::clamp(static_cast<u32>(pos.Y), 0u, texture->getSize().Height)); | ||
1459 | const core::rect<u32> clamped(leftUpper, | ||
1460 | core::dimension2du(core::clamp(static_cast<u32>(size.Width), 0u, texture->getSize().Width), | ||
1461 | core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height))); | ||
1462 | if (!clamped.isValid()) | ||
1463 | return 0; | ||
1464 | u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY)); | ||
1465 | if (!src) | ||
1466 | return 0; | ||
1467 | IImage* image = new CImage(texture->getColorFormat(), clamped.getSize()); | ||
1468 | u8* dst = static_cast<u8*>(image->lock()); | ||
1469 | src += clamped.UpperLeftCorner.Y * texture->getPitch() + image->getBytesPerPixel() * clamped.UpperLeftCorner.X; | ||
1470 | for (u32 i=0; i<clamped.getHeight(); ++i) | ||
1471 | { | ||
1472 | video::CColorConverter::convert_viaFormat(src, texture->getColorFormat(), clamped.getWidth(), dst, image->getColorFormat()); | ||
1473 | src += texture->getPitch(); | ||
1474 | dst += image->getPitch(); | ||
1475 | } | ||
1476 | image->unlock(); | ||
1477 | texture->unlock(); | ||
1478 | return image; | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | //! Sets the fog mode. | ||
1484 | void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, | ||
1485 | f32 density, bool pixelFog, bool rangeFog) | ||
1486 | { | ||
1487 | FogColor = color; | ||
1488 | FogType = fogType; | ||
1489 | FogStart = start; | ||
1490 | FogEnd = end; | ||
1491 | FogDensity = density; | ||
1492 | PixelFog = pixelFog; | ||
1493 | RangeFog = rangeFog; | ||
1494 | } | ||
1495 | |||
1496 | //! Gets the fog mode. | ||
1497 | void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end, | ||
1498 | f32& density, bool& pixelFog, bool& rangeFog) | ||
1499 | { | ||
1500 | color = FogColor; | ||
1501 | fogType = FogType; | ||
1502 | start = FogStart; | ||
1503 | end = FogEnd; | ||
1504 | density = FogDensity; | ||
1505 | pixelFog = PixelFog; | ||
1506 | rangeFog = RangeFog; | ||
1507 | } | ||
1508 | |||
1509 | //! Draws a mesh buffer | ||
1510 | void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb) | ||
1511 | { | ||
1512 | if (!mb) | ||
1513 | return; | ||
1514 | |||
1515 | //IVertexBuffer and IIndexBuffer later | ||
1516 | SHWBufferLink *HWBuffer=getBufferLink(mb); | ||
1517 | |||
1518 | if (HWBuffer) | ||
1519 | drawHardwareBuffer(HWBuffer); | ||
1520 | else | ||
1521 | drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); | ||
1522 | } | ||
1523 | |||
1524 | |||
1525 | //! Draws the normals of a mesh buffer | ||
1526 | void CNullDriver::drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length, SColor color) | ||
1527 | { | ||
1528 | const u32 count = mb->getVertexCount(); | ||
1529 | const bool normalize = mb->getMaterial().NormalizeNormals; | ||
1530 | |||
1531 | for (u32 i=0; i < count; ++i) | ||
1532 | { | ||
1533 | core::vector3df normalizedNormal = mb->getNormal(i); | ||
1534 | if (normalize) | ||
1535 | normalizedNormal.normalize(); | ||
1536 | |||
1537 | const core::vector3df& pos = mb->getPosition(i); | ||
1538 | draw3DLine(pos, pos + (normalizedNormal * length), color); | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | |||
1543 | CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb) | ||
1544 | { | ||
1545 | if (!mb || !isHardwareBufferRecommend(mb)) | ||
1546 | return 0; | ||
1547 | |||
1548 | //search for hardware links | ||
1549 | core::map< const scene::IMeshBuffer*,SHWBufferLink* >::Node* node = HWBufferMap.find(mb); | ||
1550 | if (node) | ||
1551 | return node->getValue(); | ||
1552 | |||
1553 | return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it | ||
1554 | } | ||
1555 | |||
1556 | |||
1557 | //! Update all hardware buffers, remove unused ones | ||
1558 | void CNullDriver::updateAllHardwareBuffers() | ||
1559 | { | ||
1560 | core::map<const scene::IMeshBuffer*,SHWBufferLink*>::ParentFirstIterator Iterator=HWBufferMap.getParentFirstIterator(); | ||
1561 | |||
1562 | for (;!Iterator.atEnd();Iterator++) | ||
1563 | { | ||
1564 | SHWBufferLink *Link=Iterator.getNode()->getValue(); | ||
1565 | |||
1566 | Link->LastUsed++; | ||
1567 | if (Link->LastUsed>20000) | ||
1568 | { | ||
1569 | deleteHardwareBuffer(Link); | ||
1570 | |||
1571 | // todo: needs better fix | ||
1572 | Iterator = HWBufferMap.getParentFirstIterator(); | ||
1573 | } | ||
1574 | } | ||
1575 | } | ||
1576 | |||
1577 | |||
1578 | void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer) | ||
1579 | { | ||
1580 | if (!HWBuffer) | ||
1581 | return; | ||
1582 | HWBufferMap.remove(HWBuffer->MeshBuffer); | ||
1583 | delete HWBuffer; | ||
1584 | } | ||
1585 | |||
1586 | |||
1587 | //! Remove hardware buffer | ||
1588 | void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb) | ||
1589 | { | ||
1590 | core::map<const scene::IMeshBuffer*,SHWBufferLink*>::Node* node = HWBufferMap.find(mb); | ||
1591 | if (node) | ||
1592 | deleteHardwareBuffer(node->getValue()); | ||
1593 | } | ||
1594 | |||
1595 | |||
1596 | //! Remove all hardware buffers | ||
1597 | void CNullDriver::removeAllHardwareBuffers() | ||
1598 | { | ||
1599 | while (HWBufferMap.size()) | ||
1600 | deleteHardwareBuffer(HWBufferMap.getRoot()->getValue()); | ||
1601 | } | ||
1602 | |||
1603 | |||
1604 | bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb) | ||
1605 | { | ||
1606 | if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) | ||
1607 | return false; | ||
1608 | |||
1609 | if (mb->getVertexCount()<MinVertexCountForVBO) | ||
1610 | return false; | ||
1611 | |||
1612 | return true; | ||
1613 | } | ||
1614 | |||
1615 | |||
1616 | //! Create occlusion query. | ||
1617 | /** Use node for identification and mesh for occlusion test. */ | ||
1618 | void CNullDriver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh) | ||
1619 | { | ||
1620 | if (!node) | ||
1621 | return; | ||
1622 | if (!mesh) | ||
1623 | { | ||
1624 | if ((node->getType() != scene::ESNT_MESH) && (node->getType() != scene::ESNT_ANIMATED_MESH)) | ||
1625 | return; | ||
1626 | else if (node->getType() == scene::ESNT_MESH) | ||
1627 | mesh = static_cast<scene::IMeshSceneNode*>(node)->getMesh(); | ||
1628 | else | ||
1629 | mesh = static_cast<scene::IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0); | ||
1630 | if (!mesh) | ||
1631 | return; | ||
1632 | } | ||
1633 | |||
1634 | //search for query | ||
1635 | s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | ||
1636 | if (index != -1) | ||
1637 | { | ||
1638 | if (OcclusionQueries[index].Mesh != mesh) | ||
1639 | { | ||
1640 | OcclusionQueries[index].Mesh->drop(); | ||
1641 | OcclusionQueries[index].Mesh = mesh; | ||
1642 | mesh->grab(); | ||
1643 | } | ||
1644 | } | ||
1645 | else | ||
1646 | { | ||
1647 | OcclusionQueries.push_back(SOccQuery(node, mesh)); | ||
1648 | node->setAutomaticCulling(node->getAutomaticCulling() | scene::EAC_OCC_QUERY); | ||
1649 | } | ||
1650 | } | ||
1651 | |||
1652 | |||
1653 | //! Remove occlusion query. | ||
1654 | void CNullDriver::removeOcclusionQuery(scene::ISceneNode* node) | ||
1655 | { | ||
1656 | //search for query | ||
1657 | s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | ||
1658 | if (index != -1) | ||
1659 | { | ||
1660 | node->setAutomaticCulling(node->getAutomaticCulling() & ~scene::EAC_OCC_QUERY); | ||
1661 | OcclusionQueries.erase(index); | ||
1662 | } | ||
1663 | } | ||
1664 | |||
1665 | |||
1666 | //! Remove all occlusion queries. | ||
1667 | void CNullDriver::removeAllOcclusionQueries() | ||
1668 | { | ||
1669 | for (s32 i=OcclusionQueries.size()-1; i>=0; --i) | ||
1670 | { | ||
1671 | removeOcclusionQuery(OcclusionQueries[i].Node); | ||
1672 | } | ||
1673 | } | ||
1674 | |||
1675 | |||
1676 | //! Run occlusion query. Draws mesh stored in query. | ||
1677 | /** If the mesh shall be rendered visible, use | ||
1678 | flag to enable the proper material setting. */ | ||
1679 | void CNullDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible) | ||
1680 | { | ||
1681 | if(!node) | ||
1682 | return; | ||
1683 | s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | ||
1684 | if (index==-1) | ||
1685 | return; | ||
1686 | OcclusionQueries[index].Run=0; | ||
1687 | if (!visible) | ||
1688 | { | ||
1689 | SMaterial mat; | ||
1690 | mat.Lighting=false; | ||
1691 | mat.AntiAliasing=0; | ||
1692 | mat.ColorMask=ECP_NONE; | ||
1693 | mat.GouraudShading=false; | ||
1694 | mat.ZWriteEnable=false; | ||
1695 | setMaterial(mat); | ||
1696 | } | ||
1697 | setTransform(video::ETS_WORLD, node->getAbsoluteTransformation()); | ||
1698 | const scene::IMesh* mesh = OcclusionQueries[index].Mesh; | ||
1699 | for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) | ||
1700 | { | ||
1701 | if (visible) | ||
1702 | setMaterial(mesh->getMeshBuffer(i)->getMaterial()); | ||
1703 | drawMeshBuffer(mesh->getMeshBuffer(i)); | ||
1704 | } | ||
1705 | } | ||
1706 | |||
1707 | |||
1708 | //! Run all occlusion queries. Draws all meshes stored in queries. | ||
1709 | /** If the meshes shall not be rendered visible, use | ||
1710 | overrideMaterial to disable the color and depth buffer. */ | ||
1711 | void CNullDriver::runAllOcclusionQueries(bool visible) | ||
1712 | { | ||
1713 | for (u32 i=0; i<OcclusionQueries.size(); ++i) | ||
1714 | runOcclusionQuery(OcclusionQueries[i].Node, visible); | ||
1715 | } | ||
1716 | |||
1717 | |||
1718 | //! Update occlusion query. Retrieves results from GPU. | ||
1719 | /** If the query shall not block, set the flag to false. | ||
1720 | Update might not occur in this case, though */ | ||
1721 | void CNullDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block) | ||
1722 | { | ||
1723 | } | ||
1724 | |||
1725 | |||
1726 | //! Update all occlusion queries. Retrieves results from GPU. | ||
1727 | /** If the query shall not block, set the flag to false. | ||
1728 | Update might not occur in this case, though */ | ||
1729 | void CNullDriver::updateAllOcclusionQueries(bool block) | ||
1730 | { | ||
1731 | for (u32 i=0; i<OcclusionQueries.size(); ++i) | ||
1732 | { | ||
1733 | if (OcclusionQueries[i].Run==u32(~0)) | ||
1734 | continue; | ||
1735 | updateOcclusionQuery(OcclusionQueries[i].Node, block); | ||
1736 | ++OcclusionQueries[i].Run; | ||
1737 | if (OcclusionQueries[i].Run>1000) | ||
1738 | removeOcclusionQuery(OcclusionQueries[i].Node); | ||
1739 | } | ||
1740 | } | ||
1741 | |||
1742 | |||
1743 | //! Return query result. | ||
1744 | /** Return value is the number of visible pixels/fragments. | ||
1745 | The value is a safe approximation, i.e. can be larger then the | ||
1746 | actual value of pixels. */ | ||
1747 | u32 CNullDriver::getOcclusionQueryResult(scene::ISceneNode* node) const | ||
1748 | { | ||
1749 | return ~0; | ||
1750 | } | ||
1751 | |||
1752 | |||
1753 | //! Only used by the internal engine. Used to notify the driver that | ||
1754 | //! the window was resized. | ||
1755 | void CNullDriver::OnResize(const core::dimension2d<u32>& size) | ||
1756 | { | ||
1757 | if (ViewPort.getWidth() == (s32)ScreenSize.Width && | ||
1758 | ViewPort.getHeight() == (s32)ScreenSize.Height) | ||
1759 | ViewPort = core::rect<s32>(core::position2d<s32>(0,0), | ||
1760 | core::dimension2di(size)); | ||
1761 | |||
1762 | ScreenSize = size; | ||
1763 | } | ||
1764 | |||
1765 | |||
1766 | // adds a material renderer and drops it afterwards. To be used for internal creation | ||
1767 | s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m) | ||
1768 | { | ||
1769 | s32 i = addMaterialRenderer(m); | ||
1770 | |||
1771 | if (m) | ||
1772 | m->drop(); | ||
1773 | |||
1774 | return i; | ||
1775 | } | ||
1776 | |||
1777 | |||
1778 | //! Adds a new material renderer to the video device. | ||
1779 | s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* name) | ||
1780 | { | ||
1781 | if (!renderer) | ||
1782 | return -1; | ||
1783 | |||
1784 | SMaterialRenderer r; | ||
1785 | r.Renderer = renderer; | ||
1786 | r.Name = name; | ||
1787 | |||
1788 | if (name == 0 && (MaterialRenderers.size() < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 )) | ||
1789 | { | ||
1790 | // set name of built in renderer so that we don't have to implement name | ||
1791 | // setting in all available renderers. | ||
1792 | r.Name = sBuiltInMaterialTypeNames[MaterialRenderers.size()]; | ||
1793 | } | ||
1794 | |||
1795 | MaterialRenderers.push_back(r); | ||
1796 | renderer->grab(); | ||
1797 | |||
1798 | return MaterialRenderers.size()-1; | ||
1799 | } | ||
1800 | |||
1801 | |||
1802 | //! Sets the name of a material renderer. | ||
1803 | void CNullDriver::setMaterialRendererName(s32 idx, const char* name) | ||
1804 | { | ||
1805 | if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 || | ||
1806 | idx >= (s32)MaterialRenderers.size()) | ||
1807 | return; | ||
1808 | |||
1809 | MaterialRenderers[idx].Name = name; | ||
1810 | } | ||
1811 | |||
1812 | |||
1813 | //! Creates material attributes list from a material, usable for serialization and more. | ||
1814 | io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMaterial& material, | ||
1815 | io::SAttributeReadWriteOptions* options) | ||
1816 | { | ||
1817 | io::CAttributes* attr = new io::CAttributes(this); | ||
1818 | |||
1819 | attr->addEnum("Type", material.MaterialType, sBuiltInMaterialTypeNames); | ||
1820 | |||
1821 | attr->addColor("Ambient", material.AmbientColor); | ||
1822 | attr->addColor("Diffuse", material.DiffuseColor); | ||
1823 | attr->addColor("Emissive", material.EmissiveColor); | ||
1824 | attr->addColor("Specular", material.SpecularColor); | ||
1825 | |||
1826 | attr->addFloat("Shininess", material.Shininess); | ||
1827 | attr->addFloat("Param1", material.MaterialTypeParam); | ||
1828 | attr->addFloat("Param2", material.MaterialTypeParam2); | ||
1829 | |||
1830 | core::stringc prefix="Texture"; | ||
1831 | u32 i; | ||
1832 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1833 | { | ||
1834 | if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename && material.getTexture(i)) | ||
1835 | { | ||
1836 | io::path path = FileSystem->getRelativeFilename( | ||
1837 | FileSystem->getAbsolutePath(material.getTexture(i)->getName()), options->Filename); | ||
1838 | attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i), path); | ||
1839 | } | ||
1840 | else | ||
1841 | attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i)); | ||
1842 | } | ||
1843 | |||
1844 | attr->addBool("Wireframe", material.Wireframe); | ||
1845 | attr->addBool("GouraudShading", material.GouraudShading); | ||
1846 | attr->addBool("Lighting", material.Lighting); | ||
1847 | attr->addBool("ZWriteEnable", material.ZWriteEnable); | ||
1848 | attr->addInt("ZBuffer", material.ZBuffer); | ||
1849 | attr->addBool("BackfaceCulling", material.BackfaceCulling); | ||
1850 | attr->addBool("FrontfaceCulling", material.FrontfaceCulling); | ||
1851 | attr->addBool("FogEnable", material.FogEnable); | ||
1852 | attr->addBool("NormalizeNormals", material.NormalizeNormals); | ||
1853 | attr->addBool("UseMipMaps", material.UseMipMaps); | ||
1854 | attr->addInt("AntiAliasing", material.AntiAliasing); | ||
1855 | attr->addInt("ColorMask", material.ColorMask); | ||
1856 | attr->addInt("ColorMaterial", material.ColorMaterial); | ||
1857 | attr->addInt("PolygonOffsetFactor", material.PolygonOffsetFactor); | ||
1858 | attr->addEnum("PolygonOffsetDirection", material.PolygonOffsetDirection, video::PolygonOffsetDirectionNames); | ||
1859 | |||
1860 | prefix = "BilinearFilter"; | ||
1861 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1862 | attr->addBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].BilinearFilter); | ||
1863 | prefix = "TrilinearFilter"; | ||
1864 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1865 | attr->addBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TrilinearFilter); | ||
1866 | prefix = "AnisotropicFilter"; | ||
1867 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1868 | attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].AnisotropicFilter); | ||
1869 | prefix="TextureWrapU"; | ||
1870 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1871 | attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapU, aTextureClampNames); | ||
1872 | prefix="TextureWrapV"; | ||
1873 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1874 | attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapV, aTextureClampNames); | ||
1875 | prefix="LODBias"; | ||
1876 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1877 | attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].LODBias); | ||
1878 | |||
1879 | return attr; | ||
1880 | } | ||
1881 | |||
1882 | |||
1883 | //! Fills an SMaterial structure from attributes. | ||
1884 | void CNullDriver::fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attr) | ||
1885 | { | ||
1886 | outMaterial.MaterialType = video::EMT_SOLID; | ||
1887 | |||
1888 | core::stringc name = attr->getAttributeAsString("Type"); | ||
1889 | |||
1890 | u32 i; | ||
1891 | |||
1892 | for ( i=0; i < MaterialRenderers.size(); ++i) | ||
1893 | if ( name == MaterialRenderers[i].Name ) | ||
1894 | { | ||
1895 | outMaterial.MaterialType = (video::E_MATERIAL_TYPE)i; | ||
1896 | break; | ||
1897 | } | ||
1898 | |||
1899 | outMaterial.AmbientColor = attr->getAttributeAsColor("Ambient"); | ||
1900 | outMaterial.DiffuseColor = attr->getAttributeAsColor("Diffuse"); | ||
1901 | outMaterial.EmissiveColor = attr->getAttributeAsColor("Emissive"); | ||
1902 | outMaterial.SpecularColor = attr->getAttributeAsColor("Specular"); | ||
1903 | |||
1904 | outMaterial.Shininess = attr->getAttributeAsFloat("Shininess"); | ||
1905 | outMaterial.MaterialTypeParam = attr->getAttributeAsFloat("Param1"); | ||
1906 | outMaterial.MaterialTypeParam2 = attr->getAttributeAsFloat("Param2"); | ||
1907 | |||
1908 | core::stringc prefix="Texture"; | ||
1909 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1910 | outMaterial.setTexture(i, attr->getAttributeAsTexture((prefix+core::stringc(i+1)).c_str())); | ||
1911 | |||
1912 | outMaterial.Wireframe = attr->getAttributeAsBool("Wireframe"); | ||
1913 | outMaterial.GouraudShading = attr->getAttributeAsBool("GouraudShading"); | ||
1914 | outMaterial.Lighting = attr->getAttributeAsBool("Lighting"); | ||
1915 | outMaterial.ZWriteEnable = attr->getAttributeAsBool("ZWriteEnable"); | ||
1916 | outMaterial.ZBuffer = (u8)attr->getAttributeAsInt("ZBuffer"); | ||
1917 | outMaterial.BackfaceCulling = attr->getAttributeAsBool("BackfaceCulling"); | ||
1918 | outMaterial.FrontfaceCulling = attr->getAttributeAsBool("FrontfaceCulling"); | ||
1919 | outMaterial.FogEnable = attr->getAttributeAsBool("FogEnable"); | ||
1920 | outMaterial.NormalizeNormals = attr->getAttributeAsBool("NormalizeNormals"); | ||
1921 | if (attr->existsAttribute("UseMipMaps")) // legacy | ||
1922 | outMaterial.UseMipMaps = attr->getAttributeAsBool("UseMipMaps"); | ||
1923 | else | ||
1924 | outMaterial.UseMipMaps = true; | ||
1925 | |||
1926 | // default 0 is ok | ||
1927 | outMaterial.AntiAliasing = attr->getAttributeAsInt("AntiAliasing"); | ||
1928 | if (attr->existsAttribute("ColorMask")) | ||
1929 | outMaterial.ColorMask = attr->getAttributeAsInt("ColorMask"); | ||
1930 | if (attr->existsAttribute("ColorMaterial")) | ||
1931 | outMaterial.ColorMaterial = attr->getAttributeAsInt("ColorMaterial"); | ||
1932 | if (attr->existsAttribute("PolygonOffsetFactor")) | ||
1933 | outMaterial.PolygonOffsetFactor = attr->getAttributeAsInt("PolygonOffsetFactor"); | ||
1934 | if (attr->existsAttribute("PolygonOffsetDirection")) | ||
1935 | outMaterial.PolygonOffsetDirection = (video::E_POLYGON_OFFSET)attr->getAttributeAsEnumeration("PolygonOffsetDirection", video::PolygonOffsetDirectionNames); | ||
1936 | prefix = "BilinearFilter"; | ||
1937 | if (attr->existsAttribute(prefix.c_str())) // legacy | ||
1938 | outMaterial.setFlag(EMF_BILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str())); | ||
1939 | else | ||
1940 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1941 | outMaterial.TextureLayer[i].BilinearFilter = attr->getAttributeAsBool((prefix+core::stringc(i+1)).c_str()); | ||
1942 | |||
1943 | prefix = "TrilinearFilter"; | ||
1944 | if (attr->existsAttribute(prefix.c_str())) // legacy | ||
1945 | outMaterial.setFlag(EMF_TRILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str())); | ||
1946 | else | ||
1947 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1948 | outMaterial.TextureLayer[i].TrilinearFilter = attr->getAttributeAsBool((prefix+core::stringc(i+1)).c_str()); | ||
1949 | |||
1950 | prefix = "AnisotropicFilter"; | ||
1951 | if (attr->existsAttribute(prefix.c_str())) // legacy | ||
1952 | outMaterial.setFlag(EMF_ANISOTROPIC_FILTER, attr->getAttributeAsBool(prefix.c_str())); | ||
1953 | else | ||
1954 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1955 | outMaterial.TextureLayer[i].AnisotropicFilter = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str()); | ||
1956 | |||
1957 | prefix = "TextureWrap"; | ||
1958 | if (attr->existsAttribute(prefix.c_str())) // legacy | ||
1959 | { | ||
1960 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1961 | { | ||
1962 | outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames); | ||
1963 | outMaterial.TextureLayer[i].TextureWrapV = outMaterial.TextureLayer[i].TextureWrapU; | ||
1964 | } | ||
1965 | } | ||
1966 | else | ||
1967 | { | ||
1968 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1969 | { | ||
1970 | outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"U"+core::stringc(i+1)).c_str(), aTextureClampNames); | ||
1971 | outMaterial.TextureLayer[i].TextureWrapV = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"V"+core::stringc(i+1)).c_str(), aTextureClampNames); | ||
1972 | } | ||
1973 | } | ||
1974 | |||
1975 | // default 0 is ok | ||
1976 | prefix="LODBias"; | ||
1977 | for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) | ||
1978 | outMaterial.TextureLayer[i].LODBias = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str()); | ||
1979 | } | ||
1980 | |||
1981 | |||
1982 | //! Returns driver and operating system specific data about the IVideoDriver. | ||
1983 | const SExposedVideoData& CNullDriver::getExposedVideoData() | ||
1984 | { | ||
1985 | return ExposedData; | ||
1986 | } | ||
1987 | |||
1988 | |||
1989 | //! Returns type of video driver | ||
1990 | E_DRIVER_TYPE CNullDriver::getDriverType() const | ||
1991 | { | ||
1992 | return EDT_NULL; | ||
1993 | } | ||
1994 | |||
1995 | |||
1996 | //! deletes all material renderers | ||
1997 | void CNullDriver::deleteMaterialRenders() | ||
1998 | { | ||
1999 | // delete material renderers | ||
2000 | for (u32 i=0; i<MaterialRenderers.size(); ++i) | ||
2001 | if (MaterialRenderers[i].Renderer) | ||
2002 | MaterialRenderers[i].Renderer->drop(); | ||
2003 | |||
2004 | MaterialRenderers.clear(); | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | //! Returns pointer to material renderer or null | ||
2009 | IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx) | ||
2010 | { | ||
2011 | if ( idx < MaterialRenderers.size() ) | ||
2012 | return MaterialRenderers[idx].Renderer; | ||
2013 | else | ||
2014 | return 0; | ||
2015 | } | ||
2016 | |||
2017 | |||
2018 | //! Returns amount of currently available material renderers. | ||
2019 | u32 CNullDriver::getMaterialRendererCount() const | ||
2020 | { | ||
2021 | return MaterialRenderers.size(); | ||
2022 | } | ||
2023 | |||
2024 | |||
2025 | //! Returns name of the material renderer | ||
2026 | const char* CNullDriver::getMaterialRendererName(u32 idx) const | ||
2027 | { | ||
2028 | if ( idx < MaterialRenderers.size() ) | ||
2029 | return MaterialRenderers[idx].Name.c_str(); | ||
2030 | |||
2031 | return 0; | ||
2032 | } | ||
2033 | |||
2034 | |||
2035 | //! Returns pointer to the IGPUProgrammingServices interface. | ||
2036 | IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices() | ||
2037 | { | ||
2038 | return this; | ||
2039 | } | ||
2040 | |||
2041 | |||
2042 | //! Adds a new material renderer to the VideoDriver, based on a high level shading language. | ||
2043 | s32 CNullDriver::addHighLevelShaderMaterial( | ||
2044 | const c8* vertexShaderProgram, | ||
2045 | const c8* vertexShaderEntryPointName, | ||
2046 | E_VERTEX_SHADER_TYPE vsCompileTarget, | ||
2047 | const c8* pixelShaderProgram, | ||
2048 | const c8* pixelShaderEntryPointName, | ||
2049 | E_PIXEL_SHADER_TYPE psCompileTarget, | ||
2050 | const c8* geometryShaderProgram, | ||
2051 | const c8* geometryShaderEntryPointName, | ||
2052 | E_GEOMETRY_SHADER_TYPE gsCompileTarget, | ||
2053 | scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, | ||
2054 | u32 verticesOut, | ||
2055 | IShaderConstantSetCallBack* callback, | ||
2056 | E_MATERIAL_TYPE baseMaterial, | ||
2057 | s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) | ||
2058 | { | ||
2059 | os::Printer::log("High level shader materials not available (yet) in this driver, sorry"); | ||
2060 | return -1; | ||
2061 | } | ||
2062 | |||
2063 | |||
2064 | //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), | ||
2065 | //! but tries to load the programs from files. | ||
2066 | s32 CNullDriver::addHighLevelShaderMaterialFromFiles( | ||
2067 | const io::path& vertexShaderProgramFileName, | ||
2068 | const c8* vertexShaderEntryPointName, | ||
2069 | E_VERTEX_SHADER_TYPE vsCompileTarget, | ||
2070 | const io::path& pixelShaderProgramFileName, | ||
2071 | const c8* pixelShaderEntryPointName, | ||
2072 | E_PIXEL_SHADER_TYPE psCompileTarget, | ||
2073 | const io::path& geometryShaderProgramFileName, | ||
2074 | const c8* geometryShaderEntryPointName, | ||
2075 | E_GEOMETRY_SHADER_TYPE gsCompileTarget, | ||
2076 | scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, | ||
2077 | u32 verticesOut, | ||
2078 | IShaderConstantSetCallBack* callback, | ||
2079 | E_MATERIAL_TYPE baseMaterial, | ||
2080 | s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) | ||
2081 | { | ||
2082 | io::IReadFile* vsfile = 0; | ||
2083 | io::IReadFile* psfile = 0; | ||
2084 | io::IReadFile* gsfile = 0; | ||
2085 | |||
2086 | if (vertexShaderProgramFileName.size() ) | ||
2087 | { | ||
2088 | vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); | ||
2089 | if (!vsfile) | ||
2090 | { | ||
2091 | os::Printer::log("Could not open vertex shader program file", | ||
2092 | vertexShaderProgramFileName, ELL_WARNING); | ||
2093 | } | ||
2094 | } | ||
2095 | |||
2096 | if (pixelShaderProgramFileName.size() ) | ||
2097 | { | ||
2098 | psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); | ||
2099 | if (!psfile) | ||
2100 | { | ||
2101 | os::Printer::log("Could not open pixel shader program file", | ||
2102 | pixelShaderProgramFileName, ELL_WARNING); | ||
2103 | } | ||
2104 | } | ||
2105 | |||
2106 | if (geometryShaderProgramFileName.size() ) | ||
2107 | { | ||
2108 | gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName); | ||
2109 | if (!gsfile) | ||
2110 | { | ||
2111 | os::Printer::log("Could not open geometry shader program file", | ||
2112 | geometryShaderProgramFileName, ELL_WARNING); | ||
2113 | } | ||
2114 | } | ||
2115 | |||
2116 | s32 result = addHighLevelShaderMaterialFromFiles( | ||
2117 | vsfile, vertexShaderEntryPointName, vsCompileTarget, | ||
2118 | psfile, pixelShaderEntryPointName, psCompileTarget, | ||
2119 | gsfile, geometryShaderEntryPointName, gsCompileTarget, | ||
2120 | inType, outType, verticesOut, | ||
2121 | callback, baseMaterial, userData, shadingLang); | ||
2122 | |||
2123 | if (psfile) | ||
2124 | psfile->drop(); | ||
2125 | |||
2126 | if (vsfile) | ||
2127 | vsfile->drop(); | ||
2128 | |||
2129 | if (gsfile) | ||
2130 | gsfile->drop(); | ||
2131 | |||
2132 | return result; | ||
2133 | } | ||
2134 | |||
2135 | |||
2136 | //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), | ||
2137 | //! but tries to load the programs from files. | ||
2138 | s32 CNullDriver::addHighLevelShaderMaterialFromFiles( | ||
2139 | io::IReadFile* vertexShaderProgram, | ||
2140 | const c8* vertexShaderEntryPointName, | ||
2141 | E_VERTEX_SHADER_TYPE vsCompileTarget, | ||
2142 | io::IReadFile* pixelShaderProgram, | ||
2143 | const c8* pixelShaderEntryPointName, | ||
2144 | E_PIXEL_SHADER_TYPE psCompileTarget, | ||
2145 | io::IReadFile* geometryShaderProgram, | ||
2146 | const c8* geometryShaderEntryPointName, | ||
2147 | E_GEOMETRY_SHADER_TYPE gsCompileTarget, | ||
2148 | scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, | ||
2149 | u32 verticesOut, | ||
2150 | IShaderConstantSetCallBack* callback, | ||
2151 | E_MATERIAL_TYPE baseMaterial, | ||
2152 | s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) | ||
2153 | { | ||
2154 | c8* vs = 0; | ||
2155 | c8* ps = 0; | ||
2156 | c8* gs = 0; | ||
2157 | |||
2158 | if (vertexShaderProgram) | ||
2159 | { | ||
2160 | const long size = vertexShaderProgram->getSize(); | ||
2161 | if (size) | ||
2162 | { | ||
2163 | vs = new c8[size+1]; | ||
2164 | vertexShaderProgram->read(vs, size); | ||
2165 | vs[size] = 0; | ||
2166 | } | ||
2167 | } | ||
2168 | |||
2169 | if (pixelShaderProgram) | ||
2170 | { | ||
2171 | const long size = pixelShaderProgram->getSize(); | ||
2172 | if (size) | ||
2173 | { | ||
2174 | // if both handles are the same we must reset the file | ||
2175 | if (pixelShaderProgram==vertexShaderProgram) | ||
2176 | pixelShaderProgram->seek(0); | ||
2177 | ps = new c8[size+1]; | ||
2178 | pixelShaderProgram->read(ps, size); | ||
2179 | ps[size] = 0; | ||
2180 | } | ||
2181 | } | ||
2182 | |||
2183 | if (geometryShaderProgram) | ||
2184 | { | ||
2185 | const long size = geometryShaderProgram->getSize(); | ||
2186 | if (size) | ||
2187 | { | ||
2188 | // if both handles are the same we must reset the file | ||
2189 | if ((geometryShaderProgram==vertexShaderProgram) || | ||
2190 | (geometryShaderProgram==pixelShaderProgram)) | ||
2191 | geometryShaderProgram->seek(0); | ||
2192 | gs = new c8[size+1]; | ||
2193 | geometryShaderProgram->read(gs, size); | ||
2194 | gs[size] = 0; | ||
2195 | } | ||
2196 | } | ||
2197 | |||
2198 | s32 result = this->addHighLevelShaderMaterial( | ||
2199 | vs, vertexShaderEntryPointName, vsCompileTarget, | ||
2200 | ps, pixelShaderEntryPointName, psCompileTarget, | ||
2201 | gs, geometryShaderEntryPointName, gsCompileTarget, | ||
2202 | inType, outType, verticesOut, | ||
2203 | callback, baseMaterial, userData, shadingLang); | ||
2204 | |||
2205 | delete [] vs; | ||
2206 | delete [] ps; | ||
2207 | delete [] gs; | ||
2208 | |||
2209 | return result; | ||
2210 | } | ||
2211 | |||
2212 | |||
2213 | //! Adds a new material renderer to the VideoDriver, using pixel and/or | ||
2214 | //! vertex shaders to render geometry. | ||
2215 | s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram, | ||
2216 | const c8* pixelShaderProgram, | ||
2217 | IShaderConstantSetCallBack* callback, | ||
2218 | E_MATERIAL_TYPE baseMaterial, | ||
2219 | s32 userData) | ||
2220 | { | ||
2221 | os::Printer::log("Shader materials not implemented yet in this driver, sorry."); | ||
2222 | return -1; | ||
2223 | } | ||
2224 | |||
2225 | |||
2226 | //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the | ||
2227 | //! programs from files. | ||
2228 | s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram, | ||
2229 | io::IReadFile* pixelShaderProgram, | ||
2230 | IShaderConstantSetCallBack* callback, | ||
2231 | E_MATERIAL_TYPE baseMaterial, | ||
2232 | s32 userData) | ||
2233 | { | ||
2234 | c8* vs = 0; | ||
2235 | c8* ps = 0; | ||
2236 | |||
2237 | if (vertexShaderProgram) | ||
2238 | { | ||
2239 | const long size = vertexShaderProgram->getSize(); | ||
2240 | if (size) | ||
2241 | { | ||
2242 | vs = new c8[size+1]; | ||
2243 | vertexShaderProgram->read(vs, size); | ||
2244 | vs[size] = 0; | ||
2245 | } | ||
2246 | } | ||
2247 | |||
2248 | if (pixelShaderProgram) | ||
2249 | { | ||
2250 | const long size = pixelShaderProgram->getSize(); | ||
2251 | if (size) | ||
2252 | { | ||
2253 | ps = new c8[size+1]; | ||
2254 | pixelShaderProgram->read(ps, size); | ||
2255 | ps[size] = 0; | ||
2256 | } | ||
2257 | } | ||
2258 | |||
2259 | s32 result = addShaderMaterial(vs, ps, callback, baseMaterial, userData); | ||
2260 | |||
2261 | delete [] vs; | ||
2262 | delete [] ps; | ||
2263 | |||
2264 | return result; | ||
2265 | } | ||
2266 | |||
2267 | |||
2268 | //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the | ||
2269 | //! programs from files. | ||
2270 | s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, | ||
2271 | const io::path& pixelShaderProgramFileName, | ||
2272 | IShaderConstantSetCallBack* callback, | ||
2273 | E_MATERIAL_TYPE baseMaterial, | ||
2274 | s32 userData) | ||
2275 | { | ||
2276 | io::IReadFile* vsfile = 0; | ||
2277 | io::IReadFile* psfile = 0; | ||
2278 | |||
2279 | if (vertexShaderProgramFileName.size()) | ||
2280 | { | ||
2281 | vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); | ||
2282 | if (!vsfile) | ||
2283 | { | ||
2284 | os::Printer::log("Could not open vertex shader program file", | ||
2285 | vertexShaderProgramFileName, ELL_WARNING); | ||
2286 | return -1; | ||
2287 | } | ||
2288 | } | ||
2289 | |||
2290 | if (pixelShaderProgramFileName.size()) | ||
2291 | { | ||
2292 | psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); | ||
2293 | if (!psfile) | ||
2294 | { | ||
2295 | os::Printer::log("Could not open pixel shader program file", | ||
2296 | pixelShaderProgramFileName, ELL_WARNING); | ||
2297 | if (vsfile) | ||
2298 | vsfile->drop(); | ||
2299 | return -1; | ||
2300 | } | ||
2301 | } | ||
2302 | |||
2303 | s32 result = addShaderMaterialFromFiles(vsfile, psfile, callback, | ||
2304 | baseMaterial, userData); | ||
2305 | |||
2306 | if (psfile) | ||
2307 | psfile->drop(); | ||
2308 | |||
2309 | if (vsfile) | ||
2310 | vsfile->drop(); | ||
2311 | |||
2312 | return result; | ||
2313 | } | ||
2314 | |||
2315 | |||
2316 | //! Creates a render target texture. | ||
2317 | ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d<u32>& size, | ||
2318 | const io::path&name, const ECOLOR_FORMAT format) | ||
2319 | { | ||
2320 | return 0; | ||
2321 | } | ||
2322 | |||
2323 | |||
2324 | //! Clears the ZBuffer. | ||
2325 | void CNullDriver::clearZBuffer() | ||
2326 | { | ||
2327 | } | ||
2328 | |||
2329 | |||
2330 | //! Returns a pointer to the mesh manipulator. | ||
2331 | scene::IMeshManipulator* CNullDriver::getMeshManipulator() | ||
2332 | { | ||
2333 | return MeshManipulator; | ||
2334 | } | ||
2335 | |||
2336 | |||
2337 | //! Returns an image created from the last rendered frame. | ||
2338 | IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) | ||
2339 | { | ||
2340 | return 0; | ||
2341 | } | ||
2342 | |||
2343 | |||
2344 | // prints renderer version | ||
2345 | void CNullDriver::printVersion() | ||
2346 | { | ||
2347 | core::stringw namePrint = L"Using renderer: "; | ||
2348 | namePrint += getName(); | ||
2349 | os::Printer::log(namePrint.c_str(), ELL_INFORMATION); | ||
2350 | } | ||
2351 | |||
2352 | |||
2353 | //! creates a video driver | ||
2354 | IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize) | ||
2355 | { | ||
2356 | CNullDriver* nullDriver = new CNullDriver(io, screenSize); | ||
2357 | |||
2358 | // create empty material renderers | ||
2359 | for(u32 i=0; sBuiltInMaterialTypeNames[i]; ++i) | ||
2360 | { | ||
2361 | IMaterialRenderer* imr = new IMaterialRenderer(); | ||
2362 | nullDriver->addMaterialRenderer(imr); | ||
2363 | imr->drop(); | ||
2364 | } | ||
2365 | |||
2366 | return nullDriver; | ||
2367 | } | ||
2368 | |||
2369 | |||
2370 | //! Set/unset a clipping plane. | ||
2371 | //! There are at least 6 clipping planes available for the user to set at will. | ||
2372 | //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. | ||
2373 | //! \param plane: The plane itself. | ||
2374 | //! \param enable: If true, enable the clipping plane else disable it. | ||
2375 | bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) | ||
2376 | { | ||
2377 | return false; | ||
2378 | } | ||
2379 | |||
2380 | |||
2381 | //! Enable/disable a clipping plane. | ||
2382 | void CNullDriver::enableClipPlane(u32 index, bool enable) | ||
2383 | { | ||
2384 | // not necessary | ||
2385 | } | ||
2386 | |||
2387 | |||
2388 | ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d<u32>& size, | ||
2389 | const c8* name) | ||
2390 | { | ||
2391 | os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead"); | ||
2392 | ITexture* tex = addRenderTargetTexture(size, name); | ||
2393 | tex->grab(); | ||
2394 | return tex; | ||
2395 | } | ||
2396 | |||
2397 | |||
2398 | void CNullDriver::setMinHardwareBufferVertexCount(u32 count) | ||
2399 | { | ||
2400 | MinVertexCountForVBO = count; | ||
2401 | } | ||
2402 | |||
2403 | |||
2404 | SOverrideMaterial& CNullDriver::getOverrideMaterial() | ||
2405 | { | ||
2406 | return OverrideMaterial; | ||
2407 | } | ||
2408 | |||
2409 | |||
2410 | //! Get the 2d override material for altering its values | ||
2411 | SMaterial& CNullDriver::getMaterial2D() | ||
2412 | { | ||
2413 | return OverrideMaterial2D; | ||
2414 | } | ||
2415 | |||
2416 | |||
2417 | //! Enable the 2d override material | ||
2418 | void CNullDriver::enableMaterial2D(bool enable) | ||
2419 | { | ||
2420 | OverrideMaterial2DEnabled=enable; | ||
2421 | } | ||
2422 | |||
2423 | |||
2424 | core::dimension2du CNullDriver::getMaxTextureSize() const | ||
2425 | { | ||
2426 | return core::dimension2du(0x10000,0x10000); // maybe large enough | ||
2427 | } | ||
2428 | |||
2429 | |||
2430 | //! Color conversion convenience function | ||
2431 | /** Convert an image (as array of pixels) from source to destination | ||
2432 | array, thereby converting the color format. The pixel size is | ||
2433 | determined by the color formats. | ||
2434 | \param sP Pointer to source | ||
2435 | \param sF Color format of source | ||
2436 | \param sN Number of pixels to convert, both array must be large enough | ||
2437 | \param dP Pointer to destination | ||
2438 | \param dF Color format of destination | ||
2439 | */ | ||
2440 | void CNullDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN, | ||
2441 | void* dP, ECOLOR_FORMAT dF) const | ||
2442 | { | ||
2443 | video::CColorConverter::convert_viaFormat(sP, sF, sN, dP, dF); | ||
2444 | } | ||
2445 | |||
2446 | |||
2447 | } // end namespace | ||
2448 | } // end namespace | ||